1/*! p5.js v1.2.0 December 19, 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 describe: { 62 name: 'describe', 63 params: [ 64 { 65 name: 'text', 66 description: '<p>description of the canvas</p>\n', 67 type: 'String' 68 }, 69 { 70 name: 'display', 71 description: '<p>either LABEL or FALLBACK (Optional)</p>\n', 72 type: 'Constant', 73 optional: true 74 } 75 ], 76 class: 'p5', 77 module: 'Environment' 78 }, 79 describeElement: { 80 name: 'describeElement', 81 params: [ 82 { 83 name: 'name', 84 description: '<p>name of the element</p>\n', 85 type: 'String' 86 }, 87 { 88 name: 'text', 89 description: '<p>description of the element</p>\n', 90 type: 'String' 91 }, 92 { 93 name: 'display', 94 description: '<p>either LABEL or FALLBACK (Optional)</p>\n', 95 type: 'Constant', 96 optional: true 97 } 98 ], 99 class: 'p5', 100 module: 'Environment' 101 }, 102 textOutput: { 103 name: 'textOutput', 104 params: [ 105 { 106 name: 'display', 107 description: '<p>either FALLBACK or LABEL (Optional)</p>\n', 108 type: 'Constant', 109 optional: true 110 } 111 ], 112 class: 'p5', 113 module: 'Environment' 114 }, 115 gridOutput: { 116 name: 'gridOutput', 117 params: [ 118 { 119 name: 'display', 120 description: '<p>either FALLBACK or LABEL (Optional)</p>\n', 121 type: 'Constant', 122 optional: true 123 } 124 ], 125 class: 'p5', 126 module: 'Environment' 127 }, 128 alpha: { 129 name: 'alpha', 130 params: [ 131 { 132 name: 'color', 133 description: 134 '<p><a href="#/p5.Color">p5.Color</a> object, color components,\n or CSS color</p>\n', 135 type: 'p5.Color|Number[]|String' 136 } 137 ], 138 class: 'p5', 139 module: 'Color' 140 }, 141 blue: { 142 name: 'blue', 143 params: [ 144 { 145 name: 'color', 146 description: 147 '<p><a href="#/p5.Color">p5.Color</a> object, color components,\n or CSS color</p>\n', 148 type: 'p5.Color|Number[]|String' 149 } 150 ], 151 class: 'p5', 152 module: 'Color' 153 }, 154 brightness: { 155 name: 'brightness', 156 params: [ 157 { 158 name: 'color', 159 description: 160 '<p><a href="#/p5.Color">p5.Color</a> object, color components,\n or CSS color</p>\n', 161 type: 'p5.Color|Number[]|String' 162 } 163 ], 164 class: 'p5', 165 module: 'Color' 166 }, 167 color: { 168 name: 'color', 169 class: 'p5', 170 module: 'Color', 171 overloads: [ 172 { 173 params: [ 174 { 175 name: 'gray', 176 description: 177 '<p>number specifying value between white and black.</p>\n', 178 type: 'Number' 179 }, 180 { 181 name: 'alpha', 182 description: 183 '<p>alpha value relative to current color range\n (default is 0-255)</p>\n', 184 type: 'Number', 185 optional: true 186 } 187 ] 188 }, 189 { 190 params: [ 191 { 192 name: 'v1', 193 description: 194 '<p>red or hue value relative to\n the current color range</p>\n', 195 type: 'Number' 196 }, 197 { 198 name: 'v2', 199 description: 200 '<p>
200green or saturation value\n relative to the current color range</p>\n', 201 type: 'Number' 202 }, 203 { 204 name: 'v3', 205 description: 206 '<p>blue or brightness value\n relative to the current color range</p>\n', 207 type: 'Number' 208 }, 209 { 210 name: 'alpha', 211 description: '', 212 type: 'Number', 213 optional: true 214 } 215 ] 216 }, 217 { 218 params: [ 219 { 220 name: 'value', 221 description: '<p>a color string</p>\n', 222 type: 'String' 223 } 224 ] 225 }, 226 { 227 params: [ 228 { 229 name: 'values', 230 description: 231 '<p>an array containing the red,green,blue &\n and alpha components of the color</p>\n', 232 type: 'Number[]' 233 } 234 ] 235 }, 236 { 237 params: [ 238 { 239 name: 'color', 240 description: '', 241 type: 'p5.Color' 242 } 243 ] 244 } 245 ] 246 }, 247 green: { 248 name: 'green', 249 params: [ 250 { 251 name: 'color', 252 description: 253 '<p><a href="#/p5.Color">p5.Color</a> object, color components,\n or CSS color</p>\n', 254 type: 'p5.Color|Number[]|String' 255 } 256 ], 257 class: 'p5', 258 module: 'Color' 259 }, 260 hue: { 261 name: 'hue', 262 params: [ 263 { 264 name: 'color', 265 description: 266 '<p><a href="#/p5.Color">p5.Color</a> object, color components,\n or CSS color</p>\n', 267 type: 'p5.Color|Number[]|String' 268 } 269 ], 270 class: 'p5', 271 module: 'Color' 272 }, 273 lerpColor: { 274 name: 'lerpColor', 275 params: [ 276 { 277 name: 'c1', 278 description: '<p>interpolate from this color</p>\n', 279 type: 'p5.Color' 280 }, 281 { 282 name: 'c2', 283 description: '<p>interpolate to this color</p>\n', 284 type: 'p5.Color' 285 }, 286 { 287 name: 'amt', 288 description: '<p>number between 0 and 1</p>\n', 289 type: 'Number' 290 } 291 ], 292 class: 'p5', 293 module: 'Color' 294 }, 295 lightness: { 296 name: 'lightness', 297 params: [ 298 { 299 name: 'color', 300 description: 301 '<p><a href="#/p5.Color">p5.Color</a> object, color components,\n or CSS color</p>\n', 302 type: 'p5.Color|Number[]|String' 303 } 304 ], 305 class: 'p5', 306 module: 'Color' 307 }, 308 red: { 309 name: 'red', 310 params: [ 311 { 312 name: 'color', 313 description: 314 '<p><a href="#/p5.Color">p5.Color</a> object, color components,\n or CSS color</p>\n', 315 type: 'p5.Color|Number[]|String' 316 } 317 ], 318 class: 'p5', 319 module: 'Color' 320 }, 321 saturation: { 322 name: 'saturation', 323 params: [ 324 { 325 name: 'color', 326 description: 327 '<p><a href="#/p5.Color">p5.Color</a> object, color components,\n or CSS color</p>\n', 328 type: 'p5.Color|Number[]|String' 329 } 330 ], 331 class: 'p5', 332 module: 'Color' 333 }, 334 background: { 335 name: 'background', 336 class: 'p5', 337 module: 'Color', 338 overloads: [ 339 { 340 params: [ 341 { 342 name: 'color', 343 description: 344 '<p>any value created by the <a href="#/p5/color">color()</a> function</p>\n', 345 type: 'p5.Color' 346 } 347 ], 348 chainable: 1 349 }, 350 { 351 params: [ 352 { 353 name: 'colorstring', 354 description: 355 '<p>color string, possible formats include: integer\n rgb() or rgba(), percentage rgb() or rgba(),\n 3-digit hex, 6-digit hex</p>\n', 356 type: 'String' 357 }, 358 { 359 name: 'a', 360 description: 361 '<p>opacity of the background relative to current\n color range (default is 0-255)</p>\n', 362 type: 'Number', 363 optional: true 364 } 365 ], 366 chainable: 1 367 }, 368 { 369 params: [ 370 { 371 name: 'gray', 372 description: '<p>specifies a value between white and black</p>\n', 373 type: 'Number' 374 }, 375 { 376 name: 'a', 377 description: '', 378 type: 'Number', 379 optional: true 380 } 381 ], 382 chainable: 1 383 }, 384 { 385 params: [ 386 { 387 name: 'v1', 388 description: 389 '<p>red or hue value (depending on the current color\n mode)</p>\n', 390 type: 'Number' 391 }, 392 { 393 name: 'v2', 394 description: 395 '<p>green or saturation value (depending on the current\n color mode)</p>\n', 396 type: 'Number' 397 }, 398 { 399 name: 'v3', 400 description: 401 '<p>blue or brightness value (depending on the current\n color mode)</p>\n', 402 type: 'Number' 403 }, 404 { 405 name: 'a', 406 description: '', 407 type: 'Number', 408 optional: true 409 } 410 ], 411 chainable: 1 412 }, 413 { 414 params: [ 415 { 416 name: 'values', 417 description: 418 '<p>an array containing the red, green, blue\n and alpha components of the color</p>\n', 419 type: 'Number[]' 420 } 421 ], 422 chainable: 1 423 }, 424 { 425 params: [ 426 { 427 name: 'image', 428 description: 429 '<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', 430 type: 'p5.Image' 431 }, 432 { 433 name: 'a', 434 description: '', 435 type: 'Number', 436 optional: true 437 } 438 ], 439 chainable: 1 440 } 441 ] 442 }, 443 clear: { 444 name: 'clear', 445 class: 'p5', 446 module: 'Color' 447 }, 448 colorMode: { 449 name: 'colorMode', 450 class: 'p5', 451 module: 'Color', 452 overloads: [ 453 { 454 params: [ 455 { 456 name: 'mode', 457 description: 458 '<p>either RGB, HSB or HSL, corresponding to\n Red/Green/Blue and Hue/Saturation/Brightness\n (or Lightness)</p>\n', 459 type: 'Constant' 460 }, 461 { 462 name: 'max', 463 description: '<p>range for all values</p>\n', 464 type: 'Number', 465 optional: true 466 } 467 ], 468 chainable: 1 469 }, 470 { 471 params: [ 472 { 473 name: 'mode', 474 description: '', 475 type: 'Constant' 476 }, 477 { 478 name: 'max1', 479 description: 480 '<p>range for the red or hue depending on the\n current color mode</p>\n', 481 type: 'Number' 482 }, 483 { 484 name: 'max2', 485 description: 486 '<p>range for the green or saturation depending\n on the current color mode</p>\n', 487 type: 'Number' 488 }, 489 { 490 name: 'max3', 491 description: 492 '<p>range for the blue or brightness/lightness\n depending on the current color mode</p>\n', 493 type: 'Number' 494 }, 495 { 496 name: 'maxA', 497 description: '<p>range for the alpha</p>\n', 498 type: 'Number', 499 optional: true 500 } 501 ], 502 chainable: 1 503 } 504 ] 505 }, 506 fill: { 507 name: 'fill', 508 class: 'p5', 509 module: 'Color', 510 overloads: [ 511 { 512 params: [ 513 { 514 name: 'v1', 515 description: 516 '<p>red or hue value relative to\n the current color range</p>\n', 517 type: 'Number' 518 }, 519 { 520 name: 'v2', 521 description: 522 '<p>
522green or saturation value\n relative to the current color range</p>\n', 523 type: 'Number' 524 }, 525 { 526 name: 'v3', 527 description: 528 '<p>blue or brightness value\n relative to the current color range</p>\n', 529 type: 'Number' 530 }, 531 { 532 name: 'alpha', 533 description: '', 534 type: 'Number', 535 optional: true 536 } 537 ], 538 chainable: 1 539 }, 540 { 541 params: [ 542 { 543 name: 'value', 544 description: '<p>a color string</p>\n', 545 type: 'String' 546 } 547 ], 548 chainable: 1 549 }, 550 { 551 params: [ 552 { 553 name: 'gray', 554 description: '<p>a gray value</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: 'values', 570 description: 571 '<p>an array containing the red,green,blue &\n and alpha components of the color</p>\n', 572 type: 'Number[]' 573 } 574 ], 575 chainable: 1 576 }, 577 { 578 params: [ 579 { 580 name: 'color', 581 description: '<p>the fill color</p>\n', 582 type: 'p5.Color' 583 } 584 ], 585 chainable: 1 586 } 587 ] 588 }, 589 noFill: { 590 name: 'noFill', 591 class: 'p5', 592 module: 'Color' 593 }, 594 noStroke: { 595 name: 'noStroke', 596 class: 'p5', 597 module: 'Color' 598 }, 599 stroke: { 600 name: 'stroke', 601 class: 'p5', 602 module: 'Color', 603 overloads: [ 604 { 605 params: [ 606 { 607 name: 'v1', 608 description: 609 '<p>red or hue value relative to\n the current color range</p>\n', 610 type: 'Number' 611 }, 612 { 613 name: 'v2', 614 description: 615 '<p>green or saturation value\n relative to the current color range</p>\n', 616 type: 'Number' 617 }, 618 { 619 name: 'v3', 620 description: 621 '<p>blue or brightness value\n relative to the current color range</p>\n', 622 type: 'Number' 623 }, 624 { 625 name: 'alpha', 626 description: '', 627 type: 'Number', 628 optional: true 629 } 630 ], 631 chainable: 1 632 }, 633 { 634 params: [ 635 { 636 name: 'value', 637 description: '<p>a color string</p>\n', 638 type: 'String' 639 } 640 ], 641 chainable: 1 642 }, 643 { 644 params: [ 645 { 646 name: 'gray', 647 description: '<p>a gray value</p>\n', 648 type: 'Number' 649 }, 650 { 651 name: 'alpha', 652 description: '', 653 type: 'Number', 654 optional: true 655 } 656 ], 657 chainable: 1 658 }, 659 { 660 params: [ 661 { 662 name: 'values', 663 description: 664 '<p>an array containing the red,green,blue &\n and alpha components of the color</p>\n', 665 type: 'Number[]' 666 } 667 ], 668 chainable: 1 669 }, 670 { 671 params: [ 672 { 673 name: 'color', 674 description: '<p>the stroke color</p>\n', 675 type: 'p5.Color' 676 } 677 ], 678 chainable: 1 679 } 680 ] 681 },
682 erase: { 683 name: 'erase', 684 params: [ 685 { 686 name: 'strengthFill', 687 description: 688 "<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", 689 type: 'Number', 690 optional: true 691 }, 692 { 693 name: 'strengthStroke', 694 description: 695 "<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", 696 type: 'Number', 697 optional: true 698 } 699 ], 700 class: 'p5', 701 module: 'Color' 702 }, 703 noErase: { 704 name: 'noErase', 705 class: 'p5', 706 module: 'Color' 707 }, 708 arc: { 709 name: 'arc', 710 params: [ 711 { 712 name: 'x', 713 description: "<p>x-coordinate of the arc's ellipse</p>\n", 714 type: 'Number' 715 }, 716 { 717 name: 'y', 718 description: "<p>y-coordinate of the arc's ellipse</p>\n", 719 type: 'Number' 720 }, 721 { 722 name: 'w', 723 description: "<p>width of the arc's ellipse by default</p>\n", 724 type: 'Number' 725 }, 726 { 727 name: 'h', 728 description: "<p>height of the arc's ellipse by default</p>\n", 729 type: 'Number' 730 }, 731 { 732 name: 'start', 733 description: '<p>angle to start the arc, specified in radians</p>\n', 734 type: 'Number' 735 }, 736 { 737 name: 'stop', 738 description: '<p>angle to stop the arc, specified in radians</p>\n', 739 type: 'Number' 740 }, 741 { 742 name: 'mode', 743 description: 744 '<p>optional parameter to determine the way of drawing\n the arc. either CHORD, PIE or OPEN</p>\n', 745 type: 'Constant', 746 optional: true 747 }, 748 { 749 name: 'detail', 750 description: 751 '<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', 752 type: 'Number', 753 optional: true 754 } 755 ], 756 class: 'p5', 757 module: 'Shape' 758 }, 759 ellipse: { 760 name: 'ellipse', 761 class: 'p5', 762 module: 'Shape', 763 overloads: [ 764 { 765 params: [ 766 { 767 name: 'x', 768 description: '<p>x-coordinate of the center of ellipse.</p>\n', 769 type: 'Number' 770 }, 771 { 772 name: 'y', 773 description: '<p>y-coordinate of the center of ellipse.</p>\n', 774 type: 'Number' 775 }, 776 { 777 name: 'w', 778 description: '<p>width of the ellipse.</p>\n', 779 type: 'Number' 780 }, 781 { 782 name: 'h', 783 description: '<p>height of the ellipse.</p>\n', 784 type: 'Number', 785 optional: true 786 } 787 ], 788 chainable: 1 789 }, 790 { 791 params: [ 792 { 793 name: 'x', 794 description: '', 795 type: 'Number' 796 }, 797 { 798 name: 'y', 799 description: '', 800 type: 'Number' 801 }, 802 { 803 name: 'w', 804 description: '', 805 type: 'Number' 806 }, 807 { 808 name: 'h', 809 description: '', 810 type: 'Number' 811 }, 812 { 813 name: 'detail', 814 description: 815 '<p>number of radial sectors to draw (for WebGL mode)</p>\n', 816 type: 'Integer' 817 } 818 ] 819 } 820 ] 821 }, 822 circle: { 823 name: 'circle', 824 params: [ 825 { 826 name: 'x', 827 description: '<p>x-coordinate of the centre of the circle.</p>\n', 828 type: 'Number' 829 }, 830 { 831 name: 'y', 832 description: '<p>y-coordinate of the centre of the circle.</p>\n', 833 type: 'Number' 834 }, 835 { 836 name: 'd', 837 description: '<p>diameter of the circle.</p>\n', 838 type: 'Number' 839 } 840 ], 841 class: 'p5', 842 module: 'Shape' 843 }, 844 line: { 845 name: 'line', 846 class: 'p5', 847 module: 'Shape', 848 overloads: [ 849 { 850 params: [ 851 { 852 name: 'x1', 853 description: '<p>the x-coordinate of the first point</p>\n', 854 type: 'Number' 855 }, 856 { 857 name: 'y1', 858 description: '<p>the y-coordinate of the first point</p>\n', 859 type: 'Number' 860 }, 861 { 862 name: 'x2', 863 description: '<p>the x-coordinate of the second point</p>\n', 864 type: 'Number' 865 }, 866 { 867 name: 'y2', 868 description: '<p>the y-coordinate of the second point</p>\n', 869 type: 'Number' 870 } 871 ], 872 chainable: 1 873 }, 874 { 875 params: [ 876 { 877 name: 'x1', 878 description: '', 879 type: 'Number' 880 }, 881 { 882 name: 'y1', 883 description: '', 884 type: 'Number' 885 }, 886 { 887 name: 'z1', 888 description: '<p>the z-coordinate of the first point</p>\n', 889 type: 'Number' 890 }, 891 { 892 name: 'x2', 893 description: '', 894 type: 'Number' 895 }, 896 { 897 name: 'y2', 898 description: '', 899 type: 'Number' 900 }, 901 { 902 name: 'z2', 903 description: '<p>the z-coordinate of the second point</p>\n', 904 type: 'Number' 905 } 906 ], 907 chainable: 1 908 } 909 ] 910 }, 911 point: { 912 name: 'point', 913 class: 'p5', 914 module: 'Shape', 915 overloads: [ 916 { 917 params: [ 918 { 919 name: 'x', 920 description: '<p>the x-coordinate</p>\n', 921 type: 'Number' 922 }, 923 { 924 name: 'y', 925 description: '<p>the y-coordinate</p>\n', 926 type: 'Number' 927 }, 928 { 929 name: 'z', 930 description: '<p>the z-coordinate (for WebGL mode)</p>\n', 931 type: 'Number', 932 optional: true 933 } 934 ], 935 chainable: 1 936 }, 937 { 938 params: [ 939 { 940 name: 'coordinate_vector', 941 description: '<p>the coordinate vector</p>\n', 942 type: 'p5.Vector' 943 } 944 ], 945 chainable: 1 946 } 947 ] 948 }, 949 quad: { 950 name: 'quad', 951 class: 'p5', 952 module: 'Shape', 953 overloads: [ 954 { 955 params: [ 956 { 957 name: 'x1', 958 description: '<p>the x-coordinate of the first point</p>\n', 959 type: 'Number' 960 }, 961 { 962 name: 'y1', 963 description: '<p>the y-coordinate of the first point</p>\n', 964 type: 'Number' 965 }, 966 { 967 name: 'x2', 968 description: '<p>the x-coordinate of the second point</p>\n', 969 type: 'Number' 970 }, 971 { 972 name: 'y2', 973 description: '<p>the y-coordinate of the second point</p>\n', 974 type: 'Number' 975 }, 976 { 977 name: 'x3', 978 description: '<p>the x-coordinate of the third point</p>\n', 979 type: 'Number' 980 }, 981 { 982 name: 'y3', 983 description: '<p>the y-coordinate of the third point</p>\n', 984 type: 'Number' 985 }, 986 { 987 name: 'x4', 988 description: '<p>the x-coordinate of the fourth point</p>\n', 989 type: 'Number' 990 }, 991 { 992 name: 'y4', 993 description: '<p>the y-coordinate of the fourth point</p>\n', 994 type: 'Number' 995 } 996 ], 997 chainable: 1 998 }, 999 { 1000 params: [ 1001 { 1002 name: 'x1', 1003 description: '', 1004 type: 'Number' 1005 }, 1006 { 1007 name: 'y1', 1008 description: '', 1009 type: 'Number' 1010 }, 1011 { 1012 name: 'z1', 1013 description: '<p>the z-coordinate of the first point</p>\n', 1014 type: 'Number' 1015 }, 1016 { 1017 name: 'x2', 1018 description: '', 1019 type: 'Number' 1020 }, 1021 { 1022 name: 'y2', 1023 description: '', 1024 type: 'Number' 1025 }, 1026 { 1027 name: 'z2', 1028 description: '<p>the z-coordinate of the second point</p>\n', 1029 type: 'Number' 1030 }, 1031 { 1032 name: 'x3', 1033 description: '', 1034 type: 'Number' 1035 }, 1036 { 1037 name: 'y3', 1038 description: '', 1039 type: 'Number' 1040 }, 1041 { 1042 name: 'z3', 1043 description: '<p>the z-coordinate of the third point</p>\n', 1044 type: 'Number' 1045 }, 1046 { 1047 name: 'x4', 1048 description: '', 1049 type: 'Number' 1050 }, 1051 { 1052 name: 'y4', 1053 description: '', 1054 type: 'Number' 1055 }, 1056 { 1057 name: 'z4', 1058 description: '<p>the z-coordinate of the fourth point</p>\n', 1059 type: 'Number' 1060 } 1061 ], 1062 chainable: 1 1063 } 1064 ] 1065 }, 1066 rect: { 1067 name: 'rect', 1068 class: 'p5', 1069 module: 'Shape', 1070 overloads: [ 1071 { 1072 params: [ 1073 { 1074 name: 'x', 1075 description: '<p>x-coordinate of the rectangle.</p>\n', 1076 type: 'Number' 1077 }, 1078 { 1079 name: 'y', 1080 description: '<p>y-coordinate of the rectangle.</p>\n', 1081 type: 'Number' 1082 }, 1083 { 1084 name: 'w', 1085 description: '<p>width of the rectangle.</p>\n', 1086 type: 'Number' 1087 }, 1088 { 1089 name: 'h', 1090 description: '<p>height of the rectangle.</p>\n', 1091 type: 'Number', 1092 optional: true 1093 }, 1094 { 1095 name: 'tl', 1096 description: '<p>optional radius of top-left corner.</p>\n', 1097 type: 'Number', 1098 optional: true 1099 }, 1100 { 1101 name: 'tr', 1102 description: '<p>optional radius of top-right corner.</p>\n', 1103 type: 'Number', 1104 optional: true 1105 }, 1106 { 1107 name: 'br', 1108 description: '<p>optional radius of bottom-right corner.</p>\n', 1109 type: 'Number', 1110 optional: true 1111 }, 1112 { 1113 name: 'bl', 1114 description: '<p>optional radius of bottom-left corner.</p>\n', 1115 type: 'Number', 1116 optional: true 1117 } 1118 ], 1119 chainable: 1 1120 }, 1121 { 1122 params: [ 1123 { 1124 name: 'x', 1125 description: '', 1126 type: 'Number' 1127 }, 1128
1128 { 1129 name: 'y', 1130 description: '', 1131 type: 'Number' 1132 }, 1133 { 1134 name: 'w', 1135 description: '', 1136 type: 'Number' 1137 }, 1138 { 1139 name: 'h', 1140 description: '', 1141 type: 'Number' 1142 }, 1143 { 1144 name: 'detailX', 1145 description: 1146 '<p>number of segments in the x-direction (for WebGL mode)</p>\n', 1147 type: 'Integer', 1148 optional: true 1149 }, 1150 { 1151 name: 'detailY', 1152 description: 1153 '<p>number of segments in the y-direction (for WebGL mode)</p>\n', 1154 type: 'Integer', 1155 optional: true 1156 } 1157 ], 1158 chainable: 1 1159 } 1160 ] 1161 }, 1162 square: { 1163 name: 'square', 1164 params: [ 1165 { 1166 name: 'x', 1167 description: '<p>x-coordinate of the square.</p>\n', 1168 type: 'Number' 1169 }, 1170 { 1171 name: 'y', 1172 description: '<p>y-coordinate of the square.</p>\n', 1173 type: 'Number' 1174 }, 1175 { 1176 name: 's', 1177 description: '<p>side size of the square.</p>\n', 1178 type: 'Number' 1179 }, 1180 { 1181 name: 'tl', 1182 description: '<p>optional radius of top-left corner.</p>\n', 1183 type: 'Number', 1184 optional: true 1185 }, 1186 { 1187 name: 'tr', 1188 description: '<p>optional radius of top-right corner.</p>\n', 1189 type: 'Number', 1190 optional: true 1191 }, 1192 { 1193 name: 'br', 1194 description: '<p>optional radius of bottom-right corner.</p>\n', 1195 type: 'Number', 1196 optional: true 1197 }, 1198 { 1199 name: 'bl', 1200 description: '<p>optional radius of bottom-left corner.</p>\n', 1201 type: 'Number', 1202 optional: true 1203 } 1204 ], 1205 class: 'p5', 1206 module: 'Shape' 1207 }, 1208 triangle: { 1209 name: 'triangle', 1210 params: [ 1211 { 1212 name: 'x1', 1213 description: '<p>x-coordinate of the first point</p>\n', 1214 type: 'Number' 1215 }, 1216 { 1217 name: 'y1', 1218 description: '<p>y-coordinate of the first point</p>\n', 1219 type: 'Number' 1220 }, 1221 { 1222 name: 'x2', 1223 description: '<p>x-coordinate of the second point</p>\n', 1224 type: 'Number' 1225 }, 1226 { 1227 name: 'y2', 1228 description: '<p>y-coordinate of the second point</p>\n', 1229 type: 'Number' 1230 }, 1231 { 1232 name: 'x3', 1233 description: '<p>x-coordinate of the third point</p>\n', 1234 type: 'Number' 1235 }, 1236 { 1237 name: 'y3', 1238 description: '<p>y-coordinate of the third point</p>\n', 1239 type: 'Number' 1240 } 1241 ], 1242 class: 'p5', 1243 module: 'Shape' 1244 }, 1245 ellipseMode: { 1246 name: 'ellipseMode', 1247 params: [ 1248 { 1249 name: 'mode', 1250 description: '<p>either CENTER, RADIUS, CORNER, or CORNERS</p>\n', 1251 type: 'Constant' 1252 } 1253 ], 1254 class: 'p5', 1255 module: 'Shape' 1256 }, 1257 noSmooth: { 1258 name: 'noSmooth', 1259 class: 'p5', 1260 module: 'Shape' 1261 }, 1262 rectMode: { 1263 name: 'rectMode', 1264 params: [ 1265 { 1266 name: 'mode', 1267 description: '<p>either CORNER, CORNERS, CENTER, or RADIUS</p>\n', 1268 type: 'Constant' 1269 } 1270 ], 1271 class: 'p5', 1272 module: 'Shape' 1273 }, 1274 smooth: { 1275 name: 'smooth', 1276 class: 'p5', 1277 module: 'Shape' 1278 }, 1279 strokeCap: { 1280 name: 'strokeCap', 1281 params: [ 1282 { 1283 name: 'cap', 1284 description: '<p>either ROUND, SQUARE or PROJECT</p>\n', 1285 type: 'Constant' 1286 } 1287 ], 1288 class: 'p5', 1289 module: 'Shape' 1290 }, 1291 strokeJoin: { 1292 name: 'strokeJoin', 1293 params: [ 1294 { 1295 name: 'join', 1296 description: '<p>either MITER, BEVEL, ROUND</p>\n', 1297 type: 'Constant' 1298 } 1299 ], 1300 class: 'p5', 1301 module: 'Shape' 1302 }, 1303 strokeWeight: { 1304 name: 'strokeWeight', 1305 params: [ 1306 { 1307 name: 'weight', 1308 description: '<p>the weight of the stroke (in pixels)</p>\n', 1309 type: 'Number' 1310 } 1311 ], 1312 class: 'p5', 1313 module: 'Shape' 1314 }, 1315 bezier: { 1316 name: 'bezier', 1317 class: 'p5', 1318 module: 'Shape', 1319 overloads: [ 1320 { 1321 params: [ 1322 { 1323 name: 'x1', 1324 description: '<p>x-coordinate for the first anchor point</p>\n', 1325 type: 'Number' 1326 }, 1327 { 1328 name: 'y1', 1329 description: '<p>y-coordinate for the first anchor point</p>\n', 1330 type: 'Number' 1331 }, 1332 { 1333 name: 'x2', 1334 description: '<p>x-coordinate for the first control point</p>\n', 1335 type: 'Number' 1336 }, 1337 { 1338 name: 'y2', 1339 description: '<p>y-coordinate for the first control point</p>\n', 1340 type: 'Number' 1341 }, 1342 { 1343 name: 'x3', 1344 description: '<p>x-coordinate for the second control point</p>\n', 1345 type: 'Number' 1346 }, 1347 { 1348 name: 'y3', 1349 description: '<p>y-coordinate for the second control point</p>\n', 1350 type: 'Number' 1351 }, 1352 { 1353 name: 'x4', 1354 description: '<p>x-coordinate for the second anchor point</p>\n', 1355 type: 'Number' 1356 }, 1357 { 1358 name: 'y4', 1359 description: '<p>y-coordinate for the second anchor point</p>\n', 1360 type: 'Number' 1361 } 1362 ], 1363 chainable: 1 1364 }, 1365 { 1366 params: [ 1367 { 1368 name: 'x1', 1369 description: '', 1370 type: 'Number' 1371 }, 1372 { 1373 name: 'y1', 1374 description: '', 1375 type: 'Number' 1376 }, 1377 { 1378 name: 'z1', 1379 description: '<p>z-coordinate for the first anchor point</p>\n', 1380 type: 'Number' 1381 }, 1382 { 1383 name: 'x2', 1384 description: '', 1385 type: 'Number' 1386 }, 1387 { 1388 name: 'y2', 1389 description: '', 1390 type: 'Number' 1391 }, 1392 { 1393 name: 'z2', 1394 description: '<p>z-coordinate for the first control point</p>\n', 1395 type: 'Number' 1396 }, 1397 { 1398 name: 'x3', 1399 description: '', 1400 type: 'Number' 1401 }, 1402 { 1403 name: 'y3', 1404 description: '', 1405 type: 'Number' 1406 }, 1407 { 1408 name: 'z3', 1409 description: '<p>z-coordinate for the second control point</p>\n', 1410 type: 'Number' 1411 }, 1412 { 1413 name: 'x4', 1414 description: '', 1415 type: 'Number' 1416 }, 1417 { 1418 name: 'y4', 1419 description: '', 1420 type: 'Number' 1421 }, 1422 { 1423 name: 'z4', 1424 description: '<p>z-coordinate for the second anchor point</p>\n', 1425 type: 'Number' 1426 } 1427 ], 1428 chainable: 1 1429 } 1430 ] 1431 },
1432 bezierDetail: { 1433 name: 'bezierDetail', 1434 params: [ 1435 { 1436 name: 'detail', 1437 description: '<p>resolution of the curves</p>\n', 1438 type: 'Number' 1439 } 1440 ], 1441 class: 'p5', 1442 module: 'Shape' 1443 }, 1444 bezierPoint: { 1445 name: 'bezierPoint', 1446 params: [ 1447 { 1448 name: 'a', 1449 description: '<p>coordinate of first point on the curve</p>\n', 1450 type: 'Number' 1451 }, 1452 { 1453 name: 'b', 1454 description: '<p>coordinate of first control point</p>\n', 1455 type: 'Number' 1456 }, 1457 { 1458 name: 'c', 1459 description: '<p>coordinate of second control point</p>\n', 1460 type: 'Number' 1461 }, 1462 { 1463 name: 'd', 1464 description: '<p>coordinate of second point on the curve</p>\n', 1465 type: 'Number' 1466 }, 1467 { 1468 name: 't', 1469 description: '<p>value between 0 and 1</p>\n', 1470 type: 'Number' 1471 } 1472 ], 1473 class: 'p5', 1474 module: 'Shape' 1475 }, 1476 bezierTangent: { 1477 name: 'bezierTangent', 1478 params: [ 1479 { 1480 name: 'a', 1481 description: '<p>coordinate of first point on the curve</p>\n', 1482 type: 'Number' 1483 }, 1484 { 1485 name: 'b', 1486 description: '<p>coordinate of first control point</p>\n', 1487 type: 'Number' 1488 }, 1489 { 1490 name: 'c', 1491 description: '<p>coordinate of second control point</p>\n', 1492 type: 'Number' 1493 }, 1494 { 1495 name: 'd', 1496 description: '<p>coordinate of second point on the curve</p>\n', 1497 type: 'Number' 1498 }, 1499 { 1500 name: 't', 1501 description: '<p>value between 0 and 1</p>\n', 1502 type: 'Number' 1503 } 1504 ], 1505 class: 'p5', 1506 module: 'Shape' 1507 }, 1508 curve: { 1509 name: 'curve', 1510 class: 'p5', 1511 module: 'Shape', 1512 overloads: [ 1513 { 1514 params: [ 1515 { 1516 name: 'x1', 1517 description: 1518 '<p>x-coordinate for the beginning control point</p>\n', 1519 type: 'Number' 1520 }, 1521 { 1522 name: 'y1', 1523 description: 1524 '<p>y-coordinate for the beginning control point</p>\n', 1525 type: 'Number' 1526 }, 1527 { 1528 name: 'x2', 1529 description: '<p>x-coordinate for the first point</p>\n', 1530 type: 'Number' 1531 }, 1532 { 1533 name: 'y2', 1534 description: '<p>y-coordinate for the first point</p>\n', 1535 type: 'Number' 1536 }, 1537 { 1538 name: 'x3', 1539 description: '<p>x-coordinate for the second point</p>\n', 1540 type: 'Number' 1541 }, 1542 { 1543 name: 'y3', 1544 description: '<p>y-coordinate for the second point</p>\n', 1545 type: 'Number' 1546 }, 1547 { 1548 name: 'x4', 1549 description: '<p>x-coordinate for the ending control point</p>\n', 1550 type: 'Number' 1551 }, 1552 { 1553 name: 'y4', 1554 description: '<p>y-coordinate for the ending control point</p>\n', 1555 type: 'Number' 1556 } 1557 ], 1558 chainable: 1 1559 }, 1560 { 1561 params: [ 1562 { 1563 name: 'x1', 1564 description: '', 1565 type: 'Number' 1566 }, 1567 { 1568 name: 'y1', 1569 description: '', 1570 type: 'Number' 1571 }, 1572 { 1573 name: 'z1', 1574 description: 1575 '<p>z-coordinate for the beginning control point</p>\n', 1576 type: 'Number' 1577 }, 1578 { 1579 name: 'x2', 1580 description: '', 1581 type: 'Number' 1582 }, 1583 { 1584 name: 'y2', 1585 description: '', 1586 type: 'Number' 1587 }, 1588 { 1589 name: 'z2', 1590 description: '<p>z-coordinate for the first point</p>\n', 1591 type: 'Number' 1592 }, 1593 { 1594 name: 'x3', 1595 description: '', 1596 type: 'Number' 1597 }, 1598 { 1599 name: 'y3', 1600 description: '', 1601 type: 'Number' 1602 }, 1603 { 1604 name: 'z3', 1605 description: '<p>z-coordinate for the second point</p>\n', 1606 type: 'Number' 1607 }, 1608 { 1609 name: 'x4', 1610 description: '', 1611 type: 'Number' 1612 }, 1613 { 1614 name: 'y4', 1615 description: '', 1616 type: 'Number' 1617 }, 1618 { 1619 name: 'z4', 1620 description: '<p>z-coordinate for the ending control point</p>\n', 1621 type: 'Number' 1622 } 1623 ], 1624 chainable: 1 1625 } 1626 ] 1627 }, 1628 curveDetail: { 1629 name: 'curveDetail', 1630 params: [ 1631 { 1632 name: 'resolution', 1633 description: '<p>resolution of the curves</p>\n', 1634 type: 'Number' 1635 } 1636 ], 1637 class: 'p5', 1638 module: 'Shape' 1639 }, 1640 curveTightness: { 1641 name: 'curveTightness', 1642 params: [ 1643 { 1644 name: 'amount', 1645 description: 1646 '<p>amount of deformation from the original vertices</p>\n', 1647 type: 'Number' 1648 } 1649 ], 1650 class: 'p5', 1651 module: 'Shape' 1652 }, 1653 curvePoint: { 1654 name: 'curvePoint', 1655 params: [ 1656 { 1657 name: 'a', 1658 description: '<p>coordinate of first control point of the curve</p>\n', 1659 type: 'Number' 1660 }, 1661 { 1662 name: 'b', 1663 description: '<p>coordinate of first point</p>\n', 1664 type: 'Number' 1665 }, 1666 { 1667 name: 'c', 1668 description: '<p>coordinate of second point</p>\n', 1669 type: 'Number' 1670 }, 1671 { 1672 name: 'd', 1673 description: '<p>coordinate of second control point</p>\n', 1674 type: 'Number' 1675 }, 1676 { 1677 name: 't', 1678 description: '<p>value between 0 and 1</p>\n', 1679 type: 'Number' 1680 } 1681 ], 1682 class: 'p5', 1683 module: 'Shape' 1684 }, 1685 curveTangent: { 1686 name: 'curveTangent', 1687 params: [ 1688 { 1689 name: 'a', 1690 description: '<p>coordinate of first control point</p>\n', 1691 type: 'Number' 1692 }, 1693 { 1694 name: 'b', 1695 description: '<p>coordinate of first point on the curve</p>\n', 1696 type: 'Number' 1697 }, 1698 { 1699 name: 'c', 1700 description: '<p>coordinate of second point on the curve</p>\n', 1701 type: 'Number' 1702 }, 1703 { 1704 name: 'd', 1705 description: '<p>coordinate of second conrol point</p>\n', 1706 type: 'Number' 1707 }, 1708 { 1709 name: 't', 1710 description: '<p>value between 0 and 1</p>\n', 1711 type: 'Number' 1712 } 1713 ], 1714 class: 'p5', 1715 module: 'Shape' 1716 }, 1717 beginContour: { 1718 name: 'beginContour', 1719 class: 'p5', 1720 module: 'Shape' 1721 }, 1722 beginShape: { 1723 name: 'beginShape', 1724 params: [ 1725 { 1726 name: 'kind', 1727 description: 1728 '<p>either POINTS, LINES, TRIANGLES, TRIANGLE_FAN\n TRIANGLE_STRIP, QUADS, QUAD_STRIP or TESS</p>\n', 1729 type: 'Constant', 1730 optional: true 1731 } 1732 ], 1733 class: 'p5', 1734 module: 'Shape' 1735 }, 1736 bezierVertex: { 1737 name: 'bezierVertex', 1738 class: 'p5', 1739 module: 'Shape', 1740 overloads: [ 1741 { 1742 params: [ 1743 { 1744 name: 'x2', 1745 description: '<p>x-coordinate for the first control point</p>\n', 1746 type: 'Number' 1747 }, 1748 { 1749 name: 'y2', 1750 description: '<p>y-coordinate for the first control point</p>\n', 1751 type: 'Number' 1752 }, 1753 { 1754 name: 'x3', 1755 description: '<p>x-coordinate for the second control point</p>\n', 1756 type: 'Number' 1757 }, 1758 { 1759 name: 'y3', 1760 description: '<p>y-coordinate for the second control point</p>\n', 1761 type: 'Number' 1762 }, 1763 { 1764 name: 'x4', 1765 description: '<p>
1765x-coordinate for the anchor point</p>\n', 1766 type: 'Number' 1767 }, 1768 { 1769 name: 'y4', 1770 description: '<p>y-coordinate for the anchor point</p>\n', 1771 type: 'Number' 1772 } 1773 ], 1774 chainable: 1 1775 }, 1776 { 1777 params: [ 1778 { 1779 name: 'x2', 1780 description: '', 1781 type: 'Number' 1782 }, 1783 { 1784 name: 'y2', 1785 description: '', 1786 type: 'Number' 1787 }, 1788 { 1789 name: 'z2', 1790 description: 1791 '<p>z-coordinate for the first control point (for WebGL mode)</p>\n', 1792 type: 'Number' 1793 }, 1794 { 1795 name: 'x3', 1796 description: '', 1797 type: 'Number' 1798 }, 1799 { 1800 name: 'y3', 1801 description: '', 1802 type: 'Number' 1803 }, 1804 { 1805 name: 'z3', 1806 description: 1807 '<p>z-coordinate for the second control point (for WebGL mode)</p>\n', 1808 type: 'Number' 1809 }, 1810 { 1811 name: 'x4', 1812 description: '', 1813 type: 'Number' 1814 }, 1815 { 1816 name: 'y4', 1817 description: '', 1818 type: 'Number' 1819 }, 1820 { 1821 name: 'z4', 1822 description: 1823 '<p>z-coordinate for the anchor point (for WebGL mode)</p>\n', 1824 type: 'Number' 1825 } 1826 ], 1827 chainable: 1 1828 } 1829 ] 1830 }, 1831 curveVertex: { 1832 name: 'curveVertex', 1833 class: 'p5', 1834 module: 'Shape', 1835 overloads: [ 1836 { 1837 params: [ 1838 { 1839 name: 'x', 1840 description: '<p>x-coordinate of the vertex</p>\n', 1841 type: 'Number' 1842 }, 1843 { 1844 name: 'y', 1845 description: '<p>y-coordinate of the vertex</p>\n', 1846 type: 'Number' 1847 } 1848 ], 1849 chainable: 1 1850 }, 1851 { 1852 params: [ 1853 { 1854 name: 'x', 1855 description: '', 1856 type: 'Number' 1857 }, 1858 { 1859 name: 'y', 1860 description: '', 1861 type: 'Number' 1862 }, 1863 { 1864 name: 'z', 1865 description: '<p>z-coordinate of the vertex (for WebGL mode)</p>\n', 1866 type: 'Number', 1867 optional: true 1868 } 1869 ], 1870 chainable: 1 1871 } 1872 ] 1873 }, 1874 endContour: { 1875 name: 'endContour', 1876 class: 'p5', 1877 module: 'Shape' 1878 }, 1879 endShape: { 1880 name: 'endShape', 1881 params: [ 1882 { 1883 name: 'mode', 1884 description: '<p>use CLOSE to close the shape</p>\n', 1885 type: 'Constant', 1886 optional: true 1887 } 1888 ], 1889 class: 'p5', 1890 module: 'Shape' 1891 }, 1892 quadraticVertex: { 1893 name: 'quadraticVertex', 1894 class: 'p5', 1895 module: 'Shape', 1896 overloads: [ 1897 { 1898 params: [ 1899 { 1900 name: 'cx', 1901 description: '<p>x-coordinate for the control point</p>\n', 1902 type: 'Number' 1903 }, 1904 { 1905 name: 'cy', 1906 description: '<p>y-coordinate for the control point</p>\n', 1907 type: 'Number' 1908 }, 1909 { 1910 name: 'x3', 1911 description: '<p>
1911x-coordinate for the anchor point</p>\n', 1912 type: 'Number' 1913 }, 1914 { 1915 name: 'y3', 1916 description: '<p>y-coordinate for the anchor point</p>\n', 1917 type: 'Number' 1918 } 1919 ], 1920 chainable: 1 1921 }, 1922 { 1923 params: [ 1924 { 1925 name: 'cx', 1926 description: '', 1927 type: 'Number' 1928 }, 1929 { 1930 name: 'cy', 1931 description: '', 1932 type: 'Number' 1933 }, 1934 { 1935 name: 'cz', 1936 description: 1937 '<p>z-coordinate for the control point (for WebGL mode)</p>\n', 1938 type: 'Number' 1939 }, 1940 { 1941 name: 'x3', 1942 description: '', 1943 type: 'Number' 1944 }, 1945 { 1946 name: 'y3', 1947 description: '', 1948 type: 'Number' 1949 }, 1950 { 1951 name: 'z3', 1952 description: 1953 '<p>z-coordinate for the anchor point (for WebGL mode)</p>\n', 1954 type: 'Number' 1955 } 1956 ], 1957 chainable: 1 1958 } 1959 ] 1960 }, 1961 vertex: { 1962 name: 'vertex', 1963 class: 'p5', 1964 module: 'Shape', 1965 overloads: [ 1966 { 1967 params: [ 1968 { 1969 name: 'x', 1970 description: '<p>x-coordinate of the vertex</p>\n', 1971 type: 'Number' 1972 }, 1973 { 1974 name: 'y', 1975 description: '<p>y-coordinate of the vertex</p>\n', 1976 type: 'Number' 1977 } 1978 ], 1979 chainable: 1 1980 }, 1981 { 1982 params: [ 1983 { 1984 name: 'x', 1985 description: '', 1986 type: 'Number' 1987 }, 1988 { 1989 name: 'y', 1990 description: '', 1991 type: 'Number' 1992 }, 1993 { 1994 name: 'z', 1995 description: '<p>z-coordinate of the vertex</p>\n', 1996 type: 'Number' 1997 }, 1998 { 1999 name: 'u', 2000 description: "<p>the vertex's texture u-coordinate</p>\n", 2001 type: 'Number', 2002 optional: true 2003 }, 2004 { 2005 name: 'v', 2006 description: "<p>the vertex's texture v-coordinate</p>\n", 2007 type: 'Number', 2008 optional: true 2009 } 2010 ], 2011 chainable: 1 2012 } 2013 ] 2014 }, 2015 P2D: { 2016 name: 'P2D', 2017 class: 'p5', 2018 module: 'Constants' 2019 }, 2020 WEBGL: { 2021 name: 'WEBGL', 2022 class: 'p5', 2023 module: 'Constants' 2024 }, 2025 ARROW: { 2026 name: 'ARROW', 2027 class: 'p5', 2028 module: 'Constants' 2029 }, 2030 CROSS: { 2031 name: 'CROSS', 2032 class: 'p5', 2033 module: 'Constants' 2034 }, 2035 HAND: { 2036 name: 'HAND', 2037 class: 'p5', 2038 module: 'Constants' 2039 }, 2040 MOVE: { 2041 name: 'MOVE', 2042 class: 'p5', 2043 module: 'Constants' 2044 }, 2045 TEXT: { 2046 name: 'TEXT', 2047 class: 'p5', 2048 module: 'Constants' 2049 }, 2050 WAIT: { 2051 name: 'WAIT', 2052 class: 'p5', 2053 module: 'Constants' 2054 }, 2055 HALF_PI: { 2056 name: 'HALF_PI', 2057 class: 'p5', 2058 module: 'Constants' 2059 }, 2060 PI: { 2061 name: 'PI', 2062 class: 'p5', 2063 module: 'Constants' 2064 }, 2065 QUARTER_PI: { 2066 name: 'QUARTER_PI', 2067 class: 'p5', 2068 module: 'Constants' 2069 }, 2070 TAU: { 2071 name: 'TAU', 2072 class: 'p5', 2073 module: 'Constants' 2074 }, 2075 TWO_PI: { 2076 name: 'TWO_PI', 2077 class: 'p5', 2078 module: 'Constants' 2079 }, 2080 DEGREES: { 2081 name: 'DEGREES', 2082 class: 'p5', 2083 module: 'Constants' 2084 }, 2085 RADIANS: { 2086 name: 'RADIANS', 2087 class: 'p5', 2088 module: 'Constants' 2089 }, 2090 CORNER: { 2091 name: 'CORNER', 2092 class: 'p5', 2093 module: 'Constants' 2094 }, 2095 CORNERS: { 2096 name: 'CORNERS', 2097 class: 'p5', 2098 module: 'Constants' 2099 }, 2100 RADIUS: { 2101 name: 'RADIUS', 2102 class: 'p5', 2103 module: 'Constants' 2104 }, 2105 RIGHT: { 2106 name: 'RIGHT', 2107 class: 'p5', 2108 module: 'Constants' 2109 }, 2110 LEFT: { 2111 name: 'LEFT', 2112 class: 'p5', 2113 module: 'Constants' 2114 }, 2115 CENTER: { 2116 name: 'CENTER', 2117 class: 'p5', 2118 module: 'Constants' 2119 }, 2120 TOP: { 2121 name: 'TOP', 2122 class: 'p5', 2123 module: 'Constants' 2124 }, 2125 BOTTOM: { 2126 name: 'BOTTOM', 2127 class: 'p5', 2128 module: 'Constants' 2129 }, 2130 BASELINE: { 2131 name: 'BASELINE', 2132 class: 'p5', 2133 module: 'Constants' 2134 }, 2135 POINTS: { 2136 name: 'POINTS', 2137 class: 'p5', 2138 module: 'Constants' 2139 }, 2140 LINES: { 2141 name: 'LINES', 2142 class: 'p5', 2143 module: 'Constants' 2144 }, 2145 LINE_STRIP: { 2146 name: 'LINE_STRIP', 2147 class: 'p5', 2148 module: 'Constants' 2149 }, 2150 LINE_LOOP: { 2151 name: 'LINE_LOOP', 2152 class: 'p5', 2153 module: 'Constants' 2154 }, 2155 TRIANGLES: { 2156 name: 'TRIANGLES', 2157 class: 'p5', 2158 module: 'Constants' 2159 }, 2160 TRIANGLE_FAN: { 2161 name: 'TRIANGLE_FAN', 2162 class: 'p5', 2163 module: 'Constants' 2164 }, 2165 TRIANGLE_STRIP: { 2166 name: 'TRIANGLE_STRIP', 2167 class: 'p5', 2168 module: 'Constants' 2169 }, 2170 QUADS: { 2171 name: 'QUADS', 2172 class: 'p5', 2173 module: 'Constants' 2174 }, 2175 QUAD_STRIP: { 2176 name: 'QUAD_STRIP', 2177 class: 'p5', 2178 module: 'Constants' 2179 }, 2180 TESS: { 2181 name: 'TESS', 2182 class: 'p5', 2183 module: 'Constants' 2184 }, 2185 CLOSE: { 2186 name: 'CLOSE', 2187 class: 'p5', 2188 module: 'Constants' 2189 }, 2190 OPEN: { 2191 name: 'OPEN', 2192 class: 'p5', 2193 module: 'Constants' 2194 }, 2195 CHORD: { 2196 name: 'CHORD', 2197 class: 'p5', 2198 module: 'Constants' 2199 }, 2200 PIE: { 2201 name: 'PIE', 2202 class: 'p5', 2203 module: 'Constants' 2204 }, 2205 PROJECT: { 2206 name: 'PROJECT', 2207 class: 'p5', 2208 module: 'Constants' 2209 }, 2210 SQUARE: { 2211 name: 'SQUARE', 2212 class: 'p5', 2213 module: 'Constants' 2214 }, 2215 ROUND: { 2216 name: 'ROUND', 2217 class: 'p5', 2218 module: 'Constants' 2219 }, 2220 BEVEL: { 2221 name: 'BEVEL', 2222 class: 'p5', 2223 module: 'Constants' 2224 }, 2225 MITER: { 2226 name: 'MITER', 2227 class: 'p5', 2228 module: 'Constants' 2229 }, 2230 RGB: { 2231 name: 'RGB', 2232 class: 'p5', 2233 module: 'Constants' 2234 }, 2235 HSB: { 2236 name: 'HSB', 2237 class: 'p5', 2238 module: 'Constants' 2239 }, 2240 HSL: { 2241 name: 'HSL', 2242 class: 'p5', 2243 module: 'Constants' 2244 }, 2245 AUTO: { 2246 name: 'AUTO', 2247 class: 'p5', 2248 module: 'Constants' 2249 }, 2250 ALT: { 2251 name: 'ALT', 2252 class: 'p5', 2253 module: 'Constants' 2254 }, 2255 BACKSPACE: { 2256 name: 'BACKSPACE', 2257 class: 'p5', 2258 module: 'Constants' 2259 }, 2260 CONTROL: { 2261 name: 'CONTROL', 2262 class: 'p5', 2263 module: 'Constants' 2264 }, 2265 DELETE: { 2266 name: 'DELETE', 2267 class: 'p5', 2268 module: 'Constants' 2269 }, 2270 DOWN_ARROW: { 2271 name: 'DOWN_ARROW', 2272 class: 'p5', 2273 module: 'Constants' 2274 }, 2275 ENTER: { 2276 name: 'ENTER', 2277 class: 'p5', 2278 module: 'Constants' 2279 }, 2280 ESCAPE: { 2281 name: 'ESCAPE', 2282 class: 'p5', 2283 module: 'Constants' 2284 }, 2285 LEFT_ARROW: { 2286 name: 'LEFT_ARROW', 2287 class: 'p5', 2288 module: 'Constants' 2289 }, 2290 OPTION: { 2291 name: 'OPTION', 2292 class: 'p5', 2293 module: 'Constants' 2294 }, 2295 RETURN: { 2296 name: 'RETURN', 2297 class: 'p5', 2298 module: 'Constants' 2299 }, 2300 RIGHT_ARROW: { 2301 name: 'RIGHT_ARROW', 2302 class: 'p5', 2303 module: 'Constants' 2304 }, 2305 SHIFT: { 2306 name: 'SHIFT', 2307 class: 'p5', 2308 module: 'Constants' 2309 }, 2310 TAB: { 2311 name: 'TAB', 2312 class: 'p5', 2313 module: 'Constants' 2314 }, 2315 UP_ARROW: { 2316 name: 'UP_ARROW', 2317 class: 'p5', 2318 module: 'Constants' 2319 }, 2320 BLEND: { 2321 name: 'BLEND', 2322 class: 'p5', 2323 module: 'Constants' 2324 }, 2325 REMOVE: { 2326 name: 'REMOVE', 2327 class: 'p5', 2328 module: 'Constants' 2329 }, 2330 ADD: { 2331 name: 'ADD', 2332 class: 'p5', 2333 module: 'Constants' 2334 }, 2335 DARKEST: { 2336 name: 'DARKEST', 2337 class: 'p5', 2338 module: 'Constants' 2339 }, 2340 LIGHTEST: { 2341 name: 'LIGHTEST', 2342 class: 'p5', 2343 module: 'Constants' 2344 }, 2345 DIFFERENCE: { 2346 name: 'DIFFERENCE', 2347 class: 'p5', 2348 module: 'Constants' 2349 }, 2350 SUBTRACT: { 2351 name: 'SUBTRACT', 2352 class: 'p5', 2353 module: 'Constants' 2354 }, 2355 EXCLUSION: { 2356 name: 'EXCLUSION', 2357 class: 'p5', 2358 module: 'Constants' 2359 }, 2360 MULTIPLY: { 2361 name: 'MULTIPLY', 2362 class: 'p5', 2363 module: 'Constants' 2364 }, 2365 SCREEN: { 2366 name: 'SCREEN', 2367 class: 'p5', 2368 module: 'Constants' 2369 }, 2370 REPLACE: { 2371 name: 'REPLACE', 2372 class: 'p5', 2373 module: 'Constants' 2374 }, 2375 OVERLAY: { 2376 name: 'OVERLAY', 2377 class: 'p5', 2378 module: 'Constants' 2379 }, 2380 HARD_LIGHT: { 2381 name: 'HARD_LIGHT', 2382 class: 'p5', 2383 module: 'Constants' 2384 }, 2385 SOFT_LIGHT: { 2386 name: 'SOFT_LIGHT', 2387 class: 'p5', 2388 module: 'Constants' 2389 }, 2390 DODGE: { 2391 name: 'DODGE', 2392 class: 'p5', 2393 module: 'Constants' 2394 }, 2395 BURN: { 2396 name: 'BURN', 2397 class: 'p5', 2398 module: 'Constants' 2399 }, 2400 THRESHOLD: { 2401 name: 'THRESHOLD', 2402 class: 'p5', 2403 module: 'Constants' 2404 }, 2405 GRAY: { 2406 name: 'GRAY', 2407 class: 'p5', 2408 module: 'Constants' 2409 }, 2410 OPAQUE: { 2411 name: 'OPAQUE', 2412 class: 'p5', 2413 module: 'Constants' 2414 }, 2415 INVERT: { 2416 name: 'INVERT', 2417 class: 'p5', 2418 module: 'Constants' 2419 }, 2420 POSTERIZE: { 2421 name: 'POSTERIZE', 2422 class: 'p5', 2423 module: 'Constants' 2424 }, 2425 DILATE: { 2426 name: 'DILATE', 2427 class: 'p5', 2428 module: 'Constants' 2429 }, 2430 ERODE: { 2431 name: 'ERODE', 2432 class: 'p5', 2433 module: 'Constants' 2434 }, 2435 BLUR: { 2436 name: 'BLUR', 2437 class: 'p5', 2438 module: 'Constants' 2439 }, 2440 NORMAL: { 2441 name: 'NORMAL', 2442 class: 'p5', 2443 module: 'Constants' 2444 }, 2445 ITALIC: { 2446 name: 'ITALIC', 2447 class: 'p5', 2448 module: 'Constants' 2449 }, 2450 BOLD: { 2451 name: 'BOLD', 2452 class: 'p5', 2453 module: 'Constants' 2454 }, 2455 BOLDITALIC: { 2456 name: 'BOLDITALIC', 2457 class: 'p5', 2458 module: 'Constants' 2459 }, 2460 LINEAR: { 2461 name: 'LINEAR', 2462 class: 'p5', 2463 module: 'Constants' 2464 }, 2465 QUADRATIC: { 2466 name: 'QUADRATIC', 2467 class: 'p5', 2468 module: 'Constants' 2469 }, 2470 BEZIER: { 2471 name: 'BEZIER', 2472 class: 'p5', 2473 module: 'Constants' 2474 }, 2475 CURVE: { 2476 name: 'CURVE', 2477 class: 'p5', 2478
2478 module: 'Constants' 2479 }, 2480 STROKE: { 2481 name: 'STROKE', 2482 class: 'p5', 2483 module: 'Constants' 2484 }, 2485 FILL: { 2486 name: 'FILL', 2487 class: 'p5', 2488 module: 'Constants' 2489 }, 2490 TEXTURE: { 2491 name: 'TEXTURE', 2492 class: 'p5', 2493 module: 'Constants' 2494 }, 2495 IMMEDIATE: { 2496 name: 'IMMEDIATE', 2497 class: 'p5', 2498 module: 'Constants' 2499 }, 2500 IMAGE: { 2501 name: 'IMAGE', 2502 class: 'p5', 2503 module: 'Constants' 2504 }, 2505 NEAREST: { 2506 name: 'NEAREST', 2507 class: 'p5', 2508 module: 'Constants' 2509 }, 2510 REPEAT: { 2511 name: 'REPEAT', 2512 class: 'p5', 2513 module: 'Constants' 2514 }, 2515 CLAMP: { 2516 name: 'CLAMP', 2517 class: 'p5', 2518 module: 'Constants' 2519 }, 2520 MIRROR: { 2521 name: 'MIRROR', 2522 class: 'p5', 2523 module: 'Constants' 2524 }, 2525 LANDSCAPE: { 2526 name: 'LANDSCAPE', 2527 class: 'p5', 2528 module: 'Constants' 2529 }, 2530 PORTRAIT: { 2531 name: 'PORTRAIT', 2532 class: 'p5', 2533 module: 'Constants' 2534 }, 2535 GRID: { 2536 name: 'GRID', 2537 class: 'p5', 2538 module: 'Constants' 2539 }, 2540 AXES: { 2541 name: 'AXES', 2542 class: 'p5', 2543 module: 'Constants' 2544 }, 2545 LABEL: { 2546 name: 'LABEL', 2547 class: 'p5', 2548 module: 'Constants' 2549 }, 2550 FALLBACK: { 2551 name: 'FALLBACK', 2552 class: 'p5', 2553 module: 'Constants' 2554 }, 2555 print: { 2556 name: 'print', 2557 params: [ 2558 { 2559 name: 'contents', 2560 description: 2561 '<p>any combination of Number, String, Object, Boolean,\n Array to print</p>\n', 2562 type: 'Any' 2563 } 2564 ], 2565 class: 'p5', 2566 module: 'Environment' 2567 }, 2568 frameCount: { 2569 name: 'frameCount', 2570 class: 'p5', 2571 module: 'Environment' 2572 }, 2573 deltaTime: { 2574 name: 'deltaTime', 2575 class: 'p5', 2576 module: 'Environment' 2577 }, 2578 focused: { 2579 name: 'focused', 2580 class: 'p5', 2581 module: 'Environment' 2582 }, 2583 cursor: { 2584 name: 'cursor', 2585 params: [ 2586 { 2587 name: 'type', 2588 description: 2589 "<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", 2590 type: 'String|Constant' 2591 }, 2592 { 2593 name: 'x', 2594 description: 2595 '<p>the horizontal active spot of the cursor (must be less than 32)</p>\n', 2596 type: 'Number', 2597 optional: true 2598 }, 2599 { 2600 name: 'y', 2601 description: 2602 '<p>the vertical active spot of the cursor (must be less than 32)</p>\n', 2603 type: 'Number', 2604 optional: true 2605 } 2606 ], 2607 class: 'p5', 2608 module: 'Environment' 2609 }, 2610 frameRate: { 2611 name: 'frameRate', 2612 class: 'p5', 2613 module: 'Environment', 2614 overloads: [ 2615 { 2616 params: [ 2617 { 2618 name: 'fps', 2619 description: 2620 '<p>number of frames to be displayed every second</p>\n', 2621 type: 'Number' 2622 } 2623 ], 2624 chainable: 1 2625 }, 2626 { 2627 params: [] 2628 } 2629 ] 2630 }, 2631 noCursor: { 2632 name: 'noCursor', 2633 class: 'p5', 2634 module: 'Environment' 2635 }, 2636 displayWidth: { 2637 name: 'displayWidth', 2638 class: 'p5', 2639 module: 'Environment' 2640 }, 2641 displayHeight: { 2642 name: 'displayHeight', 2643 class: 'p5', 2644 module: 'Environment' 2645 }, 2646 windowWidth: { 2647 name: 'windowWidth', 2648 class: 'p5', 2649 module: 'Environment' 2650 }, 2651 windowHeight: { 2652 name: 'windowHeight', 2653 class: 'p5', 2654 module: 'Environment' 2655 }, 2656 windowResized: { 2657 name: 'windowResized', 2658 class: 'p5', 2659 module: 'Environment' 2660 }, 2661 width: { 2662 name: 'width', 2663 class: 'p5', 2664 module: 'Environment' 2665 }, 2666 height: { 2667 name: 'height', 2668 class: 'p5', 2669 module: 'Environment' 2670 }, 2671 fullscreen: { 2672 name: 'fullscreen', 2673 params: [ 2674 { 2675 name: 'val', 2676 description: 2677 '<p>whether the sketch should be in fullscreen mode\nor not</p>\n', 2678 type: 'Boolean', 2679 optional: true 2680 } 2681 ], 2682 class: 'p5', 2683 module: 'Environment' 2684 }, 2685 pixelDensity: { 2686 name: 'pixelDensity', 2687 class: 'p5', 2688 module: 'Environment', 2689 overloads: [ 2690 { 2691 params: [ 2692 { 2693 name: 'val', 2694 description: '<p>whether or how much the sketch should scale</p>\n', 2695 type: 'Number' 2696 } 2697 ], 2698 chainable: 1 2699 }, 2700 { 2701 params: [] 2702 } 2703 ] 2704 }, 2705 displayDensity: { 2706 name: 'displayDensity', 2707 class: 'p5', 2708 module: 'Environment' 2709 }, 2710 getURL: { 2711 name: 'getURL', 2712 class: 'p5', 2713 module: 'Environment' 2714 }, 2715 getURLPath: { 2716 name: 'getURLPath', 2717 class: 'p5', 2718 module: 'Environment' 2719 }, 2720 getURLParams: { 2721 name: 'getURLParams', 2722 class: 'p5', 2723 module: 'Environment' 2724 }, 2725 preload: { 2726 name: 'preload', 2727 class: 'p5', 2728 module: 'Structure' 2729 }, 2730 setup: { 2731 name: 'setup', 2732 class: 'p5', 2733 module: 'Structure' 2734 }, 2735 draw: { 2736 name: 'draw', 2737 class: 'p5', 2738 module: 'Structure' 2739 }, 2740 remove: { 2741 name: 'remove', 2742 class: 'p5', 2743 module: 'Structure' 2744 }, 2745 disableFriendlyErrors: { 2746 name: 'disableFriendlyErrors', 2747 class: 'p5', 2748 module: 'Structure' 2749 }, 2750 let: { 2751 name: 'let', 2752 class: 'p5', 2753 module: 'Foundation' 2754 }, 2755 const: { 2756 name: 'const', 2757 class: 'p5', 2758 module: 'Foundation' 2759 }, 2760 '===': { 2761 name: '===', 2762 class: 'p5', 2763 module: 'Foundation' 2764 }, 2765 '>': { 2766 name: '>', 2767 class: 'p5', 2768 module: 'Foundation' 2769 }, 2770 '>=': { 2771 name: '>=', 2772 class: 'p5', 2773 module: 'Foundation' 2774 }, 2775 '<': { 2776 name: '<', 2777 class: 'p5', 2778 module: 'Foundation' 2779 }, 2780 '<=': { 2781 name: '<=', 2782 class: 'p5', 2783 module: 'Foundation' 2784 }, 2785 'if-else': { 2786 name: 'if-else', 2787 class: 'p5', 2788 module: 'Foundation' 2789 }, 2790 function: { 2791 name: 'function', 2792 class: 'p5', 2793 module: 'Foundation' 2794 }, 2795 return: { 2796 name: 'return', 2797 class: 'p5', 2798 module: 'Foundation' 2799 }, 2800 boolean: { 2801 name: 'boolean', 2802 params: [ 2803 { 2804 name: 'n', 2805 description: '<p>value to parse</p>\n', 2806 type: 'String|Boolean|Number|Array' 2807 } 2808 ], 2809 class: 'p5', 2810 module: 'Data' 2811 },
2812 string: { 2813 name: 'string', 2814 class: 'p5', 2815 module: 'Foundation' 2816 }, 2817 number: { 2818 name: 'number', 2819 class: 'p5', 2820 module: 'Foundation' 2821 }, 2822 object: { 2823 name: 'object', 2824 class: 'p5', 2825 module: 'Foundation' 2826 }, 2827 class: { 2828 name: 'class', 2829 class: 'p5', 2830 module: 'Foundation' 2831 }, 2832 for: { 2833 name: 'for', 2834 class: 'p5', 2835 module: 'Foundation' 2836 }, 2837 while: { 2838 name: 'while', 2839 class: 'p5', 2840 module: 'Foundation' 2841 }, 2842 createCanvas: { 2843 name: 'createCanvas', 2844 params: [ 2845 { 2846 name: 'w', 2847 description: '<p>width of the canvas</p>\n', 2848 type: 'Number' 2849 }, 2850 { 2851 name: 'h', 2852 description: '<p>height of the canvas</p>\n', 2853 type: 'Number' 2854 }, 2855 { 2856 name: 'renderer', 2857 description: '<p>either P2D or WEBGL</p>\n', 2858 type: 'Constant', 2859 optional: true 2860 } 2861 ], 2862 class: 'p5', 2863 module: 'Rendering' 2864 }, 2865 resizeCanvas: { 2866 name: 'resizeCanvas', 2867 params: [ 2868 { 2869 name: 'w', 2870 description: '<p>width of the canvas</p>\n', 2871 type: 'Number' 2872 }, 2873 { 2874 name: 'h', 2875 description: '<p>height of the canvas</p>\n', 2876 type: 'Number' 2877 }, 2878 { 2879 name: 'noRedraw', 2880 description: "<p>don't redraw the canvas immediately</p>\n", 2881 type: 'Boolean', 2882 optional: true 2883 } 2884 ], 2885 class: 'p5', 2886 module: 'Rendering' 2887 }, 2888 noCanvas: { 2889 name: 'noCanvas', 2890 class: 'p5', 2891 module: 'Rendering' 2892 }, 2893 createGraphics: { 2894 name: 'createGraphics', 2895 params: [ 2896 { 2897 name: 'w', 2898 description: '<p>width of the offscreen graphics buffer</p>\n', 2899 type: 'Number' 2900 }, 2901 { 2902 name: 'h', 2903 description: '<p>height of the offscreen graphics buffer</p>\n', 2904 type: 'Number' 2905 }, 2906 { 2907 name: 'renderer', 2908 description: 2909 '<p>either P2D or WEBGL\n undefined defaults to p2d</p>\n', 2910 type: 'Constant', 2911 optional: true 2912 } 2913 ], 2914 class: 'p5', 2915 module: 'Rendering' 2916 }, 2917 blendMode: { 2918 name: 'blendMode', 2919 params: [ 2920 { 2921 name: 'mode', 2922 description: 2923 '<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', 2924 type: 'Constant' 2925 } 2926 ], 2927 class: 'p5', 2928 module: 'Rendering' 2929 }, 2930 drawingContext: { 2931 name: 'drawingContext', 2932 class: 'p5', 2933 module: 'Rendering' 2934 }, 2935 noLoop: { 2936 name: 'noLoop', 2937 class: 'p5', 2938 module: 'Structure' 2939 }, 2940 loop: { 2941 name: 'loop', 2942 class: 'p5', 2943 module: 'Structure' 2944 }, 2945 isLooping: { 2946 name: 'isLooping', 2947 class: 'p5', 2948 module: 'Structure' 2949 }, 2950 push: { 2951 name: 'push', 2952 class: 'p5', 2953 module: 'Structure' 2954 }, 2955 pop: { 2956 name: 'pop', 2957 class: 'p5', 2958 module: 'Structure' 2959 }, 2960 redraw: { 2961 name: 'redraw', 2962 params: [ 2963 { 2964 name: 'n', 2965 description: '<p>Redraw for n-times. The default value is 1.</p>\n', 2966 type: 'Integer', 2967 optional: true 2968 } 2969 ], 2970 class: 'p5', 2971 module: 'Structure' 2972 }, 2973 p5: { 2974 name: 'p5', 2975 params: [ 2976 { 2977 name: 'sketch', 2978 description: '<p>a function containing a p5.js sketch</p>\n', 2979 type: 'Object' 2980 }, 2981 { 2982 name: 'node', 2983 description: 2984 '<p>ID or pointer to HTML DOM node to contain sketch in</p>\n', 2985 type: 'String|Object' 2986 } 2987 ], 2988 class: 'p5', 2989 module: 'Structure' 2990 }, 2991 applyMatrix: { 2992 name: 'applyMatrix', 2993 params: [ 2994 { 2995 name: 'a', 2996 description: 2997 '<p>numbers which define the 2x3 matrix to be multiplied</p>\n', 2998 type: 'Number' 2999 }, 3000 { 3001 name: 'b', 3002 description: 3003 '<p>numbers which define the 2x3 matrix to be multiplied</p>\n', 3004 type: 'Number' 3005 }, 3006 { 3007 name: 'c', 3008 description: 3009 '<p>numbers which define the 2x3 matrix to be multiplied</p>\n', 3010 type: 'Number' 3011 }, 3012 { 3013 name: 'd', 3014 description: 3015 '<p>numbers which define the 2x3 matrix to be multiplied</p>\n', 3016 type: 'Number' 3017 }, 3018 { 3019 name: 'e', 3020 description: 3021 '<p>numbers which define the 2x3 matrix to be multiplied</p>\n', 3022 type: 'Number' 3023 }, 3024 { 3025 name: 'f', 3026 description: 3027 '<p>numbers which define the 2x3 matrix to be multiplied</p>\n', 3028 type: 'Number' 3029 } 3030 ], 3031 class: 'p5', 3032 module: 'Transform' 3033 }, 3034 resetMatrix: { 3035 name: 'resetMatrix', 3036 class: 'p5', 3037 module: 'Transform' 3038 }, 3039 rotate: { 3040 name: 'rotate', 3041 params: [ 3042 { 3043 name: 'angle', 3044 description: 3045 '<p>the angle of rotation, specified in radians\n or degrees, depending on current angleMode</p>\n', 3046 type: 'Number' 3047 }, 3048 { 3049 name: 'axis', 3050 description: '<p>(in 3d) the axis to rotate around</p>\n', 3051 type: 'p5.Vector|Number[]', 3052 optional: true 3053 } 3054 ], 3055 class: 'p5', 3056 module: 'Transform' 3057 }, 3058 rotateX: { 3059 name: 'rotateX', 3060 params: [ 3061 { 3062 name: 'angle', 3063 description: 3064 '<p>the angle of rotation, specified in radians\n or degrees, depending on current angleMode</p>\n', 3065 type: 'Number' 3066 } 3067 ], 3068 class: 'p5', 3069 module: 'Transform' 3070 }, 3071 rotateY: { 3072 name: 'rotateY', 3073 params: [ 3074 { 3075 name: 'angle', 3076 description: 3077 '<p>the angle of rotation, specified in radians\n or degrees, depending on current angleMode</p>\n', 3078 type: 'Number' 3079 } 3080 ], 3081 class: 'p5', 3082 module: 'Transform' 3083 }, 3084 rotateZ: { 3085 name: 'rotateZ', 3086 params: [ 3087 { 3088 name: 'angle', 3089 description: 3090 '<p>the angle of rotation, specified in radians\n or degrees, depending on current angleMode</p>\n', 3091 type: 'Number' 3092 } 3093 ], 3094 class: 'p5', 3095 module: 'Transform' 3096 }, 3097 scale: { 3098 name: 'scale', 3099 class: 'p5', 3100 module: 'Transform', 3101 overloads: [ 3102 { 3103 params: [ 3104 { 3105 name: 's', 3106 description: 3107 '<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', 3108 type: 'Number|p5.Vector|Number[]' 3109 }, 3110 { 3111 name: 'y', 3112 description: '<p>percent to scale the object in the y-axis</p>\n', 3113 type: 'Number', 3114 optional: true 3115 }, 3116 { 3117 name: 'z', 3118 description: 3119 '<p>percent to scale the object in the z-axis (webgl only)</p>\n', 3120 type: 'Number', 3121 optional: true 3122 } 3123 ], 3124 chainable: 1 3125 }, 3126 { 3127 params: [ 3128 { 3129 name: 'scales', 3130 description: '<p>per-axis percents to scale the object</p>\n', 3131 type: 'p5.Vector|Number[]' 3132 } 3133 ], 3134 chainable: 1 3135 } 3136 ] 3137 }, 3138 shearX: { 3139 name: 'shearX', 3140 params: [ 3141 { 3142 name: 'angle', 3143 description: 3144 '<p>angle of shear specified in radians or degrees,\n depending on current angleMode</p>\n', 3145 type: 'Number' 3146 } 3147 ], 3148 class: 'p5', 3149 module: 'Transform' 3150 }, 3151 shearY: { 3152 name: 'shearY', 3153 params: [ 3154 { 3155 name: 'angle', 3156 description: 3157 '<p>angle of shear specified in radians or degrees,\n depending on current angleMode</p>\n', 3158 type: 'Number' 3159 } 3160 ], 3161 class: 'p5', 3162 module: 'Transform' 3163 }, 3164 translate: { 3165 name: 'translate', 3166 class: 'p5', 3167 module: 'Transform', 3168 overloads: [ 3169 { 3170 params: [ 3171 { 3172 name: 'x', 3173 description: '<p>left/right translation</p>\n', 3174 type: 'Number' 3175 }, 3176 { 3177 name: 'y', 3178 description: '<p>up/down translation</p>\n', 3179 type: 'Number' 3180 }, 3181 { 3182 name: 'z', 3183 description: '<p>forward/backward translation (webgl only)</p>\n', 3184 type: 'Number', 3185 optional: true 3186 } 3187 ], 3188 chainable: 1 3189 }, 3190 { 3191 params: [ 3192 { 3193 name: 'vector', 3194 description: '<p>the vector to translate by</p>\n', 3195 type: 'p5.Vector' 3196 } 3197 ], 3198 chainable: 1 3199 } 3200 ] 3201 }, 3202 storeItem: { 3203 name: 'storeItem', 3204 params: [ 3205 { 3206 name: 'key', 3207 description: '', 3208 type: 'String' 3209 }, 3210 { 3211 name: 'value', 3212 description: '', 3213 type: 'String|Number|Object|Boolean|p5.Color|p5.Vector' 3214 } 3215 ], 3216 class: 'p5', 3217 module: 'Data' 3218 }, 3219 getItem: { 3220 name: 'getItem', 3221 params: [ 3222 { 3223 name: 'key', 3224 description: 3225 '<p>name that you wish to use to store in local storage</p>\n', 3226 type: 'String' 3227 } 3228 ], 3229 class: 'p5', 3230 module: 'Data' 3231 }, 3232 clearStorage: { 3233 name: 'clearStorage', 3234 class: 'p5', 3235 module: 'Data' 3236 }, 3237 removeItem: { 3238 name: 'removeItem', 3239 params: [ 3240 { 3241 name: 'key', 3242 description: '', 3243 type: 'String' 3244 } 3245 ], 3246 class: 'p5', 3247 module: 'Data' 3248 }, 3249 createStringDict: { 3250 name: 'createStringDict', 3251 class: 'p5', 3252 module: 'Data', 3253 overloads: [ 3254 { 3255 params: [ 3256 { 3257 name: 'key', 3258 description: '', 3259 type: 'String' 3260 }, 3261 { 3262 name: 'value', 3263 description: '', 3264 type: 'String' 3265 } 3266 ] 3267 }, 3268 { 3269 params: [ 3270 { 3271 name: 'object', 3272 description: '<p>object</p>\n', 3273 type: 'Object' 3274 } 3275 ] 3276 } 3277 ] 3278 }, 3279 createNumberDict: { 3280 name: 'createNumberDict', 3281 class: 'p5', 3282 module: 'Data', 3283 overloads: [ 3284 { 3285 params: [ 3286 { 3287 name: 'key', 3288 description: '', 3289 type: 'Number' 3290 }, 3291 { 3292 name: 'value', 3293 description: '', 3294 type: 'Number' 3295 } 3296 ] 3297 }, 3298 { 3299 p
3299arams: [ 3300 { 3301 name: 'object', 3302 description: '<p>object</p>\n', 3303 type: 'Object' 3304 } 3305 ] 3306 } 3307 ] 3308 }, 3309 select: { 3310 name: 'select', 3311 params: [ 3312 { 3313 name: 'selectors', 3314 description: '<p>CSS selector string of element to search for</p>\n', 3315 type: 'String' 3316 }, 3317 { 3318 name: 'container', 3319 description: 3320 '<p>CSS selector string, <a href="#/p5.Element">p5.Element</a>, or\n HTML element to search within</p>\n', 3321 type: 'String|p5.Element|HTMLElement', 3322 optional: true 3323 } 3324 ], 3325 class: 'p5', 3326 module: 'DOM' 3327 }, 3328 selectAll: { 3329 name: 'selectAll', 3330 params: [ 3331 { 3332 name: 'selectors', 3333 description: '<p>CSS selector string of elements to search for</p>\n', 3334 type: 'String' 3335 }, 3336 { 3337 name: 'container', 3338 description: 3339 '<p>CSS selector string, <a href="#/p5.Element">p5.Element</a>\n , or HTML element to search within</p>\n', 3340 type: 'String|p5.Element|HTMLElement', 3341 optional: true 3342 } 3343 ], 3344 class: 'p5', 3345 module: 'DOM' 3346 }, 3347 removeElements: { 3348 name: 'removeElements', 3349 class: 'p5', 3350 module: 'DOM' 3351 }, 3352 changed: { 3353 name: 'changed', 3354 params: [ 3355 { 3356 name: 'fxn', 3357 description: 3358 '<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', 3359 type: 'Function|Boolean' 3360 } 3361 ], 3362 class: 'p5', 3363 module: 'DOM' 3364 }, 3365 input: { 3366 name: 'input', 3367 params: [ 3368 { 3369 name: 'fxn', 3370 description: 3371 '<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', 3372 type: 'Function|Boolean' 3373 } 3374 ], 3375 class: 'p5', 3376 module: 'DOM' 3377 }, 3378 createDiv: { 3379 name: 'createDiv', 3380 params: [ 3381 { 3382 name: 'html', 3383 description: '<p>inner HTML for element created</p>\n', 3384 type: 'String', 3385 optional: true 3386 } 3387 ], 3388 class: 'p5', 3389 module: 'DOM' 3390 }, 3391 createP: { 3392 name: 'createP', 3393 params: [ 3394 { 3395 name: 'html', 3396 description: '<p>inner HTML for element created</p>\n', 3397 type: 'String', 3398 optional: true 3399 } 3400 ], 3401 class: 'p5', 3402 module: 'DOM' 3403 }, 3404 createSpan: { 3405 name: 'createSpan', 3406 params: [ 3407 { 3408 name: 'html', 3409 description: '<p>inner HTML for element created</p>\n', 3410 type: 'String', 3411 optional: true 3412 } 3413 ], 3414 class: 'p5', 3415 module: 'DOM' 3416 }, 3417 createImg: { 3418 name: 'createImg', 3419 class: 'p5', 3420 module: 'DOM', 3421 overloads: [ 3422 { 3423 params: [ 3424 { 3425 name: 'src', 3426 description: '<p>src path or url for image</p>\n', 3427 type: 'String' 3428 }, 3429 { 3430 name: 'alt', 3431 description: 3432 '<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', 3433 type: 'String' 3434 } 3435 ] 3436 }, 3437 { 3438 params: [ 3439 { 3440 name: 'src', 3441 description: '', 3442 type: 'String' 3443 }, 3444 { 3445 name: 'alt', 3446 description: '', 3447 type: 'String' 3448 }, 3449 { 3450 name: 'crossOrigin', 3451 description: 3452 '<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', 3453 type: 'String' 3454 }, 3455 { 3456 name: 'successCallback', 3457 description: 3458 '<p>callback to be called once image data is loaded with the <a href="#/p5.Element">p5.Element</a> as argument</p>\n', 3459 type: 'Function', 3460 optional: true 3461 } 3462 ] 3463 } 3464 ] 3465 }, 3466 createA: { 3467 name: 'createA', 3468 params: [ 3469 { 3470 name: 'href', 3471 description: '<p>url of page to link to</p>\n', 3472 type: 'String' 3473 }, 3474 { 3475 name: 'html', 3476 description: '<p>inner html of link element to display</p>\n', 3477 type: 'String' 3478 }, 3479 { 3480 name: 'target', 3481 description: 3482 '<p>target where new link should open,\n could be _blank, _self, _parent, _top.</p>\n', 3483 type: 'String', 3484 optional: true 3485 } 3486 ], 3487 class: 'p5', 3488 module: 'DOM' 3489 }, 3490 createSlider: { 3491 name: 'createSlider', 3492 params: [ 3493 { 3494 name: 'min', 3495 description: '<p>minimum value of the slider</p>\n', 3496 type: 'Number' 3497 }, 3498 { 3499 name: 'max', 3500 description: '<p>maximum value of the slider</p>\n', 3501 type: 'Number' 3502 }, 3503 { 3504 name: 'value', 3505 description: '<p>default value of the slider</p>\n', 3506 type: 'Number', 3507 optional: true 3508 }, 3509 { 3510 name: 'step', 3511 description: 3512 '<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', 3513 type: 'Number', 3514 optional: true 3515 } 3516 ], 3517 class: 'p5', 3518 module: 'DOM' 3519 }, 3520 createButton: { 3521 name: 'createButton', 3522 params: [ 3523 { 3524 name: 'label', 3525 description: '<p>label displayed on the button</p>\n', 3526 type: 'String' 3527 }, 3528 { 3529 name: 'value', 3530 description: '<p>value of the button</p>\n', 3531 type: 'String', 3532 optional: true 3533 } 3534 ], 3535 class: 'p5', 3536 module: 'DOM' 3537 }, 3538 createCheckbox: { 3539 name: 'createCheckbox', 3540 params: [ 3541 { 3542 name: 'label', 3543 description: '<p>label displayed after checkbox</p>\n', 3544 type: 'String', 3545 optional: true 3546 }, 3547 { 3548 name: 'value', 3549 description: 3550 '<p>value of the checkbox; checked is true, unchecked is false</p>\n', 3551 type: 'Boolean', 3552 optional: true 3553 } 3554 ], 3555 class: 'p5', 3556 module: 'DOM' 3557 }, 3558 createSelect: { 3559 name: 'createSelect', 3560 class: 'p5', 3561 module: 'DOM', 3562 overloads: [ 3563 { 3564 params: [ 3565 { 3566 name: 'multiple', 3567 description: 3568 '<p>true if dropdown should support multiple selections</p>\n', 3569 type: 'Boolean', 3570 optional: true 3571 } 3572 ] 3573 }, 3574 { 3575 params: [ 3576 { 3577 name: 'existing', 3578 description: '<p>DOM select element</p>\n', 3579 type: 'Object' 3580 } 3581 ] 3582 } 3583 ] 3584 }, 3585 createRadio: { 3586 name: 'createRadio', 3587 class: 'p5', 3588 module: 'DOM', 3589 overloads: [ 3590 { 3591 params: [ 3592 { 3593 name: 'containerElement', 3594 description: 3595 '<p>An container HTML Element either a div\nor span inside which all existing radio inputs will be considered as options.
3595</p>\n', 3596 type: 'Object' 3597 }, 3598 { 3599 name: 'name', 3600 description: '<p>A name parameter for each Input Element.</p>\n', 3601 type: 'String', 3602 optional: true 3603 } 3604 ] 3605 }, 3606 { 3607 params: [ 3608 { 3609 name: 'name', 3610 description: '', 3611 type: 'String' 3612 } 3613 ] 3614 }, 3615 { 3616 params: [] 3617 } 3618 ] 3619 }, 3620 createColorPicker: { 3621 name: 'createColorPicker', 3622 params: [ 3623 { 3624 name: 'value', 3625 description: '<p>default color of element</p>\n', 3626 type: 'String|p5.Color', 3627 optional: true 3628 } 3629 ], 3630 class: 'p5', 3631 module: 'DOM' 3632 }, 3633 createInput: { 3634 name: 'createInput', 3635 class: 'p5', 3636 module: 'DOM', 3637 overloads: [ 3638 { 3639 params: [ 3640 { 3641 name: 'value', 3642 description: '<p>default value of the input box</p>\n', 3643 type: 'String' 3644 }, 3645 { 3646 name: 'type', 3647 description: 3648 '<p>type of text, ie text, password etc. Defaults to text.\n Needs a value to be specified first.</p>\n', 3649 type: 'String', 3650 optional: true 3651 } 3652 ] 3653 }, 3654 { 3655 params: [ 3656 { 3657 name: 'value', 3658 description: '', 3659 type: 'String', 3660 optional: true 3661 } 3662 ] 3663 } 3664 ] 3665 }, 3666 createFileInput: { 3667 name: 'createFileInput', 3668 params: [ 3669 { 3670 name: 'callback', 3671 description: '<p>callback function for when a file is loaded</p>\n', 3672 type: 'Function' 3673 }, 3674 { 3675 name: 'multiple', 3676 description: 3677 '<p>optional, to allow multiple files to be selected</p>\n', 3678 type: 'Boolean', 3679 optional: true 3680 } 3681 ], 3682 class: 'p5', 3683 module: 'DOM' 3684 }, 3685 createVideo: { 3686 name: 'createVideo', 3687 params: [ 3688 { 3689 name: 'src', 3690 description: 3691 '<p>path to a video file, or array of paths for\n supporting different browsers</p>\n', 3692 type: 'String|String[]' 3693 }, 3694 { 3695 name: 'callback', 3696 description: 3697 "<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", 3698 type: 'Function', 3699 optional: true 3700 } 3701 ], 3702 class: 'p5', 3703 module: 'DOM' 3704 }, 3705 createAudio: { 3706 name: 'createAudio', 3707 params: [ 3708 { 3709 name: 'src', 3710 description: 3711 '<p>path to an audio file, or array of paths\n for supporting different browsers</p>\n', 3712 type: 'String|String[]', 3713 optional: true 3714 }, 3715 { 3716 name: 'callback', 3717 description: 3718 "<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", 3719 type: 'Function', 3720 optional: true 3721 } 3722 ], 3723 class: 'p5', 3724 module: 'DOM' 3725 }, 3726 VIDEO: { 3727 name: 'VIDEO', 3728 class: 'p5', 3729 module: 'DOM' 3730 }, 3731 AUDIO: { 3732 name: 'AUDIO', 3733 class: 'p5', 3734 module: 'DOM' 3735 }, 3736 createCapture: { 3737 name: 'createCapture', 3738 params: [ 3739 { 3740 name: 'type', 3741 description: 3742 '<p>type of capture, either VIDEO or\n AUDIO if none specified, default both,\n or a Constraints object</p>\n', 3743 type: 'String|Constant|Object' 3744 }, 3745 { 3746 name: 'callback', 3747 description: 3748 '<p>function to be called once\n stream has loaded</p>\n', 3749 type: 'Function', 3750 optional: true 3751 } 3752 ], 3753 class: 'p5', 3754 module: 'DOM' 3755 }, 3756 createElement: { 3757 name: 'createElement', 3758 params: [ 3759 { 3760 name: 'tag', 3761 description: '<p>tag for the new element</p>\n', 3762 type: 'String' 3763 }, 3764 { 3765 name: 'content', 3766 description: '<p>html content to be inserted into the element</p>\n', 3767 type: 'String', 3768 optional: true 3769 } 3770 ], 3771 class: 'p5', 3772 module: 'DOM' 3773 }, 3774 deviceOrientation: { 3775 name: 'deviceOrientation', 3776 class: 'p5', 3777 module: 'Events' 3778 }, 3779 accelerationX: { 3780 name: 'accelerationX', 3781 class: 'p5', 3782 module: 'Events' 3783 }, 3784 accelerationY: { 3785 name: 'accelerationY', 3786 class: 'p5', 3787 module: 'Events' 3788 }, 3789 accelerationZ: { 3790 name: 'accelerationZ', 3791 class: 'p5', 3792 module: 'Events' 3793 }, 3794 pAccelerationX: { 3795 name: 'pAccelerationX', 3796 class: 'p5', 3797 module: 'Events' 3798 }, 3799 pAccelerationY: { 3800 name: 'pAccelerationY', 3801 class: 'p5', 3802 module: 'Events' 3803 }, 3804 pAccelerationZ: { 3805 name: 'pAccelerationZ', 3806 class: 'p5', 3807 module: 'Events' 3808 }, 3809 rotationX: { 3810 name: 'rotationX', 3811 class: 'p5', 3812 module: 'Events' 3813 }, 3814 rotationY: { 3815 name: 'rotationY', 3816 class: 'p5', 3817 module: 'Events' 3818 }, 3819 rotationZ: { 3820 name: 'rotationZ', 3821 class: 'p5', 3822 module: 'Events' 3823 }, 3824 pRotationX: { 3825 name: 'pRotationX', 3826 class: 'p5', 3827 module: 'Events' 3828 }, 3829 pRotationY: { 3830 name: 'pRotationY', 3831 class: 'p5', 3832 module: 'Events' 3833 }, 3834 pRotationZ: { 3835 name: 'pRotationZ', 3836 class: 'p5', 3837 module: 'Events' 3838 }, 3839 turnAxis: { 3840 name: 'turnAxis', 3841 class: 'p5', 3842 module: 'Events' 3843 }, 3844 setMoveThreshold: { 3845 name: 'setMoveThreshold', 3846 params: [ 3847 { 3848 name: 'value', 3849 description: '<p>The threshold value</p>\n', 3850 type: 'Number' 3851 } 3852 ], 3853 class: 'p5', 3854 module: 'Events' 3855 }, 3856 setShakeThreshold: { 3857 name: 'setShakeThreshold', 3858 params: [ 3859 { 3860 name: 'value', 3861 description: '<p>The threshold value</p>\n', 3862 type: 'Number' 3863 } 3864 ], 3865 class: 'p5', 3866 module: 'Events' 3867 }, 3868 deviceMoved: { 3869 name: 'deviceMoved', 3870 class: 'p5', 3871 module: 'Events' 3872 }, 3873 deviceTurned: { 3874 name: 'deviceTurned', 3875 class: 'p5', 3876 module: 'Events' 3877 }, 3878 deviceShaken: { 3879 name: 'deviceShaken', 3880 class: 'p5', 3881 module: 'Events' 3882 }, 3883 keyIsPressed: { 3884 name: 'keyIsPressed', 3885 class: 'p5', 3886 module: 'Events' 3887 }, 3888 key: { 3889 name: 'key', 3890 class: 'p5', 3891 module: 'Events' 3892 }, 3893 keyCode: { 3894 name: 'keyCode', 3895 class: 'p5', 3896 module: 'Events' 3897 }, 3898 keyPressed: { 3899 name: 'keyPressed', 3900 class: 'p5', 3901 module: 'Events' 3902 }, 3903 keyReleased: { 3904 name: 'keyReleased', 3905 class: 'p5', 3906 module: 'Events' 3907 }, 3908 keyTyped: { 3909 name: 'keyTyped', 3910 class: 'p5', 3911 module: 'Events' 3912 }, 3913 keyIsDown: { 3914 name: 'keyIsDown', 3915 params: [ 3916 { 3917 name: 'code', 3918 description: '<p>The key to check for.</p>\n', 3919 type: 'Number' 3920 } 3921 ], 3922 class: 'p5', 3923 module: 'Events' 3924 }, 3925 movedX: { 3926 name: 'movedX', 3927 class: 'p5', 3928 module: 'Events' 3929 }, 3930 movedY: { 3931 name: 'movedY', 3932 class: 'p5', 3933 module: 'Events' 3934 }, 3935 mouseX: { 3936 name: 'mouseX', 3937 class: 'p5', 3938 module: 'Events' 3939 }, 3940 mouseY: { 3941 name: 'mouseY', 3942 class: 'p5', 3943 module: 'Events' 3944 }, 3945 pmouseX: { 3946 name: 'pmouseX', 3947 class: 'p5', 3948 module: 'Events' 3949 }, 3950 pmouseY: { 3951 name: 'pmouseY', 3952 class: 'p5', 3953 module: 'Events' 3954 }, 3955 winMouseX: { 3956 name: 'winMouseX', 3957 class: 'p5', 3958 module: 'Events' 3959 }, 3960 winMouseY: { 3961 name: 'winMouseY', 3962 class: 'p5', 3963 module: 'Events' 3964 }, 3965 pwinMouseX: { 3966 name: 'pwinMouseX', 3967 class: 'p5', 3968 module: 'Events' 3969 }, 3970 pwinMouseY: { 3971 name: 'pwinMouseY', 3972 class: 'p5', 3973 module: 'Events' 3974 }, 3975 mouseButton: { 3976 name: 'mouseButton', 3977 class: 'p5', 3978 module: 'Events' 3979 }, 3980 mouseIsPressed: { 3981 name: 'mouseIsPressed', 3982 class: 'p5', 3983 module: 'Events' 3984 }, 3985 mouseMoved: { 3986 name: 'mouseMoved', 3987 params: [ 3988 { 3989 name: 'event', 3990 description: '<p>optional MouseEvent callback argument.</p>\n', 3991 type: 'Object', 3992 optional: true 3993 } 3994 ], 3995 class: 'p5', 3996 module: 'Events' 3997 }, 3998 mouseDragged: { 3999 name: 'mouseDragged', 4000 params: [ 4001 { 4002 name: 'event', 4003 description: '<p>optional MouseEvent callback argument.</p>\n', 4004 type: 'Object', 4005 optional: true 4006 } 4007 ], 4008 class: 'p5', 4009 module: 'Events' 4010 }, 4011 mousePressed: { 4012 name: 'mousePressed', 4013 params: [ 4014 { 4015 name: 'event', 4016 description: '<p>optional MouseEvent callback argument.</p>\n', 4017 type: 'Object', 4018 optional: true 4019 } 4020 ], 4021 class: 'p5', 4022 module: 'Events' 4023 }, 4024 mouseReleased: { 4025 name: 'mouseReleased', 4026 params: [ 4027 { 4028 name: 'event', 4029 description: '<p>optional MouseEvent callback argument.</p>\n', 4030 type: 'Object', 4031 optional: true 4032 } 4033 ], 4034 class: 'p5', 4035 module: 'Events' 4036 }, 4037 mouseClicked: { 4038 name: 'mouseClicked', 4039 params: [ 4040 { 4041 name: 'event', 4042 description: '<p>optional MouseEvent callback argument.</p>\n', 4043 type: 'Object', 4044 optional: true 4045 } 4046 ], 4047 class: 'p5', 4048 module: 'Events' 4049 }, 4050 doubleClicked: { 4051 name: 'doubleClicked', 4052 params: [ 4053 { 4054 name: 'event', 4055 description: '<p>optional MouseEvent callback argument.</p>\n', 4056 type: 'Object', 4057 optional: true 4058 } 4059 ], 4060 class: 'p5', 4061 module: 'Events' 4062 }, 4063 mouseWheel: { 4064 name: 'mouseWheel', 4065 params: [ 4066 { 4067 name: 'event', 4068 description: '<p>optional WheelEvent callback argument.</p>\n', 4069 type: 'Object', 4070 optional: true 4071 } 4072 ], 4073 class: 'p5', 4074 module: 'Events' 4075 }, 4076 requestPointerLock: { 4077 name: 'requestPointerLock', 4078 class: 'p5', 4079 module: 'Events' 4080 }, 4081 exitPointerLock: { 4082 name: 'exitPointerLock', 4083 class: 'p5', 4084 module: 'Events' 4085 }, 4086 touches: { 4087 name: 'touches', 4088 class: 'p5', 4089 module: 'Events' 4090
4090 }, 4091 touchStarted: { 4092 name: 'touchStarted', 4093 params: [ 4094 { 4095 name: 'event', 4096 description: '<p>optional TouchEvent callback argument.</p>\n', 4097 type: 'Object', 4098 optional: true 4099 } 4100 ], 4101 class: 'p5', 4102 module: 'Events' 4103 }, 4104 touchMoved: { 4105 name: 'touchMoved', 4106 params: [ 4107 { 4108 name: 'event', 4109 description: '<p>optional TouchEvent callback argument.</p>\n', 4110 type: 'Object', 4111 optional: true 4112 } 4113 ], 4114 class: 'p5', 4115 module: 'Events' 4116 }, 4117 touchEnded: { 4118 name: 'touchEnded', 4119 params: [ 4120 { 4121 name: 'event', 4122 description: '<p>optional TouchEvent callback argument.</p>\n', 4123 type: 'Object', 4124 optional: true 4125 } 4126 ], 4127 class: 'p5', 4128 module: 'Events' 4129 }, 4130 createImage: { 4131 name: 'createImage', 4132 params: [ 4133 { 4134 name: 'width', 4135 description: '<p>width in pixels</p>\n', 4136 type: 'Integer' 4137 }, 4138 { 4139 name: 'height', 4140 description: '<p>height in pixels</p>\n', 4141 type: 'Integer' 4142 } 4143 ], 4144 class: 'p5', 4145 module: 'Image' 4146 }, 4147 saveCanvas: { 4148 name: 'saveCanvas', 4149 class: 'p5', 4150 module: 'Image', 4151 overloads: [ 4152 { 4153 params: [ 4154 { 4155 name: 'selectedCanvas', 4156 description: 4157 '<p>a variable\n representing a specific html5 canvas (optional)</p>\n', 4158 type: 'p5.Element|HTMLCanvasElement' 4159 }, 4160 { 4161 name: 'filename', 4162 description: '', 4163 type: 'String', 4164 optional: true 4165 }, 4166 { 4167 name: 'extension', 4168 description: "<p>'jpg' or 'png'</p>\n", 4169 type: 'String', 4170 optional: true 4171 } 4172 ] 4173 }, 4174 { 4175 params: [ 4176 { 4177 name: 'filename', 4178 description: '', 4179 type: 'String', 4180 optional: true 4181 }, 4182 { 4183 name: 'extension', 4184 description: '', 4185 type: 'String', 4186 optional: true 4187 } 4188 ] 4189 } 4190 ] 4191 }, 4192 saveFrames: { 4193 name: 'saveFrames', 4194 params: [ 4195 { 4196 name: 'filename', 4197 description: '', 4198 type: 'String' 4199 }, 4200 { 4201 name: 'extension', 4202 description: "<p>'jpg' or 'png'</p>\n", 4203 type: 'String' 4204 }, 4205 { 4206 name: 'duration', 4207 description: '<p>Duration in seconds to save the frames for.</p>\n', 4208 type: 'Number' 4209 }, 4210 { 4211 name: 'framerate', 4212 description: '<p>Framerate to save the frames in.</p>\n', 4213 type: 'Number' 4214 }, 4215 { 4216 name: 'callback', 4217 description: 4218 '<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', 4219 type: 'Function(Array)', 4220 optional: true 4221 } 4222 ], 4223 class: 'p5', 4224 module: 'Image' 4225 }, 4226 loadImage: { 4227 name: 'loadImage', 4228 params: [ 4229 { 4230 name: 'path', 4231 description: '<p>Path of the image to be loaded</p>\n', 4232 type: 'String' 4233 }, 4234 { 4235 name: 'successCallback', 4236 description: 4237 '<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', 4238 type: 'function(p5.Image)', 4239 optional: true 4240 }, 4241 { 4242 name: 'failureCallback', 4243 description: 4244 '<p>called with event error if\n the image fails to load.</p>\n', 4245 type: 'Function(Event)', 4246 optional: true 4247 } 4248 ], 4249 class: 'p5', 4250 module: 'Image' 4251 }, 4252 image: { 4253 name: 'image', 4254 class: 'p5', 4255 module: 'Image', 4256 overloads: [ 4257 { 4258 params: [ 4259 { 4260 name: 'img', 4261 description: '<p>the image to display</p>\n', 4262 type: 'p5.Image|p5.Element' 4263 }, 4264 { 4265 name: 'x', 4266 description: 4267 '<p>the x-coordinate of the top-left corner of the image</p>\n', 4268 type: 'Number' 4269 }, 4270 { 4271 name: 'y', 4272 description: 4273 '<p>the y-coordinate of the top-left corner of the image</p>\n', 4274 type: 'Number' 4275 }, 4276 { 4277 name: 'width', 4278 description: '<p>the width to draw the image</p>\n', 4279 type: 'Number', 4280 optional: true 4281 }, 4282 { 4283 name: 'height', 4284 description: '<p>the height to draw the image</p>\n', 4285 type: 'Number', 4286 optional: true 4287 } 4288 ] 4289 }, 4290 { 4291 params: [ 4292 { 4293 name: 'img', 4294 description: '', 4295 type: 'p5.Image|p5.Element' 4296 }, 4297 { 4298 name: 'dx', 4299 description: 4300 '<p>the x-coordinate of the destination\n rectangle in which to draw the source image</p>\n', 4301 type: 'Number' 4302 }, 4303 { 4304 name: 'dy', 4305 description: 4306 '<p>the y-coordinate of the destination\n rectangle in which to draw the source image</p>\n', 4307 type: 'Number' 4308 }, 4309 { 4310 name: 'dWidth', 4311 description: '<p>the width of the destination rectangle</p>\n', 4312 type: 'Number' 4313 }, 4314 { 4315 name: 'dHeight', 4316 description: '<p>the height of the destination rectangle</p>\n', 4317 type: 'Number' 4318 }, 4319 { 4320 name: 'sx', 4321 description: 4322 '<p>the x-coordinate of the subsection of the source\nimage to draw into the destination rectangle</p>\n', 4323 type: 'Number' 4324 }, 4325 { 4326 name: 'sy', 4327 description: 4328 '<p>the y-coordinate of the subsection of the source\nimage to draw into the destination rectangle</p>\n', 4329 type: 'Number' 4330 }, 4331 { 4332 name: 'sWidth', 4333 description: 4334 '<p>the width of the subsection of the\n source image to draw into the destination\n rectangle</p>\n', 4335 type: 'Number', 4336 optional: true 4337 }, 4338 { 4339 name: 'sHeight', 4340 description: 4341 '<p>the height of the subsection of the\n source image to draw into the destination rectangle</p>\n', 4342 type: 'Number', 4343 optional: true 4344 } 4345 ] 4346 } 4347 ] 4348 }, 4349 tint: { 4350 name: 'tint', 4351 class: 'p5', 4352 module: 'Image', 4353 overloads: [ 4354 { 4355 params: [ 4356 { 4357 name: 'v1', 4358 description: 4359 '<p>red or hue value relative to\n the current color range</p>\n', 4360 type: 'Number' 4361 }, 4362 { 4363 name: 'v2', 4364 description: 4365 '<p>
4365green or saturation value\n relative to the current color range</p>\n', 4366 type: 'Number' 4367 }, 4368 { 4369 name: 'v3', 4370 description: 4371 '<p>blue or brightness value\n relative to the current color range</p>\n', 4372 type: 'Number' 4373 }, 4374 { 4375 name: 'alpha', 4376 description: '', 4377 type: 'Number', 4378 optional: true 4379 } 4380 ] 4381 }, 4382 { 4383 params: [ 4384 { 4385 name: 'value', 4386 description: '<p>a color string</p>\n', 4387 type: 'String' 4388 } 4389 ] 4390 }, 4391 { 4392 params: [ 4393 { 4394 name: 'gray', 4395 description: '<p>a gray value</p>\n', 4396 type: 'Number' 4397 }, 4398 { 4399 name: 'alpha', 4400 description: '', 4401 type: 'Number', 4402 optional: true 4403 } 4404 ] 4405 }, 4406 { 4407 params: [ 4408 { 4409 name: 'values', 4410 description: 4411 '<p>an array containing the red,green,blue &\n and alpha components of the color</p>\n', 4412 type: 'Number[]' 4413 } 4414 ] 4415 }, 4416 { 4417 params: [ 4418 { 4419 name: 'color', 4420 description: '<p>the tint color</p>\n', 4421 type: 'p5.Color' 4422 } 4423 ] 4424 } 4425 ] 4426 }, 4427 noTint: { 4428 name: 'noTint', 4429 class: 'p5', 4430 module: 'Image' 4431 }, 4432 imageMode: { 4433 name: 'imageMode', 4434 params: [ 4435 { 4436 name: 'mode', 4437 description: '<p>either CORNER, CORNERS, or CENTER</p>\n', 4438 type: 'Constant' 4439 } 4440 ], 4441 class: 'p5', 4442 module: 'Image' 4443 }, 4444 pixels: { 4445 name: 'pixels', 4446 class: 'p5', 4447 module: 'Image' 4448 }, 4449 blend: { 4450 name: 'blend', 4451 class: 'p5', 4452 module: 'Image', 4453 overloads: [ 4454 { 4455 params: [ 4456 { 4457 name: 'srcImage', 4458 description: '<p>source image</p>\n', 4459 type: 'p5.Image' 4460 }, 4461 { 4462 name: 'sx', 4463 description: 4464 "<p>X coordinate of the source's upper left corner</p>\n", 4465 type: 'Integer' 4466 }, 4467 { 4468 name: 'sy', 4469 description: 4470 "<p>Y coordinate of the source's upper left corner</p>\n", 4471 type: 'Integer' 4472 }, 4473 { 4474 name: 'sw', 4475 description: '<p>source image width</p>\n', 4476 type: 'Integer' 4477 }, 4478 { 4479 name: 'sh', 4480 description: '<p>source image height</p>\n', 4481 type: 'Integer' 4482 }, 4483 { 4484 name: 'dx', 4485 description: 4486 "<p>X coordinate of the destination's upper left corner</p>\n", 4487 type: 'Integer' 4488 }, 4489 { 4490 name: 'dy', 4491 description: 4492 "<p>Y coordinate of the destination's upper left corner</p>\n", 4493 type: 'Integer' 4494 }, 4495 { 4496 name: 'dw', 4497 description: '<p>destination image width</p>\n', 4498 type: 'Integer' 4499 }, 4500 { 4501 name: 'dh', 4502 description: '<p>destination image height</p>\n', 4503 type: 'Integer' 4504 }, 4505 { 4506 name: 'blendMode', 4507 description: 4508 '<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', 4509 type: 'Constant' 4510 } 4511 ] 4512 }, 4513 { 4514 params: [ 4515 { 4516 name: 'sx', 4517 description: '', 4518 type: 'Integer' 4519 }, 4520 { 4521 name: 'sy', 4522 description: '', 4523 type: 'Integer' 4524 }, 4525 { 4526 name: 'sw', 4527 description: '', 4528 type: 'Integer' 4529 }, 4530 { 4531 name: 'sh', 4532 description: '', 4533 type: 'Integer' 4534 }, 4535 { 4536 name: 'dx', 4537 description: '', 4538 type: 'Integer' 4539 }, 4540 { 4541 name: 'dy', 4542 description: '', 4543 type: 'Integer' 4544 }, 4545 { 4546 name: 'dw', 4547 description: '', 4548 type: 'Integer' 4549 }, 4550 { 4551 name: 'dh', 4552 description: '', 4553 type: 'Integer' 4554 }, 4555 { 4556 name: 'blendMode', 4557 description: '', 4558 type: 'Constant' 4559 } 4560 ] 4561 } 4562 ] 4563 }, 4564 copy: { 4565 name: 'copy', 4566 class: 'p5', 4567 module: 'Image', 4568 overloads: [ 4569 { 4570 params: [ 4571 { 4572 name: 'srcImage', 4573 description: '<p>source image</p>\n', 4574 type: 'p5.Image|p5.Element' 4575 }, 4576 { 4577 name: 'sx', 4578 description: 4579 "<p>X coordinate of the source's upper left corner</p>\n", 4580 type: 'Integer' 4581 }, 4582 { 4583 name: 'sy', 4584 description: 4585 "<p>Y coordinate of the source's upper left corner</p>\n", 4586 type: 'Integer' 4587 }, 4588 { 4589 name: 'sw', 4590 description: '<p>source image width</p>\n', 4591 type: 'Integer' 4592 }, 4593 { 4594 name: 'sh', 4595 description: '<p>source image height</p>\n', 4596 type: 'Integer' 4597 }, 4598 { 4599 name: 'dx', 4600 description: 4601 "<p>X coordinate of the destination's upper left corner</p>\n", 4602 type: 'Integer' 4603 }, 4604 { 4605 name: 'dy', 4606 description: 4607 "<p>Y coordinate of the destination's upper left corner</p>\n", 4608 type: 'Integer' 4609 }, 4610 { 4611 name: 'dw', 4612 description: '<p>destination image width</p>\n', 4613 type: 'Integer' 4614 }, 4615 { 4616 name: 'dh', 4617 description: '<p>destination image height</p>\n', 4618 type: 'Integer' 4619 } 4620 ] 4621 }, 4622 { 4623 params: [ 4624 { 4625 name: 'sx', 4626 description: '', 4627 type: 'Integer' 4628 }, 4629 { 4630 name: 'sy', 4631 description: '', 4632 type: 'Integer' 4633 }, 4634 { 4635 name: 'sw', 4636 description: '', 4637 type: 'Integer' 4638 }, 4639 { 4640 name: 'sh', 4641 description: '', 4642 type: 'Integer' 4643 }, 4644 { 4645 name: 'dx', 4646 description: '', 4647 type: 'Integer' 4648 }, 4649 { 4650 name: 'dy', 4651 description: '', 4652 type: 'Integer' 4653 }, 4654 { 4655 name: 'dw', 4656 description: '', 4657 type: 'Integer' 4658 }, 4659 { 4660 name: 'dh', 4661 description: '', 4662 type: 'Integer' 4663 } 4664 ] 4665 } 4666 ] 4667 }, 4668 filter: { 4669 name: 'filter', 4670 params: [ 4671 { 4672 name: 'filterType', 4673 description: 4674 '<p>either THRESHOLD, GRAY, OPAQUE, INVERT,\n POSTERIZE, BLUR, ERODE, DILATE or BLUR.\
4674n See Filters.js for docs on\n each available filter</p>\n', 4675 type: 'Constant' 4676 }, 4677 { 4678 name: 'filterParam', 4679 description: 4680 '<p>an optional parameter unique\n to each filter, see above</p>\n', 4681 type: 'Number', 4682 optional: true 4683 } 4684 ], 4685 class: 'p5', 4686 module: 'Image' 4687 }, 4688 get: { 4689 name: 'get', 4690 class: 'p5', 4691 module: 'Image', 4692 overloads: [ 4693 { 4694 params: [ 4695 { 4696 name: 'x', 4697 description: '<p>x-coordinate of the pixel</p>\n', 4698 type: 'Number' 4699 }, 4700 { 4701 name: 'y', 4702 description: '<p>y-coordinate of the pixel</p>\n', 4703 type: 'Number' 4704 }, 4705 { 4706 name: 'w', 4707 description: '<p>width</p>\n', 4708 type: 'Number' 4709 }, 4710 { 4711 name: 'h', 4712 description: '<p>height</p>\n', 4713 type: 'Number' 4714 } 4715 ] 4716 }, 4717 { 4718 params: [] 4719 }, 4720 { 4721 params: [ 4722 { 4723 name: 'x', 4724 description: '', 4725 type: 'Number' 4726 }, 4727 { 4728 name: 'y', 4729 description: '', 4730 type: 'Number' 4731 } 4732 ] 4733 } 4734 ] 4735 }, 4736 loadPixels: { 4737 name: 'loadPixels', 4738 class: 'p5', 4739 module: 'Image' 4740 }, 4741 set: { 4742 name: 'set', 4743 params: [ 4744 { 4745 name: 'x', 4746 description: '<p>x-coordinate of the pixel</p>\n', 4747 type: 'Number' 4748 }, 4749 { 4750 name: 'y', 4751 description: '<p>y-coordinate of the pixel</p>\n', 4752 type: 'Number' 4753 }, 4754 { 4755 name: 'c', 4756 description: 4757 '<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', 4758 type: 'Number|Number[]|Object' 4759 } 4760 ], 4761 class: 'p5', 4762 module: 'Image' 4763 }, 4764 updatePixels: { 4765 name: 'updatePixels', 4766 params: [ 4767 { 4768 name: 'x', 4769 description: 4770 '<p>x-coordinate of the upper-left corner of region\n to update</p>\n', 4771 type: 'Number', 4772 optional: true 4773 }, 4774 { 4775 name: 'y', 4776 description: 4777 '<p>y-coordinate of the upper-left corner of region\n to update</p>\n', 4778 type: 'Number', 4779 optional: true 4780 }, 4781 { 4782 name: 'w', 4783 description: '<p>width of region to update</p>\n', 4784 type: 'Number', 4785 optional: true 4786 }, 4787 { 4788 name: 'h', 4789 description: '<p>height of region to update</p>\n', 4790 type: 'Number', 4791 optional: true 4792 } 4793 ], 4794 class: 'p5', 4795 module: 'Image' 4796 }, 4797 loadJSON: { 4798 name: 'loadJSON', 4799 class: 'p5', 4800 module: 'IO', 4801 overloads: [ 4802 { 4803 params: [ 4804 { 4805 name: 'path', 4806 description: '<p>name of the file or url to load</p>\n', 4807 type: 'String' 4808 }, 4809 { 4810 name: 'jsonpOptions', 4811 description: '<p>options object for jsonp related settings</p>\n', 4812 type: 'Object', 4813 optional: true 4814 }, 4815 { 4816 name: 'datatype', 4817 description: '<p>"json" or "jsonp"</p>\n', 4818 type: 'String', 4819 optional: true 4820 }, 4821 { 4822 name: 'callback', 4823 description: 4824 '<p>function to be executed after\n <a href="#/p5/loadJSON">loadJSON()</a> completes, data is passed\n in as first argument</p>\n', 4825 type: 'Function', 4826 optional: true 4827 }, 4828 { 4829 name: 'errorCallback', 4830 description: 4831 '<p>function to be executed if\n there is an error, response is passed\n in as first argument</p>\n', 4832 type: 'Function', 4833 optional: true 4834 } 4835 ] 4836 }, 4837 { 4838 params: [ 4839 { 4840 name: 'path', 4841 description: '', 4842 type: 'String' 4843 }, 4844 { 4845 name: 'datatype', 4846 description: '', 4847 type: 'String' 4848 }, 4849 { 4850 name: 'callback', 4851 description: '', 4852 type: 'Function', 4853 optional: true 4854 }, 4855 { 4856 name: 'errorCallback', 4857 description: '', 4858 type: 'Function', 4859 optional: true 4860 } 4861 ] 4862 }, 4863 { 4864 params: [ 4865 { 4866 name: 'path', 4867 description: '', 4868 type: 'String' 4869 }, 4870 { 4871 name: 'callback', 4872 description: '', 4873 type: 'Function' 4874 }, 4875 { 4876 name: 'errorCallback', 4877 description: '', 4878 type: 'Function', 4879 optional: true 4880 } 4881 ] 4882 } 4883 ] 4884 }, 4885 loadStrings: { 4886 name: 'loadStrings', 4887 params: [ 4888 { 4889 name: 'filename', 4890 description: '<p>name of the file or url to load</p>\n', 4891 type: 'String' 4892 }, 4893 { 4894 name: 'callback', 4895 description: 4896 '<p>function to be executed after <a href="#/p5/loadStrings">loadStrings()</a>\n completes, Array is passed in as first\n argument</p>\n', 4897 type: 'Function', 4898 optional: true 4899 }, 4900 { 4901 name: 'errorCallback', 4902 description: 4903 '<p>function to be executed if\n there is an error, response is passed\n in as first argument</p>\n', 4904 type: 'Function', 4905 optional: true 4906 } 4907 ], 4908 class: 'p5', 4909 module: 'IO' 4910 }, 4911 loadTable: { 4912 name: 'loadTable', 4913 params: [ 4914 { 4915 name: 'filename', 4916 description: '<p>name of the file or URL to load</p>\n', 4917 type: 'String' 4918 }, 4919 { 4920 name: 'extension', 4921 description: 4922 '<p>parse the table by comma-separated values "csv", semicolon-separated\n values "ssv", or tab-separated values "tsv"</p>\n', 4923 type: 'String', 4924 optional: true 4925 }, 4926 { 4927 name: 'header', 4928 description: '<p>"header" to indicate table has header row</p>\n', 4929 type: 'String', 4930 optional: true 4931 }, 4932 { 4933 name: 'callback', 4934 description: 4935 '<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', 4936 type: 'Function', 4937 optional: true 4938 }, 4939 { 4940 name: 'errorCallback', 4941 description: 4942 '<p>function to be executed if\n there is an error, response is passed\n in as first argument</p>\n', 4943 type: 'Function', 4944 optional: true 4945 } 4946 ], 4947 class: 'p5', 4948 module: 'IO' 4949 }, 4950 loadXML: { 4951 name: 'loadXML', 4952 params: [ 4953 { 4954 name: 'filename', 4955 description: '<p>name of the file or URL to load</p>\n', 4956 type: 'String' 4957 }, 4958 { 4959 name: 'callback', 4960 description: 4961 '<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', 4962 type: 'Function', 4963 optional: true 4964 }, 4965 { 4966 name: 'errorCallback', 4967 description: 4968 '<p>function to be executed if\n there is an error, response is passed\n in as first argument</p>\n', 4969 type: 'Function', 4970 optional: true 4971 } 4972 ], 4973 class: 'p5', 4974 module: 'IO' 4975 }, 4976 loadBytes: { 4977 name: 'loadBytes', 4978 params: [ 4979 { 4980 name: 'file', 4981 description: '<p>name of the file or URL to load</p>\n', 4982 type: 'String' 4983 }, 4984 { 4985 name: 'callback', 4986 description: 4987 '<p>function to be executed after <a href="#/p5/loadBytes">loadBytes()</a>\n completes</p>\n', 4988 type: 'Function', 4989 optional: true 4990 }, 4991 { 4992 name: 'errorCallback', 4993 description: 4994 '<p>function to be executed if there\n is an error</p>\n', 4995 type: 'Function', 4996 optional: true 4997 } 4998 ], 4999 class: 'p5', 5000 module: 'IO' 5001 }, 5002 httpGet: { 5003 name: 'httpGet', 5004 class: 'p5', 5005 module: 'IO', 5006 overloads: [ 5007 { 5008 params: [ 5009 { 5010 name: 'path', 5011 description: '<p>name of the file or url to load</p>\n', 5012 type: 'String' 5013 }, 5014 { 5015 name: 'datatype', 5016 description: 5017 '<p>"json", "jsonp", "binary", "arrayBuffer",\n "xml", or "text"</p>\n', 5018 type: 'String', 5019 optional: true 5020 }, 5021 { 5022 name: 'data', 5023 description: '<p>param data passed sent with request</p>\n', 5024 type: 'Object|Boolean', 5025 optional: true 5026 }, 5027 { 5028 name: 'callback', 5029 description: 5030 '<p>function to be executed after\n <a href="#/p5/httpGet">httpGet()</a> completes, data is passed in\n as first argument</p>\n', 5031 type: 'Function', 5032 optional: true 5033 }, 5034 { 5035 name: 'errorCallback', 5036 description: 5037 '<p>function to be executed if\n there is an error, response is passed\n in as first argument</p>\n', 5038 type: 'Function', 5039 optional: true 5040 } 5041 ] 5042 }, 5043 { 5044 params: [ 5045 { 5046 name: 'path', 5047 description: '', 5048 type: 'String' 5049 }, 5050 { 5051 name: 'data', 5052 description: '', 5053 type: 'Object|Boolean' 5054 }, 5055 { 5056 name: 'callback', 5057 description: '', 5058 type: 'Function', 5059 optional: true 5060 }, 5061 { 5062 name: 'errorCallback', 5063 description: '', 5064 type: 'Function', 5065 optional: true 5066 } 5067 ] 5068 }, 5069 { 5070 params: [ 5071 { 5072 name: 'path', 5073 description: '', 5074 type: 'String' 5075 }, 5076 { 5077 name: 'callback', 5078 description: '', 5079 type: 'Function' 5080 }, 5081 { 5082 name: 'errorCallback', 5083 description: '', 5084 type: 'Function', 5085 optional: true 5086 } 5087 ] 5088 } 5089 ] 5090 }, 5091 httpPost: { 5092 name: 'httpPost', 5093 class: 'p5', 5094 module: 'IO'
5094, 5095 overloads: [ 5096 { 5097 params: [ 5098 { 5099 name: 'path', 5100 description: '<p>name of the file or url to load</p>\n', 5101 type: 'String' 5102 }, 5103 { 5104 name: 'datatype', 5105 description: 5106 '<p>"json", "jsonp", "xml", or "text".\n If omitted, <a href="#/p5/httpPost">httpPost()</a> will guess.</p>\n', 5107 type: 'String', 5108 optional: true 5109 }, 5110 { 5111 name: 'data', 5112 description: '<p>param data passed sent with request</p>\n', 5113 type: 'Object|Boolean', 5114 optional: true 5115 }, 5116 { 5117 name: 'callback', 5118 description: 5119 '<p>function to be executed after\n <a href="#/p5/httpPost">httpPost()</a> completes, data is passed in\n as first argument</p>\n', 5120 type: 'Function', 5121 optional: true 5122 }, 5123 { 5124 name: 'errorCallback', 5125 description: 5126 '<p>function to be executed if\n there is an error, response is passed\n in as first argument</p>\n', 5127 type: 'Function', 5128 optional: true 5129 } 5130 ] 5131 }, 5132 { 5133 params: [ 5134 { 5135 name: 'path', 5136 description: '', 5137 type: 'String' 5138 }, 5139 { 5140 name: 'data', 5141 description: '', 5142 type: 'Object|Boolean' 5143 }, 5144 { 5145 name: 'callback', 5146 description: '', 5147 type: 'Function', 5148 optional: true 5149 }, 5150 { 5151 name: 'errorCallback', 5152 description: '', 5153 type: 'Function', 5154 optional: true 5155 } 5156 ] 5157 }, 5158 { 5159 params: [ 5160 { 5161 name: 'path', 5162 description: '', 5163 type: 'String' 5164 }, 5165 { 5166 name: 'callback', 5167 description: '', 5168 type: 'Function' 5169 }, 5170 { 5171 name: 'errorCallback', 5172 description: '', 5173 type: 'Function', 5174 optional: true 5175 } 5176 ] 5177 } 5178 ] 5179 }, 5180 httpDo: { 5181 name: 'httpDo', 5182 class: 'p5', 5183 module: 'IO', 5184 overloads: [ 5185 { 5186 params: [ 5187 { 5188 name: 'path', 5189 description: '<p>name of the file or url to load</p>\n', 5190 type: 'String' 5191 }, 5192 { 5193 name: 'method', 5194 description: 5195 '<p>either "GET", "POST", or "PUT",\n defaults to "GET"</p>\n', 5196 type: 'String', 5197 optional: true 5198 }, 5199 { 5200 name: 'datatype', 5201 description: '<p>"json", "jsonp", "xml", or "text"</p>\n', 5202 type: 'String', 5203 optional: true 5204 }, 5205 { 5206 name: 'data', 5207 description: '<p>param data passed sent with request</p>\n', 5208 type: 'Object', 5209 optional: true 5210 }, 5211 { 5212 name: 'callback', 5213 description: 5214 '<p>function to be executed after\n <a href="#/p5/httpGet">httpGet()</a> completes, data is passed in\n as first argument</p>\n', 5215 type: 'Function', 5216 optional: true 5217 }, 5218 { 5219 name: 'errorCallback', 5220 description: 5221 '<p>function to be executed if\n there is an error, response is passed\n in as first argument</p>\n', 5222 type: 'Function', 5223 optional: true 5224 } 5225 ] 5226 }, 5227 { 5228 params: [ 5229 { 5230 name: 'path', 5231 description: '', 5232 type: 'String' 5233 }, 5234 { 5235 name: 'options', 5236 description: 5237 '<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', 5238 type: 'Object' 5239 }, 5240 { 5241 name: 'callback', 5242 description: '', 5243 type: 'Function', 5244 optional: true 5245 }, 5246 { 5247 name: 'errorCallback', 5248 description: '', 5249 type: 'Function', 5250 optional: true 5251 } 5252 ] 5253 } 5254 ] 5255 }, 5256 createWriter: { 5257 name: 'createWriter', 5258 params: [ 5259 { 5260 name: 'name', 5261 description: '<p>name of the file to be created</p>\n', 5262 type: 'String' 5263 }, 5264 { 5265 name: 'extension', 5266 description: '', 5267 type: 'String', 5268 optional: true 5269 } 5270 ], 5271 class: 'p5', 5272 module: 'IO' 5273 }, 5274 save: { 5275 name: 'save', 5276 params: [ 5277 { 5278 name: 'objectOrFilename', 5279 description: 5280 '<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', 5281 type: 'Object|String', 5282 optional: true 5283 }, 5284 { 5285 name: 'filename', 5286 description: 5287 '<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', 5288 type: 'String', 5289 optional: true 5290 }, 5291 { 5292 name: 'options', 5293 description: 5294 '<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', 5295 type: 'Boolean|String', 5296 optional: true 5297 } 5298 ], 5299 class: 'p5', 5300 module: 'IO' 5301 }, 5302 saveJSON: { 5303 name: 'saveJSON', 5304 params: [ 5305 { 5306 name: 'json', 5307 description: '', 5308 type: 'Array|Object' 5309 }, 5310 { 5311 name: 'filename', 5312 description: '', 5313 type: 'String' 5314 }, 5315 { 5316 name: 'optimize', 5317 description: 5318 '<p>If true, removes line breaks\n and spaces from the output\n file to optimize filesize\n (but not readability).</p>\n', 5319 type: 'Boolean', 5320 optional: true 5321 } 5322 ], 5323 class: 'p5', 5324 module: 'IO' 5325 }, 5326 saveStrings: { 5327 name: 'saveStrings', 5328 params: [ 5329 { 5330 name: 'list', 5331 description: '<p>string array to be written</p>\n', 5332 type: 'String[]' 5333 }, 5334 { 5335 name: 'filename', 5336 description: '<p>filename for output</p>\n', 5337 type: 'String' 5338 }, 5339 { 5340 name: 'extension', 5341 description: "<p>the filename's extension</p>\n", 5342 type: 'String', 5343 optional: true 5344 }, 5345 { 5346 name: 'isCRLF', 5347 description: '<p>if true, change line-break to CRLF</p>\n', 5348 type: 'Boolean', 5349 optional: true 5350 } 5351 ], 5352 class: 'p5', 5353 module: 'IO' 5354 }, 5355 saveTable: { 5356 name: 'saveTable', 5357 params: [ 5358 { 5359 name: 'Table', 5360 description: 5361 '<p>the <a href="#/p5.Table">Table</a> object to save to a file</p>\n', 5362 type: 'p5.Table' 5363 }, 5364 { 5365 name: 'filename', 5366 description: '<p>the filename to which the Table should be saved</p>\n', 5367 type: 'String' 5368 }, 5369 { 5370 name: 'options', 5371 description: '<p>can be one of "tsv", "csv", or "html"</p>\n', 5372 type: 'String', 5373 optional: true 5374 } 5375 ], 5376 class: 'p5', 5377 module: 'IO' 5378 }, 5379 abs: { 5380 name: 'abs', 5381 params: [ 5382 { 5383 name: 'n', 5384 description: '<p>number to compute</p>\n', 5385 type: 'Number' 5386 } 5387 ], 5388 class: 'p5', 5389 module: 'Math' 5390 }, 5391 ceil: { 5392 name: 'ceil', 5393 params: [ 5394 { 5395 name: 'n', 5396 description: '<p>number to round up</p>\n', 5397 type: 'Number' 5398 } 5399 ], 5400 class: 'p5', 5401 module: 'Math' 5402 }, 5403 constrain: { 5404 name: 'constrain', 5405 params: [ 5406 { 5407 name: 'n', 5408 description: '<p>number to constrain</p>\n', 5409 type: 'Number' 5410 }, 5411 { 5412 name: 'low', 5413 description: '<p>minimum limit</p>\n', 5414 type: 'Number' 5415 }, 5416 { 5417 name: 'high', 5418 description: '<p>maximum limit</p>\n', 5419 type: 'Number' 5420 } 5421 ], 5422 class: 'p5', 5423 module: 'Math' 5424 }, 5425 dist: { 5426 name: 'dist', 5427 class: 'p5', 5428 module: 'Math', 5429 overloads: [ 5430 { 5431 params: [ 5432 { 5433 name: 'x1', 5434 description: '<p>x-coordinate of the first point</p>\n', 5435 type: 'Number' 5436 }, 5437 { 5438 name: 'y1', 5439 description: '<p>y-coordinate of the first point</p>\n', 5440 type: 'Number' 5441 }, 5442 { 5443 name: 'x2', 5444 description: '<p>x-coordinate of the second point</p>\n', 5445 type: 'Number' 5446 }, 5447 { 5448 name: 'y2', 5449 description: '<p>y-coordinate of the second point</p>\n', 5450 type: 'Number' 5451 } 5452 ] 5453 }, 5454 { 5455 params: [ 5456 { 5457 name: 'x1', 5458 description: '', 5459 type: 'Number' 5460 }, 5461 { 5462 name: 'y1', 5463 description: '', 5464 type: 'Number' 5465 }, 5466 { 5467 name: 'z1', 5468 description: '<p>z-coordinate of the first point</p>\n', 5469 type: 'Number' 5470 }, 5471 { 5472 name: 'x2', 5473 description: '', 5474 type: 'Number' 5475 }, 5476 { 5477 name: 'y2', 5478 description: '', 5479 type: 'Number' 5480 }, 5481 { 5482 name: 'z2', 5483 description: '<p>z-coordinate of the second point</p>\n', 5484 type: 'Number' 5485 } 5486 ] 5487 } 5488 ] 5489 }, 5490 exp: { 5491 name: 'exp', 5492 params: [ 5493 { 5494 name: 'n', 5495 description: '<p>exponent to raise</p>\n', 5496 type: 'Number' 5497 } 5498 ], 5499 class: 'p5', 5500 module: 'Math' 5501 }, 5502 floor: { 5503 name: 'floor', 5504 params: [ 5505 { 5506 name: 'n', 5507 description: '<p>number to round down</p>\n', 5508 type: 'Number' 5509 } 5510 ], 5511 class: 'p5', 5512 module: 'Math' 5513 }, 5514 lerp: { 5515 name: 'lerp', 5516 params: [ 5517 { 5518 name: 'start', 5519 description: '<p>first value</p>\n', 5520 type: 'Number' 5521
5521 }, 5522 { 5523 name: 'stop', 5524 description: '<p>second value</p>\n', 5525 type: 'Number' 5526 }, 5527 { 5528 name: 'amt', 5529 description: '<p>number</p>\n', 5530 type: 'Number' 5531 } 5532 ], 5533 class: 'p5', 5534 module: 'Math' 5535 }, 5536 log: { 5537 name: 'log', 5538 params: [ 5539 { 5540 name: 'n', 5541 description: '<p>number greater than 0</p>\n', 5542 type: 'Number' 5543 } 5544 ], 5545 class: 'p5', 5546 module: 'Math' 5547 }, 5548 mag: { 5549 name: 'mag', 5550 params: [ 5551 { 5552 name: 'a', 5553 description: '<p>first value</p>\n', 5554 type: 'Number' 5555 }, 5556 { 5557 name: 'b', 5558 description: '<p>second value</p>\n', 5559 type: 'Number' 5560 } 5561 ], 5562 class: 'p5', 5563 module: 'Math' 5564 }, 5565 map: { 5566 name: 'map', 5567 params: [ 5568 { 5569 name: 'value', 5570 description: '<p>the incoming value to be converted</p>\n', 5571 type: 'Number' 5572 }, 5573 { 5574 name: 'start1', 5575 description: "<p>lower bound of the value's current range</p>\n", 5576 type: 'Number' 5577 }, 5578 { 5579 name: 'stop1', 5580 description: "<p>upper bound of the value's current range</p>\n", 5581 type: 'Number' 5582 }, 5583 { 5584 name: 'start2', 5585 description: "<p>lower bound of the value's target range</p>\n", 5586 type: 'Number' 5587 }, 5588 { 5589 name: 'stop2', 5590 description: "<p>upper bound of the value's target range</p>\n", 5591 type: 'Number' 5592 }, 5593 { 5594 name: 'withinBounds', 5595 description: '<p>constrain the value to the newly mapped range</p>\n', 5596 type: 'Boolean', 5597 optional: true 5598 } 5599 ], 5600 class: 'p5', 5601 module: 'Math' 5602 }, 5603 max: { 5604 name: 'max', 5605 class: 'p5', 5606 module: 'Math', 5607 overloads: [ 5608 { 5609 params: [ 5610 { 5611 name: 'n0', 5612 description: '<p>Number to compare</p>\n', 5613 type: 'Number' 5614 }, 5615 { 5616 name: 'n1', 5617 description: '<p>Number to compare</p>\n', 5618 type: 'Number' 5619 } 5620 ] 5621 }, 5622 { 5623 params: [ 5624 { 5625 name: 'nums', 5626 description: '<p>Numbers to compare</p>\n', 5627 type: 'Number[]' 5628 } 5629 ] 5630 } 5631 ] 5632 }, 5633 min: { 5634 name: 'min', 5635 class: 'p5', 5636 module: 'Math', 5637 overloads: [ 5638 { 5639 params: [ 5640 { 5641 name: 'n0', 5642 description: '<p>Number to compare</p>\n', 5643 type: 'Number' 5644 }, 5645 { 5646 name: 'n1', 5647 description: '<p>Number to compare</p>\n', 5648 type: 'Number' 5649 } 5650 ] 5651 }, 5652 { 5653 params: [ 5654 { 5655 name: 'nums', 5656 description: '<p>Numbers to compare</p>\n', 5657 type: 'Number[]' 5658 } 5659 ] 5660 } 5661 ] 5662 }, 5663 norm: { 5664 name: 'norm', 5665 params: [ 5666 { 5667 name: 'value', 5668 description: '<p>incoming value to be normalized</p>\n', 5669 type: 'Number' 5670 }, 5671 { 5672 name: 'start', 5673 description: "<p>lower bound of the value's current range</p>\n", 5674 type: 'Number' 5675 }, 5676 { 5677 name: 'stop', 5678 description: "<p>upper bound of the value's current range</p>\n", 5679 type: 'Number' 5680 } 5681 ], 5682 class: 'p5', 5683 module: 'Math' 5684 }, 5685 pow: { 5686 name: 'pow', 5687 params: [ 5688 { 5689 name: 'n', 5690 description: '<p>base of the exponential expression</p>\n', 5691 type: 'Number' 5692 }, 5693 { 5694 name: 'e', 5695 description: '<p>power by which to raise the base</p>\n', 5696 type: 'Number' 5697 } 5698 ], 5699 class: 'p5', 5700 module: 'Math' 5701 }, 5702 round: { 5703 name: 'round', 5704 params: [ 5705 { 5706 name: 'n', 5707 description: '<p>number to round</p>\n', 5708 type: 'Number' 5709 }, 5710 { 5711 name: 'decimals', 5712 description: 5713 '<p>number of decimal places to round to, default is 0</p>\n', 5714 type: 'Number', 5715 optional: true 5716 } 5717 ], 5718 class: 'p5', 5719 module: 'Math' 5720 }, 5721 sq: { 5722 name: 'sq', 5723 params: [ 5724 { 5725 name: 'n', 5726 description: '<p>number to square</p>\n', 5727 type: 'Number' 5728 } 5729 ], 5730 class: 'p5', 5731 module: 'Math' 5732 }, 5733 sqrt: { 5734 name: 'sqrt', 5735 params: [ 5736 { 5737 name: 'n', 5738 description: '<p>non-negative number to square root</p>\n', 5739 type: 'Number' 5740 } 5741 ], 5742 class: 'p5', 5743 module: 'Math' 5744 }, 5745 fract: { 5746 name: 'fract', 5747 params: [ 5748 { 5749 name: 'num', 5750 description: 5751 '<p>Number whose fractional part needs to be found out</p>\n', 5752 type: 'Number' 5753 } 5754 ], 5755 class: 'p5', 5756 module: 'Math' 5757 }, 5758 createVector: { 5759 name: 'createVector', 5760 params: [ 5761 { 5762 name: 'x', 5763 description: '<p>x component of the vector</p>\n', 5764 type: 'Number', 5765 optional: true 5766 }, 5767 { 5768 name: 'y', 5769 description: '<p>y component of the vector</p>\n', 5770 type: 'Number', 5771 optional: true 5772 }, 5773 { 5774 name: 'z', 5775 description: '<p>z component of the vector</p>\n', 5776 type: 'Number', 5777 optional: true 5778 } 5779 ], 5780 class: 'p5', 5781 module: 'Math' 5782 }, 5783 noise: { 5784 name: 'noise', 5785 params: [ 5786 { 5787 name: 'x', 5788 description: '<p>x-coordinate in noise space</p>\n', 5789 type: 'Number' 5790 }, 5791 { 5792 name: 'y', 5793 description: '<p>y-coordinate in noise space</p>\n', 5794 type: 'Number', 5795 optional: true 5796 }, 5797 { 5798 name: 'z', 5799 description: '<p>z-coordinate in noise space</p>\n', 5800 type: 'Number', 5801 optional: true 5802 } 5803 ], 5804 class: 'p5', 5805 module: 'Math' 5806 }, 5807 noiseDetail: { 5808 name: 'noiseDetail', 5809 params: [ 5810 { 5811 name: 'lod', 5812 description: '<p>number of octaves to be used by the noise</p>\n', 5813 type: 'Number' 5814 }, 5815 { 5816 name: 'falloff', 5817 description: '<p>falloff factor for each octave</p>\n', 5818 type: 'Number' 5819 } 5820 ], 5821 class: 'p5', 5822 module: 'Math' 5823 }, 5824 noiseSeed: { 5825 name: 'noiseSeed', 5826 params: [ 5827 { 5828 name: 'seed', 5829 description: '<p>the seed value</p>\n', 5830 type: 'Number' 5831 } 5832 ], 5833 class: 'p5', 5834 module: 'Math' 5835 }, 5836 randomSeed: { 5837 name: 'randomSeed', 5838 params: [ 5839 { 5840 name: 'seed', 5841 description: '<p>the seed value</p>\n', 5842 type: 'Number' 5843 } 5844 ], 5845 class: 'p5', 5846 module: 'Math' 5847 }, 5848 random: { 5849 name: 'random', 5850 class: 'p5', 5851 module: 'Math', 5852 overloads: [ 5853 { 5854 params: [ 5855 { 5856 name: 'min', 5857 description: '<p>the lower bound (inclusive)</p>\n', 5858 type: 'Number', 5859 optional: true 5860 }, 5861 { 5862 name: 'max', 5863 description: '<p>the upper bound (exclusive)</p>\n', 5864 type: 'Number', 5865 optional: true 5866 } 5867 ] 5868 }, 5869 { 5870 params: [ 5871 { 5872 name: 'choices', 5873 description: '<p>the array to choose from</p>\n', 5874 type: 'Array' 5875 } 5876 ] 5877 } 5878 ] 5879 }, 5880 randomGaussian: { 5881 name: 'randomGaussian', 5882 params: [ 5883 { 5884 name: 'mean', 5885 description: '<p>the mean</p>\n', 5886 type: 'Number', 5887 optional: true 5888 }, 5889 { 5890 name: 'sd', 5891 description: '<p>the standard deviation</p>\n', 5892 type: 'Number', 5893 optional: true 5894 } 5895 ], 5896 class: 'p5', 5897 module: 'Math' 5898 }, 5899 acos: { 5900 name: 'acos', 5901 params: [ 5902 { 5903 name: 'value', 5904 description: '<p>the value whose arc cosine is to be returned</p>\n', 5905 type: 'Number' 5906 } 5907 ], 5908 class: 'p5', 5909 module: 'Math' 5910 }, 5911 asin: { 5912 name: 'asin', 5913 params: [ 5914 { 5915 name: 'value', 5916 description: '<p>the value whose arc sine is to be returned</p>\n', 5917 type: 'Number' 5918 } 5919 ], 5920 class: 'p5', 5921 module: 'Math' 5922 }, 5923 atan: { 5924 name: 'atan', 5925 params: [ 5926 { 5927 name: 'value', 5928 description: '<p>the value whose arc tangent is to be returned</p>\n', 5929 type: 'Number' 5930 } 5931 ], 5932 class: 'p5', 5933 module: 'Math' 5934 }, 5935 atan2: { 5936 name: 'atan2', 5937 params: [ 5938 { 5939 name: 'y', 5940 description: '<p>y-coordinate of the point</p>\n', 5941 type: 'Number' 5942 }, 5943 { 5944 name: 'x', 5945 description: '<p>x-coordinate of the point</p>\n', 5946 type: 'Number' 5947 } 5948 ], 5949 class: 'p5', 5950 module: 'Math' 5951 }, 5952 cos: { 5953 name: 'cos', 5954 params: [ 5955 { 5956 name: 'angle', 5957 description: '<p>the angle</p>\n', 5958 type: 'Number' 5959 } 5960 ], 5961 class: 'p5', 5962 module: 'Math' 5963 }, 5964 sin: { 5965 name: 'sin', 5966 params: [ 5967 { 5968 name: 'angle', 5969 description: '<p>the angle</p>\n', 5970 type: 'Number' 5971 } 5972 ], 5973 class: 'p5', 5974 module: 'Math' 5975 }, 5976 tan: { 5977 name: 'tan', 5978 params: [ 5979 { 5980 name: 'angle', 5981 description: '<p>the angle</p>\n', 5982 type: 'Number' 5983 } 5984 ], 5985 class: 'p5', 5986 module: 'Math' 5987 }, 5988 degrees: { 5989 name: 'degrees', 5990 params: [ 5991 { 5992 name: 'radians', 5993 description: '<p>the radians value to convert to degrees</p>\n', 5994 type: 'Number' 5995 } 5996 ], 5997 class: 'p5', 5998 module: 'Math' 5999 }, 6000 radians: { 6001 name: 'radians', 6002 params: [ 6003 { 6004 name: 'degrees', 6005 description: '<p>the degree value to convert to radians</p>\n', 6006 type: 'Number' 6007 } 6008 ], 6009 class: 'p5', 6010 module: 'Math' 6011 }, 6012 angleMode: { 6013 name: 'angleMode', 6014 params: [ 6015 { 6016 name: 'mode', 6017 description: '<p>either RADIANS or DEGREES</p>\n', 6018 type: 'Constant' 6019 } 6020 ], 6021 class: 'p5', 6022 module: 'Math' 6023 }, 6024 textAlign: { 6025 name: 'textAlign', 6026 class: 'p5', 6027 module: 'Typography', 6028 overloads: [ 6029 { 6030 params: [ 6031 { 6032 name: 'horizAlign', 6033 description: 6034 '<p>horizontal alignment, either LEFT,\n CENTER, or RIGHT</p>\n', 6035 type: 'Constant' 6036
6036 }, 6037 { 6038 name: 'vertAlign', 6039 description: 6040 '<p>vertical alignment, either TOP,\n BOTTOM, CENTER, or BASELINE</p>\n', 6041 type: 'Constant', 6042 optional: true 6043 } 6044 ], 6045 chainable: 1 6046 }, 6047 { 6048 params: [] 6049 } 6050 ] 6051 }, 6052 textLeading: { 6053 name: 'textLeading', 6054 class: 'p5', 6055 module: 'Typography', 6056 overloads: [ 6057 { 6058 params: [ 6059 { 6060 name: 'leading', 6061 description: 6062 '<p>the size in pixels for spacing between lines</p>\n', 6063 type: 'Number' 6064 } 6065 ], 6066 chainable: 1 6067 }, 6068 { 6069 params: [] 6070 } 6071 ] 6072 }, 6073 textSize: { 6074 name: 'textSize', 6075 class: 'p5', 6076 module: 'Typography', 6077 overloads: [ 6078 { 6079 params: [ 6080 { 6081 name: 'theSize', 6082 description: '<p>the size of the letters in units of pixels</p>\n', 6083 type: 'Number' 6084 } 6085 ], 6086 chainable: 1 6087 }, 6088 { 6089 params: [] 6090 } 6091 ] 6092 }, 6093 textStyle: { 6094 name: 'textStyle', 6095 class: 'p5', 6096 module: 'Typography', 6097 overloads: [ 6098 { 6099 params: [ 6100 { 6101 name: 'theStyle', 6102 description: 6103 '<p>styling for text, either NORMAL,\n ITALIC, BOLD or BOLDITALIC</p>\n', 6104 type: 'Constant' 6105 } 6106 ], 6107 chainable: 1 6108 }, 6109 { 6110 params: [] 6111 } 6112 ] 6113 }, 6114 textWidth: { 6115 name: 'textWidth', 6116 params: [ 6117 { 6118 name: 'theText', 6119 description: '<p>the String of characters to measure</p>\n', 6120 type: 'String' 6121 } 6122 ], 6123 class: 'p5', 6124 module: 'Typography' 6125 }, 6126 textAscent: { 6127 name: 'textAscent', 6128 class: 'p5', 6129 module: 'Typography' 6130 }, 6131 textDescent: { 6132 name: 'textDescent', 6133 class: 'p5', 6134 module: 'Typography' 6135 }, 6136 loadFont: { 6137 name: 'loadFont', 6138 params: [ 6139 { 6140 name: 'path', 6141 description: '<p>name of the file or url to load</p>\n', 6142 type: 'String' 6143 }, 6144 { 6145 name: 'callback', 6146 description: 6147 '<p>function to be executed after\n <a href="#/p5/loadFont">loadFont()</a> completes</p>\n', 6148 type: 'Function', 6149 optional: true 6150 }, 6151 { 6152 name: 'onError', 6153 description: 6154 '<p>function to be executed if\n an error occurs</p>\n', 6155 type: 'Function', 6156 optional: true 6157 } 6158 ], 6159 class: 'p5', 6160 module: 'Typography' 6161 }, 6162 text: { 6163 name: 'text', 6164 params: [ 6165 { 6166 name: 'str', 6167 description: 6168 '<p>the alphanumeric\n symbols to be displayed</p>\n', 6169 type: 'String|Object|Array|Number|Boolean' 6170 }, 6171 { 6172 name: 'x', 6173 description: '<p>x-coordinate of text</p>\n', 6174 type: 'Number' 6175 }, 6176 { 6177 name: 'y', 6178 description: '<p>y-coordinate of text</p>\n', 6179 type: 'Number' 6180 }, 6181 { 6182 name: 'x2', 6183 description: 6184 '<p>by default, the width of the text box,\n see <a href="#/p5/rectMode">rectMode()</a> for more info</p>\n', 6185 type: 'Number', 6186 optional: true 6187 }, 6188 { 6189 name: 'y2', 6190 description: 6191 '<p>by default, the height of the text box,\n see <a href="#/p5/rectMode">rectMode()</a> for more info</p>\n', 6192 type: 'Number', 6193 optional: true 6194 } 6195 ], 6196 class: 'p5', 6197 module: 'Typography' 6198 }, 6199 textFont: { 6200 name: 'textFont', 6201 class: 'p5', 6202 module: 'Typography', 6203 overloads: [ 6204 { 6205 params: [] 6206 }, 6207 { 6208 params: [ 6209 { 6210 name: 'font', 6211 description: 6212 '<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', 6213 type: 'Object|String' 6214 }, 6215 { 6216 name: 'size', 6217 description: '<p>the font size to use</p>\n', 6218 type: 'Number', 6219 optional: true 6220 } 6221 ], 6222 chainable: 1 6223 } 6224 ] 6225 }, 6226 append: { 6227 name: 'append', 6228 params: [ 6229 { 6230 name: 'array', 6231 description: '<p>Array to append</p>\n', 6232 type: 'Array' 6233 }, 6234 { 6235 name: 'value', 6236 description: '<p>to be added to the Array</p>\n', 6237 type: 'Any' 6238 } 6239 ], 6240 class: 'p5', 6241 module: 'Data' 6242 }, 6243 arrayCopy: { 6244 name: 'arrayCopy', 6245 class: 'p5', 6246 module: 'Data', 6247 overloads: [ 6248 { 6249 params: [ 6250 { 6251 name: 'src', 6252 description: '<p>the source Array</p>\n', 6253 type: 'Array' 6254 }, 6255 { 6256 name: 'srcPosition', 6257 description: '<p>starting position in the source Array</p>\n', 6258 type: 'Integer' 6259 }, 6260 { 6261 name: 'dst', 6262 description: '<p>the destination Array</p>\n', 6263 type: 'Array' 6264 }, 6265 { 6266 name: 'dstPosition', 6267 description: '<p>starting position in the destination Array</p>\n', 6268 type: 'Integer' 6269 }, 6270 { 6271 name: 'length', 6272 description: '<p>number of Array elements to be copied</p>\n', 6273 type: 'Integer' 6274 } 6275 ] 6276 }, 6277 { 6278 params: [ 6279 { 6280 name: 'src', 6281 description: '', 6282 type: 'Array' 6283 }, 6284 { 6285 name: 'dst', 6286 description: '', 6287 type: 'Array' 6288 }, 6289 { 6290 name: 'length', 6291 description: '', 6292 type: 'Integer', 6293 optional: true 6294 } 6295 ] 6296 } 6297 ] 6298 }, 6299 concat: { 6300 name: 'concat', 6301 params: [ 6302 { 6303 name: 'a', 6304 description: '<p>first Array to concatenate</p>\n', 6305 type: 'Array' 6306 }, 6307 { 6308 name: 'b', 6309 description: '<p>second Array to concatenate</p>\n', 6310 type: 'Array' 6311 } 6312 ], 6313 class: 'p5', 6314 module: 'Data' 6315 }, 6316 reverse: { 6317 name: 'reverse', 6318 params: [ 6319 { 6320 name: 'list', 6321 description: '<p>Array to reverse</p>\n', 6322 type: 'Array' 6323 } 6324 ], 6325 class: 'p5', 6326 module: 'Data' 6327 }, 6328 shorten: { 6329 name: 'shorten', 6330 params: [ 6331 { 6332 name: 'list', 6333 description: '<p>Array to shorten</p>\n', 6334 type: 'Array' 6335 } 6336 ], 6337 class: 'p5', 6338 module: 'Data' 6339 }, 6340 shuffle: { 6341 name: 'shuffle', 6342 params: [ 6343 { 6344 name: 'array', 6345 description: '<p>Array to shuffle</p>\n', 6346 type: 'Array' 6347 }, 6348 { 6349 name: 'bool', 6350 description: '<p>modify passed array</p>\n', 6351 type: 'Boolean', 6352 optional: true 6353 } 6354 ], 6355 class: 'p5', 6356 module: 'Data' 6357 }, 6358 sort: { 6359 name: 'sort', 6360 params: [ 6361 { 6362 name: 'list', 6363 description: '<p>Array to sort</p>\n', 6364 type: 'Array' 6365 }, 6366 { 6367 name: 'count', 6368 description: '<p>number of elements to sort, starting from 0</p>\n', 6369 type: 'Integer', 6370 optional: true 6371 } 6372 ], 6373 class: 'p5', 6374 module: 'Data' 6375 }, 6376 splice: { 6377 name: 'splice', 6378 params: [ 6379 { 6380 name: 'list', 6381 description: '<p>Array to splice into</p>\n', 6382 type: 'Array' 6383 }, 6384 { 6385 name: 'value', 6386 description: '<p>value to be spliced in</p>\n', 6387 type: 'Any' 6388 }, 6389 { 6390 name: 'position', 6391 description: '<p>in the array from which to insert data</p>\n', 6392 type: 'Integer' 6393 } 6394 ], 6395 class: 'p5', 6396 module: 'Data' 6397 }, 6398 subset: { 6399 name: 'subset', 6400 params: [ 6401 { 6402 name: 'list', 6403 description: '<p>Array to extract from</p>\n', 6404 type: 'Array' 6405 }, 6406 { 6407 name: 'start', 6408 description: '<p>position to begin</p>\n', 6409 type: 'Integer' 6410 }, 6411 { 6412 name: 'count', 6413 description: '<p>number of values to extract</p>\n', 6414 type: 'Integer', 6415 optional: true 6416 } 6417 ], 6418 class: 'p5', 6419 module: 'Data' 6420 }, 6421 float: { 6422 name: 'float', 6423 params: [ 6424 { 6425 name: 'str', 6426 description: '<p>float string to parse</p>\n', 6427 type: 'String' 6428 } 6429 ], 6430 class: 'p5', 6431 module: 'Data' 6432 }, 6433 int: { 6434 name: 'int', 6435 class: 'p5', 6436 module: 'Data', 6437 overloads: [ 6438 { 6439 params: [ 6440 { 6441 name: 'n', 6442 description: '<p>value to parse</p>\n', 6443 type: 'String|Boolean|Number' 6444 }, 6445 { 6446 name: 'radix', 6447 description: '<p>the radix to convert to (default: 10)</p>\n', 6448 type: 'Integer', 6449 optional: true 6450 } 6451 ] 6452 }, 6453 { 6454 params: [ 6455 { 6456 name: 'ns', 6457 description: '<p>values to parse</p>\n', 6458 type: 'Array' 6459 } 6460 ] 6461 } 6462 ] 6463 }, 6464 str: { 6465 name: 'str', 6466 params: [ 6467 { 6468 name: 'n', 6469 description: '<p>value to parse</p>\n', 6470 type: 'String|Boolean|Number|Array' 6471 } 6472 ], 6473 class: 'p5', 6474 module: 'Data' 6475 }, 6476 byte: { 6477 name: 'byte', 6478 class: 'p5', 6479 module: 'Data', 6480 overloads: [ 6481 { 6482 params: [ 6483 { 6484 name: 'n', 6485 description: '<p>value to parse</p>\n', 6486 type: 'String|Boolean|Number' 6487 } 6488 ] 6489 }, 6490 { 6491 params: [ 6492 { 6493 name: 'ns', 6494 description: '<p>values to parse</p>\n', 6495 type: 'Array' 6496 } 6497 ] 6498 } 6499 ] 6500 }, 6501 char: { 6502 name: 'char', 6503 class: 'p5', 6504 module: 'Data', 6505 overloads: [ 6506 { 6507 params: [ 6508 { 6509 name: 'n', 6510 description: '<p>value to parse</p>\n', 6511 type: 'String|Number' 6512 } 6513 ] 6514 }, 6515 { 6516 params: [ 6517 { 6518 name: 'ns', 6519 description: '<p>values to parse</p>\n', 6520 type: 'Array' 6521 } 6522 ] 6523 } 6524 ] 6525 }, 6526 unchar: { 6527 name: 'unchar', 6528 class: 'p5', 6529 module: 'Data', 6530 overloads: [ 6531 { 6532 params: [ 6533
6533 { 6534 name: 'n', 6535 description: '<p>value to parse</p>\n', 6536 type: 'String' 6537 } 6538 ] 6539 }, 6540 { 6541 params: [ 6542 { 6543 name: 'ns', 6544 description: '<p>values to parse</p>\n', 6545 type: 'Array' 6546 } 6547 ] 6548 } 6549 ] 6550 }, 6551 hex: { 6552 name: 'hex', 6553 class: 'p5', 6554 module: 'Data', 6555 overloads: [ 6556 { 6557 params: [ 6558 { 6559 name: 'n', 6560 description: '<p>value to parse</p>\n', 6561 type: 'Number' 6562 }, 6563 { 6564 name: 'digits', 6565 description: '', 6566 type: 'Number', 6567 optional: true 6568 } 6569 ] 6570 }, 6571 { 6572 params: [ 6573 { 6574 name: 'ns', 6575 description: '<p>array of values to parse</p>\n', 6576 type: 'Number[]' 6577 }, 6578 { 6579 name: 'digits', 6580 description: '', 6581 type: 'Number', 6582 optional: true 6583 } 6584 ] 6585 } 6586 ] 6587 }, 6588 unhex: { 6589 name: 'unhex', 6590 class: 'p5', 6591 module: 'Data', 6592 overloads: [ 6593 { 6594 params: [ 6595 { 6596 name: 'n', 6597 description: '<p>value to parse</p>\n', 6598 type: 'String' 6599 } 6600 ] 6601 }, 6602 { 6603 params: [ 6604 { 6605 name: 'ns', 6606 description: '<p>values to parse</p>\n', 6607 type: 'Array' 6608 } 6609 ] 6610 } 6611 ] 6612 }, 6613 join: { 6614 name: 'join', 6615 params: [ 6616 { 6617 name: 'list', 6618 description: '<p>array of Strings to be joined</p>\n', 6619 type: 'Array' 6620 }, 6621 { 6622 name: 'separator', 6623 description: '<p>String to be placed between each item</p>\n', 6624 type: 'String' 6625 } 6626 ], 6627 class: 'p5', 6628 module: 'Data' 6629 }, 6630 match: { 6631 name: 'match', 6632 params: [ 6633 { 6634 name: 'str', 6635 description: '<p>the String to be searched</p>\n', 6636 type: 'String' 6637 }, 6638 { 6639 name: 'regexp', 6640 description: '<p>the regexp to be used for matching</p>\n', 6641 type: 'String' 6642 } 6643 ], 6644 class: 'p5', 6645 module: 'Data' 6646 }, 6647 matchAll: { 6648 name: 'matchAll', 6649 params: [ 6650 { 6651 name: 'str', 6652 description: '<p>the String to be searched</p>\n', 6653 type: 'String' 6654 }, 6655 { 6656 name: 'regexp', 6657 description: '<p>the regexp to be used for matching</p>\n', 6658 type: 'String' 6659 } 6660 ], 6661 class: 'p5', 6662 module: 'Data' 6663 }, 6664 nf: { 6665 name: 'nf', 6666 class: 'p5', 6667 module: 'Data', 6668 overloads: [ 6669 { 6670 params: [ 6671 { 6672 name: 'num', 6673 description: '<p>the Number to format</p>\n', 6674 type: 'Number|String' 6675 }, 6676 { 6677 name: 'left', 6678 description: 6679 '<p>number of digits to the left of the\n decimal point</p>\n', 6680 type: 'Integer|String', 6681 optional: true 6682 }, 6683 { 6684 name: 'right', 6685 description: 6686 '<p>number of digits to the right of the\n decimal point</p>\n', 6687 type: 'Integer|String', 6688 optional: true 6689 } 6690 ] 6691 }, 6692 { 6693 params: [ 6694 { 6695 name: 'nums', 6696 description: '<p>the Numbers to format</p>\n', 6697 type: 'Array' 6698 }, 6699 { 6700 name: 'left', 6701 description: '', 6702 type: 'Integer|String', 6703 optional: true 6704 }, 6705 { 6706 name: 'right', 6707 description: '', 6708 type: 'Integer|String', 6709 optional: true 6710 } 6711 ] 6712 } 6713 ] 6714 }, 6715 nfc: { 6716 name: 'nfc', 6717 class: 'p5', 6718 module: 'Data', 6719 overloads: [ 6720 { 6721 params: [ 6722 { 6723 name: 'num', 6724 description: '<p>the Number to format</p>\n', 6725 type: 'Number|String' 6726 }, 6727 { 6728 name: 'right', 6729 description: 6730 '<p>number of digits to the right of the\n decimal point</p>\n', 6731 type: 'Integer|String', 6732 optional: true 6733 } 6734 ] 6735 }, 6736 { 6737 params: [ 6738 { 6739 name: 'nums', 6740 description: '<p>the Numbers to format</p>\n', 6741 type: 'Array' 6742 }, 6743 { 6744 name: 'right', 6745 description: '', 6746 type: 'Integer|String', 6747 optional: true 6748 } 6749 ] 6750 } 6751 ] 6752 }, 6753 nfp: { 6754 name: 'nfp', 6755 class: 'p5', 6756 module: 'Data', 6757 overloads: [ 6758 { 6759 params: [ 6760 { 6761 name: 'num', 6762 description: '<p>the Number to format</p>\n', 6763 type: 'Number' 6764 }, 6765 { 6766 name: 'left', 6767 description: 6768 '<p>number of digits to the left of the decimal\n point</p>\n', 6769 type: 'Integer', 6770 optional: true 6771 }, 6772 { 6773 name: 'right', 6774 description: 6775 '<p>number of digits to the right of the\n decimal point</p>\n', 6776 type: 'Integer', 6777 optional: true 6778 } 6779 ] 6780 }, 6781 { 6782 params: [ 6783 { 6784 name: 'nums', 6785 description: '<p>the Numbers to format</p>\n', 6786 type: 'Number[]' 6787 }, 6788 { 6789 name: 'left', 6790 description: '', 6791 type: 'Integer', 6792 optional: true 6793 }, 6794 { 6795 name: 'right', 6796 description: '', 6797 type: 'Integer', 6798 optional: true 6799 } 6800 ] 6801 } 6802 ] 6803 }, 6804 nfs: { 6805 name: 'nfs', 6806 class: 'p5', 6807 module: 'Data', 6808 overloads: [ 6809 { 6810 params: [ 6811 { 6812 name: 'num', 6813 description: '<p>the Number to format</p>\n', 6814 type: 'Number' 6815 }, 6816 { 6817 name: 'left', 6818 description: 6819 '<p>number of digits to the left of the decimal\n point</p>\n', 6820 type: 'Integer', 6821 optional: true 6822 }, 6823 { 6824 name: 'right', 6825 description: 6826 '<p>number of digits to the right of the\n decimal point</p>\n', 6827 type: 'Integer', 6828 optional: true 6829 } 6830 ] 6831 }, 6832 { 6833 params: [ 6834 { 6835 name: 'nums', 6836 description: '<p>the Numbers to format</p>\n', 6837 type: 'Array' 6838 }, 6839 { 6840 name: 'left', 6841 description: '', 6842 type: 'Integer', 6843 optional: true 6844 }, 6845 { 6846 name: 'right', 6847 description: '', 6848 type: 'Integer', 6849 optional: true 6850 } 6851 ] 6852 } 6853 ] 6854 }, 6855 split: { 6856 name: 'split', 6857 params: [ 6858 { 6859 name: 'value', 6860 description: '<p>the String to be split</p>\n', 6861 type: 'String' 6862 }, 6863 { 6864 name: 'delim', 6865 description: '<p>the String used to separate the data</p>\n', 6866 type: 'String' 6867 } 6868 ], 6869 class: 'p5', 6870 module: 'Data' 6871 }, 6872 splitTokens: { 6873 name: 'splitTokens', 6874 params: [ 6875 { 6876 name: 'value', 6877 description: '<p>the String to be split</p>\n', 6878 type: 'String' 6879 }, 6880 { 6881 name: 'delim', 6882 description: 6883 '<p>list of individual Strings that will be used as\n separators</p>\n', 6884 type: 'String', 6885 optional: true 6886 } 6887 ], 6888 class: 'p5', 6889 module: 'Data' 6890 }, 6891 trim: { 6892 name: 'trim', 6893 class: 'p5', 6894 module: 'Data', 6895 overloads: [ 6896 { 6897 params: [ 6898 { 6899 name: 'str', 6900 description: '<p>a String to be trimmed</p>\n', 6901 type: 'String' 6902 } 6903 ] 6904 }, 6905 { 6906 params: [ 6907 { 6908 name: 'strs', 6909 description: '<p>an Array of Strings to be trimmed</p>\n', 6910 type: 'Array' 6911 } 6912 ] 6913 } 6914 ] 6915 }, 6916 day: { 6917 name: 'day', 6918 class: 'p5', 6919 module: 'IO' 6920 }, 6921 hour: { 6922 name: 'hour', 6923 class: 'p5', 6924 module: 'IO' 6925 }, 6926 minute: { 6927 name: 'minute', 6928 class: 'p5', 6929 module: 'IO' 6930 }, 6931 millis: { 6932 name: 'millis', 6933 class: 'p5', 6934 module: 'IO' 6935 }, 6936 month: { 6937 name: 'month', 6938 class: 'p5', 6939 module: 'IO' 6940 }, 6941 second: { 6942 name: 'second', 6943 class: 'p5', 6944 module: 'IO' 6945 }, 6946 year: { 6947 name: 'year', 6948 class: 'p5', 6949 module: 'IO' 6950 },
6951 plane: { 6952 name: 'plane', 6953 params: [ 6954 { 6955 name: 'width', 6956 description: '<p>width of the plane</p>\n', 6957 type: 'Number', 6958 optional: true 6959 }, 6960 { 6961 name: 'height', 6962 description: '<p>height of the plane</p>\n', 6963 type: 'Number', 6964 optional: true 6965 }, 6966 { 6967 name: 'detailX', 6968 description: 6969 '<p>Optional number of triangle\n subdivisions in x-dimension</p>\n', 6970 type: 'Integer', 6971 optional: true 6972 }, 6973 { 6974 name: 'detailY', 6975 description: 6976 '<p>Optional number of triangle\n subdivisions in y-dimension</p>\n', 6977 type: 'Integer', 6978 optional: true 6979 } 6980 ], 6981 class: 'p5', 6982 module: 'Shape' 6983 }, 6984 box: { 6985 name: 'box', 6986 params: [ 6987 { 6988 name: 'width', 6989 description: '<p>width of the box</p>\n', 6990 type: 'Number', 6991 optional: true 6992 }, 6993 { 6994 name: 'Height', 6995 description: '<p>height of the box</p>\n', 6996 type: 'Number', 6997 optional: true 6998 }, 6999 { 7000 name: 'depth', 7001 description: '<p>depth of the box</p>\n', 7002 type: 'Number', 7003 optional: true 7004 }, 7005 { 7006 name: 'detailX', 7007 description: 7008 '<p>Optional number of triangle\n subdivisions in x-dimension</p>\n', 7009 type: 'Integer', 7010 optional: true 7011 }, 7012 { 7013 name: 'detailY', 7014 description: 7015 '<p>Optional number of triangle\n subdivisions in y-dimension</p>\n', 7016 type: 'Integer', 7017 optional: true 7018 } 7019 ], 7020 class: 'p5', 7021 module: 'Shape' 7022 }, 7023 sphere: { 7024 name: 'sphere', 7025 params: [ 7026 { 7027 name: 'radius', 7028 description: '<p>radius of circle</p>\n', 7029 type: 'Number', 7030 optional: true 7031 }, 7032 { 7033 name: 'detailX', 7034 description: '<p>optional number of subdivisions in x-dimension</p>\n', 7035 type: 'Integer', 7036 optional: true 7037 }, 7038 { 7039 name: 'detailY', 7040 description: '<p>optional number of subdivisions in y-dimension</p>\n', 7041 type: 'Integer', 7042 optional: true 7043 } 7044 ], 7045 class: 'p5', 7046 module: 'Shape' 7047 }, 7048 cylinder: { 7049 name: 'cylinder', 7050 params: [ 7051 { 7052 name: 'radius', 7053 description: '<p>radius of the surface</p>\n', 7054 type: 'Number', 7055 optional: true 7056 }, 7057 { 7058 name: 'height', 7059 description: '<p>height of the cylinder</p>\n', 7060 type: 'Number', 7061 optional: true 7062 }, 7063 { 7064 name: 'detailX', 7065 description: 7066 '<p>number of subdivisions in x-dimension;\n default is 24</p>\n', 7067 type: 'Integer', 7068 optional: true 7069 }, 7070 { 7071 name: 'detailY', 7072 description: 7073 '<p>number of subdivisions in y-dimension;\n default is 1</p>\n', 7074 type: 'Integer', 7075 optional: true 7076 }, 7077 { 7078 name: 'bottomCap', 7079 description: '<p>whether to draw the bottom of the cylinder</p>\n', 7080 type: 'Boolean', 7081 optional: true 7082 }, 7083 { 7084 name: 'topCap', 7085 description: '<p>whether to draw the top of the cylinder</p>\n', 7086 type: 'Boolean', 7087 optional: true 7088 } 7089 ], 7090 class: 'p5', 7091 module: 'Shape' 7092 }, 7093 cone: { 7094 name: 'cone', 7095 params: [ 7096 { 7097 name: 'radius', 7098 description: '<p>radius of the bottom surface</p>\n', 7099 type: 'Number', 7100 optional: true 7101 }, 7102 { 7103 name: 'height', 7104 description: '<p>height of the cone</p>\n', 7105 type: 'Number', 7106 optional: true 7107 }, 7108 { 7109 name: 'detailX', 7110 description: 7111 '<p>number of segments,\n the more segments the smoother geometry\n default is 24</p>\n', 7112 type: 'Integer', 7113 optional: true 7114 }, 7115 { 7116 name: 'detailY', 7117 description: 7118 '<p>number of segments,\n the more segments the smoother geometry\n default is 1</p>\n', 7119 type: 'Integer', 7120 optional: true 7121 }, 7122 { 7123 name: 'cap', 7124 description: '<p>whether to draw the base of the cone</p>\n', 7125 type: 'Boolean', 7126 optional: true 7127 } 7128 ], 7129 class: 'p5', 7130 module: 'Shape' 7131 }, 7132 ellipsoid: { 7133 name: 'ellipsoid', 7134 params: [ 7135 { 7136 name: 'radiusx', 7137 description: '<p>x-radius of ellipsoid</p>\n', 7138 type: 'Number', 7139 optional: true 7140 }, 7141 { 7142 name: 'radiusy', 7143 description: '<p>y-radius of ellipsoid</p>\n', 7144 type: 'Number', 7145 optional: true 7146 }, 7147 { 7148 name: 'radiusz', 7149 description: '<p>z-radius of ellipsoid</p>\n', 7150 type: 'Number', 7151 optional: true 7152 }, 7153 { 7154 name: 'detailX', 7155 description: 7156 '<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', 7157 type: 'Integer', 7158 optional: true 7159 }, 7160 { 7161 name: 'detailY', 7162 description: 7163 '<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', 7164 type: 'Integer', 7165 optional: true 7166 } 7167 ], 7168 class: 'p5', 7169 module: 'Shape' 7170 }, 7171 torus: { 7172 name: 'torus', 7173 params: [ 7174 { 7175 name: 'radius', 7176 description: '<p>radius of the whole ring</p>\n', 7177 type: 'Number', 7178 optional: true 7179 }, 7180 { 7181 name: 'tubeRadius', 7182 description: '<p>radius of the tube</p>\n', 7183 type: 'Number', 7184 optional: true 7185 }, 7186 { 7187 name: 'detailX', 7188 description: 7189 '<p>number of segments in x-dimension,\n the more segments the smoother geometry\n default is 24</p>\n', 7190 type: 'Integer', 7191 optional: true 7192 }, 7193 { 7194 name: 'detailY', 7195 description: 7196 '<p>number of segments in y-dimension,\n the more segments the smoother geometry\n default is 16</p>\n', 7197 type: 'Integer', 7198 optional: true 7199 } 7200 ], 7201 class: 'p5', 7202 module: 'Shape' 7203 }, 7204 orbitControl: { 7205 name: 'orbitControl', 7206 params: [ 7207 { 7208 name: 'sensitivityX', 7209 description: '<p>sensitivity to mouse movement along X axis</p>\n', 7210 type: 'Number', 7211 optional: true 7212 }, 7213 { 7214 name: 'sensitivityY', 7215 description: '<p>sensitivity to mouse movement along Y axis</p>\n', 7216 type: 'Number', 7217 optional: true 7218 }, 7219 { 7220 name: 'sensitivityZ', 7221 description: '<p>sensitivity to scroll movement along Z axis</p>\n', 7222 type: 'Number', 7223 optional: true 7224 } 7225 ], 7226 class: 'p5', 7227 module: 'Lights, Camera' 7228 }, 7229 debugMode: { 7230 name: 'debugMode', 7231 class: 'p5', 7232 module: 'Lights, Camera', 7233 overloads: [ 7234 { 7235 params: [] 7236 }, 7237 { 7238 params: [ 7239 { 7240 name: 'mode', 7241 description: '<p>either GRID or AXES</p>\n', 7242 type: 'Constant' 7243 } 7244 ] 7245 }, 7246 { 7247 params: [ 7248 { 7249 name: 'mode', 7250 description: '', 7251 type: 'Constant' 7252 }, 7253 { 7254 name: 'gridSize', 7255 description: '<p>size of one side of the grid</p>\n', 7256 type: 'Number', 7257 optional: true 7258 }, 7259 { 7260 name: 'gridDivisions', 7261 description: '<p>number of divisions in the grid</p>\n', 7262 type: 'Number', 7263 optional: true 7264 }, 7265 { 7266 name: 'xOff', 7267 description: '<p>X axis offset from origin (0,0,0)</p>\n', 7268 type: 'Number', 7269 optional: true 7270 }, 7271 { 7272 name: 'yOff', 7273 description: '<p>Y axis offset from origin (0,0,0)</p>\n', 7274 type: 'Number', 7275 optional: true 7276 }, 7277 { 7278 name: 'zOff', 7279 description: '<p>Z axis offset from origin (0,0,0)</p>\n', 7280 type: 'Number', 7281 optional: true 7282 } 7283 ] 7284 }, 7285 { 7286 params: [ 7287 { 7288 name: 'mode', 7289 description: '', 7290 type: 'Constant' 7291 }, 7292 { 7293 name: 'axesSize', 7294 description: '<p>size of axes icon</p>\n', 7295 type: 'Number', 7296 optional: true 7297 }, 7298 { 7299 name: 'xOff', 7300 description: '', 7301 type: 'Number', 7302 optional: true 7303 }, 7304 { 7305 name: 'yOff', 7306 description: '', 7307 type: 'Number', 7308 optional: true 7309 }, 7310 { 7311 name: 'zOff', 7312 description: '', 7313 type: 'Number', 7314 optional: true 7315 } 7316 ] 7317 }, 7318 { 7319 params: [ 7320 { 7321 name: 'gridSize', 7322 description: '', 7323 type: 'Number', 7324 optional: true 7325 }, 7326 { 7327 name: 'gridDivisions', 7328 description: '', 7329 type: 'Number', 7330 optional: true 7331 }, 7332 { 7333 name: 'gridXOff', 7334 description: '', 7335 type: 'Number', 7336 optional: true 7337 }, 7338 { 7339 name: 'gridYOff', 7340 description: '', 7341 type: 'Number', 7342 optional: true 7343 }, 7344 { 7345 name: 'gridZOff', 7346 description: '', 7347 type: 'Number', 7348 optional: true 7349 }, 7350 { 7351 name: 'axesSize', 7352 description: '', 7353 type: 'Number', 7354 optional: true 7355 }, 7356 { 7357 name: 'axesXOff', 7358 description: '', 7359 type: 'Number', 7360 optional: true 7361 }, 7362 { 7363 name: 'axesYOff', 7364 description: '', 7365 type: 'Number', 7366 optional: true 7367 }, 7368 { 7369 name: 'axesZOff', 7370 description: '', 7371 type: 'Number', 7372 optional: true 7373 } 7374 ] 7375 } 7376 ] 7377 }, 7378 noDebugMode: { 7379 name: 'noDebugMode', 7380 class: 'p5', 7381 module: 'Lights, Camera' 7382 }, 7383 ambientLight: { 7384 name: 'ambientLight', 7385 class: 'p5', 7386 module: 'Lights, Camera', 7387 overloads: [ 7388 { 7389 params: [ 7390 { 7391 name: 'v1', 7392 description: 7393
7393 '<p>red or hue value relative to\n the current color range</p>\n', 7394 type: 'Number' 7395 }, 7396 { 7397 name: 'v2', 7398 description: 7399 '<p>green or saturation value\n relative to the current color range</p>\n', 7400 type: 'Number' 7401 }, 7402 { 7403 name: 'v3', 7404 description: 7405 '<p>blue or brightness value\n relative to the current color range</p>\n', 7406 type: 'Number' 7407 }, 7408 { 7409 name: 'alpha', 7410 description: '<p>the alpha value</p>\n', 7411 type: 'Number', 7412 optional: true 7413 } 7414 ], 7415 chainable: 1 7416 }, 7417 { 7418 params: [ 7419 { 7420 name: 'value', 7421 description: '<p>a color string</p>\n', 7422 type: 'String' 7423 } 7424 ], 7425 chainable: 1 7426 }, 7427 { 7428 params: [ 7429 { 7430 name: 'gray', 7431 description: '<p>a gray value</p>\n', 7432 type: 'Number' 7433 }, 7434 { 7435 name: 'alpha', 7436 description: '', 7437 type: 'Number', 7438 optional: true 7439 } 7440 ], 7441 chainable: 1 7442 }, 7443 { 7444 params: [ 7445 { 7446 name: 'values', 7447 description: 7448 '<p>an array containing the red,green,blue &\n and alpha components of the color</p>\n', 7449 type: 'Number[]' 7450 } 7451 ], 7452 chainable: 1 7453 }, 7454 { 7455 params: [ 7456 { 7457 name: 'color', 7458 description: '<p>the ambient light color</p>\n', 7459 type: 'p5.Color' 7460 } 7461 ], 7462 chainable: 1 7463 } 7464 ] 7465 }, 7466 specularColor: { 7467 name: 'specularColor', 7468 class: 'p5', 7469 module: 'Lights, Camera', 7470 overloads: [ 7471 { 7472 params: [ 7473 { 7474 name: 'v1', 7475 description: 7476 '<p>red or hue value relative to\n the current color range</p>\n', 7477 type: 'Number' 7478 }, 7479 { 7480 name: 'v2', 7481 description: 7482 '<p>green or saturation value\n relative to the current color range</p>\n', 7483 type: 'Number' 7484 }, 7485 { 7486 name: 'v3', 7487 description: 7488 '<p>blue or brightness value\n relative to the current color range</p>\n', 7489 type: 'Number' 7490 } 7491 ], 7492 chainable: 1 7493 }, 7494 { 7495 params: [ 7496 { 7497 name: 'value', 7498 description: '<p>a color string</p>\n', 7499 type: 'String' 7500 } 7501 ], 7502 chainable: 1 7503 }, 7504 { 7505 params: [ 7506 { 7507 name: 'gray', 7508 description: '<p>a gray value</p>\n', 7509 type: 'Number' 7510 } 7511 ], 7512 chainable: 1 7513 }, 7514 { 7515 params: [ 7516 { 7517 name: 'values', 7518 description: 7519 '<p>an array containing the red,green,blue &\n and alpha components of the color</p>\n', 7520 type: 'Number[]' 7521 } 7522 ], 7523 chainable: 1 7524 }, 7525 { 7526 params: [ 7527 { 7528 name: 'color', 7529 description: '<p>the ambient light color</p>\n', 7530 type: 'p5.Color' 7531 } 7532 ], 7533 chainable: 1 7534 } 7535 ] 7536 }, 7537 directionalLight: { 7538 name: 'directionalLight', 7539 class: 'p5', 7540 module: 'Lights, Camera', 7541 overloads: [ 7542 { 7543 params: [ 7544 { 7545 name: 'v1', 7546 description: 7547 '<p>red or hue value (depending on the current\ncolor mode),</p>\n', 7548 type: 'Number' 7549 }, 7550 { 7551 name: 'v2', 7552 description: '<p>green or saturation value</p>\n', 7553 type: 'Number' 7554 }, 7555 { 7556 name: 'v3', 7557 description: '<p>blue or brightness value</p>\n', 7558 type: 'Number' 7559 }, 7560 { 7561 name: 'position', 7562 description: '<p>the direction of the light</p>\n', 7563 type: 'p5.Vector' 7564 } 7565 ], 7566 chainable: 1 7567 }, 7568 { 7569 params: [ 7570 { 7571 name: 'color', 7572 description: 7573 '<p>color Array, CSS color string,\n or <a href="#/p5.Color">p5.Color</a> value</p>\n', 7574 type: 'Number[]|String|p5.Color' 7575 }, 7576 { 7577 name: 'x', 7578 description: '<p>x axis direction</p>\n', 7579 type: 'Number' 7580 }, 7581 { 7582 name: 'y', 7583 description: '<p>y axis direction</p>\n', 7584 type: 'Number' 7585 }, 7586 { 7587 name: 'z', 7588 description: '<p>z axis direction</p>\n', 7589 type: 'Number' 7590 } 7591 ], 7592 chainable: 1 7593 }, 7594 { 7595 params: [ 7596 { 7597 name: 'color', 7598 description: '', 7599 type: 'Number[]|String|p5.Color' 7600 }, 7601 { 7602 name: 'position', 7603 description: '', 7604 type: 'p5.Vector' 7605 } 7606 ], 7607 chainable: 1 7608 }, 7609 { 7610 params: [ 7611 { 7612 name: 'v1', 7613 description: '', 7614 type: 'Number' 7615 }, 7616 { 7617 name: 'v2', 7618 description: '', 7619 type: 'Number' 7620 }, 7621 { 7622 name: 'v3', 7623 description: '', 7624 type: 'Number' 7625 }, 7626 { 7627 name: 'x', 7628 description: '', 7629 type: 'Number' 7630 }, 7631 { 7632 name: 'y', 7633 description: '', 7634 type: 'Number' 7635 }, 7636 { 7637 name: 'z', 7638 description: '', 7639 type: 'Number' 7640 } 7641 ], 7642 chainable: 1 7643 } 7644 ] 7645 }, 7646 pointLight: { 7647 name: 'pointLight', 7648 class: 'p5', 7649 module: 'Lights, Camera', 7650 overloads: [ 7651 { 7652 params: [ 7653 { 7654 name: 'v1', 7655 description: 7656 '<p>red or hue value (depending on the current\ncolor mode),</p>\n', 7657 type: 'Number' 7658 }, 7659 { 7660 name: 'v2', 7661 description: '<p>green or saturation value</p>\n', 7662 type: 'Number' 7663 }, 7664 { 7665 name: 'v3', 7666 description: '<p>blue or brightness value</p>\n', 7667 type: 'Number' 7668 }, 7669 { 7670 name: 'x', 7671 description: '<p>x axis position</p>\n', 7672 type: 'Number' 7673 }, 7674 { 7675 name: 'y', 7676 description: '<p>y axis position</p>\n', 7677 type: 'Number' 7678 }, 7679 { 7680 name: 'z', 7681 description: '<p>z axis position</p>\n', 7682 type: 'Number' 7683 } 7684 ], 7685 chainable: 1 7686 }, 7687 { 7688 params: [ 7689 { 7690 name: 'v1', 7691 description: '', 7692 type: 'Number' 7693 }, 7694 { 7695 name: 'v2', 7696 description: '', 7697 type: 'Number' 7698 }, 7699 { 7700 name: 'v3', 7701 description: '', 7702 type: 'Number' 7703 }, 7704 { 7705 name: 'position', 7706 description: '<p>the position of the light</p>\n', 7707 type: 'p5.Vector' 7708 } 7709 ], 7710 chainable: 1 7711 }, 7712 { 7713 params: [ 7714 { 7715 name: 'color', 7716 description: 7717 '<p>color Array, CSS color string,\nor <a href="#/p5.Color">p5.Color</a> value</p>\n', 7718 type: 'Number[]|String|p5.Color' 7719 }, 7720 { 7721 name: 'x', 7722 description: '', 7723 type: 'Number' 7724 }, 7725 { 7726 name: 'y', 7727 description: '', 7728 type: 'Number' 7729 }, 7730 { 7731 name: 'z', 7732 description: '', 7733 type: 'Number' 7734 } 7735 ], 7736 chainable: 1 7737 }, 7738 { 7739 params: [ 7740 { 7741 name: 'color', 7742 description: '', 7743 type: 'Number[]|String|p5.Color' 7744 }, 7745 { 7746 name: 'position', 7747 description: '', 7748 type: 'p5.Vector' 7749 } 7750 ], 7751 chainable: 1 7752 } 7753 ] 7754 }, 7755 lights: { 7756 name: 'lights', 7757 class: 'p5', 7758 module: 'Lights, Camera' 7759 }, 7760 lightFalloff: { 7761 name: 'lightFalloff', 7762 params: [ 7763 { 7764 name: 'constant', 7765 description: '<p>constant value for determining falloff</p>\n', 7766 type: 'Number' 7767 }, 7768 { 7769 name: 'linear', 7770 description: '<p>linear value for determining falloff</p>\n', 7771 type: 'Number' 7772 }, 7773 { 7774 name: 'quadratic', 7775 description: '<p>quadratic value for determining falloff</p>\n', 7776 type: 'Number' 7777 } 7778 ], 7779 class: 'p5', 7780 module: 'Lights, Camera' 7781 }, 7782 spotLight: { 7783 name: 'spotLight', 7784 class: 'p5', 7785 module: 'Lights, Camera', 7786 overloads: [ 7787 { 7788 params: [ 7789 { 7790 name: 'v1', 7791 description: 7792 '<p>red or hue value (depending on the current\ncolor mode),</p>\n', 7793 type: 'Number' 7794 }, 7795 { 7796 name: 'v2', 7797 description: '<p>green or saturation value</p>\n', 7798 type: 'Number' 7799 }, 7800 { 7801 name: 'v3', 7802 description: '<p>blue or brightness value</p>\n', 7803 type: 'Number' 7804 }, 7805 { 7806 name: 'x', 7807 description: '<p>x axis position</p>\n', 7808 type: 'Number' 7809 }, 7810 { 7811 name: 'y', 7812 description: '<p>y axis position</p>\n', 7813 type: 'Number' 7814 }, 7815 { 7816 name: 'z', 7817 description: '<p>z axis position</p>\n', 7818 type: 'Number' 7819 }, 7820 { 7821 name: 'rx', 7822 description: '<p>x axis direction of light</p>\n', 7823 type: 'Number' 7824 }, 7825 { 7826 name: 'ry', 7827 description: '<p>y axis direction of light</p>\n', 7828 type: 'Number' 7829 }, 7830 { 7831 name: 'rz', 7832 description: '<p>z axis direction of light</p>\n', 7833 type: 'Number' 7834 }, 7835 { 7836 name: 'angle', 7837 description: 7838 '<p>optional parameter for angle. Defaults to PI/3</p>\n', 7839 type: 'Number', 7840 optional: true 7841 }, 7842 { 7843 name: 'conc', 7844 description: 7845 '<p>optional parameter for concentration. Defaults to 100</p>\n', 7846 type: 'Nu
7846mber', 7847 optional: true 7848 } 7849 ], 7850 chainable: 1 7851 }, 7852 { 7853 params: [ 7854 { 7855 name: 'color', 7856 description: 7857 '<p>color Array, CSS color string,\nor <a href="#/p5.Color">p5.Color</a> value</p>\n', 7858 type: 'Number[]|String|p5.Color' 7859 }, 7860 { 7861 name: 'position', 7862 description: '<p>the position of the light</p>\n', 7863 type: 'p5.Vector' 7864 }, 7865 { 7866 name: 'direction', 7867 description: '<p>the direction of the light</p>\n', 7868 type: 'p5.Vector' 7869 }, 7870 { 7871 name: 'angle', 7872 description: '', 7873 type: 'Number', 7874 optional: true 7875 }, 7876 { 7877 name: 'conc', 7878 description: '', 7879 type: 'Number', 7880 optional: true 7881 } 7882 ] 7883 }, 7884 { 7885 params: [ 7886 { 7887 name: 'v1', 7888 description: '', 7889 type: 'Number' 7890 }, 7891 { 7892 name: 'v2', 7893 description: '', 7894 type: 'Number' 7895 }, 7896 { 7897 name: 'v3', 7898 description: '', 7899 type: 'Number' 7900 }, 7901 { 7902 name: 'position', 7903 description: '', 7904 type: 'p5.Vector' 7905 }, 7906 { 7907 name: 'direction', 7908 description: '', 7909 type: 'p5.Vector' 7910 }, 7911 { 7912 name: 'angle', 7913 description: '', 7914 type: 'Number', 7915 optional: true 7916 }, 7917 { 7918 name: 'conc', 7919 description: '', 7920 type: 'Number', 7921 optional: true 7922 } 7923 ] 7924 }, 7925 { 7926 params: [ 7927 { 7928 name: 'color', 7929 description: '', 7930 type: 'Number[]|String|p5.Color' 7931 }, 7932 { 7933 name: 'x', 7934 description: '', 7935 type: 'Number' 7936 }, 7937 { 7938 name: 'y', 7939 description: '', 7940 type: 'Number' 7941 }, 7942 { 7943 name: 'z', 7944 description: '', 7945 type: 'Number' 7946 }, 7947 { 7948 name: 'direction', 7949 description: '', 7950 type: 'p5.Vector' 7951 }, 7952 { 7953 name: 'angle', 7954 description: '', 7955 type: 'Number', 7956 optional: true 7957 }, 7958 { 7959 name: 'conc', 7960 description: '', 7961 type: 'Number', 7962 optional: true 7963 } 7964 ] 7965 }, 7966 { 7967 params: [ 7968 { 7969 name: 'color', 7970 description: '', 7971 type: 'Number[]|String|p5.Color' 7972 }, 7973 { 7974 name: 'position', 7975 description: '', 7976 type: 'p5.Vector' 7977 }, 7978 { 7979 name: 'rx', 7980 description: '', 7981 type: 'Number' 7982 }, 7983 { 7984 name: 'ry', 7985 description: '', 7986 type: 'Number' 7987 }, 7988 { 7989 name: 'rz', 7990 description: '', 7991 type: 'Number' 7992 }, 7993 { 7994 name: 'angle', 7995 description: '', 7996 type: 'Number', 7997 optional: true 7998 }, 7999 { 8000 name: 'conc', 8001 description: '', 8002 type: 'Number', 8003 optional: true 8004 } 8005 ] 8006 }, 8007 { 8008 params: [ 8009 { 8010 name: 'v1', 8011 description: '', 8012 type: 'Number' 8013 }, 8014 { 8015 name: 'v2', 8016 description: '', 8017 type: 'Number' 8018 }, 8019 { 8020 name: 'v3', 8021 description: '', 8022 type: 'Number' 8023 }, 8024 { 8025 name: 'x', 8026 description: '', 8027 type: 'Number' 8028 }, 8029 { 8030 name: 'y', 8031 description: '', 8032 type: 'Number' 8033 }, 8034 { 8035 name: 'z', 8036 description: '', 8037 type: 'Number' 8038 }, 8039 { 8040 name: 'direction', 8041 description: '', 8042 type: 'p5.Vector' 8043 }, 8044 { 8045 name: 'angle', 8046 description: '', 8047 type: 'Number', 8048 optional: true 8049 }, 8050 { 8051 name: 'conc', 8052 description: '', 8053 type: 'Number', 8054 optional: true 8055 } 8056 ] 8057 }, 8058 { 8059 params: [ 8060 { 8061 name: 'v1', 8062 description: '', 8063 type: 'Number' 8064 }, 8065 { 8066 name: 'v2', 8067 description: '', 8068 type: 'Number' 8069 }, 8070 { 8071 name: 'v3', 8072 description: '', 8073 type: 'Number' 8074 }, 8075 { 8076 name: 'position', 8077 description: '', 8078 type: 'p5.Vector' 8079 }, 8080 { 8081 name: 'rx', 8082 description: '', 8083 type: 'Number' 8084 }, 8085 { 8086 name: 'ry', 8087 description: '', 8088 type: 'Number' 8089 }, 8090 { 8091 name: 'rz', 8092 description: '', 8093 type: 'Number' 8094 }, 8095 { 8096 name: 'angle', 8097 description: '', 8098 type: 'Number', 8099 optional: true 8100 }, 8101 { 8102 name: 'conc', 8103 description: '', 8104 type: 'Number', 8105 optional: true 8106 } 8107 ] 8108 }, 8109 { 8110 params: [ 8111 { 8112 name: 'color', 8113 description: '', 8114 type: 'Number[]|String|p5.Color' 8115 }, 8116 { 8117 name: 'x', 8118 description: '', 8119 type: 'Number' 8120 }, 8121 { 8122 name: 'y', 8123 description: '', 8124 type: 'Number' 8125 }, 8126 { 8127 name: 'z', 8128 description: '', 8129 type: 'Number' 8130 }, 8131 { 8132 name: 'rx', 8133 description: '', 8134 type: 'Number' 8135 }, 8136 { 8137 name: 'ry', 8138 description: '', 8139 type: 'Number' 8140 }, 8141 { 8142 name: 'rz', 8143 description: '', 8144 type: 'Number' 8145 }, 8146 { 8147 name: 'angle', 8148 description: '', 8149 type: 'Number', 8150 optional: true 8151 }, 8152 { 8153 name: 'conc', 8154 description: '', 8155 type: 'Number', 8156 optional: true 8157 } 8158 ] 8159 } 8160 ] 8161 }, 8162 noLights: { 8163 name: 'noLights', 8164 class: 'p5', 8165 module: 'Lights, Camera' 8166 },
8167 loadModel: { 8168 name: 'loadModel', 8169 class: 'p5', 8170 module: 'Shape', 8171 overloads: [ 8172 { 8173 params: [ 8174 { 8175 name: 'path', 8176 description: '<p>Path of the model to be loaded</p>\n', 8177 type: 'String' 8178 }, 8179 { 8180 name: 'normalize', 8181 description: 8182 '<p>If true, scale the model to a\n standardized size when loading</p>\n', 8183 type: 'Boolean' 8184 }, 8185 { 8186 name: 'successCallback', 8187 description: 8188 '<p>Function to be called\n once the model is loaded. Will be passed\n the 3D model object.</p>\n', 8189 type: 'function(p5.Geometry)', 8190 optional: true 8191 }, 8192 { 8193 name: 'failureCallback', 8194 description: 8195 '<p>called with event error if\n the model fails to load.</p>\n', 8196 type: 'Function(Event)', 8197 optional: true 8198 }, 8199 { 8200 name: 'fileType', 8201 description: 8202 '<p>The file extension of the model\n (<code>.stl</code>, <code>.obj</code>).</p>\n', 8203 type: 'String', 8204 optional: true 8205 } 8206 ] 8207 }, 8208 { 8209 params: [ 8210 { 8211 name: 'path', 8212 description: '', 8213 type: 'String' 8214 }, 8215 { 8216 name: 'successCallback', 8217 description: '', 8218 type: 'function(p5.Geometry)', 8219 optional: true 8220 }, 8221 { 8222 name: 'failureCallback', 8223 description: '', 8224 type: 'Function(Event)', 8225 optional: true 8226 }, 8227 { 8228 name: 'fileType', 8229 description: '', 8230 type: 'String', 8231 optional: true 8232 } 8233 ] 8234 } 8235 ] 8236 }, 8237 model: { 8238 name: 'model', 8239 params: [ 8240 { 8241 name: 'model', 8242 description: '<p>Loaded 3d model to be rendered</p>\n', 8243 type: 'p5.Geometry' 8244 } 8245 ], 8246 class: 'p5', 8247 module: 'Shape' 8248 }, 8249 loadShader: { 8250 name: 'loadShader', 8251 params: [ 8252 { 8253 name: 'vertFilename', 8254 description: 8255 '<p>path to file containing vertex shader\nsource code</p>\n', 8256 type: 'String' 8257 }, 8258 { 8259 name: 'fragFilename', 8260 description: 8261 '<p>path to file containing fragment shader\nsource code</p>\n', 8262 type: 'String' 8263 }, 8264 { 8265 name: 'callback', 8266 description: 8267 '<p>callback to be executed after loadShader\ncompletes. On success, the Shader object is passed as the first argument.</p>\n', 8268 type: 'Function', 8269 optional: true 8270 }, 8271 { 8272 name: 'errorCallback', 8273 description: 8274 '<p>callback to be executed when an error\noccurs inside loadShader. On error, the error is passed as the first\nargument.</p>\n', 8275 type: 'Function', 8276 optional: true 8277 } 8278 ], 8279 class: 'p5', 8280 module: 'Lights, Camera' 8281 }, 8282 createShader: { 8283 name: 'createShader', 8284 params: [ 8285 { 8286 name: 'vertSrc', 8287 description: '<p>source code for the vertex shader</p>\n', 8288 type: 'String' 8289 }, 8290 { 8291 name: 'fragSrc', 8292 description: '<p>source code for the fragment shader</p>\n', 8293 type: 'String' 8294 } 8295 ], 8296 class: 'p5', 8297 module: 'Lights, Camera' 8298 }, 8299 shader: { 8300 name: 'shader', 8301 params: [ 8302 { 8303 name: 's', 8304 description: 8305 '<p>the desired <a href="#/p5.Shader">p5.Shader</a> to use for rendering\nshapes.</p>\n', 8306 type: 'p5.Shader', 8307 optional: true 8308 } 8309 ], 8310 class: 'p5', 8311 module: 'Lights, Camera' 8312 }, 8313 resetShader: { 8314 name: 'resetShader', 8315 class: 'p5', 8316 module: 'Lights, Camera' 8317 }, 8318 normalMaterial: { 8319 name: 'normalMaterial', 8320 class: 'p5', 8321 module: 'Lights, Camera' 8322 }, 8323 texture: { 8324 name: 'texture', 8325 params: [ 8326 { 8327 name: 'tex', 8328 description: 8329 '<p>2-dimensional graphics\n to render as texture</p>\n', 8330 type: 'p5.Image|p5.MediaElement|p5.Graphics' 8331 } 8332 ], 8333 class: 'p5', 8334 module: 'Lights, Camera' 8335 }, 8336 textureMode: { 8337 name: 'textureMode', 8338 params: [ 8339 { 8340 name: 'mode', 8341 description: '<p>either IMAGE or NORMAL</p>\n', 8342 type: 'Constant' 8343 } 8344 ], 8345 class: 'p5', 8346 module: 'Lights, Camera' 8347 }, 8348 textureWrap: { 8349 name: 'textureWrap', 8350 params: [ 8351 { 8352 name: 'wrapX', 8353 description: '<p>either CLAMP, REPEAT, or MIRROR</p>\n', 8354 type: 'Constant' 8355 }, 8356 { 8357 name: 'wrapY', 8358 description: '<p>either CLAMP, REPEAT, or MIRROR</p>\n', 8359 type: 'Constant', 8360 optional: true 8361 } 8362 ], 8363 class: 'p5', 8364 module: 'Lights, Camera' 8365 }, 8366 ambientMaterial: { 8367 name: 'ambientMaterial', 8368 class: 'p5', 8369 module: 'Lights, Camera', 8370 overloads: [ 8371 { 8372 params: [ 8373 { 8374 name: 'v1', 8375 description: 8376 '<p>gray value, red or hue value\n (depending on the current color mode),</p>\n', 8377 type: 'Number' 8378 }, 8379 { 8380 name: 'v2', 8381 description: '<p>green or saturation value</p>\n', 8382 type: 'Number', 8383 optional: true 8384 }, 8385 { 8386 name: 'v3', 8387 description: '<p>blue or brightness value</p>\n', 8388 type: 'Number', 8389 optional: true 8390 } 8391 ], 8392 chainable: 1 8393 }, 8394 { 8395 params: [ 8396 { 8397 name: 'color', 8398 description: '<p>color, color Array, or CSS color string</p>\n', 8399 type: 'Number[]|String|p5.Color' 8400 } 8401 ], 8402 chainable: 1 8403 } 8404 ] 8405 }, 8406 emissiveMaterial: { 8407 name: 'emissiveMaterial', 8408 class: 'p5', 8409 module: 'Lights, Camera', 8410 overloads: [ 8411 { 8412 params: [ 8413 { 8414 name: 'v1', 8415 description: 8416 '<p>gray value, red or hue value\n (depending on the current color mode),</p>\n', 8417 type: 'Number' 8418 }, 8419 { 8420 name: 'v2', 8421 description: '<p>green or saturation value</p>\n', 8422 type: 'Number', 8423 optional: true 8424 }, 8425 { 8426 name: 'v3', 8427 description: '<p>blue or brightness value</p>\n', 8428 type: 'Number', 8429 optional: true 8430 }, 8431 { 8432 name: 'a', 8433 description: '<p>opacity</p>\n', 8434 type: 'Number', 8435 optional: true 8436 } 8437 ], 8438 chainable: 1 8439 }, 8440 { 8441 params: [ 8442 { 8443 name: 'color', 8444 description: '<p>color, color Array, or CSS color string</p>\n', 8445 type: 'Number[]|String|p5.Color' 8446 } 8447 ], 8448 chainable: 1 8449 } 8450 ] 8451 }, 8452 specularMaterial: { 8453 name: 'specularMaterial', 8454 class: 'p5', 8455 module: 'Lights, Camera', 8456 overloads: [ 8457 { 8458 params: [ 8459 { 8460 name: 'gray', 8461 description: 8462 '<p>number specifying value between white and black.</p>\n', 8463 type: 'Number' 8464 }, 8465 { 8466 name: 'alpha', 8467 description: 8468 '<p>alpha value relative to current color range\n (default is 0-255)</p>\n', 8469 type: 'Number', 8470 optional: true 8471 } 8472 ], 8473 chainable: 1 8474 }, 8475 { 8476 params: [ 8477 { 8478 name: 'v1', 8479 description: 8480 '<p>red or hue value relative to\n the current color range</p>\n', 8481 type: 'Number' 8482 }, 8483 { 8484 name: 'v2', 8485 description: 8486 '<p>
8486green or saturation value\n relative to the current color range</p>\n', 8487 type: 'Number' 8488 }, 8489 { 8490 name: 'v3', 8491 description: 8492 '<p>blue or brightness value\n relative to the current color range</p>\n', 8493 type: 'Number' 8494 }, 8495 { 8496 name: 'alpha', 8497 description: '', 8498 type: 'Number', 8499 optional: true 8500 } 8501 ], 8502 chainable: 1 8503 }, 8504 { 8505 params: [ 8506 { 8507 name: 'color', 8508 description: '<p>color Array, or CSS color string</p>\n', 8509 type: 'Number[]|String|p5.Color' 8510 } 8511 ], 8512 chainable: 1 8513 } 8514 ] 8515 }, 8516 shininess: { 8517 name: 'shininess', 8518 params: [ 8519 { 8520 name: 'shine', 8521 description: 8522 '<p>Degree of Shininess.\n Defaults to 1.</p>\n', 8523 type: 'Number' 8524 } 8525 ], 8526 class: 'p5', 8527 module: 'Lights, Camera' 8528 }, 8529 camera: { 8530 name: 'camera', 8531 params: [ 8532 { 8533 name: 'x', 8534 description: '<p>camera position value on x axis</p>\n', 8535 type: 'Number', 8536 optional: true 8537 }, 8538 { 8539 name: 'y', 8540 description: '<p>camera position value on y axis</p>\n', 8541 type: 'Number', 8542 optional: true 8543 }, 8544 { 8545 name: 'z', 8546 description: '<p>camera position value on z axis</p>\n', 8547 type: 'Number', 8548 optional: true 8549 }, 8550 { 8551 name: 'centerX', 8552 description: '<p>x coordinate representing center of the sketch</p>\n', 8553 type: 'Number', 8554 optional: true 8555 }, 8556 { 8557 name: 'centerY', 8558 description: '<p>y coordinate representing center of the sketch</p>\n', 8559 type: 'Number', 8560 optional: true 8561 }, 8562 { 8563 name: 'centerZ', 8564 description: '<p>z coordinate representing center of the sketch</p>\n', 8565 type: 'Number', 8566 optional: true 8567 }, 8568 { 8569 name: 'upX', 8570 description: "<p>x component of direction 'up' from camera</p>\n", 8571 type: 'Number', 8572 optional: true 8573 }, 8574 { 8575 name: 'upY', 8576 description: "<p>y component of direction 'up' from camera</p>\n", 8577 type: 'Number', 8578 optional: true 8579 }, 8580 { 8581 name: 'upZ', 8582 description: "<p>z component of direction 'up' from camera</p>\n", 8583 type: 'Number', 8584 optional: true 8585 } 8586 ], 8587 class: 'p5', 8588 module: 'Lights, Camera' 8589 }, 8590 perspective: { 8591 name: 'perspective', 8592 params: [ 8593 { 8594 name: 'fovy', 8595 description: 8596 '<p>camera frustum vertical field of view,\n from bottom to top of view, in <a href="#/p5/angleMode">angleMode</a> units</p>\n', 8597 type: 'Number', 8598 optional: true 8599 }, 8600 { 8601 name: 'aspect', 8602 description: '<p>camera frustum aspect ratio</p>\n', 8603 type: 'Number', 8604 optional: true 8605 }, 8606 { 8607 name: 'near', 8608 description: '<p>frustum near plane length</p>\n', 8609 type: 'Number', 8610 optional: true 8611 }, 8612 { 8613 name: 'far', 8614 description: '<p>frustum far plane length</p>\n', 8615 type: 'Number', 8616 optional: true 8617 } 8618 ], 8619 class: 'p5', 8620 module: 'Lights, Camera' 8621 }, 8622 ortho: { 8623 name: 'ortho', 8624 params: [ 8625 { 8626 name: 'left', 8627 description: '<p>camera frustum left plane</p>\n', 8628 type: 'Number', 8629 optional: true 8630 }, 8631 { 8632 name: 'right', 8633 description: '<p>camera frustum right plane</p>\n', 8634 type: 'Number', 8635 optional: true 8636 }, 8637 { 8638 name: 'bottom', 8639 description: '<p>camera frustum bottom plane</p>\n', 8640 type: 'Number', 8641 optional: true 8642 }, 8643 { 8644 name: 'top', 8645 description: '<p>camera frustum top plane</p>\n', 8646 type: 'Number', 8647 optional: true 8648 }, 8649 { 8650 name: 'near', 8651 description: '<p>camera frustum near plane</p>\n', 8652 type: 'Number', 8653 optional: true 8654 }, 8655 { 8656 name: 'far', 8657 description: '<p>camera frustum far plane</p>\n', 8658 type: 'Number', 8659 optional: true 8660 } 8661 ], 8662 class: 'p5', 8663 module: 'Lights, Camera' 8664 }, 8665 frustum: { 8666 name: 'frustum', 8667 params: [ 8668 { 8669 name: 'left', 8670 description: '<p>camera frustum left plane</p>\n', 8671 type: 'Number', 8672 optional: true 8673 }, 8674 { 8675 name: 'right', 8676 description: '<p>camera frustum right plane</p>\n', 8677 type: 'Number', 8678 optional: true 8679 }, 8680 { 8681 name: 'bottom', 8682 description: '<p>camera frustum bottom plane</p>\n', 8683 type: 'Number', 8684 optional: true 8685 }, 8686 { 8687 name: 'top', 8688 description: '<p>camera frustum top plane</p>\n', 8689 type: 'Number', 8690 optional: true 8691 }, 8692 { 8693 name: 'near', 8694 description: '<p>camera frustum near plane</p>\n', 8695 type: 'Number', 8696 optional: true 8697 }, 8698 { 8699 name: 'far', 8700 description: '<p>camera frustum far plane</p>\n', 8701 type: 'Number', 8702 optional: true 8703 } 8704 ], 8705 class: 'p5', 8706 module: 'Lights, Camera' 8707 }, 8708 createCamera: { 8709 name: 'createCamera', 8710 class: 'p5', 8711 module: 'Lights, Camera' 8712 }, 8713 setCamera: { 8714 name: 'setCamera', 8715 params: [ 8716 { 8717 name: 'cam', 8718 description: '<p>p5.Camera object</p>\n', 8719 type: 'p5.Camera' 8720 } 8721 ], 8722 class: 'p5', 8723 module: 'Lights, Camera' 8724 }, 8725 setAttributes: { 8726 name: 'setAttributes', 8727 class: 'p5', 8728 module: 'Rendering', 8729 overloads: [ 8730 { 8731 params: [ 8732 { 8733 name: 'key', 8734 description: '<p>Name of attribute</p>\n', 8735 type: 'String' 8736 }, 8737 { 8738 name: 'value', 8739 description: '<p>New value of named attribute</p>\n', 8740 type: 'Boolean' 8741 } 8742 ] 8743 }, 8744 { 8745 params: [ 8746 { 8747 name: 'obj', 8748 description: '<p>object with key-value pairs</p>\n', 8749 type: 'Object' 8750 } 8751 ] 8752 } 8753 ] 8754 }, 8755 sampleRate: { 8756 name: 'sampleRate', 8757 class: 'p5', 8758 module: 'p5.sound' 8759 }, 8760 freqToMidi: { 8761 name: 'freqToMidi', 8762 params: [ 8763 { 8764 name: 'frequency', 8765 description: 8766 '<p>A freqeuncy, for example, the "A"\n above Middle C is 440Hz</p>\n', 8767 type: 'Number' 8768 } 8769 ], 8770 class: 'p5', 8771 module: 'p5.sound' 8772 }, 8773 midiToFreq: { 8774 name: 'midiToFreq', 8775 params: [ 8776 { 8777 name: 'midiNote', 8778 description: '<p>
8778The number of a MIDI note</p>\n', 8779 type: 'Number' 8780 } 8781 ], 8782 class: 'p5', 8783 module: 'p5.sound' 8784 }, 8785 soundFormats: { 8786 name: 'soundFormats', 8787 params: [ 8788 { 8789 name: 'formats', 8790 description: "<p>i.e. 'mp3', 'wav', 'ogg'</p>\n", 8791 type: 'String', 8792 optional: true, 8793 multiple: true 8794 } 8795 ], 8796 class: 'p5', 8797 module: 'p5.sound' 8798 }, 8799 getAudioContext: { 8800 name: 'getAudioContext', 8801 class: 'p5', 8802 module: 'p5.sound' 8803 }, 8804 userStartAudio: { 8805 params: [ 8806 { 8807 name: 'element(s)', 8808 description: 8809 '<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', 8810 type: 'Element|Array', 8811 optional: true 8812 }, 8813 { 8814 name: 'callback', 8815 description: 8816 '<p>Callback to invoke when the AudioContext\n has started</p>\n', 8817 type: 'Function', 8818 optional: true 8819 } 8820 ], 8821 name: 'userStartAudio', 8822 class: 'p5', 8823 module: 'p5.sound' 8824 }, 8825 loadSound: { 8826 name: 'loadSound', 8827 params: [ 8828 { 8829 name: 'path', 8830 description: 8831 "<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", 8832 type: 'String|Array' 8833 }, 8834 { 8835 name: 'successCallback', 8836 description: '<p>Name of a function to call once file loads</p>\n', 8837 type: 'Function', 8838 optional: true 8839 }, 8840 { 8841 name: 'errorCallback', 8842 description: 8843 '<p>Name of a function to call if there is\n an error loading the file.</p>\n', 8844 type: 'Function', 8845 optional: true 8846 }, 8847 { 8848 name: 'whileLoading', 8849 description: 8850 '<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', 8851 type: 'Function', 8852 optional: true 8853 } 8854 ], 8855 class: 'p5', 8856 module: 'p5.sound' 8857 }, 8858 createConvolver: { 8859 name: 'createConvolver', 8860 params: [ 8861 { 8862 name: 'path', 8863 description: '<p>path to a sound file</p>\n', 8864 type: 'String' 8865 }, 8866 { 8867 name: 'callback', 8868 description: 8869 '<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', 8870 type: 'Function', 8871 optional: true 8872 }, 8873 { 8874 name: 'errorCallback', 8875 description: 8876 '<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', 8877 type: 'Function', 8878 optional: true 8879 } 8880 ], 8881 class: 'p5', 8882 module: 'p5.sound' 8883 }, 8884 setBPM: { 8885 name: 'setBPM', 8886 params: [ 8887 { 8888 name: 'BPM', 8889 description: '<p>Beats Per Minute</p>\n', 8890 type: 'Number' 8891 }, 8892 { 8893 name: 'rampTime', 8894 description: '<p>Seconds from now</p>\n', 8895 type: 'Number' 8896 } 8897 ], 8898 class: 'p5', 8899 module: 'p5.sound' 8900 }, 8901 saveSound: { 8902 name: 'saveSound', 8903 params: [ 8904 { 8905 name: 'soundFile', 8906 description: '<p>
8906p5.SoundFile that you wish to save</p>\n', 8907 type: 'p5.SoundFile' 8908 }, 8909 { 8910 name: 'fileName', 8911 description: '<p>name of the resulting .wav file.</p>\n', 8912 type: 'String' 8913 } 8914 ], 8915 class: 'p5', 8916 module: 'p5.sound' 8917 } 8918 }, 8919 'p5.Color': { 8920 toString: { 8921 name: 'toString', 8922 params: [ 8923 { 8924 name: 'format', 8925 description: 8926 "<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", 8927 type: 'String', 8928 optional: true 8929 } 8930 ], 8931 class: 'p5.Color', 8932 module: 'Color' 8933 }, 8934 setRed: { 8935 name: 'setRed', 8936 params: [ 8937 { 8938 name: 'red', 8939 description: '<p>the new red value</p>\n', 8940 type: 'Number' 8941 } 8942 ], 8943 class: 'p5.Color', 8944 module: 'Color' 8945 }, 8946 setGreen: { 8947 name: 'setGreen', 8948 params: [ 8949 { 8950 name: 'green', 8951 description: '<p>the new green value</p>\n', 8952 type: 'Number' 8953 } 8954 ], 8955 class: 'p5.Color', 8956 module: 'Color' 8957 }, 8958 setBlue: { 8959 name: 'setBlue', 8960 params: [ 8961 { 8962 name: 'blue', 8963 description: '<p>the new blue value</p>\n', 8964 type: 'Number' 8965 } 8966 ], 8967 class: 'p5.Color', 8968 module: 'Color' 8969 }, 8970 setAlpha: { 8971 name: 'setAlpha', 8972 params: [ 8973 { 8974 name: 'alpha', 8975 description: '<p>the new alpha value</p>\n', 8976 type: 'Number' 8977 } 8978 ], 8979 class: 'p5.Color', 8980 module: 'Color' 8981 } 8982 }, 8983 'p5.Element': { 8984 elt: { 8985 name: 'elt', 8986 class: 'p5.Element', 8987 module: 'DOM' 8988 }, 8989 parent: { 8990 name: 'parent', 8991 class: 'p5.Element', 8992 module: 'DOM', 8993 overloads: [ 8994 { 8995 params: [ 8996 { 8997 name: 'parent', 8998 description: 8999 '<p>the ID, DOM node, or <a href="#/p5.Element">p5.Element</a>\n of desired parent element</p>\n', 9000 type: 'String|p5.Element|Object' 9001 } 9002 ], 9003 chainable: 1 9004 }, 9005 { 9006 params: [] 9007 } 9008 ] 9009 }, 9010 id: { 9011 name: 'id', 9012 class: 'p5.Element', 9013 module: 'DOM', 9014 overloads: [ 9015 { 9016 params: [ 9017 { 9018 name: 'id', 9019 description: '<p>ID of the element</p>\n', 9020 type: 'String' 9021 } 9022 ], 9023 chainable: 1 9024 }, 9025 { 9026 params: [] 9027 } 9028 ] 9029 }, 9030 class: { 9031 name: 'class', 9032 class: 'p5.Element', 9033 module: 'DOM', 9034 overloads: [ 9035 { 9036 params: [ 9037 { 9038 name: 'class', 9039 description: '<p>class to add</p>\n', 9040 type: 'String' 9041 } 9042 ], 9043 chainable: 1 9044 }, 9045 { 9046 params: [] 9047 } 9048 ] 9049 }, 9050 mousePressed: { 9051 name: 'mousePressed', 9052 params: [ 9053 { 9054 name: 'fxn', 9055 description: 9056 '<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', 9057 type: 'Function|Boolean' 9058 } 9059 ], 9060 class: 'p5.Element', 9061 module: 'DOM' 9062 }, 9063 doubleClicked: { 9064 name: 'doubleClicked', 9065 params: [ 9066 { 9067 name: 'fxn', 9068 description: 9069 '<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', 9070 type: 'Function|Boolean' 9071 } 9072 ], 9073 class: 'p5.Element', 9074 module: 'DOM' 9075 }, 9076 mouseWheel: { 9077 name: 'mouseWheel', 9078 params: [ 9079 { 9080 name: 'fxn', 9081 description: 9082 '<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', 9083 type: 'Function|Boolean' 9084 } 9085 ], 9086 class: 'p5.Element', 9087 module: 'DOM' 9088 }, 9089 mouseReleased: { 9090 name: 'mouseReleased', 9091 params: [ 9092 { 9093 name: 'fxn', 9094 description: 9095 '<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', 9096 type: 'Function|Boolean' 9097 } 9098 ], 9099 class: 'p5.Element', 9100 module: 'DOM' 9101 }, 9102 mouseClicked: { 9103 name: 'mouseClicked', 9104 params: [ 9105 { 9106 name: 'fxn', 9107 description: 9108 '<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', 9109 type: 'Function|Boolean' 9110 } 9111 ], 9112 class: 'p5.Element', 9113 module: 'DOM' 9114 }, 9115 mouseMoved: { 9116 name: 'mouseMoved', 9117 params: [ 9118 { 9119 name: 'fxn', 9120 description: 9121 '<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', 9122 type: 'Function|Boolean' 9123 } 9124 ], 9125 class: 'p5.Element', 9126 module: 'DOM' 9127 }, 9128 mouseOver: { 9129 name: 'mouseOver', 9130 params: [ 9131 { 9132 name: 'fxn', 9133 description: 9134 '<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', 9135 type: 'Function|Boolean' 9136 } 9137 ], 9138 class: 'p5.Element', 9139 module: 'DOM' 9140 }, 9141 mouseOut: { 9142 name: 'mouseOut', 9143 params: [ 9144 { 9145 name: 'fxn', 9146 description: 9147 '<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', 9148 type: 'Function|Boolean' 9149 } 9150 ], 9151 class: 'p5.Element', 9152 module: 'DOM' 9153 }, 9154 touchStarted: { 9155 name: 'touchStarted', 9156 params: [ 9157 { 9158 name: 'fxn', 9159 description: 9160 '<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', 9161 type: 'Function|Boolean' 9162 } 9163 ], 9164 class: 'p5.Element', 9165 module: 'DOM' 9166 }, 9167 touchMoved: { 9168 name: 'touchMoved', 9169 params: [ 9170 { 9171 name: 'fxn', 9172 description: 9173 '<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', 9174 type: 'Function|Boolean' 9175 } 9176 ], 9177 class: 'p5.Element', 9178 module: 'DOM' 9179 }, 9180 touchEnded: { 9181 name: 'touchEnded', 9182 params: [ 9183 { 9184 name: 'fxn', 9185 description: 9186 '<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', 9187 type: 'Function|Boolean' 9188 } 9189 ], 9190 class: 'p5.Element', 9191 module: 'DOM' 9192 }, 9193 dragOver: { 9194 name: 'dragOver', 9195 params: [ 9196 { 9197 name: 'fxn', 9198 description: 9199 '<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', 9200 type: 'Function|Boolean' 9201 } 9202 ], 9203 class: 'p5.Element', 9204 module: 'DOM' 9205 }, 9206 dragLeave: { 9207 name: 'dragLeave', 9208 params: [ 9209 { 9210 name: 'fxn', 9211 description: 9212 '<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', 9213 type: 'Function|Boolean' 9214 } 9215 ], 9216 class: 'p5.Element', 9217 module: 'DOM' 9218 }, 9219 addClass: { 9220 name: 'addClass', 9221 params: [ 9222 { 9223 name: 'class', 9224 description: '<p>name of class to add</p>\n', 9225 type: 'String' 9226 } 9227 ], 9228 class: 'p5.Element', 9229 module: 'DOM' 9230 }, 9231 removeClass: { 9232 name: 'removeClass', 9233 params: [ 9234 { 9235 name: 'class', 9236 description: '<p>name of class to remove</p>\n', 9237 type: 'String' 9238 } 9239 ], 9240 class: 'p5.Element', 9241 module: 'DOM' 9242 }, 9243 hasClass: { 9244 name: 'hasClass', 9245 params: [ 9246 { 9247 name: 'c', 9248 description: '<p>class name of class to check</p>\n', 9249 type: 'String' 9250 } 9251 ], 9252 class: 'p5.Element', 9253 module: 'DOM' 9254 }, 9255 toggleClass: { 9256 name: 'toggleClass', 9257 params: [ 9258 { 9259 name: 'c', 9260 description: '<p>class name to toggle</p>\n', 9261 type: 'String' 9262 } 9263 ], 9264 class: 'p5.Element', 9265 module: 'DOM' 9266 }, 9267 child: { 9268 name: 'child', 9269 class: 'p5.Element', 9270 module: 'DOM', 9271 overloads: [ 9272 { 9273 params: [] 9274 }, 9275 { 9276 params: [ 9277 { 9278 name: 'child', 9279 description: 9280 '<p>the ID, DOM node, or <a href="#/p5.Element">p5.Element</a>\n to add to the current element</p>\n', 9281 type: 'String|p5.Element', 9282 optional: true 9283 } 9284 ], 9285 chainable: 1 9286 } 9287 ] 9288 }, 9289 center: { 9290 name: 'center', 9291 params: [ 9292 { 9293 name: 'align', 9294 description: 9295 "<p>passing 'vertical', 'horizontal' aligns element accordingly</p>\n", 9296 type: 'String', 9297 optional: true 9298 } 9299 ], 9300 class: 'p5.Element', 9301 module: 'DOM' 9302 }, 9303 html: { 9304 name: 'html', 9305 class: 'p5.Element', 9306 module: 'DOM', 9307 overloads: [ 9308 { 9309 params: [] 9310 }, 9311 { 9312 params: [ 9313 { 9314 name: 'html', 9315 description: '<p>the HTML to be placed inside the element</p>\n', 9316 type: 'String', 9317 optional: true 9318 }, 9319 { 9320 name: 'append', 9321 description: '<p>whether to append HTML to existing</p>\n', 9322 type: 'Boolean', 9323 optional: true 9324 } 9325 ], 9326
9326 chainable: 1 9327 } 9328 ] 9329 }, 9330 position: { 9331 name: 'position', 9332 class: 'p5.Element', 9333 module: 'DOM', 9334 overloads: [ 9335 { 9336 params: [] 9337 }, 9338 { 9339 params: [ 9340 { 9341 name: 'x', 9342 description: 9343 '<p>x-position relative to upper left of window (optional)</p>\n', 9344 type: 'Number', 9345 optional: true 9346 }, 9347 { 9348 name: 'y', 9349 description: 9350 '<p>y-position relative to upper left of window (optional)</p>\n', 9351 type: 'Number', 9352 optional: true 9353 }, 9354 { 9355 name: 'positionType', 9356 description: 9357 '<p>it can be static, fixed, relative, sticky, initial or inherit (optional)</p>\n', 9358 type: 'String' 9359 } 9360 ], 9361 chainable: 1 9362 } 9363 ] 9364 }, 9365 style: { 9366 name: 'style', 9367 class: 'p5.Element', 9368 module: 'DOM', 9369 overloads: [ 9370 { 9371 params: [ 9372 { 9373 name: 'property', 9374 description: '<p>property to be set</p>\n', 9375 type: 'String' 9376 } 9377 ] 9378 }, 9379 { 9380 params: [ 9381 { 9382 name: 'property', 9383 description: '', 9384 type: 'String' 9385 }, 9386 { 9387 name: 'value', 9388 description: '<p>value to assign to property</p>\n', 9389 type: 'String|p5.Color' 9390 } 9391 ], 9392 chainable: 1 9393 } 9394 ] 9395 }, 9396 attribute: { 9397 name: 'attribute', 9398 class: 'p5.Element', 9399 module: 'DOM', 9400 overloads: [ 9401 { 9402 params: [] 9403 }, 9404 { 9405 params: [ 9406 { 9407 name: 'attr', 9408 description: '<p>attribute to set</p>\n', 9409 type: 'String' 9410 }, 9411 { 9412 name: 'value', 9413 description: '<p>value to assign to attribute</p>\n', 9414 type: 'String' 9415 } 9416 ], 9417 chainable: 1 9418 } 9419 ] 9420 }, 9421 removeAttribute: { 9422 name: 'removeAttribute', 9423 params: [ 9424 { 9425 name: 'attr', 9426 description: '<p>attribute to remove</p>\n', 9427 type: 'String' 9428 } 9429 ], 9430 class: 'p5.Element', 9431 module: 'DOM' 9432 }, 9433 value: { 9434 name: 'value', 9435 class: 'p5.Element', 9436 module: 'DOM', 9437 overloads: [ 9438 { 9439 params: [] 9440 }, 9441 { 9442 params: [ 9443 { 9444 name: 'value', 9445 description: '', 9446 type: 'String|Number' 9447 } 9448 ], 9449 chainable: 1 9450 } 9451 ] 9452 }, 9453 show: { 9454 name: 'show', 9455 class: 'p5.Element', 9456 module: 'DOM' 9457 }, 9458 hide: { 9459 name: 'hide', 9460 class: 'p5.Element', 9461 module: 'DOM' 9462 }, 9463 size: { 9464 name: 'size', 9465 class: 'p5.Element', 9466 module: 'DOM', 9467 overloads: [ 9468 { 9469 params: [] 9470 }, 9471 { 9472 params: [ 9473 { 9474 name: 'w', 9475 description: 9476 '<p>width of the element, either AUTO, or a number</p>\n', 9477 type: 'Number|Constant' 9478 }, 9479 { 9480 name: 'h', 9481 description: 9482 '<p>height of the element, either AUTO, or a number</p>\n', 9483 type: 'Number|Constant', 9484 optional: true 9485 } 9486 ], 9487 chainable: 1 9488 } 9489 ] 9490 }, 9491 remove: { 9492 name: 'remove', 9493 class: 'p5.Element', 9494 module: 'DOM' 9495 }, 9496 drop: { 9497 name: 'drop', 9498 params: [ 9499 { 9500 name: 'callback', 9501 description: 9502 '<p>callback to receive loaded file, called for each file dropped.</p>\n', 9503 type: 'Function' 9504 }, 9505 { 9506 name: 'fxn', 9507 description: 9508 '<p>callback triggered once when files are dropped with the drop event.</p>\n', 9509 type: 'Function', 9510 optional: true 9511 } 9512 ], 9513 class: 'p5.Element', 9514 module: 'DOM' 9515 } 9516 }, 9517 'p5.Graphics': { 9518 reset: { 9519 name: 'reset', 9520 class: 'p5.Graphics', 9521 module: 'Rendering' 9522 }, 9523 remove: { 9524 name: 'remove', 9525 class: 'p5.Graphics', 9526 module: 'Rendering' 9527 } 9528 }, 9529 JSON: {
9530 stringify: { 9531 name: 'stringify', 9532 params: [ 9533 { 9534 name: 'object', 9535 description: 9536 '<p>:Javascript object that you would like to convert to JSON</p>\n', 9537 type: 'Object' 9538 } 9539 ], 9540 class: 'JSON', 9541 module: 'Foundation' 9542 } 9543 }, 9544 console: { 9545 log: { 9546 name: 'log', 9547 params: [ 9548 { 9549 name: 'message', 9550 description: 9551 '<p>:Message that you would like to print to the console</p>\n', 9552 type: 'String|Expression|Object' 9553 } 9554 ], 9555 class: 'console', 9556 module: 'Foundation' 9557 } 9558 }, 9559 'p5.TypedDict': { 9560 size: { 9561 name: 'size', 9562 class: 'p5.TypedDict', 9563 module: 'Data' 9564 }, 9565 hasKey: { 9566 name: 'hasKey', 9567 params: [ 9568 { 9569 name: 'key', 9570 description: '<p>that you want to look up</p>\n', 9571 type: 'Number|String' 9572 } 9573 ], 9574 class: 'p5.TypedDict', 9575 module: 'Data' 9576 }, 9577 get: { 9578 name: 'get', 9579 params: [ 9580 { 9581 name: 'the', 9582 description: '<p>key you want to access</p>\n', 9583 type: 'Number|String' 9584 } 9585 ], 9586 class: 'p5.TypedDict', 9587 module: 'Data' 9588 }, 9589 set: { 9590 name: 'set', 9591 params: [ 9592 { 9593 name: 'key', 9594 description: '', 9595 type: 'Number|String' 9596 }, 9597 { 9598 name: 'value', 9599 description: '', 9600 type: 'Number|String' 9601 } 9602 ], 9603 class: 'p5.TypedDict', 9604 module: 'Data' 9605 }, 9606 create: { 9607 name: 'create', 9608 class: 'p5.TypedDict', 9609 module: 'Data', 9610 overloads: [ 9611 { 9612 params: [ 9613 { 9614 name: 'key', 9615 description: '', 9616 type: 'Number|String' 9617 }, 9618 { 9619 name: 'value', 9620 description: '', 9621 type: 'Number|String' 9622 } 9623 ] 9624 }, 9625 { 9626 params: [ 9627 { 9628 name: 'obj', 9629 description: '<p>key/value pair</p>\n', 9630 type: 'Object' 9631 } 9632 ] 9633 } 9634 ] 9635 }, 9636 clear: { 9637 name: 'clear', 9638 class: 'p5.TypedDict', 9639 module: 'Data' 9640 }, 9641 remove: { 9642 name: 'remove', 9643 params: [ 9644 { 9645 name: 'key', 9646 description: '<p>for the pair to remove</p>\n', 9647 type: 'Number|String' 9648 } 9649 ], 9650 class: 'p5.TypedDict', 9651 module: 'Data' 9652 }, 9653 print: { 9654 name: 'print', 9655 class: 'p5.TypedDict', 9656 module: 'Data' 9657 }, 9658 saveTable: { 9659 name: 'saveTable', 9660 class: 'p5.TypedDict', 9661 module: 'Data' 9662 }, 9663 saveJSON: { 9664 name: 'saveJSON', 9665 class: 'p5.TypedDict', 9666 module: 'Data' 9667 } 9668 }, 9669 'p5.NumberDict': { 9670 add: { 9671 name: 'add', 9672 params: [ 9673 { 9674 name: 'Key', 9675 description: '<p>for the value you wish to add to</p>\n', 9676 type: 'Number' 9677 }, 9678 { 9679 name: 'Number', 9680 description: '<p>to add to the value</p>\n', 9681 type: 'Number' 9682 } 9683 ], 9684 class: 'p5.NumberDict', 9685 module: 'Data' 9686 }, 9687 sub: { 9688 name: 'sub', 9689 params: [ 9690 { 9691 name: 'Key', 9692 description: '<p>
9692for the value you wish to subtract from</p>\n', 9693 type: 'Number' 9694 }, 9695 { 9696 name: 'Number', 9697 description: '<p>to subtract from the value</p>\n', 9698 type: 'Number' 9699 } 9700 ], 9701 class: 'p5.NumberDict', 9702 module: 'Data' 9703 }, 9704 mult: { 9705 name: 'mult', 9706 params: [ 9707 { 9708 name: 'Key', 9709 description: '<p>for value you wish to multiply</p>\n', 9710 type: 'Number' 9711 }, 9712 { 9713 name: 'Amount', 9714 description: '<p>to multiply the value by</p>\n', 9715 type: 'Number' 9716 } 9717 ], 9718 class: 'p5.NumberDict', 9719 module: 'Data' 9720 }, 9721 div: { 9722 name: 'div', 9723 params: [ 9724 { 9725 name: 'Key', 9726 description: '<p>for value you wish to divide</p>\n', 9727 type: 'Number' 9728 }, 9729 { 9730 name: 'Amount', 9731 description: '<p>to divide the value by</p>\n', 9732 type: 'Number' 9733 } 9734 ], 9735 class: 'p5.NumberDict', 9736 module: 'Data' 9737 }, 9738 minValue: { 9739 name: 'minValue', 9740 class: 'p5.NumberDict', 9741 module: 'Data' 9742 }, 9743 maxValue: { 9744 name: 'maxValue', 9745 class: 'p5.NumberDict', 9746 module: 'Data' 9747 }, 9748 minKey: { 9749 name: 'minKey', 9750 class: 'p5.NumberDict', 9751 module: 'Data' 9752 }, 9753 maxKey: { 9754 name: 'maxKey', 9755 class: 'p5.NumberDict', 9756 module: 'Data' 9757 } 9758 }, 9759 'p5.MediaElement': { 9760 src: { 9761 name: 'src', 9762 class: 'p5.MediaElement', 9763 module: 'DOM' 9764 }, 9765 play: { 9766 name: 'play', 9767 class: 'p5.MediaElement', 9768 module: 'DOM' 9769 }, 9770 stop: { 9771 name: 'stop', 9772 class: 'p5.MediaElement', 9773 module: 'DOM' 9774 }, 9775 pause: { 9776 name: 'pause', 9777 class: 'p5.MediaElement', 9778 module: 'DOM' 9779 }, 9780 loop: { 9781 name: 'loop', 9782 class: 'p5.MediaElement', 9783 module: 'DOM' 9784 }, 9785 noLoop: { 9786 name: 'noLoop', 9787 class: 'p5.MediaElement', 9788 module: 'DOM' 9789 }, 9790 autoplay: { 9791 name: 'autoplay', 9792 params: [ 9793 { 9794 name: 'shouldAutoplay', 9795 description: '<p>whether the element should autoplay</p>\n', 9796 type: 'Boolean' 9797 } 9798 ], 9799 class: 'p5.MediaElement', 9800 module: 'DOM' 9801 }, 9802 volume: { 9803 name: 'volume', 9804 class: 'p5.MediaElement', 9805 module: 'DOM', 9806 overloads: [ 9807 { 9808 params: [] 9809 }, 9810 { 9811 params: [ 9812 { 9813 name: 'val', 9814 description: '<p>volume between 0.0 and 1.0</p>\n', 9815 type: 'Number' 9816 } 9817 ], 9818 chainable: 1 9819 } 9820 ] 9821 }, 9822 speed: { 9823 name: 'speed', 9824 class: 'p5.MediaElement', 9825 module: 'DOM', 9826 overloads: [ 9827 { 9828 params: [] 9829 }, 9830 { 9831 params: [ 9832 { 9833 name: 'speed', 9834 description: '<p>speed multiplier for element playback</p>\n', 9835 type: 'Number' 9836 } 9837 ], 9838 chainable: 1 9839 } 9840 ] 9841 }, 9842 time: { 9843 name: 'time', 9844 class: 'p5.MediaElement', 9845 module: 'DOM', 9846 overloads: [ 9847 { 9848 params: [] 9849 }, 9850 { 9851 params: [ 9852 { 9853 name: 'time', 9854 description: '<p>time to jump to (in seconds)</p>\n', 9855 type: 'Number' 9856 } 9857 ], 9858 chainable: 1 9859 } 9860 ] 9861 }, 9862 duration: { 9863 name: 'duration', 9864 class: 'p5.MediaElement', 9865 module: 'DOM' 9866 }, 9867 onended: { 9868 name: 'onended', 9869 params: [ 9870 { 9871 name: 'callback', 9872 description: 9873 '<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', 9874 type: 'Function' 9875 } 9876 ], 9877 class: 'p5.MediaElement', 9878 module: 'DOM' 9879 }, 9880 connect: { 9881 name: 'connect', 9882 params: [ 9883 { 9884 name: 'audioNode', 9885 description: 9886 '<p>AudioNode from the Web Audio API,\nor an object from the p5.sound library</p>\n', 9887 type: 'AudioNode|Object' 9888 } 9889 ], 9890 class: 'p5.MediaElement', 9891 module: 'DOM' 9892 }, 9893 disconnect: { 9894 name: 'disconnect', 9895 class: 'p5.MediaElement', 9896 module: 'DOM' 9897 }, 9898 showControls: { 9899 name: 'showControls', 9900 class: 'p5.MediaElement', 9901 module: 'DOM' 9902 }, 9903 hideControls: { 9904 name: 'hideControls', 9905 class: 'p5.MediaElement', 9906 module: 'DOM' 9907 }, 9908 addCue: { 9909 name: 'addCue', 9910 params: [ 9911 { 9912 name: 'time', 9913 description: 9914 "<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", 9915 type: 'Number' 9916 }, 9917 { 9918 name: 'callback', 9919 description: 9920 '<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', 9921 type: 'Function' 9922 }, 9923 { 9924 name: 'value', 9925 description: 9926 '<p>An object to be passed as the\n second parameter to the\n callback function.</p>\n', 9927 type: 'Object', 9928 optional: true 9929 } 9930 ], 9931 class: 'p5.MediaElement', 9932 module: 'DOM' 9933 }, 9934 removeCue: { 9935 name: 'removeCue', 9936 params: [ 9937 { 9938 name: 'id', 9939 description: '<p>ID of the cue, as returned by addCue</p>\n', 9940 type: 'Number' 9941 } 9942 ], 9943 class: 'p5.MediaElement', 9944 module: 'DOM' 9945 }, 9946 clearCues: { 9947 name: 'clearCues', 9948 params: [ 9949 { 9950 name: 'id', 9951 description: '<p>ID of the cue, as returned by addCue</p>\n', 9952 type: 'Number' 9953 } 9954 ], 9955 class: 'p5.MediaElement', 9956 module: 'DOM' 9957 } 9958 }, 9959 'p5.File': { 9960 file: { 9961 name: 'file', 9962 class: 'p5.File', 9963 module: 'DOM' 9964 }, 9965 type: { 9966 name: 'type', 9967 class: 'p5.File', 9968 module: 'DOM' 9969 }, 9970 subtype: { 9971 name: 'subtype', 9972 class: 'p5.File', 9973 module: 'DOM' 9974 }, 9975 name: { 9976 name: 'name', 9977 class: 'p5.File', 9978 module: 'DOM' 9979 }, 9980 size: { 9981 name: 'size', 9982 class: 'p5.File', 9983 module: 'DOM' 9984 }, 9985 data: { 9986 name: 'data', 9987 class: 'p5.File', 9988 module: 'DOM' 9989 } 9990 }, 9991 'p5.Image': { 9992 width: { 9993 name: 'width', 9994 class: 'p5.Image', 9995 module: 'Image' 9996 }, 9997 height: { 9998 name: 'height', 9999 class: 'p5.Image', 10000 module: 'Image' 10001 }, 10002 pixels: { 10003 name: 'pixels', 10004 class: 'p5.Image', 10005 module: 'Image' 10006 }, 10007 loadPixels: { 10008 name: 'loadPixels', 10009 class: 'p5.Image', 10010 module: 'Image' 10011 }, 10012 updatePixels: { 10013 name: 'updatePixels', 10014 class: 'p5.Image', 10015 module: 'Image', 10016 overloads: [ 10017 { 10018 params: [ 10019 { 10020 name: 'x', 10021 description: 10022 '<p>x-offset of the target update area for the\n underlying canvas</p>\n', 10023 type: 'Integer' 10024 }, 10025 { 10026 name: 'y', 10027 description: 10028 '<p>y-offset of the target update area for the\n underlying canvas</p>\n', 10029 type: 'Integer' 10030 }, 10031 { 10032 name: 'w', 10033 description: 10034 '<p>height of the target update area for the\n underlying canvas</p>\n', 10035 type: 'Integer' 10036 }, 10037 { 10038 name: 'h', 10039 description: 10040 '<p>height of the target update area for the\n underlying canvas</p>\n', 10041 type: 'Integer' 10042 } 10043 ] 10044 }, 10045 { 10046 params: [] 10047 } 10048 ] 10049 }, 10050 get: { 10051 name: 'get', 10052 class: 'p5.Image', 10053 module: 'Image', 10054 overloads: [ 10055 { 10056 params: [ 10057 { 10058 name: 'x', 10059 description: '<p>x-coordinate of the pixel</p>\n', 10060 type: 'Number' 10061 }, 10062 { 10063 name: 'y', 10064 description: '<p>y-coordinate of the pixel</p>\n', 10065 type: 'Number' 10066 }, 10067 { 10068 name: 'w', 10069 description: '<p>width</p>\n', 10070 type: 'Number' 10071 }, 10072 { 10073 name: 'h', 10074 description: '<p>height</p>\n', 10075 type: 'Number' 10076 } 10077 ] 10078 }, 10079 { 10080 params: [] 10081 }, 10082 { 10083 params: [ 10084 { 10085 name: 'x', 10086 description: '', 10087 type: 'Number' 10088 }, 10089 { 10090 name: 'y', 10091 description: '', 10092 type: 'Number' 10093 } 10094 ] 10095 } 10096 ] 10097 }, 10098 set: { 10099 name: 'set', 10100 params: [ 10101 { 10102 name: 'x', 10103 description: '<p>x-coordinate of the pixel</p>\n', 10104 type: 'Number' 10105 }, 10106 { 10107 name: 'y', 10108 description: '<p>y-coordinate of the pixel</p>\n', 10109 type: 'Number' 10110 }, 10111 { 10112 name: 'a', 10113 description: 10114 '<p>grayscale value | pixel array |\n a <a href="#/p5.Color">p5.Color</a> | image to copy</p>\n', 10115 type: 'Number|Number[]|Object' 10116 } 10117 ], 10118 class: 'p5.Image', 10119 module: 'Image' 10120 }, 10121 resize: { 10122 name: 'resize', 10123 params: [ 10124 { 10125 name: 'width', 10126 description: '<p>the resized image width</p>\n', 10127 type: 'Number' 10128 }, 10129 { 10130 name: 'height', 10131 description: '<p>the resized image height</p>\n', 10132 type: 'Number' 10133 } 10134 ], 10135 class: 'p5.Image', 10136 module: 'Image' 10137 }, 10138 copy: { 10139 name: 'copy', 10140 class: 'p5.Image', 10141 module: 'Image', 10142 overloads: [ 10143 { 10144 params: [ 10145 { 10146 name: 'srcImage', 10147 description: '<p>source image</p>\n', 10148 type: 'p5.Image|p5.Element' 10149 }, 10150 { 10151 name: 'sx', 10152 description: 10153 "<p>X coordinate of the source's upper left corner</p>\n", 10154 type: 'Integer' 10155 }, 10156 { 10157 name: 'sy', 10158 description: 10159 "<p>Y coordinate of the source's upper left corner</p>\n", 10160 type: 'Integer' 10161 }, 10162 { 10163 name: 'sw', 10164 description: '<p>source image width</p>\n', 10165 type: 'Integer' 10166 }, 10167 { 10168 name: 'sh', 10169 description: '<p>source image height</p>\n', 10170 type: 'Integer' 10171 }, 10172 { 10173 name: 'dx', 10174 description: 10175 "<p>X coordinate of
10175the destination's upper left corner</p>\n", 10176 type: 'Integer' 10177 }, 10178 { 10179 name: 'dy', 10180 description: 10181 "<p>Y coordinate of the destination's upper left corner</p>\n", 10182 type: 'Integer' 10183 }, 10184 { 10185 name: 'dw', 10186 description: '<p>destination image width</p>\n', 10187 type: 'Integer' 10188 }, 10189 { 10190 name: 'dh', 10191 description: '<p>destination image height</p>\n', 10192 type: 'Integer' 10193 } 10194 ] 10195 }, 10196 { 10197 params: [ 10198 { 10199 name: 'sx', 10200 description: '', 10201 type: 'Integer' 10202 }, 10203 { 10204 name: 'sy', 10205 description: '', 10206 type: 'Integer' 10207 }, 10208 { 10209 name: 'sw', 10210 description: '', 10211 type: 'Integer' 10212 }, 10213 { 10214 name: 'sh', 10215 description: '', 10216 type: 'Integer' 10217 }, 10218 { 10219 name: 'dx', 10220 description: '', 10221 type: 'Integer' 10222 }, 10223 { 10224 name: 'dy', 10225 description: '', 10226 type: 'Integer' 10227 }, 10228 { 10229 name: 'dw', 10230 description: '', 10231 type: 'Integer' 10232 }, 10233 { 10234 name: 'dh', 10235 description: '', 10236 type: 'Integer' 10237 } 10238 ] 10239 } 10240 ] 10241 }, 10242 mask: { 10243 name: 'mask', 10244 params: [ 10245 { 10246 name: 'srcImage', 10247 description: '<p>source image</p>\n', 10248 type: 'p5.Image' 10249 } 10250 ], 10251 class: 'p5.Image', 10252 module: 'Image' 10253 }, 10254 filter: { 10255 name: 'filter', 10256 params: [ 10257 { 10258 name: 'filterType', 10259 description: 10260 '<p>either THRESHOLD, GRAY, OPAQUE, INVERT,\n POSTERIZE, ERODE, DILATE or BLUR.\n See Filters.js for docs on\n each available filter</p>\n', 10261 type: 'Constant' 10262 }, 10263 { 10264 name: 'filterParam', 10265 description: 10266 '<p>an optional parameter unique\n to each filter, see above</p>\n', 10267 type: 'Number', 10268 optional: true 10269 } 10270 ], 10271 class: 'p5.Image', 10272 module: 'Image' 10273 }, 10274 blend: { 10275 name: 'blend', 10276 class: 'p5.Image', 10277 module: 'Image', 10278 overloads: [ 10279 { 10280 params: [ 10281 { 10282 name: 'srcImage', 10283 description: '<p>source image</p>\n', 10284 type: 'p5.Image' 10285 }, 10286 { 10287 name: 'sx', 10288 description: 10289 "<p>X coordinate of the source's upper left corner</p>\n", 10290 type: 'Integer' 10291 }, 10292 { 10293 name: 'sy', 10294 description: 10295 "<p>Y coordinate of the source's upper left corner</p>\n", 10296 type: 'Integer' 10297 }, 10298 { 10299 name: 'sw', 10300 description: '<p>source image width</p>\n', 10301 type: 'Integer' 10302 }, 10303 { 10304 name: 'sh', 10305 description: '<p>source image height</p>\n', 10306 type: 'Integer' 10307 }, 10308 { 10309 name: 'dx', 10310 description: 10311 "<p>X coordinate of the destination's upper left corner</p>\n", 10312 type: 'Integer' 10313 }, 10314 { 10315 name: 'dy', 10316 description: 10317 "<p>Y coordinate of the destination's upper left corner</p>\n", 10318 type: 'Integer' 10319 }, 10320 { 10321 name: 'dw', 10322 description: '<p>destination image width</p>\n', 10323 type: 'Integer' 10324 }, 10325 { 10326 name: 'dh', 10327 description: '<p>destination image height</p>\n', 10328 type: 'Integer' 10329 }, 10330 { 10331 name: 'blendMode', 10332 description: 10333 '<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', 10334 type: 'Constant' 10335 } 10336 ] 10337 }, 10338 { 10339 params: [ 10340 { 10341 name: 'sx', 10342 description: '', 10343 type: 'Integer' 10344 }, 10345 { 10346 name: 'sy', 10347 description: '', 10348 type: 'Integer' 10349 }, 10350 { 10351 name: 'sw', 10352 description: '', 10353 type: 'Integer' 10354 }, 10355 { 10356 name: 'sh', 10357 description: '', 10358 type: 'Integer' 10359 }, 10360 { 10361 name: 'dx', 10362 description: '', 10363 type: 'Integer' 10364 }, 10365 { 10366 name: 'dy', 10367 description: '', 10368 type: 'Integer' 10369 }, 10370 { 10371 name: 'dw', 10372 description: '', 10373 type: 'Integer' 10374 }, 10375 { 10376 name: 'dh', 10377 description: '', 10378 type: 'Integer' 10379 }, 10380 { 10381 name: 'blendMode', 10382 description: '', 10383 type: 'Constant' 10384 } 10385 ] 10386 } 10387 ] 10388 }, 10389 save: { 10390 name: 'save', 10391 params: [ 10392 { 10393 name: 'filename', 10394 description: '<p>give your file a name</p>\n', 10395 type: 'String' 10396 }, 10397 { 10398 name: 'extension', 10399 description: "<p>'png' or 'jpg'</p>\n", 10400 type: 'String' 10401 } 10402 ], 10403 class: 'p5.Image', 10404 module: 'Image' 10405 }, 10406 reset: { 10407 name: 'reset', 10408 class: 'p5.Image', 10409 module: 'Image' 10410 }, 10411 getCurrentFrame: { 10412 name: 'getCurrentFrame', 10413 class: 'p5.Image', 10414 module: 'Image' 10415 }, 10416 setFrame: { 10417 name: 'setFrame', 10418 params: [ 10419 { 10420 name: 'index', 10421 description: 10422 '<p>the index for the frame that should be displayed</p>\n', 10423 type: 'Number' 10424 } 10425 ], 10426 class: 'p5.Image', 10427 module: 'Image' 10428 }, 10429 numFrames: { 10430 name: 'numFrames', 10431 class: 'p5.Image', 10432 module: 'Image' 10433 }, 10434 play: { 10435 name: 'play', 10436 class: 'p5.Image', 10437 module: 'Image' 10438 }, 10439 pause: { 10440 name: 'pause', 10441 class: 'p5.Image', 10442 module: 'Image' 10443 }, 10444 delay: { 10445 name: 'delay', 10446 params: [ 10447 { 10448 name: 'd', 10449 description: 10450 '<p>the amount in milliseconds to delay between switching frames</p>\n', 10451 type: 'Number' 10452 }, 10453 { 10454 name: 'index', 10455 description: 10456 '<p>the index of the frame that should have the new delay value {optional}</p>\n', 10457 type: 'Number', 10458 optional: true 10459 } 10460 ], 10461 class: 'p5.Image', 10462 module: 'Image' 10463 } 10464 }, 10465 'p5.PrintWriter': { 10466 write: { 10467 name: 'write', 10468 params: [ 10469 { 10470 name: 'data', 10471 description: '<p>all data to be written by the PrintWriter</p>\n', 10472 type: 'Array' 10473 } 10474 ], 10475 class: 'p5.PrintWriter', 10476 module: 'IO' 10477 }, 10478 print: { 10479 name: 'print', 10480 params: [ 10481 { 10482 name: 'data', 10483 description: '<p>all data to be printed by the PrintWriter</p>\n', 10484 type: 'Array' 10485 } 10486 ], 10487 class: 'p5.PrintWriter', 10488 module: 'IO' 10489 }, 10490 clear: { 10491 name: 'clear', 10492 class: 'p5.PrintWriter', 10493 module: 'IO' 10494 }, 10495 close: { 10496 name: 'close', 10497 class: 'p5.PrintWriter', 10498 module: 'IO' 10499 } 10500 }, 10501 'p5.Table': { 10502 columns: { 10503 name: 'columns', 10504 class: 'p5.Table', 10505 module: 'IO' 10506 }, 10507 rows: { 10508 name: 'rows', 10509 class: 'p5.Table', 10510 module: 'IO' 10511 }, 10512 addRow: { 10513 name: 'addRow', 10514 params: [ 10515 { 10516 name: 'row', 10517 description: '<p>row to be added to the table</p>\n', 10518 type: 'p5.TableRow', 10519 optional: true 10520 } 10521 ], 10522 class: 'p5.Table', 10523 module: 'IO' 10524 }, 10525 removeRow: { 10526 name: 'removeRow', 10527 params: [ 10528 { 10529 name: 'id', 10530 description: '<p>ID number of the row to remove</p>\n', 10531 type: 'Integer' 10532 } 10533 ], 10534 class: 'p5.Table', 10535 module: 'IO' 10536 }, 10537 getRow: { 10538 name: 'getRow', 10539 params: [ 10540 { 10541 name: 'rowID', 10542 description: '<p>ID number of the row to get</p>\n', 10543 type: 'Integer' 10544 } 10545 ], 10546 class: 'p5.Table', 10547 module: 'IO' 10548 }, 10549 getRows: { 10550 name: 'getRows', 10551 class: 'p5.Table', 10552 module: 'IO' 10553 }, 10554 findRow: { 10555 name: 'findRow', 10556 params: [ 10557 { 10558 name: 'value', 10559 description: '<p>The value to match</p>\n', 10560 type: 'String' 10561 }, 10562 { 10563 name: 'column', 10564 description: 10565 '<p>ID number or title of the\n column to search</p>\n', 10566 type: 'Integer|String' 10567 } 10568 ], 10569 class: 'p5.Table', 10570 module: 'IO' 10571 }, 10572 findRows: { 10573 name: 'findRows', 10574 params: [ 10575 { 10576 name: 'value', 10577 description: '<p>The value to match</p>\n', 10578 type: 'String' 10579 }, 10580 { 10581 name: 'column', 10582 description: 10583 '<p>ID number or title of the\n column to search</p>\n', 10584 type: 'Integer|String' 10585 } 10586 ], 10587 class: 'p5.Table', 10588 module: 'IO' 10589 }, 10590 matchRow: { 10591 name: 'matchRow', 10592 params: [ 10593 { 10594 name: 'regexp', 10595 description: '<p>The regular expression to match</p>\n', 10596 type: 'String|RegExp' 10597 }, 10598 { 10599 name: 'column', 10600 description: 10601 '<p>The column ID (number) or\n title (string)</p>\n', 10602 type: 'String|Integer' 10603 } 10604 ], 10605 class: 'p5.Table', 10606 module: 'IO' 10607 }, 10608 matchRows: { 10609 name: 'matchRows', 10610 params: [ 10611 { 10612 name: 'regexp', 10613 description: '<p>The regular expression to match</p>\n', 10614 type: 'String' 10615 }, 10616 { 10617 name: 'column', 10618 description: 10619 '<p>The column ID (number) or\n title (string)</p>\n', 10620 type: 'String|Integer', 10621 optional: true 10622 } 10623 ], 10624 class: 'p5.Table', 10625 module: 'IO' 10626 }, 10627 getColumn: { 10628 name: 'getColumn', 10629 params: [ 10630 { 10631 name: 'column', 10632 description: '<p>String or Number of the column to return</p>\n', 10633 type: 'String|Number' 10634 } 10635 ], 10636 class: 'p5.Table', 10637 module: 'IO' 10638 }, 10639 clearRows: { 10640 name: 'clearRows', 10641 class: 'p5.Table', 10642 module: 'IO' 10643 }, 10644 addColumn: { 10645 name: 'addColumn', 10646 params: [
10646 10647 { 10648 name: 'title', 10649 description: '<p>title of the given column</p>\n', 10650 type: 'String', 10651 optional: true 10652 } 10653 ], 10654 class: 'p5.Table', 10655 module: 'IO' 10656 }, 10657 getColumnCount: { 10658 name: 'getColumnCount', 10659 class: 'p5.Table', 10660 module: 'IO' 10661 }, 10662 getRowCount: { 10663 name: 'getRowCount', 10664 class: 'p5.Table', 10665 module: 'IO' 10666 }, 10667 removeTokens: { 10668 name: 'removeTokens', 10669 params: [ 10670 { 10671 name: 'chars', 10672 description: '<p>String listing characters to be removed</p>\n', 10673 type: 'String' 10674 }, 10675 { 10676 name: 'column', 10677 description: 10678 '<p>Column ID (number)\n or name (string)</p>\n', 10679 type: 'String|Integer', 10680 optional: true 10681 } 10682 ], 10683 class: 'p5.Table', 10684 module: 'IO' 10685 }, 10686 trim: { 10687 name: 'trim', 10688 params: [ 10689 { 10690 name: 'column', 10691 description: 10692 '<p>Column ID (number)\n or name (string)</p>\n', 10693 type: 'String|Integer', 10694 optional: true 10695 } 10696 ], 10697 class: 'p5.Table', 10698 module: 'IO' 10699 }, 10700 removeColumn: { 10701 name: 'removeColumn', 10702 params: [ 10703 { 10704 name: 'column', 10705 description: '<p>columnName (string) or ID (number)</p>\n', 10706 type: 'String|Integer' 10707 } 10708 ], 10709 class: 'p5.Table', 10710 module: 'IO' 10711 }, 10712 set: { 10713 name: 'set', 10714 params: [ 10715 { 10716 name: 'row', 10717 description: '<p>row ID</p>\n', 10718 type: 'Integer' 10719 }, 10720 { 10721 name: 'column', 10722 description: 10723 '<p>column ID (Number)\n or title (String)</p>\n', 10724 type: 'String|Integer' 10725 }, 10726 { 10727 name: 'value', 10728 description: '<p>value to assign</p>\n', 10729 type: 'String|Number' 10730 } 10731 ], 10732 class: 'p5.Table', 10733 module: 'IO' 10734 }, 10735 setNum: { 10736 name: 'setNum', 10737 params: [ 10738 { 10739 name: 'row', 10740 description: '<p>row ID</p>\n', 10741 type: 'Integer' 10742 }, 10743 { 10744 name: 'column', 10745 description: 10746 '<p>column ID (Number)\n or title (String)</p>\n', 10747 type: 'String|Integer' 10748 }, 10749 { 10750 name: 'value', 10751 description: '<p>value to assign</p>\n', 10752 type: 'Number' 10753 } 10754 ], 10755 class: 'p5.Table', 10756 module: 'IO' 10757 }, 10758 setString: { 10759 name: 'setString', 10760 params: [ 10761 { 10762 name: 'row', 10763 description: '<p>row ID</p>\n', 10764 type: 'Integer' 10765 }, 10766 { 10767 name: 'column', 10768 description: 10769 '<p>column ID (Number)\n or title (String)</p>\n', 10770 type: 'String|Integer' 10771 }, 10772 { 10773 name: 'value', 10774 description: '<p>value to assign</p>\n', 10775 type: 'String' 10776 } 10777 ], 10778 class: 'p5.Table', 10779 module: 'IO' 10780 }, 10781 get: { 10782 name: 'get', 10783 params: [ 10784 { 10785 name: 'row', 10786 description: '<p>row ID</p>\n', 10787 type: 'Integer' 10788 }, 10789 { 10790 name: 'column', 10791 description: 10792 '<p>columnName (string) or\n ID (number)</p>\n', 10793 type: 'String|Integer' 10794 } 10795 ], 10796 class: 'p5.Table', 10797 module: 'IO' 10798 }, 10799 getNum: { 10800 name: 'getNum', 10801 params: [ 10802 { 10803 name: 'row', 10804 description: '<p>row ID</p>\n', 10805 type: 'Integer' 10806 }, 10807 { 10808 name: 'column', 10809 description: 10810 '<p>columnName (string) or\n ID (number)</p>\n', 10811 type: 'String|Integer' 10812 } 10813 ], 10814 class: 'p5.Table', 10815 module: 'IO' 10816 }, 10817 getString: { 10818 name: 'getString', 10819 params: [ 10820 { 10821 name: 'row', 10822 description: '<p>row ID</p>\n', 10823 type: 'Integer' 10824 }, 10825 { 10826 name: 'column', 10827 description: 10828 '<p>columnName (string) or\n ID (number)</p>\n', 10829 type: 'String|Integer' 10830 } 10831 ], 10832 class: 'p5.Table', 10833 module: 'IO' 10834 }, 10835 getObject: { 10836 name: 'getObject', 10837 params: [ 10838 { 10839 name: 'headerColumn', 10840 description: 10841 '<p>Name of the column which should be used to\n title each row object (optional)</p>\n', 10842 type: 'String', 10843 optional: true 10844 } 10845 ], 10846 class: 'p5.Table', 10847 module: 'IO' 10848 }, 10849 getArray: { 10850 name: 'getArray', 10851 class: 'p5.Table', 10852 module: 'IO' 10853 } 10854 }, 10855 'p5.TableRow': { 10856 set: { 10857 name: 'set', 10858 params: [ 10859 { 10860 name: 'column', 10861 description: 10862 '<p>Column ID (Number)\n or Title (String)</p>\n', 10863 type: 'String|Integer' 10864 }, 10865 { 10866 name: 'value', 10867 description: '<p>The value to be stored</p>\n', 10868 type: 'String|Number' 10869 } 10870 ], 10871 class: 'p5.TableRow', 10872 module: 'IO' 10873 }, 10874 setNum: { 10875 name: 'setNum', 10876 params: [ 10877 { 10878 name: 'column', 10879 description: 10880 '<p>Column ID (Number)\n or Title (String)</p>\n', 10881 type: 'String|Integer' 10882 }, 10883 { 10884 name: 'value', 10885 description: 10886 '<p>The value to be stored\n as a Float</p>\n', 10887 type: 'Number|String' 10888 } 10889 ], 10890 class: 'p5.TableRow', 10891 module: 'IO' 10892 }, 10893 setString: { 10894 name: 'setString', 10895 params: [ 10896 { 10897 name: 'column', 10898 description: 10899 '<p>Column ID (Number)\n or Title (String)</p>\n', 10900 type: 'String|Integer' 10901 }, 10902 { 10903 name: 'value', 10904 description: 10905 '<p>The value to be stored\n as a String</p>\n', 10906 type: 'String|Number|Boolean|Object' 10907 } 10908 ], 10909 class: 'p5.TableRow', 10910 module: 'IO' 10911 }, 10912 get: { 10913 name: 'get', 10914 params: [ 10915 { 10916 name: 'column', 10917 description: 10918 '<p>columnName (string) or\n ID (number)</p>\n', 10919 type: 'String|Integer' 10920 } 10921 ], 10922 class: 'p5.TableRow', 10923 module: 'IO' 10924 }, 10925 getNum: { 10926 name: 'getNum', 10927 params: [ 10928 { 10929 name: 'column', 10930 description: 10931 '<p>columnName (string) or\n ID (number)</p>\n', 10932 type: 'String|Integer' 10933 } 10934 ], 10935 class: 'p5.TableRow', 10936 module: 'IO' 10937 }, 10938 getString: { 10939 name: 'getString', 10940 params: [ 10941 { 10942 name: 'column', 10943 description: 10944 '<p>columnName (string) or\n ID (number)</p>\n', 10945 type: 'String|Integer' 10946 } 10947 ], 10948 class: 'p5.TableRow', 10949 module: 'IO' 10950 } 10951 }, 10952 'p5.XML': { 10953 getParent: { 10954 name: 'getParent', 10955 class: 'p5.XML', 10956 module: 'IO' 10957 }, 10958 getName: { 10959 name: 'getName', 10960 class: 'p5.XML', 10961 module: 'IO' 10962 }, 10963 setName: { 10964 name: 'setName', 10965 params: [ 10966 { 10967 name: 'the', 10968 description: '<p>new name of the node</p>\n', 10969 type: 'String' 10970 } 10971 ], 10972 class: 'p5.XML', 10973 module: 'IO' 10974 }, 10975 hasChildren: { 10976 name: 'hasChildren', 10977 class: 'p5.XML', 10978 module: 'IO' 10979 }, 10980 listChildren: { 10981 name: 'listChildren', 10982 class: 'p5.XML', 10983 module: 'IO' 10984 }, 10985 getChildren: { 10986 name: 'getChildren', 10987 params: [ 10988 { 10989 name: 'name', 10990 description: '<p>element name</p>\n', 10991 type: 'String', 10992 optional: true 10993 } 10994 ], 10995 class: 'p5.XML', 10996 module: 'IO' 10997 }, 10998 getChild: { 10999 name: 'getChild', 11000 params: [ 11001 { 11002 name: 'name', 11003 description: '<p>element name or index</p>\n', 11004 type: 'String|Integer' 11005 } 11006 ], 11007 class: 'p5.XML', 11008 module: 'IO' 11009 }, 11010 addChild: { 11011 name: 'addChild', 11012 params: [ 11013 { 11014 name: 'node', 11015 description: 11016 '<p>a <a href="#/p5.XML">p5.XML</a> Object which will be the child to be added</p>\n', 11017 type: 'p5.XML' 11018 } 11019 ], 11020 class: 'p5.XML', 11021 module: 'IO' 11022 }, 11023 removeChild: { 11024 name: 'removeChild', 11025 params: [ 11026 { 11027 name: 'name', 11028 description: '<p>element name or index</p>\n', 11029 type: 'String|Integer' 11030 } 11031 ], 11032 class: 'p5.XML', 11033 module: 'IO' 11034 }, 11035 getAttributeCount: { 11036 name: 'getAttributeCount', 11037 class: 'p5.XML', 11038 module: 'IO' 11039 }, 11040 listAttributes: { 11041 name: 'listAttributes', 11042 class: 'p5.XML', 11043 module: 'IO' 11044 }, 11045 hasAttribute: { 11046 name: 'hasAttribute', 11047 params: [ 11048 { 11049 name: 'the', 11050 description: '<p>attribute to be checked</p>\n', 11051 type: 'String' 11052 } 11053 ], 11054 class: 'p5.XML', 11055 module: 'IO' 11056 }, 11057 getNum: { 11058 name: 'getNum', 11059 params: [ 11060 { 11061 name: 'name', 11062 description: '<p>the non-null full name of the attribute</p>\n', 11063 type: 'String' 11064 }, 11065 { 11066 name: 'defaultValue', 11067 description: '<p>the default value of the attribute</p>\n', 11068 type: 'Number', 11069 optional: true 11070 } 11071 ], 11072 class: 'p5.XML', 11073 module: 'IO' 11074 }, 11075 getString: { 11076 name: 'getString', 11077 params: [ 11078 { 11079 name: 'name', 11080 description: '<p>the non-null full name of the attribute</p>\n', 11081 type: 'String' 11082 }, 11083 { 11084 name: 'defaultValue', 11085 description: '<p>the default value of the attribute</p>\n', 11086 type: 'Number', 11087 optional: true 11088 } 11089 ], 11090 class: 'p5.XML', 11091 module: 'IO' 11092 }, 11093 setAttribute: { 11094 name: 'setAttribute', 11095 params: [ 11096 { 11097 name: 'name', 11098 description: '<p>the full name of the attribute</p>\n', 11099 type: 'String' 11100 }, 11101 { 11102 name: 'value', 11103 description: '<p>the value of the attribute</p>\n', 11104 type: 'Number|String|Boolean' 11105 } 11106 ], 11107 class: 'p5.XML', 11108 module: 'IO' 11109 }, 11110 getContent: { 11111 name: 'getContent', 11112 params: [ 11113 { 11114 name: 'defaultValue', 11115 description: '<p>value returned if no content is found</p>\n', 11116 type: 'String', 11117 optional: true 11118 } 11119 ], 11120 class: 'p5.XML', 11121 module: 'IO' 11122 }, 11123 setContent: { 11124 name: 'setContent', 11125 params: [ 11126 { 11127 name: 'text', 11128 description: '<p>the new content</p>\n', 11129 type: 'String' 11130 } 11131 ], 11132 class: 'p5.XML', 11133 module: 'IO' 11134 }, 11135 serialize: { 11136 name: 'serialize', 11137 class: 'p5.XML', 11138 module: 'IO' 11139 } 11140 }, 11141 'p5.Vector': { 11142 x: { 11143 name: 'x', 11144 class: 'p5.Vector', 11145
11145 module: 'Math' 11146 }, 11147 y: { 11148 name: 'y', 11149 class: 'p5.Vector', 11150 module: 'Math' 11151 }, 11152 z: { 11153 name: 'z', 11154 class: 'p5.Vector', 11155 module: 'Math' 11156 }, 11157 toString: { 11158 name: 'toString', 11159 class: 'p5.Vector', 11160 module: 'Math' 11161 }, 11162 set: { 11163 name: 'set', 11164 class: 'p5.Vector', 11165 module: 'Math', 11166 overloads: [ 11167 { 11168 params: [ 11169 { 11170 name: 'x', 11171 description: '<p>the x component of the vector</p>\n', 11172 type: 'Number', 11173 optional: true 11174 }, 11175 { 11176 name: 'y', 11177 description: '<p>the y component of the vector</p>\n', 11178 type: 'Number', 11179 optional: true 11180 }, 11181 { 11182 name: 'z', 11183 description: '<p>the z component of the vector</p>\n', 11184 type: 'Number', 11185 optional: true 11186 } 11187 ], 11188 chainable: 1 11189 }, 11190 { 11191 params: [ 11192 { 11193 name: 'value', 11194 description: '<p>the vector to set</p>\n', 11195 type: 'p5.Vector|Number[]' 11196 } 11197 ], 11198 chainable: 1 11199 } 11200 ] 11201 }, 11202 copy: { 11203 name: 'copy', 11204 class: 'p5.Vector', 11205 module: 'Math' 11206 }, 11207 add: { 11208 name: 'add', 11209 class: 'p5.Vector', 11210 module: 'Math', 11211 overloads: [ 11212 { 11213 params: [ 11214 { 11215 name: 'x', 11216 description: '<p>the x component of the vector to be added</p>\n', 11217 type: 'Number' 11218 }, 11219 { 11220 name: 'y', 11221 description: '<p>the y component of the vector to be added</p>\n', 11222 type: 'Number', 11223 optional: true 11224 }, 11225 { 11226 name: 'z', 11227 description: '<p>the z component of the vector to be added</p>\n', 11228 type: 'Number', 11229 optional: true 11230 } 11231 ], 11232 chainable: 1 11233 }, 11234 { 11235 params: [ 11236 { 11237 name: 'value', 11238 description: '<p>the vector to add</p>\n', 11239 type: 'p5.Vector|Number[]' 11240 } 11241 ], 11242 chainable: 1 11243 }, 11244 { 11245 params: [ 11246 { 11247 name: 'v1', 11248 description: 11249 '<p>a <a href="#/p5.Vector">p5.Vector</a> to add</p>\n', 11250 type: 'p5.Vector' 11251 }, 11252 { 11253 name: 'v2', 11254 description: 11255 '<p>a <a href="#/p5.Vector">p5.Vector</a> to add</p>\n', 11256 type: 'p5.Vector' 11257 }, 11258 { 11259 name: 'target', 11260 description: '<p>the vector to receive the result (Optional)</p>\n', 11261 type: 'p5.Vector', 11262 optional: true 11263 } 11264 ], 11265 static: 1 11266 } 11267 ] 11268 }, 11269 rem: { 11270 name: 'rem', 11271 class: 'p5.Vector', 11272 module: 'Math', 11273 overloads: [ 11274 { 11275 params: [ 11276 { 11277 name: 'x', 11278 description: '<p>the x component of divisor vector</p>\n', 11279 type: 'Number' 11280 }, 11281 { 11282 name: 'y', 11283 description: '<p>the y component of divisor vector</p>\n', 11284 type: 'Number' 11285 }, 11286 { 11287 name: 'z', 11288 description: '<p>the z component of divisor vector</p>\n', 11289 type: 'Number' 11290 } 11291 ], 11292 chainable: 1 11293 }, 11294 { 11295 params: [ 11296 { 11297 name: 'value', 11298 description: '<p>divisor vector</p>\n', 11299 type: 'p5.Vector | Number[]' 11300 } 11301 ], 11302 chainable: 1 11303 }, 11304 { 11305 params: [ 11306 { 11307 name: 'v1', 11308 description: 11309 '<p>dividend <a href="#/p5.Vector">p5.Vector</a></p>\n', 11310 type: 'p5.Vector' 11311 }, 11312 { 11313 name: 'v2', 11314 description: '<p>divisor <a href="#/p5.Vector">p5.Vector</a></p>\n', 11315 type: 'p5.Vector' 11316 } 11317 ], 11318 static: 1 11319 }, 11320 { 11321 params: [ 11322 { 11323 name: 'v1', 11324 description: '', 11325 type: 'p5.Vector' 11326 }, 11327 { 11328 name: 'v2', 11329 description: '', 11330 type: 'p5.Vector' 11331 } 11332 ], 11333 static: 1 11334 } 11335 ] 11336 }, 11337 sub: { 11338 name: 'sub', 11339 class: 'p5.Vector', 11340 module: 'Math', 11341 overloads: [ 11342 { 11343 params: [ 11344 { 11345 name: 'x', 11346 description: '<p>the x component of the vector to subtract</p>\n', 11347 type: 'Number' 11348 }, 11349 { 11350 name: 'y', 11351 description: '<p>the y component of the vector to subtract</p>\n', 11352 type: 'Number', 11353 optional: true 11354 }, 11355 { 11356 name: 'z', 11357 description: '<p>the z component of the vector to subtract</p>\n', 11358 type: 'Number', 11359 optional: true 11360 } 11361 ], 11362 chainable: 1 11363 }, 11364 { 11365 params: [ 11366 { 11367 name: 'value', 11368 description: '<p>the vector to subtract</p>\n', 11369 type: 'p5.Vector|Number[]' 11370 } 11371 ], 11372 chainable: 1 11373 }, 11374 { 11375 params: [ 11376 { 11377 name: 'v1', 11378 description: 11379 '<p>a <a href="#/p5.Vector">p5.Vector</a> to subtract from</p>\n', 11380 type: 'p5.Vector' 11381 }, 11382 { 11383 name: 'v2', 11384 description: 11385 '<p>a <a href="#/p5.Vector">p5.Vector</a> to subtract</p>\n', 11386 type: 'p5.Vector' 11387 }, 11388 { 11389 name: 'target', 11390 description: '<p>the vector to receive the result (Optional)</p>\n', 11391 type: 'p5.Vector', 11392 optional: true 11393 } 11394 ], 11395 static: 1 11396 } 11397 ] 11398 }, 11399 mult: { 11400 name: 'mult', 11401 class: 'p5.Vector', 11402 module: 'Math', 11403 overloads: [ 11404 { 11405 params: [ 11406 { 11407 name: 'n', 11408 description: '<p>The number to multiply with the vector</p>\n', 11409 type: 'Number' 11410 } 11411 ], 11412 chainable: 1 11413 }, 11414 { 11415 params: [ 11416 { 11417 name: 'x', 11418 description: 11419 '<p>The number to multiply with the x component of the vector</p>\n', 11420 type: 'Number' 11421 }, 11422 { 11423 name: 'y', 11424 description: 11425 '<p>The number to multiply with the y component of the vector</p>\n', 11426 type: 'Number' 11427 }, 11428 { 11429 name: 'z', 11430 description: 11431 '<p>The number to multiply with the z component of the vector</p>\n', 11432 type: 'Number', 11433 optional: true 11434 } 11435 ], 11436 chainable: 1 11437 }, 11438 { 11439 params: [ 11440 { 11441 name: 'arr', 11442 description: 11443 '<p>The array to multiply with the components of the vector</p>\n', 11444 type: 'Number[]' 11445 } 11446 ], 11447 chainable: 1 11448 }, 11449 { 11450 params: [ 11451 { 11452 name: 'v', 11453 description: 11454 '<p>The vector to multiply with the components of the original vector</p>\n', 11455 type: 'p5.Vector' 11456 } 11457 ], 11458 chainable: 1 11459 }, 11460 { 11461 params: [ 11462 { 11463 name: 'x', 11464 description: '', 11465 type: 'Number' 11466 }, 11467 { 11468 name: 'y', 11469 description: '', 11470 type: 'Number' 11471 }, 11472 { 11473 name: 'z', 11474 description: '', 11475 type: 'Number', 11476 optional: true 11477 } 11478 ], 11479 static: 1 11480 }, 11481 { 11482 params: [ 11483 { 11484 name: 'v', 11485 description: '', 11486 type: 'p5.Vector' 11487 }, 11488 { 11489 name: 'n', 11490 description: '', 11491 type: 'Number' 11492 }, 11493 { 11494 name: 'target', 11495 description: '<p>the vector to receive the result (Optional)</p>\n', 11496 type: 'p5.Vector', 11497 optional: true 11498 } 11499 ], 11500 static: 1 11501 }, 11502 { 11503 params: [ 11504 { 11505 name: 'v0', 11506 description: '', 11507 type: 'p5.Vector' 11508 }, 11509 { 11510 name: 'v1', 11511 description: '', 11512 type: 'p5.Vector' 11513 }, 11514 { 11515 name: 'target', 11516 description: '', 11517 type: 'p5.Vector', 11518 optional: true 11519 } 11520 ], 11521 static: 1 11522 }, 11523 { 11524 params: [ 11525 { 11526 name: 'v0', 11527 description: '', 11528 type: 'p5.Vector' 11529 }, 11530 { 11531 name: 'arr', 11532 description: '', 11533 type: 'Number[]' 11534 }, 11535 { 11536 name: 'target', 11537 description: '', 11538 type: 'p5.Vector', 11539 optional: true 11540 } 11541 ], 11542 static: 1 11543 } 11544 ] 11545 }, 11546 div: { 11547 name: 'div', 11548 class: 'p5.Vector', 11549 module: 'Math', 11550 overloads: [ 11551 { 11552 params: [ 11553 { 11554 name: 'n', 11555 description: '<p>The number to divide the vector by</p>\n', 11556 type: 'Number' 11557 } 11558 ], 11559 chainable: 1 11560 }, 11561 { 11562 params: [ 11563 { 11564 name: 'x', 11565 description: 11566 '<p>The number to divide with the x component of the vector</p>\n', 11567 type: 'Number' 11568 }, 11569 { 11570 name: 'y', 11571 description: 11572 '<p>The number to divide with the y component of the vector</p>\n', 11573 type: 'Number' 11574 }, 11575 { 11576 name: 'z', 11577 description: 11578 '<p>The number to divide with the z component of the vector</p>\n', 11579 type: 'Number', 11580 optional: true 11581 } 11582 ], 11583 chainable: 1 11584 }, 11585 { 11586 params: [ 11587 { 11588 name: 'arr', 11589 description: 11590 '<p>The array to divide the components of the vector by</p>\n', 11591 type: 'Number[]' 11592 } 11593 ], 11594 chainable: 1 11595 }, 11596 { 11597 params: [ 11598 { 11599 name: 'v', 11600 description: 11601 '<p>The vector to divide the components of the original vector by</p>\n', 11602 type: 'p5.Vector' 11603 } 11604 ], 11605 chainable: 1 11606 }, 11607 { 11608 params: [ 11609 { 11610 name: 'x', 11611 description: '', 11612 type: 'Number' 11613 }, 11614 { 11615 name: 'y', 11616 description: '', 11617 type: 'Number' 11618 }, 11619 { 11620 name: 'z', 11621 description: '', 11622 type: 'Num
11622ber', 11623 optional: true 11624 } 11625 ], 11626 static: 1 11627 }, 11628 { 11629 params: [ 11630 { 11631 name: 'v', 11632 description: '', 11633 type: 'p5.Vector' 11634 }, 11635 { 11636 name: 'n', 11637 description: '', 11638 type: 'Number' 11639 }, 11640 { 11641 name: 'target', 11642 description: '<p>the vector to receive the result (Optional)</p>\n', 11643 type: 'p5.Vector', 11644 optional: true 11645 } 11646 ], 11647 static: 1 11648 }, 11649 { 11650 params: [ 11651 { 11652 name: 'v0', 11653 description: '', 11654 type: 'p5.Vector' 11655 }, 11656 { 11657 name: 'v1', 11658 description: '', 11659 type: 'p5.Vector' 11660 }, 11661 { 11662 name: 'target', 11663 description: '', 11664 type: 'p5.Vector', 11665 optional: true 11666 } 11667 ], 11668 static: 1 11669 }, 11670 { 11671 params: [ 11672 { 11673 name: 'v0', 11674 description: '', 11675 type: 'p5.Vector' 11676 }, 11677 { 11678 name: 'arr', 11679 description: '', 11680 type: 'Number[]' 11681 }, 11682 { 11683 name: 'target', 11684 description: '', 11685 type: 'p5.Vector', 11686 optional: true 11687 } 11688 ], 11689 static: 1 11690 } 11691 ] 11692 }, 11693 mag: { 11694 name: 'mag', 11695 class: 'p5.Vector', 11696 module: 'Math', 11697 overloads: [ 11698 { 11699 params: [] 11700 }, 11701 { 11702 params: [ 11703 { 11704 name: 'vecT', 11705 description: '<p>the vector to return the magnitude of</p>\n', 11706 type: 'p5.Vector' 11707 } 11708 ], 11709 static: 1 11710 } 11711 ] 11712 }, 11713 magSq: { 11714 name: 'magSq', 11715 class: 'p5.Vector', 11716 module: 'Math' 11717 }, 11718 dot: { 11719 name: 'dot', 11720 class: 'p5.Vector', 11721 module: 'Math', 11722 overloads: [ 11723 { 11724 params: [ 11725 { 11726 name: 'x', 11727 description: '<p>x component of the vector</p>\n', 11728 type: 'Number' 11729 }, 11730 { 11731 name: 'y', 11732 description: '<p>y component of the vector</p>\n', 11733 type: 'Number', 11734 optional: true 11735 }, 11736 { 11737 name: 'z', 11738 description: '<p>z component of the vector</p>\n', 11739 type: 'Number', 11740 optional: true 11741 } 11742 ] 11743 }, 11744 { 11745 params: [ 11746 { 11747 name: 'value', 11748 description: 11749 '<p>value component of the vector or a <a href="#/p5.Vector">p5.Vector</a></p>\n', 11750 type: 'p5.Vector' 11751 } 11752 ] 11753 }, 11754 { 11755 params: [ 11756 { 11757 name: 'v1', 11758 description: 11759 '<p>the first <a href="#/p5.Vector">p5.Vector</a></p>\n', 11760 type: 'p5.Vector' 11761 }, 11762 { 11763 name: 'v2', 11764 description: 11765 '<p>the second <a href="#/p5.Vector">p5.Vector</a></p>\n', 11766 type: 'p5.Vector' 11767 } 11768 ], 11769 static: 1 11770 } 11771 ] 11772 }, 11773 cross: { 11774 name: 'cross', 11775 class: 'p5.Vector', 11776 module: 'Math', 11777 overloads: [ 11778 { 11779 params: [ 11780 { 11781 name: 'v', 11782 description: 11783 '<p><a href="#/p5.Vector">p5.Vector</a> to be crossed</p>\n', 11784 type: 'p5.Vector' 11785 } 11786 ] 11787 }, 11788 { 11789 params: [ 11790 { 11791 name: 'v1', 11792 description: 11793 '<p>the first <a href="#/p5.Vector">p5.Vector</a></p>\n', 11794 type: 'p5.Vector' 11795 }, 11796 { 11797 name: 'v2', 11798 description: 11799 '<p>the second <a href="#/p5.Vector">p5.Vector</a></p>\n', 11800 type: 'p5.Vector' 11801 } 11802 ], 11803 static: 1 11804 } 11805 ] 11806 }, 11807 dist: { 11808 name: 'dist', 11809 class: 'p5.Vector', 11810 module: 'Math', 11811 overloads: [ 11812 { 11813 params: [ 11814 { 11815 name: 'v', 11816 description: 11817 '<p>the x, y, and z coordinates of a <a href="#/p5.Vector">p5.Vector</a></p>\n', 11818 type: 'p5.Vector' 11819 } 11820 ] 11821 }, 11822 { 11823 params: [ 11824 { 11825 name: 'v1', 11826 description: 11827 '<p>the first <a href="#/p5.Vector">p5.Vector</a></p>\n', 11828 type: 'p5.Vector' 11829 }, 11830 { 11831 name: 'v2', 11832 description: 11833 '<p>the second <a href="#/p5.Vector">p5.Vector</a></p>\n', 11834 type: 'p5.Vector' 11835 } 11836 ], 11837 static: 1 11838 } 11839 ] 11840 }, 11841 normalize: { 11842 name: 'normalize', 11843 class: 'p5.Vector', 11844 module: 'Math' 11845 }, 11846 limit: { 11847 name: 'limit', 11848 params: [ 11849 { 11850 name: 'max', 11851 description: '<p>the maximum magnitude for the vector</p>\n', 11852 type: 'Number' 11853 } 11854 ], 11855 class: 'p5.Vector', 11856 module: 'Math' 11857 }, 11858 setMag: { 11859 name: 'setMag', 11860 params: [ 11861 { 11862 name: 'len', 11863 description: '<p>the new length for this vector</p>\n', 11864 type: 'Number' 11865 } 11866 ], 11867 class: 'p5.Vector', 11868 module: 'Math' 11869 }, 11870 heading: { 11871 name: 'heading', 11872 class: 'p5.Vector', 11873 module: 'Math' 11874 }, 11875 setHeading: { 11876 name: 'setHeading', 11877 params: [ 11878 { 11879 name: 'angle', 11880 description: '<p>the angle of rotation</p>\n', 11881 type: 'Number' 11882 } 11883 ], 11884 class: 'p5.Vector', 11885 module: 'Math' 11886 }, 11887 rotate: { 11888 name: 'rotate', 11889 params: [ 11890 { 11891 name: 'angle', 11892 description: '<p>the angle of rotation</p>\n', 11893 type: 'Number' 11894 } 11895 ], 11896 class: 'p5.Vector', 11897 module: 'Math' 11898 }, 11899 angleBetween: { 11900 name: 'angleBetween', 11901 params: [ 11902 { 11903 name: 'value', 11904 description: 11905 '<p>the x, y, and z components of a <a href="#/p5.Vector">p5.Vector</a></p>\n', 11906 type: 'p5.Vector' 11907 } 11908 ], 11909 class: 'p5.Vector', 11910 module: 'Math' 11911 }, 11912 lerp: { 11913 name: 'lerp', 11914 class: 'p5.Vector', 11915 module: 'Math', 11916 overloads: [ 11917 { 11918 params: [ 11919 { 11920 name: 'x', 11921 description: '<p>the x component</p>\n', 11922 type: 'Number' 11923 }, 11924 { 11925 name: 'y', 11926 description: '<p>the y component</p>\n', 11927 type: 'Number' 11928 }, 11929 { 11930 name: 'z', 11931 description: '<p>the z component</p>\n', 11932 type: 'Number' 11933 }, 11934 { 11935 name: 'amt', 11936 description: 11937 '<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', 11938 type: 'Number' 11939 } 11940 ], 11941 chainable: 1 11942 }, 11943 { 11944 params: [ 11945 { 11946 name: 'v', 11947 description: 11948 '<p>the <a href="#/p5.Vector">p5.Vector</a> to lerp to</p>\n', 11949 type: 'p5.Vector' 11950 }, 11951 { 11952 name: 'amt', 11953 description: '', 11954 type: 'Number' 11955 } 11956 ], 11957 chainable: 1 11958 }, 11959 { 11960 params: [ 11961 { 11962 name: 'v1', 11963 description: '', 11964 type: 'p5.Vector' 11965 }, 11966 { 11967 name: 'v2', 11968 description: '', 11969 type: 'p5.Vector' 11970 }, 11971 { 11972 name: 'amt', 11973 description: '', 11974 type: 'Number' 11975 }, 11976 { 11977 name: 'target', 11978 description: '<p>the vector to receive the result (Optional)</p>\n', 11979 type: 'p5.Vector', 11980 optional: true 11981 } 11982 ], 11983 static: 1 11984 } 11985 ] 11986 }, 11987 reflect: { 11988 name: 'reflect', 11989 params: [ 11990 { 11991 name: 'surfaceNormal', 11992 description: 11993 '<p>the <a href="#/p5.Vector">p5.Vector</a> to reflect about, will be normalized by this method</p>\n', 11994 type: 'p5.Vector' 11995 } 11996 ], 11997 class: 'p5.Vector', 11998 module: 'Math' 11999 }, 12000 array: { 12001 name: 'array', 12002 class: 'p5.Vector', 12003 module: 'Math' 12004 }, 12005 equals: { 12006 name: 'equals', 12007 class: 'p5.Vector', 12008 module: 'Math', 12009 overloads: [ 12010 { 12011 params: [ 12012 { 12013 name: 'x', 12014 description: '<p>the x component of the vector</p>\n', 12015 type: 'Number', 12016 optional: true 12017 }, 12018 { 12019 name: 'y', 12020 description: '<p>the y component of the vector</p>\n', 12021 type: 'Number', 12022 optional: true 12023 }, 12024 { 12025 name: 'z', 12026 description: '<p>the z component of the vector</p>\n', 12027 type: 'Number', 12028 optional: true 12029 } 12030 ] 12031 }, 12032 { 12033 params: [ 12034 { 12035 name: 'value', 12036 description: '<p>the vector to compare</p>\n', 12037 type: 'p5.Vector|Array' 12038 } 12039 ] 12040 } 12041 ] 12042 }, 12043 fromAngle: { 12044 name: 'fromAngle', 12045 params: [ 12046 { 12047 name: 'angle', 12048 description: 12049 '<p>the desired angle, in radians (unaffected by <a href="#/p5/angleMode">angleMode</a>)</p>\n', 12050 type: 'Number' 12051 }, 12052 { 12053 name: 'length', 12054 description: '<p>the length of the new vector (defaults to 1)</p>\n', 12055 type: 'Number', 12056 optional: true 12057 } 12058 ], 12059 class: 'p5.Vector', 12060 module: 'Math' 12061 }, 12062 fromAngles: { 12063 name: 'fromAngles', 12064 params: [ 12065 { 12066 name: 'theta', 12067 description: '<p>the polar angle, in radians (zero is up)</p>\n', 12068 type: 'Number' 12069 }, 12070 { 12071 name: 'phi', 12072 description: 12073 '<p>the azimuthal angle, in radians\n (zero is out of the screen)</p>\n', 12074 type: 'Number' 12075 }, 12076 { 12077 name: 'length', 12078 description: '<p>the length of the new vector (defaults to 1)</p>\n', 12079 type: 'Number', 12080 optional: true 12081 } 12082 ], 12083 class: 'p5.Vector', 12084 module: 'Math' 12085 }, 12086 random2D: { 12087 name: 'random2D', 12088 class: 'p5.Vector', 12089 module: 'Math' 12090 }, 12091 random3D: { 12092 name: 'random3D', 12093 class: 'p5.Vector', 12094 module: 'Math' 12095 } 12096 }, 12097 'p5.Font': { 12098 font: { 12099 name: 'font', 12100 class: 'p5.Font', 12101 module: 'Typography' 12102 }, 12103 textBounds: { 12104 name: 'textBounds', 12105 params: [ 12106 { 12107 name: 'line', 12108 description: '<p>a line of text</p>\n', 12109 type: 'String' 12110 }, 12111 { 12112
12112 name: 'x', 12113 description: '<p>x-position</p>\n', 12114 type: 'Number' 12115 }, 12116 { 12117 name: 'y', 12118 description: '<p>y-position</p>\n', 12119 type: 'Number' 12120 }, 12121 { 12122 name: 'fontSize', 12123 description: '<p>font size to use (optional) Default is 12.</p>\n', 12124 type: 'Number', 12125 optional: true 12126 }, 12127 { 12128 name: 'options', 12129 description: 12130 "<p>opentype options (optional)\n opentype fonts contains alignment and baseline options.\n Default is 'LEFT' and 'alphabetic'</p>\n", 12131 type: 'Object', 12132 optional: true 12133 } 12134 ], 12135 class: 'p5.Font', 12136 module: 'Typography' 12137 }, 12138 textToPoints: { 12139 name: 'textToPoints', 12140 params: [ 12141 { 12142 name: 'txt', 12143 description: '<p>a line of text</p>\n', 12144 type: 'String' 12145 }, 12146 { 12147 name: 'x', 12148 description: '<p>x-position</p>\n', 12149 type: 'Number' 12150 }, 12151 { 12152 name: 'y', 12153 description: '<p>y-position</p>\n', 12154 type: 'Number' 12155 }, 12156 { 12157 name: 'fontSize', 12158 description: '<p>font size to use (optional)</p>\n', 12159 type: 'Number' 12160 }, 12161 { 12162 name: 'options', 12163 description: 12164 '<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', 12165 type: 'Object', 12166 optional: true 12167 } 12168 ], 12169 class: 'p5.Font', 12170 module: 'Typography' 12171 } 12172 }, 12173 'p5.Camera': { 12174 perspective: { 12175 name: 'perspective', 12176 class: 'p5.Camera', 12177 module: 'Lights, Camera' 12178 }, 12179 ortho: { 12180 name: 'ortho', 12181 class: 'p5.Camera', 12182 module: 'Lights, Camera' 12183 }, 12184 frustum: { 12185 name: 'frustum', 12186 class: 'p5.Camera', 12187 module: 'Lights, Camera' 12188 }, 12189 pan: { 12190 name: 'pan', 12191 params: [ 12192 { 12193 name: 'angle', 12194 description: 12195 '<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', 12196 type: 'Number' 12197 } 12198 ], 12199 class: 'p5.Camera', 12200 module: 'Lights, Camera' 12201 }, 12202 tilt: { 12203 name: 'tilt', 12204 params: [ 12205 { 12206 name: 'angle', 12207 description: 12208 '<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', 12209 type: 'Number' 12210 } 12211 ], 12212 class: 'p5.Camera', 12213 module: 'Lights, Camera' 12214 }, 12215 lookAt: { 12216 name: 'lookAt', 12217 params: [ 12218 { 12219 name: 'x', 12220 description: '<p>x position of a point in world space</p>\n', 12221 type: 'Number' 12222 }, 12223 { 12224 name: 'y', 12225 description: '<p>y position of a point in world space</p>\n', 12226 type: 'Number' 12227 }, 12228 { 12229 name: 'z', 12230 description: '<p>z position of a point in world space</p>\n', 12231 type: 'Number' 12232 } 12233 ], 12234 class: 'p5.Camera', 12235 module: 'Lights, Camera' 12236 }, 12237 camera: { 12238 name: 'camera', 12239 class: 'p5.Camera', 12240 module: 'Lights, Camera' 12241 }, 12242 move: { 12243 name: 'move', 12244 params: [ 12245 { 12246 name: 'x', 12247 description: "<p>amount to move along camera's left-right axis</p>\n", 12248 type: 'Number' 12249 }, 12250 { 12251 name: 'y', 12252 description: "<p>amount to move along camera's up-down axis</p>\n", 12253 type: 'Number' 12254 }, 12255 { 12256 name: 'z', 12257 description: 12258 "<p>amount to move along camera's forward-backward axis</p>\n", 12259 type: 'Number' 12260 } 12261 ], 12262 class: 'p5.Camera', 12263 module: 'Lights, Camera' 12264 }, 12265 setPosition: { 12266 name: 'setPosition', 12267 params: [ 12268 { 12269 name: 'x', 12270 description: '<p>x position of a point in world space</p>\n', 12271 type: 'Number' 12272 }, 12273 { 12274 name: 'y', 12275 description: '<p>y position of a point in world space</p>\n', 12276 type: 'Number' 12277 }, 12278 { 12279 name: 'z', 12280 description: '<p>z position of a point in world space</p>\n', 12281 type: 'Number' 12282 } 12283 ], 12284 class: 'p5.Camera', 12285 module: 'Lights, Camera' 12286 } 12287 }, 12288 'p5.Geometry': { 12289 computeFaces: { 12290 name: 'computeFaces', 12291 class: 'p5.Geometry', 12292 module: 'Lights, Camera' 12293 }, 12294 computeNormals: { 12295 name: 'computeNormals', 12296 class: 'p5.Geometry', 12297 module: 'Lights, Camera' 12298 }, 12299 averageNormals: { 12300 name: 'averageNormals', 12301 class: 'p5.Geometry', 12302 module: 'Lights, Camera' 12303 }, 12304 averagePoleNormals: { 12305 name: 'averagePoleNormals', 12306 class: 'p5.Geometry', 12307 module: 'Lights, Camera' 12308 }, 12309 normalize: { 12310 name: 'normalize', 12311 class: 'p5.Geometry', 12312 module: 'Lights, Camera' 12313 } 12314 }, 12315 'p5.Shader': { 12316 setUniform: { 12317 name: 'setUniform', 12318 params: [ 12319 { 12320 name: 'uniformName', 12321 description: '<p>the name of the uniform in the\nshader program</p>\n', 12322 type: 'String' 12323 }, 12324 { 12325 name: 'data', 12326 description: 12327 '<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', 12328 type: 'Object|Number|Boolean|Number[]' 12329 } 12330 ], 12331 class: 'p5.Shader', 12332 module: 'Lights, Camera' 12333 } 12334 }, 12335 'p5.sound': { 12336 getMasterVolume: { 12337 name: 'getMasterVolume', 12338 class: 'p5.sound', 12339 module: 'p5.sound' 12340 }, 12341 masterVolume: { 12342 name: 'masterVolume', 12343 params: [ 12344 { 12345 name: 'volume', 12346 description: 12347 '<p>Volume (amplitude) between 0.0\n and 1.0 or modulating signal/oscillator</p>\n', 12348 type: 'Number|Object' 12349 }, 12350 { 12351 name: 'rampTime', 12352 description: '<p>Fade for t seconds</p>\n', 12353 type: 'Number', 12354 optional: true 12355 }, 12356 { 12357 name: 'timeFromNow', 12358 description: 12359 '<p>Schedule this event to happen at\n t seconds
12359in the future</p>\n', 12360 type: 'Number', 12361 optional: true 12362 } 12363 ], 12364 class: 'p5.sound', 12365 module: 'p5.sound' 12366 }, 12367 soundOut: { 12368 name: 'soundOut', 12369 class: 'p5.sound', 12370 module: 'p5.sound' 12371 } 12372 }, 12373 'p5.Effect': { 12374 amp: { 12375 name: 'amp', 12376 params: [ 12377 { 12378 name: 'vol', 12379 description: '<p>amplitude between 0 and 1.0</p>\n', 12380 type: 'Number', 12381 optional: true 12382 }, 12383 { 12384 name: 'rampTime', 12385 description: '<p>create a fade that lasts until rampTime</p>\n', 12386 type: 'Number', 12387 optional: true 12388 }, 12389 { 12390 name: 'tFromNow', 12391 description: 12392 '<p>schedule this event to happen in tFromNow seconds</p>\n', 12393 type: 'Number', 12394 optional: true 12395 } 12396 ], 12397 class: 'p5.Effect', 12398 module: 'p5.sound' 12399 }, 12400 chain: { 12401 name: 'chain', 12402 params: [ 12403 { 12404 name: 'arguments', 12405 description: '<p>Chain together multiple sound objects</p>\n', 12406 type: 'Object', 12407 optional: true 12408 } 12409 ], 12410 class: 'p5.Effect', 12411 module: 'p5.sound' 12412 }, 12413 drywet: { 12414 name: 'drywet', 12415 params: [ 12416 { 12417 name: 'fade', 12418 description: '<p>The desired drywet value (0 - 1.0)</p>\n', 12419 type: 'Number', 12420 optional: true 12421 } 12422 ], 12423 class: 'p5.Effect', 12424 module: 'p5.sound' 12425 }, 12426 connect: { 12427 name: 'connect', 12428 params: [ 12429 { 12430 name: 'unit', 12431 description: '', 12432 type: 'Object' 12433 } 12434 ], 12435 class: 'p5.Effect', 12436 module: 'p5.sound' 12437 }, 12438 disconnect: { 12439 name: 'disconnect', 12440 class: 'p5.Effect', 12441 module: 'p5.sound' 12442 } 12443 }, 12444 'p5.Filter': { 12445 biquadFilter: { 12446 name: 'biquadFilter', 12447 class: 'p5.Filter', 12448 module: 'p5.sound' 12449 }, 12450 process: { 12451 name: 'process', 12452 params: [ 12453 { 12454 name: 'Signal', 12455 description: '<p>An object that outputs audio</p>\n', 12456 type: 'Object' 12457 }, 12458 { 12459 name: 'freq', 12460 description: '<p>Frequency in Hz, from 10 to 22050</p>\n', 12461 type: 'Number', 12462 optional: true 12463 }, 12464 { 12465 name: 'res', 12466 description: 12467 '<p>Resonance/Width of the filter frequency\n from 0.001 to 1000</p>\n', 12468 type: 'Number', 12469 optional: true 12470 } 12471 ], 12472 class: 'p5.Filter', 12473 module: 'p5.sound' 12474 }, 12475 set: { 12476 name: 'set', 12477 params: [ 12478 { 12479 name: 'freq', 12480 description: '<p>Frequency in Hz, from 10 to 22050</p>\n', 12481 type: 'Number', 12482 optional: true 12483 }, 12484 { 12485 name: 'res', 12486 description: '<p>Resonance (Q) from 0.001 to 1000</p>\n', 12487 type: 'Number', 12488 optional: true 12489 }, 12490 { 12491 name: 'timeFromNow', 12492 description: 12493 '<p>schedule this event to happen\n seconds from now</p>\n', 12494 type: 'Number', 12495 optional: true 12496 } 12497 ], 12498 class: 'p5.Filter', 12499 module: 'p5.sound' 12500 }, 12501 freq: { 12502 name: 'freq', 12503 params: [ 12504 { 12505 name: 'freq', 12506 description: '<p>Filter Frequency</p>\n', 12507 type: 'Number' 12508 }, 12509 { 12510 name: 'timeFromNow', 12511 description: 12512 '<p>schedule this event to happen\n seconds from now</p>\n', 12513 type: 'Number', 12514 optional: true 12515 } 12516 ], 12517 class: 'p5.Filter', 12518 module: 'p5.sound' 12519 }, 12520 res: { 12521 name: 'res', 12522 params: [ 12523 { 12524 name: 'res', 12525 description: 12526 '<p>Resonance/Width of filter freq\n from 0.001 to 1000</p>\n', 12527 type: 'Number' 12528 }, 12529 { 12530 name: 'timeFromNow', 12531 description: 12532 '<p>schedule this event to happen\n seconds from now</p>\n', 12533 type: 'Number', 12534 optional: true 12535 } 12536 ], 12537 class: 'p5.Filter', 12538 module: 'p5.sound' 12539 }, 12540 gain: { 12541 name: 'gain', 12542 params: [ 12543 { 12544 name: 'gain', 12545 description: '', 12546 type: 'Number' 12547 } 12548 ], 12549 class: 'p5.Filter', 12550 module: 'p5.sound' 12551 }, 12552 toggle: { 12553 name: 'toggle', 12554 class: 'p5.Filter', 12555 module: 'p5.sound' 12556 }, 12557 setType: { 12558 name: 'setType', 12559 params: [ 12560 { 12561 name: 't', 12562 description: '', 12563 type: 'String' 12564 } 12565 ], 12566 class: 'p5.Filter', 12567 module: 'p5.sound' 12568 } 12569 }, 12570 'p5.Oscillator': { 12571 start: { 12572 name: 'start', 12573 params: [ 12574 { 12575 name: 'time', 12576 description: '<p>startTime in seconds from now.</p>\n', 12577 type: 'Number', 12578 optional: true 12579 }, 12580 { 12581 name: 'frequency', 12582 description: '<p>frequency in Hz.</p>\n', 12583 type: 'Number', 12584 optional: true 12585 } 12586 ], 12587 class: 'p5.Oscillator', 12588 module: 'p5.sound' 12589 }, 12590 stop: { 12591 name: 'stop', 12592 params: [ 12593 { 12594 name: 'secondsFromNow', 12595 description: '<p>Time, in seconds from now.</p>\n', 12596 type: 'Number' 12597 } 12598 ], 12599 class: 'p5.Oscillator', 12600 module: 'p5.sound' 12601 }, 12602 amp: { 12603 name: 'amp', 12604 params: [ 12605 { 12606 name: 'vol', 12607 description: 12608 '<p>between 0 and 1.0\n or a modulating signal/oscillator</p>\n', 12609 type: 'Number|Object' 12610 }, 12611 { 12612 name: 'rampTime', 12613 description: '<p>create a fade that lasts rampTime</p>\n', 12614 type: 'Number', 12615 optional: true 12616 }, 12617 { 12618 name: 'timeFromNow', 12619 description: 12620 '<p>schedule this event to happen\n seconds from now</p>\n', 12621 type: 'Number', 12622 optional: true 12623 } 12624 ], 12625 class: 'p5.Oscillator', 12626 module: 'p5.sound' 12627 }, 12628 freq: { 12629 name: 'freq', 12630 params: [ 12631 { 12632 name: 'Frequency', 12633 description: 12634 '<p>Frequency in Hz\n or modulating signal/oscillator</p>\n', 12635 type: 'Number|Object' 12636 }, 12637 { 12638 name: 'rampTime', 12639 description: '<p>Ramp time (in seconds)</p>\n', 12640 type: 'Number', 12641 optional: true 12642 }, 12643 { 12644 name: 'timeFromNow', 12645 description: 12646 '<p>Schedule this event to happen\n at x seconds from now</p>\n', 12647 type: 'Number', 12648 optional: true 12649 } 12650 ], 12651 class: 'p5.Oscillator', 12652 module: 'p5.sound' 12653 }, 12654 setType: { 12655 name: 'setType', 12656 params: [ 12657 { 12658 name: 'type', 12659 description: "<p>'sine', 'triangle', 'sawtooth' or 'square'.</p>\n", 12660 type: 'String' 12661 } 12662 ], 12663 class: 'p5.Oscillator', 12664 module: 'p5.sound' 12665 }, 12666 connect: { 12667 name: 'connect', 12668 params: [ 12669 { 12670 name: 'unit', 12671 description: '<p>A p5.sound or Web Audio object</p>\n', 12672 type: 'Object' 12673 } 12674 ], 12675 class: 'p5.Oscillator', 12676 module: 'p5.sound' 12677 }, 12678 disconnect: { 12679 name: 'disconnect', 12680 class: 'p5.Oscillator', 12681 module: 'p5.sound' 12682 }, 12683 pan: { 12684 name: 'pan', 12685 params: [ 12686 { 12687 name: 'panning', 12688 description: '<p>Number between -1 and 1</p>\n', 12689 type: 'Number' 12690 }, 12691 { 12692 name: 'timeFromNow', 12693 description: 12694 '<p>schedule this event to happen\n seconds from now</p>\n', 12695 type: 'Number' 12696 } 12697 ], 12698 class: 'p5.Oscillator', 12699 module: 'p5.sound' 12700 }, 12701 phase: { 12702 name: 'phase', 12703 params: [ 12704 { 12705 name: 'phase', 12706 description: '<p>float between 0.0 and 1.0</p>\n', 12707 type: 'Number' 12708 } 12709 ], 12710 class: 'p5.Oscillator', 12711 module: 'p5.sound' 12712 }, 12713 add: { 12714 name: 'add', 12715 params: [ 12716 { 12717 name: 'number', 12718 description: '<p>Constant number to add</p>\n', 12719 type: 'Number' 12720 } 12721 ], 12722 class: 'p5.Oscillator', 12723 module: 'p5.sound' 12724 }, 12725 mult: { 12726 name: 'mult', 12727 params: [ 12728 { 12729 name: 'number', 12730 description: '<p>Constant number to multiply</p>\n', 12731 type: 'Number' 12732 } 12733 ], 12734 class: 'p5.Oscillator', 12735 module: 'p5.sound' 12736 }, 12737 scale: { 12738 name: 'scale', 12739 params: [ 12740 { 12741 name: 'inMin', 12742 description: '<p>input range minumum</p>\n', 12743 type: 'Number' 12744 }, 12745 { 12746 name: 'inMax', 12747 description: '<p>input range maximum</p>\n', 12748 type: 'Number' 12749 }, 12750 { 12751 name: 'outMin', 12752 description: '<p>input range minumum</p>\n', 12753 type: 'Number' 12754 }, 12755 { 12756 name: 'outMax', 12757 description: '<p>input range maximum</p>\n', 12758 type: 'Number' 12759 } 12760 ], 12761 class: 'p5.Oscillator', 12762 module: 'p5.sound' 12763 } 12764 }, 12765 'p5.MonoSynth': { 12766 play: { 12767 name: 'play', 12768 params: [ 12769 { 12770 name: 'note', 12771 description: 12772 '<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', 12773 type: 'String | Number' 12774 }, 12775 { 12776 name: 'velocity', 12777 description: 12778 '<p>velocity of the note to play (ranging from 0 to 1)</p>\n', 12779 type: 'Number', 12780 optional: true 12781 }, 12782 { 12783 name: 'secondsFromNow', 12784 description: '<p>time from now (in seconds) at which to play</p>\n', 12785 type: 'Number', 12786 optional: true 12787 }, 12788 { 12789 name: 'sustainTime', 12790 description: 12791 '<p>time to sustain before releasing the envelope. Defaults to 0.15 seconds.</p>\n', 12792 type: 'Number', 12793 optional: true 12794 } 12795 ], 12796 class: 'p5.MonoSynth', 12797 module: 'p5.sound' 12798 }, 12799 triggerAttack: { 12800 params: [ 12801 { 12802 name: 'note', 12803 description: 12804 '<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', 12805 type: 'String | Number' 12806 }, 12807 { 12808 name: 'velocity', 12809 description: 12810 '<p>velocity of the note to play (ranging from 0 to 1)</p>\n', 12811 type: 'Number', 12812 optional: true 12813 }, 12814 { 12815 name: 'secondsFromNow', 12816 description: '<p>time from now (in seconds) at which to play</p>\n', 12817 type: 'Number', 12818 optional: true 12819 } 12820 ], 12821 name: 'triggerAttack', 12822 class: 'p5.MonoSynth', 12823 module: 'p5.sound' 12824 }, 12825 triggerRelease: { 12826 params: [ 12827 { 12828 name: 'secondsFromNo
12828w', 12829 description: '<p>time to trigger the release</p>\n', 12830 type: 'Number' 12831 } 12832 ], 12833 name: 'triggerRelease', 12834 class: 'p5.MonoSynth', 12835 module: 'p5.sound' 12836 }, 12837 setADSR: { 12838 name: 'setADSR', 12839 params: [ 12840 { 12841 name: 'attackTime', 12842 description: 12843 '<p>Time (in seconds before envelope\n reaches Attack Level</p>\n', 12844 type: 'Number' 12845 }, 12846 { 12847 name: 'decayTime', 12848 description: 12849 '<p>Time (in seconds) before envelope\n reaches Decay/Sustain Level</p>\n', 12850 type: 'Number', 12851 optional: true 12852 }, 12853 { 12854 name: 'susRatio', 12855 description: 12856 '<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', 12857 type: 'Number', 12858 optional: true 12859 }, 12860 { 12861 name: 'releaseTime', 12862 description: '<p>Time in seconds from now (defaults to 0)</p>\n', 12863 type: 'Number', 12864 optional: true 12865 } 12866 ], 12867 class: 'p5.MonoSynth', 12868 module: 'p5.sound' 12869 }, 12870 attack: { 12871 name: 'attack', 12872 class: 'p5.MonoSynth', 12873 module: 'p5.sound' 12874 }, 12875 decay: { 12876 name: 'decay', 12877 class: 'p5.MonoSynth', 12878 module: 'p5.sound' 12879 }, 12880 sustain: { 12881 name: 'sustain', 12882 class: 'p5.MonoSynth', 12883 module: 'p5.sound' 12884 }, 12885 release: { 12886 name: 'release', 12887 class: 'p5.MonoSynth', 12888 module: 'p5.sound' 12889 }, 12890 amp: { 12891 name: 'amp', 12892 params: [ 12893 { 12894 name: 'vol', 12895 description: '<p>desired volume</p>\n', 12896 type: 'Number' 12897 }, 12898 { 12899 name: 'rampTime', 12900 description: '<p>Time to reach new volume</p>\n', 12901 type: 'Number', 12902 optional: true 12903 } 12904 ], 12905 class: 'p5.MonoSynth', 12906 module: 'p5.sound' 12907 }, 12908 connect: { 12909 name: 'connect', 12910 params: [ 12911 { 12912 name: 'unit', 12913 description: '<p>A p5.sound or Web Audio object</p>\n', 12914 type: 'Object' 12915 } 12916 ], 12917 class: 'p5.MonoSynth', 12918 module: 'p5.sound' 12919 }, 12920 disconnect: { 12921 name: 'disconnect', 12922 class: 'p5.MonoSynth', 12923 module: 'p5.sound' 12924 }, 12925 dispose: { 12926 name: 'dispose', 12927 class: 'p5.MonoSynth', 12928 module: 'p5.sound' 12929 } 12930 }, 12931 'p5.AudioVoice': { 12932 connect: { 12933 name: 'connect', 12934 params: [ 12935 { 12936 name: 'unit', 12937 description: '', 12938 type: 'Object' 12939 } 12940 ], 12941 class: 'p5.AudioVoice', 12942 module: 'p5.sound' 12943 }, 12944 disconnect: { 12945 name: 'disconnect', 12946 class: 'p5.AudioVoice', 12947 module: 'p5.sound' 12948 } 12949 }, 12950 'p5.PolySynth': { 12951 notes: { 12952 name: 'notes', 12953 class: 'p5.PolySynth', 12954 module: 'p5.sound' 12955 }, 12956 polyvalue: { 12957 name: 'polyvalue', 12958 class: 'p5.PolySynth', 12959 module: 'p5.sound' 12960 }, 12961 AudioVoice: { 12962 name: 'AudioVoice', 12963 class: 'p5.PolySynth', 12964 module: 'p5.sound' 12965 }, 12966 play: { 12967 name: 'play', 12968 params: [ 12969 { 12970 name: 'note', 12971 description: 12972 '<p>midi note to play (ranging from 0 to 127 - 60 being a middle C)</p>\n', 12973 type: 'Number', 12974 optional: true 12975 }, 12976 { 12977 name: 'velocity', 12978 description: 12979 '<p>velocity of the note to play (ranging from 0 to 1)</p>\n', 12980 type: 'Number', 12981 optional: true 12982 }, 12983 { 12984 name: 'secondsFromNow', 12985 description: '<p>time from now (in seconds) at which to play</p>\n', 12986 type: 'Number', 12987 optional: true 12988 }, 12989 { 12990 name: 'sustainTime', 12991 description: '<p>time to sustain before releasing the envelope</p>\n', 12992 type: 'Number', 12993 optional: true 12994 } 12995 ], 12996 class: 'p5.PolySynth', 12997 module: 'p5.sound' 12998 }, 12999 noteADSR: { 13000 name: 'noteADSR', 13001 params: [ 13002 { 13003 name: 'note', 13004 description: '<p>Midi note on which ADSR should be set.</p>\n', 13005 type: 'Number', 13006 optional: true 13007 }, 13008 { 13009 name: 'attackTime', 13010 description: 13011 '<p>Time (in seconds before envelope\n reaches Attack Level</p>\n', 13012 type: 'Number', 13013 optional: true 13014 }, 13015 { 13016 name: 'decayTime', 13017 description: 13018 '<p>Time (in seconds) before envelope\n reaches Decay/Sustain Level</p>\n', 13019 type: 'Number', 13020 optional: true 13021 }, 13022 { 13023 name: 'susRatio', 13024 description: 13025 '<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', 13026 type: 'Number', 13027 optional: true 13028 }, 13029 { 13030 name: 'releaseTime', 13031 description: '<p>Time in seconds from now (defaults to 0)</p>\n', 13032 type: 'Number', 13033 optional: true 13034 } 13035 ], 13036 class: 'p5.PolySynth', 13037 module: 'p5.sound' 13038 }, 13039 setADSR: { 13040 name: 'setADSR', 13041 params: [ 13042 { 13043 name: 'attackTime', 13044 description: 13045 '<p>Time (in seconds before envelope\n reaches Attack Level</p>\n', 13046 type: 'Number', 13047 optional: true 13048 }, 13049 { 13050 name: 'decayTime', 13051 description: 13052 '<p>Time (in seconds) before envelope\n reaches Decay/Sustain Level</p>\n', 13053 type: 'Number', 13054 optional: true 13055 }, 13056 { 13057 name: 'susRatio', 13058 description: 13059 '<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', 13060 type: 'Number', 13061 optional: true 13062 }, 13063 { 13064 name: 'releaseTime', 13065 description: '<p>Time in seconds from now (defaults to 0)</p>\n', 13066 type: 'Number', 13067 optional: true 13068 } 13069 ], 13070 class: 'p5.PolySynth', 13071 module: 'p5.sound' 13072 }, 13073 noteAttack: { 13074 name: 'noteAttack', 13075 params: [ 13076 { 13077 name: 'note', 13078 description: '<p>midi note on which attack should be triggered.</p>\n', 13079 type: 'Number', 13080 optional: true 13081 }, 13082 { 13083 name: 'velocity', 13084 description: 13085 '<p>velocity of the note to play (ranging from 0 to 1)/</p>\n', 13086 type: 'Number', 13087 optional: true 13088 }, 13089 { 13090 name: 'secondsFromNow', 13091 description: '<p>time from now (in seconds)</p>\n', 13092 type: 'Number', 13093 optional: true 13094 } 13095 ], 13096 class: 'p5.PolySynth', 13097 module: 'p5.sound' 13098 }, 13099 noteRelease: { 13100 name: 'noteRelease', 13101 params: [ 13102 { 13103 name: 'note', 13104 description: 13105 '<p>midi note on which attack should be triggered.\n If no value is provided, all notes will be released.</p>\n', 13106 type: 'Number', 13107 optional: true 13108 }, 13109 { 13110 name: 'secondsFromNow', 13111 description: '<p>time to trigger the release</p>\n', 13112 type: 'Number', 13113 optional: true 13114 } 13115 ], 13116 class: 'p5.PolySynth', 13117 module: 'p5.sound' 13118 }, 13119 connect: { 13120 name: 'connect', 13121 params: [ 13122 { 13123 name: 'unit', 13124 description: '<p>A p5.sound or Web Audio object</p>\n', 13125 type: 'Object' 13126 } 13127 ], 13128 class: 'p5.PolySynth', 13129 module: 'p5.sound' 13130 }, 13131 disconnect: { 13132 name: 'disconnect', 13133 class: 'p5.PolySynth', 13134 module: 'p5.sound' 13135 }, 13136 dispose: { 13137 name: 'dispose', 13138 class: 'p5.PolySynth', 13139 module: 'p5.sound' 13140 } 13141 }, 13142 'p5.SoundFile': { 13143 isLoaded: { 13144 name: 'isLoaded', 13145 class: 'p5.SoundFile', 13146 module: 'p5.sound' 13147 }, 13148 play: { 13149 name: 'play', 13150 params: [ 13151 { 13152 name: 'startTime', 13153 description: 13154 '<p>(optional) schedule playback to start (in seconds from now).</p>\n', 13155 type: 'Number', 13156 optional: true 13157 }, 13158 { 13159 name: 'rate', 13160 description: '<p>(optional) playback rate</p>\n', 13161 type: 'Number', 13162 optional: true 13163 }, 13164 { 13165 name: 'amp', 13166 description: 13167 '<p>(optional) amplitude (volume)\n of playback</p>\n', 13168 type: 'Number', 13169 optional: true 13170 }, 13171 { 13172 name: 'cueStart', 13173 description: '<p>(optional) cue start time in seconds</p>\n', 13174 type: 'Number', 13175 optional: true 13176 }, 13177 { 13178 name: 'duration', 13179 description: '<p>(optional) duration of playback in seconds</p>\n', 13180 type: 'Number', 13181 optional: true 13182 } 13183 ], 13184 class: 'p5.SoundFile', 13185 module: 'p5.sound' 13186 }, 13187 playMode: { 13188 name: 'playMode', 13189 params: [ 13190 { 13191 name: 'str', 13192 description: "<p>'restart' or 'sustain' or 'untilDone'</p>\n", 13193 type: 'String' 13194 } 13195 ], 13196 class: 'p5.SoundFile', 13197 module: 'p5.sound' 13198 }, 13199 pause: { 13200 name: 'pause', 13201 params: [ 13202 { 13203 name: 'startTime', 13204 description: 13205 '<p>(optional) schedule event to occur\n seconds from now</p>\n', 13206 type: 'Number', 13207 optional: true 13208 } 13209 ], 13210 class: 'p5.SoundFile', 13211 module: 'p5.sound' 13212 }, 13213 loop: { 13214 name: 'loop', 13215 params: [ 13216 { 13217 name: 'startTime', 13218 description: 13219 '<p>(optional) schedule event to occur\n seconds from now</p>\n', 13220 type: 'Number', 13221 optional: true 13222 }, 13223 { 13224 name: 'rate', 13225 description: '<p>(optional) playback rate</p>\n', 13226 type: 'Number', 13227 optional: true 13228 }, 13229 { 13230 name: 'amp', 13231 description: '<p>(optional) playback volume</p>\n', 13232 type: 'Number', 13233 optional: true 13234 }, 13235 { 13236 name: 'cueLoopStart', 13237 description: '<p>(optional) startTime in seconds</p>\n', 13238 type: 'Number', 13239 optional: true 13240 }, 13241 { 13242
13242 name: 'duration', 13243 description: '<p>(optional) loop duration in seconds</p>\n', 13244 type: 'Number', 13245 optional: true 13246 } 13247 ], 13248 class: 'p5.SoundFile', 13249 module: 'p5.sound' 13250 }, 13251 setLoop: { 13252 name: 'setLoop', 13253 params: [ 13254 { 13255 name: 'Boolean', 13256 description: '<p>set looping to true or false</p>\n', 13257 type: 'Boolean' 13258 } 13259 ], 13260 class: 'p5.SoundFile', 13261 module: 'p5.sound' 13262 }, 13263 isLooping: { 13264 name: 'isLooping', 13265 class: 'p5.SoundFile', 13266 module: 'p5.sound' 13267 }, 13268 isPlaying: { 13269 name: 'isPlaying', 13270 class: 'p5.SoundFile', 13271 module: 'p5.sound' 13272 }, 13273 isPaused: { 13274 name: 'isPaused', 13275 class: 'p5.SoundFile', 13276 module: 'p5.sound' 13277 }, 13278 stop: { 13279 name: 'stop', 13280 params: [ 13281 { 13282 name: 'startTime', 13283 description: 13284 '<p>(optional) schedule event to occur\n in seconds from now</p>\n', 13285 type: 'Number', 13286 optional: true 13287 } 13288 ], 13289 class: 'p5.SoundFile', 13290 module: 'p5.sound' 13291 }, 13292 setVolume: { 13293 name: 'setVolume', 13294 params: [ 13295 { 13296 name: 'volume', 13297 description: 13298 '<p>Volume (amplitude) between 0.0\n and 1.0 or modulating signal/oscillator</p>\n', 13299 type: 'Number|Object' 13300 }, 13301 { 13302 name: 'rampTime', 13303 description: '<p>Fade for t seconds</p>\n', 13304 type: 'Number', 13305 optional: true 13306 }, 13307 { 13308 name: 'timeFromNow', 13309 description: 13310 '<p>Schedule this event to happen at\n t seconds in the future</p>\n', 13311 type: 'Number', 13312 optional: true 13313 } 13314 ], 13315 class: 'p5.SoundFile', 13316 module: 'p5.sound' 13317 }, 13318 pan: { 13319 name: 'pan', 13320 params: [ 13321 { 13322 name: 'panValue', 13323 description: '<p>Set the stereo panner</p>\n', 13324 type: 'Number', 13325 optional: true 13326 }, 13327 { 13328 name: 'timeFromNow', 13329 description: 13330 '<p>schedule this event to happen\n seconds from now</p>\n', 13331 type: 'Number', 13332 optional: true 13333 } 13334 ], 13335 class: 'p5.SoundFile', 13336 module: 'p5.sound' 13337 }, 13338 getPan: { 13339 name: 'getPan', 13340 class: 'p5.SoundFile', 13341 module: 'p5.sound' 13342 }, 13343 rate: { 13344 name: 'rate', 13345 params: [ 13346 { 13347 name: 'playbackRate', 13348 description: 13349 '<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', 13350 type: 'Number', 13351 optional: true 13352 } 13353 ], 13354 class: 'p5.SoundFile', 13355 module: 'p5.sound' 13356 }, 13357 duration: { 13358 name: 'duration', 13359 class: 'p5.SoundFile', 13360 module: 'p5.sound' 13361 }, 13362 currentTime: { 13363 name: 'currentTime', 13364 class: 'p5.SoundFile', 13365 module: 'p5.sound' 13366 }, 13367 jump: { 13368 name: 'jump', 13369 params: [ 13370 { 13371 name: 'cueTime', 13372 description: '<p>cueTime of the soundFile in seconds.</p>\n', 13373 type: 'Number' 13374 }, 13375 { 13376 name: 'duration', 13377 description: '<p>duration in seconds.</p>\n', 13378 type: 'Number' 13379 } 13380 ], 13381 class: 'p5.SoundFile', 13382 module: 'p5.sound' 13383 }, 13384 channels: { 13385 name: 'channels', 13386 class: 'p5.SoundFile', 13387 module: 'p5.sound' 13388 }, 13389 sampleRate: { 13390 name: 'sampleRate', 13391 class: 'p5.SoundFile', 13392 module: 'p5.sound' 13393 }, 13394 frames: { 13395 name: 'frames', 13396 class: 'p5.SoundFile', 13397 module: 'p5.sound' 13398 }, 13399 getPeaks: { 13400 name: 'getPeaks', 13401 params: [ 13402 { 13403 name: 'length', 13404 description: 13405 '<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', 13406 type: 'Number', 13407 optional: true 13408 } 13409 ], 13410 class: 'p5.SoundFile', 13411 module: 'p5.sound' 13412 }, 13413 reverseBuffer: { 13414 name: 'reverseBuffer', 13415 class: 'p5.SoundFile', 13416 module: 'p5.sound' 13417 }, 13418 onended: { 13419 name: 'onended', 13420 params: [ 13421 { 13422 name: 'callback', 13423 description: 13424 '<p>function to call when the\n soundfile has ended.</p>\n', 13425 type: 'Function' 13426 } 13427 ], 13428 class: 'p5.SoundFile', 13429 module: 'p5.sound' 13430 }, 13431 connect: { 13432 name: 'connect', 13433 params: [ 13434 { 13435 name: 'object', 13436 description: '<p>Audio object that accepts an input</p>\n', 13437 type: 'Object', 13438 optional: true 13439 } 13440 ], 13441 class: 'p5.SoundFile', 13442 module: 'p5.sound' 13443 }, 13444 disconnect: { 13445 name: 'disconnect', 13446 class: 'p5.SoundFile', 13447 module: 'p5.sound' 13448 }, 13449 setPath: { 13450 name: 'setPath', 13451 params: [ 13452 { 13453 name: 'path', 13454 description: '<p>path to audio file</p>\n', 13455 type: 'String' 13456 }, 13457 { 13458 name: 'callback', 13459 description: '<p>Callback</p>\n', 13460 type: 'Function' 13461 } 13462 ], 13463 class: 'p5.SoundFile', 13464 module: 'p5.sound' 13465 }, 13466 setBuffer: { 13467 name: 'setBuffer', 13468 params: [ 13469 { 13470 name: 'buf', 13471 description: 13472 '<p>Array of Float32 Array(s). 2 Float32 Arrays\n will create a stereo source. 1 will create\n a mono source.</p>\n', 13473 type: 'Array' 13474 } 13475 ], 13476 class: 'p5.SoundFile', 13477 module: 'p5.sound' 13478 }, 13479 processPeaks: { 13480 name: 'processPeaks', 13481 params: [ 13482 { 13483 name: 'callback', 13484 description: '<p>a function to call once this data is returned</p>\n', 13485 type: 'Function' 13486 }, 13487 { 13488 name: 'initThreshold', 13489 description: '<p>initial threshold defaults to 0.9</p>\n', 13490 type: 'Number', 13491 optional: true 13492 }, 13493 { 13494 name: 'minThreshold', 13495 description: '<p>minimum threshold defaults to 0.22</p>\n', 13496 type: 'Number', 13497 optional: true 13498 }, 13499 { 13500 name: 'minPeaks', 13501 description: '<p>minimum number of peaks defaults to 200</p>\n', 13502 type: 'Number', 13503 optional: true 13504 } 13505 ], 13506 class: 'p5.SoundFile', 13507 module: 'p5.sound' 13508 }, 13509 addCue: { 13510 name: 'addCue', 13511 params: [ 13512 { 13513 name: 'time', 13514 description: 13515 "<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", 13516 type: 'Number' 13517 }, 13518 { 13519 name: 'callback', 13520 description: 13521 '<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', 13522 type: 'Function' 13523 }, 13524 { 13525 name: 'value', 13526 description: 13527 '<p>An object to be passed as the\n second parameter to the\n callback function.</p>\n', 13528 type: 'Object', 13529 optional: true 13530 } 13531 ], 13532 class: 'p5.SoundFile', 13533 module: 'p5.sound' 13534 }, 13535 removeCue: { 13536 name: 'removeCue', 13537 params: [ 13538 { 13539 name: 'id', 13540 description: '<p>ID of the cue, as returned by addCue</p>\n', 13541 type: 'Number' 13542 } 13543 ], 13544 class: 'p5.SoundFile', 13545 module: 'p5.sound' 13546 }, 13547 clearCues: { 13548 name: 'clearCues', 13549 class: 'p5.SoundFile', 13550 module: 'p5.sound' 13551 }, 13552 save: { 13553 name: 'save', 13554 params: [ 13555 { 13556 name: 'fileName', 13557 description: '<p>name of the resulting .wav file.</p>\n', 13558 type: 'String', 13559 optional: true 13560 } 13561 ], 13562 class: 'p5.SoundFile', 13563 module: 'p5.sound' 13564 }, 13565 getBlob: { 13566 name: 'getBlob', 13567 class: 'p5.SoundFile', 13568 module: 'p5.sound' 13569 } 13570 }, 13571 'p5.Amplitude': { 13572 setInput: { 13573 name: 'setInput', 13574 params: [ 13575 { 13576 name: 'snd', 13577 description: 13578 '<p>set the sound source\n (optional, defaults to\n master output)</p>\n', 13579 type: 'SoundObject|undefined', 13580 optional: true 13581 }, 13582 { 13583 name: 'smoothing', 13584 description: 13585 '<p>a range between 0.0 and 1.0\n to smooth amplitude readings</p>\n', 13586 type: 'Number|undefined', 13587 optional: true 13588 } 13589 ], 13590 class: 'p5.Amplitude', 13591 module: 'p5.sound' 13592 }, 13593 getLevel: { 13594 name: 'getLevel', 13595 params: [ 13596 { 13597 name: 'channel', 13598 description: 13599 '<p>Optionally return only channel 0 (left) or 1 (right)</p>\n', 13600 type: 'Number', 13601 optional: true 13602 } 13603 ], 13604 class: 'p5.Amplitude', 13605 module: 'p5.sound' 13606 }, 13607 toggleNormalize: { 13608 name: 'toggleNormalize', 13609 params: [ 13610 { 13611 name: 'boolean', 13612 description: '<p>set normalize to true (1) or false (0)</p>\n', 13613 type: 'Boolean', 13614 optional: true 13615 } 13616 ], 13617 class: 'p5.Amplitude', 13618 module: 'p5.sound' 13619 }, 13620 smooth: { 13621 name: 'smooth', 13622 params: [ 13623 { 13624 name: 'set', 13625 description: '<p>smoothing from 0.0 <= 1</p>\n', 13626 type: 'Number' 13627 } 13628 ], 13629 class: 'p5.Amplitude', 13630 module: 'p5.sound' 13631 } 13632 }, 13633 'p5.FFT': { 13634 setInput: { 13635 name: 'setInput', 13636 params: [ 13637 { 13638 name: 'source', 13639 description: '<p>p5.sound object (or web audio API source node)</p>\n', 13640 type: 'Object', 13641 optional: true 13642 } 13643 ], 13644 class: 'p5.FFT', 13645 module: 'p5.sound' 13646 }, 13647 waveform: { 13648 name: 'waveform', 13649 params: [ 13650 { 13651 name: 'bins', 13652 description: 13653 '<p>Must be a power of two between\n 16 and 1024. Defaults to 1024.</p>\n', 13654 type: 'Number', 13655 optional: true 13656 }, 13657 { 13658 name: 'precision', 13659 description: 13660 '<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', 13661 type: 'String', 13662 optional: true 13663 } 13664 ], 13665 class: 'p5.FFT', 13666 module: 'p5.sound' 13667 }, 13668 analyze: { 13669 name: 'analyze', 13670 params: [ 13671 { 13672 name: 'bins', 13673 description: 13674 '<p>Must be a power of two between\n 16 and 1024. Defaults to 1024.</p>\n', 13675 type: 'Number', 13676 optional: true 13677 }, 13678 { 13679 name: 'scale', 13680 description: 13681 '<p>If "dB," returns decibel\n float measurements between\n -14
136810 and 0 (max).\n Otherwise returns integers from 0-255.</p>\n', 13682 type: 'Number', 13683 optional: true 13684 } 13685 ], 13686 class: 'p5.FFT', 13687 module: 'p5.sound' 13688 }, 13689 getEnergy: { 13690 name: 'getEnergy', 13691 params: [ 13692 { 13693 name: 'frequency1', 13694 description: 13695 '<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', 13696 type: 'Number|String' 13697 }, 13698 { 13699 name: 'frequency2', 13700 description: 13701 '<p>If a second frequency is given,\n will return average amount of\n energy that exists between the\n two frequencies.</p>\n', 13702 type: 'Number', 13703 optional: true 13704 } 13705 ], 13706 class: 'p5.FFT', 13707 module: 'p5.sound' 13708 }, 13709 getCentroid: { 13710 name: 'getCentroid', 13711 class: 'p5.FFT', 13712 module: 'p5.sound' 13713 }, 13714 smooth: { 13715 name: 'smooth', 13716 params: [ 13717 { 13718 name: 'smoothing', 13719 description: 13720 '<p>0.0 < smoothing < 1.0.\n Defaults to 0.8.</p>\n', 13721 type: 'Number' 13722 } 13723 ], 13724 class: 'p5.FFT', 13725 module: 'p5.sound' 13726 }, 13727 linAverages: { 13728 name: 'linAverages', 13729 params: [ 13730 { 13731 name: 'N', 13732 description: '<p>Number of returned frequency groups</p>\n', 13733 type: 'Number' 13734 } 13735 ], 13736 class: 'p5.FFT', 13737 module: 'p5.sound' 13738 }, 13739 logAverages: { 13740 name: 'logAverages', 13741 params: [ 13742 { 13743 name: 'octaveBands', 13744 description: '<p>Array of Octave Bands objects for grouping</p>\n', 13745 type: 'Array' 13746 } 13747 ], 13748 class: 'p5.FFT', 13749 module: 'p5.sound' 13750 }, 13751 getOctaveBands: { 13752 name: 'getOctaveBands', 13753 params: [ 13754 { 13755 name: 'N', 13756 description: 13757 '<p>Specifies the 1/N type of generated octave bands</p>\n', 13758 type: 'Number' 13759 }, 13760 { 13761 name: 'fCtr0', 13762 description: '<p>Minimum central frequency for the lowest band</p>\n', 13763 type: 'Number' 13764 } 13765 ], 13766 class: 'p5.FFT', 13767 module: 'p5.sound' 13768 } 13769 }, 13770 'p5.Signal': { 13771 fade: { 13772 name: 'fade', 13773 params: [ 13774 { 13775 name: 'value', 13776 description: '<p>Value to set this signal</p>\n', 13777 type: 'Number' 13778 }, 13779 { 13780 name: 'secondsFromNow', 13781 description: '<p>Length of fade, in seconds from now</p>\n', 13782 type: 'Number', 13783 optional: true 13784 } 13785 ], 13786 class: 'p5.Signal', 13787 module: 'p5.sound' 13788 }, 13789 setInput: { 13790 name: 'setInput', 13791 params: [ 13792 { 13793 name: 'input', 13794 description: '', 13795 type: 'Object' 13796 } 13797 ], 13798 class: 'p5.Signal', 13799 module: 'p5.sound' 13800 }, 13801 add: { 13802 name: 'add', 13803 params: [ 13804 { 13805 name: 'number', 13806 description: '', 13807 type: 'Number' 13808 } 13809 ], 13810 class: 'p5.Signal', 13811 module: 'p5.sound' 13812 }, 13813 mult: { 13814 name: 'mult', 13815 params: [ 13816 { 13817 name: 'number', 13818 description: '<p>to multiply</p>\n', 13819 type: 'Number' 13820 } 13821 ], 13822 class: 'p5.Signal', 13823 module: 'p5.sound' 13824 }, 13825 scale: { 13826 name: 'scale', 13827 params: [ 13828 { 13829 name: 'number', 13830 description: '<p>to multiply</p>\n', 13831 type: 'Number' 13832 }, 13833 { 13834 name: 'inMin', 13835 description: '<p>input range minumum</p>\n', 13836 type: 'Number' 13837 }, 13838 { 13839 name: 'inMax', 13840 description: '<p>input range maximum</p>\n', 13841 type: 'Number' 13842 }, 13843 { 13844 name: 'outMin', 13845 description: '<p>input range minumum</p>\n', 13846 type: 'Number' 13847 }, 13848 { 13849 name: 'outMax', 13850 description: '<p>input range maximum</p>\n', 13851 type: 'Number' 13852 } 13853 ], 13854 class: 'p5.Signal', 13855 module: 'p5.sound' 13856 } 13857 },
13858 'p5.Envelope': { 13859 attackTime: { 13860 name: 'attackTime', 13861 class: 'p5.Envelope', 13862 module: 'p5.sound' 13863 }, 13864 attackLevel: { 13865 name: 'attackLevel', 13866 class: 'p5.Envelope', 13867 module: 'p5.sound' 13868 }, 13869 decayTime: { 13870 name: 'decayTime', 13871 class: 'p5.Envelope', 13872 module: 'p5.sound' 13873 }, 13874 decayLevel: { 13875 name: 'decayLevel', 13876 class: 'p5.Envelope', 13877 module: 'p5.sound' 13878 }, 13879 releaseTime: { 13880 name: 'releaseTime', 13881 class: 'p5.Envelope', 13882 module: 'p5.sound' 13883 }, 13884 releaseLevel: { 13885 name: 'releaseLevel', 13886 class: 'p5.Envelope', 13887 module: 'p5.sound' 13888 }, 13889 set: { 13890 name: 'set', 13891 params: [ 13892 { 13893 name: 'attackTime', 13894 description: 13895 '<p>Time (in seconds) before level\n reaches attackLevel</p>\n', 13896 type: 'Number' 13897 }, 13898 { 13899 name: 'attackLevel', 13900 description: 13901 '<p>Typically an amplitude between\n 0.0 and 1.0</p>\n', 13902 type: 'Number' 13903 }, 13904 { 13905 name: 'decayTime', 13906 description: '<p>Time</p>\n', 13907 type: 'Number' 13908 }, 13909 { 13910 name: 'decayLevel', 13911 description: 13912 '<p>Amplitude (In a standard ADSR envelope,\n decayLevel = sustainLevel)</p>\n', 13913 type: 'Number' 13914 }, 13915 { 13916 name: 'releaseTime', 13917 description: '<p>Release Time (in seconds)</p>\n', 13918 type: 'Number' 13919 }, 13920 { 13921 name: 'releaseLevel', 13922 description: '<p>Amplitude</p>\n', 13923 type: 'Number' 13924 } 13925 ], 13926 class: 'p5.Envelope', 13927 module: 'p5.sound' 13928 }, 13929 setADSR: { 13930 name: 'setADSR', 13931 params: [ 13932 { 13933 name: 'attackTime', 13934 description: 13935 '<p>Time (in seconds before envelope\n reaches Attack Level</p>\n', 13936 type: 'Number' 13937 }, 13938 { 13939 name: 'decayTime', 13940 description: 13941 '<p>Time (in seconds) before envelope\n reaches Decay/Sustain Level</p>\n', 13942 type: 'Number', 13943 optional: true 13944 }, 13945 { 13946 name: 'susRatio', 13947 description: 13948 '<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', 13949 type: 'Number', 13950 optional: true 13951 }, 13952 { 13953 name: 'releaseTime', 13954 description: '<p>Time in seconds from now (defaults to 0)</p>\n', 13955 type: 'Number', 13956 optional: true 13957 } 13958 ], 13959 class: 'p5.Envelope', 13960 module: 'p5.sound' 13961 }, 13962 setRange: { 13963 name: 'setRange', 13964 params: [ 13965 { 13966 name: 'aLevel', 13967 description: '<p>attack level (defaults to 1)</p>\n', 13968 type: 'Number' 13969 }, 13970 { 13971 name: 'rLevel', 13972 description: '<p>release level (defaults to 0)</p>\n', 13973 type: 'Number' 13974 } 13975 ], 13976 class: 'p5.Envelope', 13977 module: 'p5.sound' 13978 }, 13979 setInput: { 13980 name: 'setInput', 13981 params: [ 13982 { 13983 name: 'inputs', 13984 description: 13985 '<p>A p5.sound object or\n Web Audio Param.</p>\n', 13986 type: 'Object', 13987 optional: true, 13988 multiple: true 13989 } 13990 ], 13991 class: 'p5.Envelope', 13992 module: 'p5.sound' 13993 }, 13994 setExp: { 13995 name: 'setExp', 13996 params: [ 13997 { 13998 name: 'isExp', 13999 description: '<p>true is exponential, false is linear</p>\n', 14000 type: 'Boolean' 14001 } 14002 ], 14003 class: 'p5.Envelope', 14004 module: 'p5.sound' 14005 }, 14006 play: { 14007 name: 'play', 14008 params: [ 14009 { 14010 name: 'unit', 14011 description: 14012 '<p>A p5.sound object or\n Web Audio Param.</p>\n', 14013 type: 'Object' 14014 }, 14015 { 14016 name: 'startTime', 14017 description: '<p>time from now (in seconds) at which to play</p>\n', 14018 type: 'Number', 14019 optional: true 14020 }, 14021 { 14022 name: 'sustainTime', 14023 description: '<p>time to sustain before releasing the envelope</p>\n', 14024 type: 'Number', 14025 optional: true 14026 } 14027 ], 14028 class: 'p5.Envelope', 14029 module: 'p5.sound' 14030 }, 14031 triggerAttack: { 14032 name: 'triggerAttack', 14033 params: [ 14034 { 14035 name: 'unit', 14036 description: '<p>p5.sound Object or Web Audio Param</p>\n', 14037 type: 'Object' 14038 }, 14039 { 14040 name: 'secondsFromNow', 14041 description: '<p>time from now (in seconds)</p>\n', 14042 type: 'Number' 14043 } 14044 ], 14045 class: 'p5.Envelope', 14046 module: 'p5.sound' 14047 }, 14048 triggerRelease: { 14049 name: 'triggerRelease', 14050 params: [ 14051 { 14052 name: 'unit', 14053 description: '<p>p5.sound Object or Web Audio Param</p>\n', 14054 type: 'Object' 14055 }, 14056 { 14057 name: 'secondsFromNow', 14058 description: '<p>time to trigger the release</p>\n', 14059 type: 'Number' 14060 } 14061 ], 14062 class: 'p5.Envelope', 14063 module: 'p5.sound' 14064 }, 14065 ramp: { 14066 name: 'ramp', 14067 params: [ 14068 { 14069 name: 'unit', 14070 description: '<p>p5.sound Object or Web Audio Param</p>\n', 14071 type: 'Object' 14072 }, 14073 { 14074 name: 'secondsFromNow', 14075 description: '<p>When to trigger the ramp</p>\n', 14076 type: 'Number' 14077 }, 14078 { 14079 name: 'v', 14080 description: '<p>Target value</p>\n', 14081 type: 'Number' 14082 }, 14083 { 14084 name: 'v2', 14085 description: '<p>Second target value (optional)</p>\n', 14086 type: 'Number', 14087 optional: true 14088 } 14089 ], 14090 class: 'p5.Envelope', 14091 module: 'p5.sound' 14092 }, 14093 add: { 14094 name: 'add', 14095 params: [ 14096 { 14097 name: 'number', 14098 description: '<p>Constant number to add</p>\n', 14099 type: 'Number' 14100 } 14101 ], 14102 class: 'p5.Envelope', 14103 module: 'p5.sound' 14104 }, 14105 mult: { 14106 name: 'mult', 14107 params: [ 14108 { 14109 name: 'number', 14110 description: '<p>Constant number to multiply</p>\n', 14111 type: 'Number' 14112 } 14113 ], 14114 class: 'p5.Envelope', 14115 module: 'p5.sound' 14116 }, 14117 scale: { 14118 name: 'scale', 14119 params: [ 14120 { 14121 name: 'inMin', 14122 description: '<p>input range minumum</p>\n', 14123 type: 'Number' 14124 }, 14125 { 14126 name: 'inMax', 14127 description: '<p>input range maximum</p>\n', 14128 type: 'Number' 14129 }, 14130 { 14131 name: 'outMin', 14132 description: '<p>input range minumum</p>\n', 14133 type: 'Number' 14134 }, 14135 { 14136 name: 'outMax', 14137 description: '<p>input range maximum</p>\n', 14138 type: 'Number' 14139 } 14140 ], 14141 class: 'p5.Envelope', 14142 module: 'p5.sound' 14143 } 14144 }, 14145 'p5.Pulse': { 14146 width: { 14147 name: 'width', 14148 params: [ 14149 { 14150 name: 'width', 14151 description: 14152 '<p>Width between the pulses (0 to 1.0,\n defaults to 0)</p>\n', 14153 type: 'Number', 14154 optional: true 14155 } 14156 ], 14157 class: 'p5.Pulse', 14158 module: 'p5.sound' 14159 } 14160 }, 14161 'p5.Noise': { 14162 setType: { 14163 name: 'setType', 14164 params: [ 14165 { 14166 name: 'type', 14167 description: "<p>'white', 'pink' or 'brown'</p>\n", 14168 type: 'String', 14169 optional: true 14170 } 14171 ], 14172 class: 'p5.Noise', 14173 module: 'p5.sound' 14174 } 14175 }, 14176 'p5.AudioIn': { 14177 input: { 14178 name: 'input', 14179 class: 'p5.AudioIn', 14180 module: 'p5.sound' 14181 }, 14182 output: { 14183 name: 'output', 14184 class: 'p5.AudioIn', 14185 module: 'p5.sound' 14186 }, 14187 stream: { 14188 name: 'stream', 14189 class: 'p5.AudioIn', 14190 module: 'p5.sound' 14191 }, 14192 mediaStream: { 14193 name: 'mediaStream', 14194 class: 'p5.AudioIn', 14195 module: 'p5.sound' 14196 }, 14197 currentSource: { 14198 name: 'currentSource', 14199 class: 'p5.AudioIn', 14200 module: 'p5.sound' 14201 }, 14202 enabled: { 14203 name: 'enabled', 14204 class: 'p5.AudioIn', 14205 module: 'p5.sound' 14206 }, 14207 amplitude: { 14208 name: 'amplitude', 14209 class: 'p5.AudioIn', 14210 module: 'p5.sound' 14211 }, 14212 start: { 14213 name: 'start', 14214 params: [ 14215 { 14216 name: 'successCallback', 14217 description: 14218 '<p>Name of a function to call on\n success.</p>\n', 14219 type: 'Function', 14220 optional: true 14221 }, 14222 { 14223 name: 'errorCallback', 14224 description: 14225 '<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', 14226 type: 'Function', 14227 optional: true 14228 } 14229 ], 14230 class: 'p5.AudioIn', 14231 module: 'p5.sound' 14232 }, 14233 stop: { 14234 name: 'stop', 14235 class: 'p5.AudioIn', 14236 module: 'p5.sound' 14237 }, 14238 connect: { 14239 name: 'connect', 14240 params: [ 14241 { 14242 name: 'unit', 14243 description: 14244 '<p>An object that accepts audio input,\n such as an FFT</p>\n', 14245 type: 'Object', 14246 optional: true 14247 } 14248 ], 14249 class: 'p5.AudioIn', 14250 module: 'p5.sound' 14251 }, 14252 disconnect: { 14253 name: 'disconnect', 14254 class: 'p5.AudioIn', 14255 module: 'p5.sound' 14256 }, 14257 getLevel: { 14258 name: 'getLevel', 14259 params: [ 14260 { 14261 name: 'smoothing', 14262 description: 14263 '<p>Smoothing is 0.0 by default.\n Smooths values based on previous values.</p>\n', 14264 type: 'Number', 14265 optional: true 14266 } 14267 ], 14268 class: 'p5.AudioIn', 14269 module: 'p5.sound' 14270 }, 14271 amp: { 14272 name: 'amp', 14273 params: [ 14274 { 14275 name: 'vol', 14276 description: '<p>between 0 and 1.0</p>\n', 14277 type: 'Number' 14278 }, 14279 { 14280 name: 'time', 14281 description: '<p>ramp time (optional)</p>\n', 14282 type: 'Number', 14283 optional: true 14284 } 14285 ], 14286 class: 'p5.AudioIn', 14287 module: 'p5.sound' 14288 }, 14289 getSources: { 14290 name: 'getSources', 14291 params: [ 14292 { 14293 name: 'successCallback', 14294 description: 14295 '<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', 14296 type: 'Function', 14297 optional: true 14298 }, 14299 { 14300 name: 'errorCallback', 14301 description: 14302 '<p>This optional callback receives the error\n message as its argument.</p>\n', 14303 type: 'Function', 14304 optional: true 14305 } 14306 ], 14307 class: 'p5.AudioIn', 14308 module: 'p5.sound' 14309 }, 14310 setSource: { 14311 name: 'setSource', 14312
14312 params: [ 14313 { 14314 name: 'num', 14315 description: '<p>position of input source in the array</p>\n', 14316 type: 'Number' 14317 } 14318 ], 14319 class: 'p5.AudioIn', 14320 module: 'p5.sound' 14321 } 14322 }, 14323 'p5.EQ': { 14324 bands: { 14325 name: 'bands', 14326 class: 'p5.EQ', 14327 module: 'p5.sound' 14328 }, 14329 process: { 14330 name: 'process', 14331 params: [ 14332 { 14333 name: 'src', 14334 description: '<p>Audio source</p>\n', 14335 type: 'Object' 14336 } 14337 ], 14338 class: 'p5.EQ', 14339 module: 'p5.sound' 14340 } 14341 }, 14342 'p5.Panner3D': { 14343 panner: { 14344 name: 'panner', 14345 class: 'p5.Panner3D', 14346 module: 'p5.sound' 14347 }, 14348 process: { 14349 name: 'process', 14350 params: [ 14351 { 14352 name: 'src', 14353 description: '<p>Input source</p>\n', 14354 type: 'Object' 14355 } 14356 ], 14357 class: 'p5.Panner3D', 14358 module: 'p5.sound' 14359 }, 14360 set: { 14361 name: 'set', 14362 params: [ 14363 { 14364 name: 'xVal', 14365 description: '', 14366 type: 'Number' 14367 }, 14368 { 14369 name: 'yVal', 14370 description: '', 14371 type: 'Number' 14372 }, 14373 { 14374 name: 'zVal', 14375 description: '', 14376 type: 'Number' 14377 }, 14378 { 14379 name: 'time', 14380 description: '', 14381 type: 'Number' 14382 } 14383 ], 14384 class: 'p5.Panner3D', 14385 module: 'p5.sound' 14386 }, 14387 positionX: { 14388 name: 'positionX', 14389 class: 'p5.Panner3D', 14390 module: 'p5.sound' 14391 }, 14392 positionY: { 14393 name: 'positionY', 14394 class: 'p5.Panner3D', 14395 module: 'p5.sound' 14396 }, 14397 positionZ: { 14398 name: 'positionZ', 14399 class: 'p5.Panner3D', 14400 module: 'p5.sound' 14401 }, 14402 orient: { 14403 name: 'orient', 14404 params: [ 14405 { 14406 name: 'xVal', 14407 description: '', 14408 type: 'Number' 14409 }, 14410 { 14411 name: 'yVal', 14412 description: '', 14413 type: 'Number' 14414 }, 14415 { 14416 name: 'zVal', 14417 description: '', 14418 type: 'Number' 14419 }, 14420 { 14421 name: 'time', 14422 description: '', 14423 type: 'Number' 14424 } 14425 ], 14426 class: 'p5.Panner3D', 14427 module: 'p5.sound' 14428 }, 14429 orientX: { 14430 name: 'orientX', 14431 class: 'p5.Panner3D', 14432 module: 'p5.sound' 14433 }, 14434 orientY: { 14435 name: 'orientY', 14436 class: 'p5.Panner3D', 14437 module: 'p5.sound' 14438 }, 14439 orientZ: { 14440 name: 'orientZ', 14441 class: 'p5.Panner3D', 14442 module: 'p5.sound' 14443 }, 14444 setFalloff: { 14445 name: 'setFalloff', 14446 params: [ 14447 { 14448 name: 'maxDistance', 14449 description: '', 14450 type: 'Number', 14451 optional: true 14452 }, 14453 { 14454 name: 'rolloffFactor', 14455 description: '', 14456 type: 'Number', 14457 optional: true 14458 } 14459 ], 14460 class: 'p5.Panner3D', 14461 module: 'p5.sound' 14462 }, 14463 maxDist: { 14464 name: 'maxDist', 14465 params: [ 14466 { 14467 name: 'maxDistance', 14468 description: '', 14469 type: 'Number' 14470 } 14471 ], 14472 class: 'p5.Panner3D', 14473 module: 'p5.sound' 14474 }, 14475 rollof: { 14476 name: 'rollof', 14477 params: [ 14478 { 14479 name: 'rolloffFactor', 14480 description: '', 14481 type: 'Number' 14482 } 14483 ], 14484 class: 'p5.Panner3D', 14485 module: 'p5.sound' 14486 } 14487 }, 14488 'p5.Delay': { 14489 leftDelay: { 14490 name: 'leftDelay', 14491 class: 'p5.Delay', 14492 module: 'p5.sound' 14493 }, 14494 rightDelay: { 14495 name: 'rightDelay', 14496 class: 'p5.Delay', 14497 module: 'p5.sound' 14498 }, 14499 process: { 14500 name: 'process', 14501 params: [ 14502 { 14503 name: 'Signal', 14504 description: '<p>An object that outputs audio</p>\n', 14505 type: 'Object' 14506 }, 14507 { 14508 name: 'delayTime', 14509 description: 14510 '<p>Time (in seconds) of the delay/echo.\n Some browsers limit delayTime to\n 1 second.</p>\n', 14511 type: 'Number', 14512 optional: true 14513 }, 14514 { 14515 name: 'feedback', 14516 description: 14517 '<p>sends the delay back through itself\n in a loop that decreases in volume\n each time.</p>\n', 14518 type: 'Number', 14519 optional: true 14520 }, 14521 { 14522 name: 'lowPass', 14523 description: 14524 '<p>Cutoff frequency. Only frequencies\n below the lowPass will be part of the\n delay.</p>\n', 14525 type: 'Number', 14526 optional: true 14527 } 14528 ], 14529 class: 'p5.Delay', 14530 module: 'p5.sound' 14531 }, 14532 delayTime: { 14533 name: 'delayTime', 14534 params: [ 14535 { 14536 name: 'delayTime', 14537 description: '<p>Time (in seconds) of the delay</p>\n', 14538 type: 'Number' 14539 } 14540 ], 14541 class: 'p5.Delay', 14542 module: 'p5.sound' 14543 }, 14544 feedback: { 14545 name: 'feedback', 14546 params: [ 14547 { 14548 name: 'feedback', 14549 description: 14550 '<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', 14551 type: 'Number|Object' 14552 } 14553 ], 14554 class: 'p5.Delay', 14555 module: 'p5.sound' 14556 }, 14557 filter: { 14558 name: 'filter', 14559 params: [ 14560 { 14561 name: 'cutoffFreq', 14562 description: 14563 '<p>A lowpass filter will cut off any\n frequencies higher than the filter frequency.</p>\n', 14564 type: 'Number|Object' 14565 }, 14566 { 14567 name: 'res', 14568 description: 14569 '<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', 14570 type: 'Number|Object' 14571 } 14572 ], 14573 class: 'p5.Delay', 14574 module: 'p5.sound' 14575 }, 14576 setType: { 14577 name: 'setType', 14578 params: [ 14579 { 14580 name: 'type', 14581 description: "<p>'pingPong' (1) or 'default' (0)</p>\n", 14582 type: 'String|Number' 14583 } 14584 ], 14585 class: 'p5.Delay', 14586 module: 'p5.sound' 14587 }, 14588 amp: { 14589 name: 'amp', 14590 params: [ 14591 { 14592 name: 'volume', 14593 description: '<p>amplitude between 0 and 1.0</p>\n', 14594 type: 'Number' 14595 }, 14596 { 14597 name: 'rampTime', 14598 description: '<p>create a fade that lasts rampTime</p>\n', 14599 type: 'Number', 14600 optional: true 14601 }, 14602 { 14603 name: 'timeFromNow', 14604 description: 14605 '<p>schedule this event to happen\n seconds from now</p>\n', 14606 type: 'Number', 14607 optional: true 14608 } 14609 ], 14610 class: 'p5.Delay', 14611 module: 'p5.sound' 14612 }, 14613 connect: { 14614 name: 'connect', 14615 params: [ 14616 { 14617 name: 'unit', 14618 description: '', 14619 type: 'Object' 14620 } 14621 ], 14622 class: 'p5.Delay', 14623 module: 'p5.sound' 14624 }, 14625 disconnect: { 14626 name: 'disconnect', 14627 class: 'p5.Delay', 14628 module: 'p5.sound' 14629 } 14630 }, 14631 'p5.Reverb': { 14632 process: { 14633 name: 'process', 14634 params: [ 14635 { 14636 name: 'src', 14637 description: 14638 '<p>p5.sound / Web Audio object with a sound\n output.</p>\n', 14639 type: 'Object' 14640 }, 14641 { 14642 name: 'seconds', 14643 description: 14644 '<p>Duration of the reverb, in seconds.\n Min: 0, Max: 10. Defaults to 3.</p>\n', 14645 type: 'Number', 14646 optional: true 14647 }, 14648 { 14649 name: 'decayRate', 14650 description: 14651 '<p>Percentage of decay with each echo.\n Min: 0, Max: 100. Defaults to 2.</p>\n', 14652 type: 'Number', 14653 optional: true 14654 }, 14655 { 14656 name: 'reverse', 14657 description: '<p>Play the reverb backwards or forwards.</p>\n', 14658 type: 'Boolean', 14659 optional: true 14660 } 14661 ], 14662 class: 'p5.Reverb', 14663 module: 'p5.sound' 14664 }, 14665 set: { 14666 name: 'set', 14667 params: [ 14668 { 14669 name: 'seconds', 14670 description: 14671 '<p>Duration of the reverb, in seconds.\n Min: 0, Max: 10. Defaults to 3.</p>\n', 14672 type: 'Number', 14673 optional: true 14674 }, 14675 { 14676 name: 'decayRate', 14677 description: 14678 '<p>Percentage of decay with each echo.\n Min: 0, Max: 100. Defaults to 2.</p>\n', 14679 type: 'Number', 14680 optional: true 14681 }, 14682 { 14683 name: 'reverse', 14684 description: '<p>Play the reverb backwards or forwards.</p>\n', 14685 type: 'Boolean', 14686 optional: true 14687 } 14688 ], 14689 class: 'p5.Reverb', 14690 module: 'p5.sound' 14691 }, 14692 amp: { 14693 name: 'amp', 14694 params: [ 14695 { 14696 name: 'volume', 14697 description: '<p>amplitude between 0 and 1.0</p>\n', 14698 type: 'Number' 14699 }, 14700 { 14701 name: 'rampTime', 14702 description: '<p>create a fade that lasts rampTime</p>\n', 14703 type: 'Number', 14704 optional: true 14705 }, 14706 { 14707 name: 'timeFromNow', 14708 description: 14709 '<p>schedule this event to happen\n seconds from now</p>\n', 14710 type: 'Number', 14711 optional: true 14712 } 14713 ], 14714 class: 'p5.Reverb', 14715 module: 'p5.sound' 14716 }, 14717 connect: { 14718 name: 'connect', 14719 params: [ 14720 { 14721 name: 'unit', 14722 description: '', 14723 type: 'Object' 14724 } 14725 ], 14726 class: 'p5.Reverb', 14727 module: 'p5.sound' 14728 }, 14729 disconnect: { 14730 name: 'disconnect', 14731 class: 'p5.Reverb', 14732 module: 'p5.sound' 14733 } 14734 }, 14735 'p5.Convolver': { 14736 convolverNode: { 14737 name: 'convolverNode', 14738 class: 'p5.Convolver', 14739 module: 'p5.sound' 14740 }, 14741 process: { 14742 name: 'process', 14743 params: [ 14744 { 14745 name: 'src', 14746 description: 14747 '<p>p5.sound / Web Audio object with a sound\n output.</p>\n', 14748 type: 'Object' 14749 } 14750 ], 14751 class: 'p5.Convolver', 14752 module: 'p5.sound' 14753 }, 14754 impulses: { 14755 name: 'impulses', 14756 class: 'p5.Convolver', 14757 module: 'p5.sound' 14758 }, 14759 addImpulse: { 14760 name: 'addImpulse', 14761 params: [ 14762 { 14763 name: 'path', 14764 description: '<p>
14764path to a sound file</p>\n', 14765 type: 'String' 14766 }, 14767 { 14768 name: 'callback', 14769 description: '<p>function (optional)</p>\n', 14770 type: 'Function' 14771 }, 14772 { 14773 name: 'errorCallback', 14774 description: '<p>function (optional)</p>\n', 14775 type: 'Function' 14776 } 14777 ], 14778 class: 'p5.Convolver', 14779 module: 'p5.sound' 14780 }, 14781 resetImpulse: { 14782 name: 'resetImpulse', 14783 params: [ 14784 { 14785 name: 'path', 14786 description: '<p>path to a sound file</p>\n', 14787 type: 'String' 14788 }, 14789 { 14790 name: 'callback', 14791 description: '<p>function (optional)</p>\n', 14792 type: 'Function' 14793 }, 14794 { 14795 name: 'errorCallback', 14796 description: '<p>function (optional)</p>\n', 14797 type: 'Function' 14798 } 14799 ], 14800 class: 'p5.Convolver', 14801 module: 'p5.sound' 14802 }, 14803 toggleImpulse: { 14804 name: 'toggleImpulse', 14805 params: [ 14806 { 14807 name: 'id', 14808 description: 14809 '<p>Identify the impulse by its original filename\n (String), or by its position in the\n <code>.impulses</code> Array (Number).</p>\n', 14810 type: 'String|Number' 14811 } 14812 ], 14813 class: 'p5.Convolver', 14814 module: 'p5.sound' 14815 } 14816 }, 14817 'p5.Phrase': { 14818 sequence: { 14819 name: 'sequence', 14820 class: 'p5.Phrase', 14821 module: 'p5.sound' 14822 } 14823 }, 14824 'p5.Part': { 14825 setBPM: { 14826 name: 'setBPM', 14827 params: [ 14828 { 14829 name: 'BPM', 14830 description: '<p>Beats Per Minute</p>\n', 14831 type: 'Number' 14832 }, 14833 { 14834 name: 'rampTime', 14835 description: '<p>Seconds from now</p>\n', 14836 type: 'Number', 14837 optional: true 14838 } 14839 ], 14840 class: 'p5.Part', 14841 module: 'p5.sound' 14842 }, 14843 getBPM: { 14844 name: 'getBPM', 14845 class: 'p5.Part', 14846 module: 'p5.sound' 14847 }, 14848 start: { 14849 name: 'start', 14850 params: [ 14851 { 14852 name: 'time', 14853 description: '<p>seconds from now</p>\n', 14854 type: 'Number', 14855 optional: true 14856 } 14857 ], 14858 class: 'p5.Part', 14859 module: 'p5.sound' 14860 }, 14861 loop: { 14862 name: 'loop', 14863 params: [ 14864 { 14865 name: 'time', 14866 description: '<p>seconds from now</p>\n', 14867 type: 'Number', 14868 optional: true 14869 } 14870 ], 14871 class: 'p5.Part', 14872 module: 'p5.sound' 14873 }, 14874 noLoop: { 14875 name: 'noLoop', 14876 class: 'p5.Part', 14877 module: 'p5.sound' 14878 }, 14879 stop: { 14880 name: 'stop', 14881 params: [ 14882 { 14883 name: 'time', 14884 description: '<p>seconds from now</p>\n', 14885 type: 'Number', 14886 optional: true 14887 } 14888 ], 14889 class: 'p5.Part', 14890 module: 'p5.sound' 14891 }, 14892 pause: { 14893 name: 'pause', 14894 params: [ 14895 { 14896 name: 'time', 14897 description: '<p>seconds from now</p>\n', 14898 type: 'Number' 14899 } 14900 ], 14901 class: 'p5.Part', 14902 module: 'p5.sound' 14903 }, 14904 addPhrase: { 14905 name: 'addPhrase', 14906 params: [ 14907 { 14908 name: 'phrase', 14909 description: '<p>reference to a p5.Phrase</p>\n', 14910 type: 'p5.Phrase' 14911 } 14912 ], 14913 class: 'p5.Part', 14914 module: 'p5.sound' 14915 }, 14916 removePhrase: { 14917 name: 'removePhrase', 14918 params: [ 14919 { 14920 name: 'phraseName', 14921 description: '', 14922 type: 'String' 14923 } 14924 ], 14925 class: 'p5.Part', 14926 module: 'p5.sound' 14927 }, 14928 getPhrase: { 14929 name: 'getPhrase', 14930 params: [ 14931 { 14932 name: 'phraseName', 14933 description: '', 14934 type: 'String' 14935 } 14936 ], 14937 class: 'p5.Part', 14938 module: 'p5.sound' 14939 }, 14940 replaceSequence: { 14941 name: 'replaceSequence', 14942 params: [ 14943 { 14944 name: 'phraseName', 14945 description: '', 14946 type: 'String' 14947 }, 14948 { 14949 name: 'sequence', 14950 description: 14951 '<p>Array of values to pass into the callback\n at each step of the phrase.</p>\n', 14952 type: 'Array' 14953 } 14954 ], 14955 class: 'p5.Part', 14956 module: 'p5.sound' 14957 }, 14958 onStep: { 14959 name: 'onStep', 14960 params: [ 14961 { 14962 name: 'callback', 14963 description: 14964 '<p>The name of the callback\n you want to fire\n on every beat/tatum.</p>\n', 14965 type: 'Function' 14966 } 14967 ], 14968 class: 'p5.Part', 14969 module: 'p5.sound' 14970 } 14971 }, 14972 'p5.Score': { 14973 start: { 14974 name: 'start', 14975 class: 'p5.Score', 14976 module: 'p5.sound' 14977 }, 14978 stop: { 14979 name: 'stop', 14980 class: 'p5.Score', 14981 module: 'p5.sound' 14982 }, 14983 pause: { 14984 name: 'pause', 14985 class: 'p5.Score', 14986 module: 'p5.sound' 14987 }, 14988 loop: { 14989 name: 'loop', 14990 class: 'p5.Score', 14991 module: 'p5.sound' 14992 }, 14993 noLoop: { 14994 name: 'noLoop', 14995 class: 'p5.Score', 14996 module: 'p5.sound' 14997 }, 14998 setBPM: { 14999 name: 'setBPM', 15000 params: [ 15001 { 15002 name: 'BPM', 15003 description: '<p>Beats Per Minute</p>\n', 15004 type: 'Number' 15005 }, 15006 { 15007 name: 'rampTime', 15008 description: '<p>Seconds from now</p>\n', 15009 type: 'Number' 15010 } 15011 ], 15012 class: 'p5.Score', 15013 module: 'p5.sound' 15014 } 15015 }, 15016 'p5.SoundLoop': { 15017 musicalTimeMode: { 15018 name: 'musicalTimeMode', 15019 class: 'p5.SoundLoop', 15020 module: 'p5.sound' 15021 }, 15022 maxIterations: { 15023 name: 'maxIterations', 15024 class: 'p5.SoundLoop', 15025 module: 'p5.sound' 15026 }, 15027 start: { 15028 name: 'start', 15029 params: [ 15030 { 15031 name: 'timeFromNow', 15032 description: '<p>schedule a starting time</p>\n', 15033 type: 'Number', 15034 optional: true 15035 } 15036 ], 15037 class: 'p5.SoundLoop', 15038 module: 'p5.sound' 15039 }, 15040 stop: { 15041 name: 'stop', 15042 params: [ 15043 { 15044 name: 'timeFromNow', 15045 description: '<p>schedule a stopping time</p>\n', 15046 type: 'Number', 15047 optional: true 15048 } 15049 ], 15050 class: 'p5.SoundLoop', 15051 module: 'p5.sound' 15052 }, 15053 pause: { 15054 name: 'pause', 15055 params: [ 15056 { 15057 name: 'timeFromNow', 15058 description: '<p>schedule a pausing time</p>\n', 15059 type: 'Number', 15060 optional: true 15061 } 15062 ], 15063 class: 'p5.SoundLoop', 15064 module: 'p5.sound' 15065 }, 15066 syncedStart: { 15067 name: 'syncedStart', 15068 params: [ 15069 { 15070 name: 'otherLoop', 15071 description: '<p>a p5.SoundLoop to sync with</p>\n', 15072 type: 'Object' 15073 }, 15074 { 15075 name: 'timeFromNow', 15076 description: 15077 '<p>Start the loops in sync after timeFromNow seconds</p>\n', 15078 type: 'Number', 15079 optional: true 15080 } 15081 ], 15082 class: 'p5.SoundLoop', 15083 module: 'p5.sound' 15084 }, 15085 bpm: { 15086 name: 'bpm', 15087 class: 'p5.SoundLoop', 15088 module: 'p5.sound' 15089 }, 15090 timeSignature: { 15091 name: 'timeSignature', 15092 class: 'p5.SoundLoop', 15093 module: 'p5.sound' 15094 }, 15095 interval: { 15096 name: 'interval', 15097 class: 'p5.SoundLoop', 15098 module: 'p5.sound' 15099 }, 15100 iterations: { 15101 name: 'iterations', 15102 class: 'p5.SoundLoop', 15103 module: 'p5.sound' 15104 } 15105 }, 15106 'p5.Compressor': { 15107 compressor: { 15108 name: 'compressor', 15109 class: 'p5.Compressor', 15110 module: 'p5.sound' 15111 }, 15112 process: { 15113 name: 'process', 15114 params: [ 15115 { 15116 name: 'src', 15117 description: '<p>Sound source to be connected</p>\n', 15118 type: 'Object' 15119 }, 15120 { 15121 name: 'attack', 15122 description: 15123 '<p>The amount of time (in seconds) to reduce the gain by 10dB,\n default = .003, range 0 - 1</p>\n', 15124 type: 'Number', 15125 optional: true 15126 }, 15127 { 15128 name: 'knee', 15129 description: 15130 '<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', 15131 type: 'Number', 15132 optional: true 15133 }, 15134 { 15135 name: 'ratio', 15136 description: 15137 '<p>The amount of dB change in input for a 1 dB change in output\n default = 12, range 1 - 20</p>\n', 15138 type: 'Number', 15139 optional: true 15140 }, 15141 { 15142 name: 'threshold', 15143 description: 15144 '<p>The decibel value above which the compression will start taking effect\n default = -24, range -100 - 0</p>\n', 15145 type: 'Number', 15146 optional: true 15147 }, 15148 { 15149 name: 'release', 15150 description: 15151 '<p>The amount of time (in seconds) to increase the gain by 10dB\n default = .25, range 0 - 1</p>\n', 15152 type: 'Number', 15153 optional: true 15154 } 15155 ], 15156 class: 'p5.Compressor', 15157 module: 'p5.sound' 15158 }, 15159 set: { 15160 name: 'set', 15161 params: [ 15162 { 15163 name: 'attack', 15164 description: 15165 '<p>The amount of time (in seconds) to reduce the gain by 10dB,\n default = .003, range 0 - 1</p>\n', 15166 type: 'Number' 15167 }, 15168 { 15169 name: 'knee', 15170 description: 15171 '<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', 15172 type: 'Number' 15173 }, 15174 { 15175 name: 'ratio', 15176 description: 15177 '<p>The amount of dB change in input for a 1 dB change in output\n default = 12, range 1 - 20</p>\n', 15178 type: 'Number' 15179 }, 15180 { 15181 name: 'threshold', 15182 description: 15183 '<p>The decibel value above which the compression will start taking effect\n default = -24, range -100 - 0</p>\n', 15184 type: 'Number' 15185 }, 15186 { 15187 name: 'release', 15188 description: 15189 '<p>The amount of time (in seconds) to increase the gain by 10dB\n default = .25, range 0 - 1</p>\n', 15190 type: 'Number' 15191 } 15192 ], 15193 class: 'p5.Compressor', 15194 module: 'p5.sound' 15195 }, 15196 attack: { 15197 name: 'attack', 15198 params: [ 15199 { 15200 name: 'attack', 15201 description: 15202 '<p>Attack is the amount of time (in seconds) to reduce the gain by 10dB,\n default = .003, range 0 - 1</p>\n', 15203 type: 'Number', 15204 optional: true 15205 }, 15206 { 15207 name: 'time', 15208 description: 15209 '<p>Assign time value to schedule the change in value</p>\n', 15210 type: 'Number', 15211 optional: true 15212 } 15213 ], 15214 class: 'p5.Compressor', 15215 module: 'p5.sound' 15216 }, 15217 knee: { 15218 name: 'knee', 15219 params: [ 15220 { 15221 name: 'knee', 15222 description: 15223 '<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', 15224 type: 'Number', 15225 optional: true 15226 }, 15227 { 15228 name: 'time', 15229 description: 15230 '<p>Assign time value to schedule the change in value</p>\n', 15231
15231 type: 'Number', 15232 optional: true 15233 } 15234 ], 15235 class: 'p5.Compressor', 15236 module: 'p5.sound' 15237 }, 15238 ratio: { 15239 name: 'ratio', 15240 params: [ 15241 { 15242 name: 'ratio', 15243 description: 15244 '<p>The amount of dB change in input for a 1 dB change in output\n default = 12, range 1 - 20</p>\n', 15245 type: 'Number', 15246 optional: true 15247 }, 15248 { 15249 name: 'time', 15250 description: 15251 '<p>Assign time value to schedule the change in value</p>\n', 15252 type: 'Number', 15253 optional: true 15254 } 15255 ], 15256 class: 'p5.Compressor', 15257 module: 'p5.sound' 15258 }, 15259 threshold: { 15260 name: 'threshold', 15261 params: [ 15262 { 15263 name: 'threshold', 15264 description: 15265 '<p>The decibel value above which the compression will start taking effect\n default = -24, range -100 - 0</p>\n', 15266 type: 'Number' 15267 }, 15268 { 15269 name: 'time', 15270 description: 15271 '<p>Assign time value to schedule the change in value</p>\n', 15272 type: 'Number', 15273 optional: true 15274 } 15275 ], 15276 class: 'p5.Compressor', 15277 module: 'p5.sound' 15278 }, 15279 release: { 15280 name: 'release', 15281 params: [ 15282 { 15283 name: 'release', 15284 description: 15285 '<p>The amount of time (in seconds) to increase the gain by 10dB\n default = .25, range 0 - 1</p>\n', 15286 type: 'Number' 15287 }, 15288 { 15289 name: 'time', 15290 description: 15291 '<p>Assign time value to schedule the change in value</p>\n', 15292 type: 'Number', 15293 optional: true 15294 } 15295 ], 15296 class: 'p5.Compressor', 15297 module: 'p5.sound' 15298 }, 15299 reduction: { 15300 name: 'reduction', 15301 class: 'p5.Compressor', 15302 module: 'p5.sound' 15303 } 15304 }, 15305 'p5.SoundRecorder': { 15306 setInput: { 15307 name: 'setInput', 15308 params: [ 15309 { 15310 name: 'unit', 15311 description: 15312 '<p>p5.sound object or a web audio unit\n that outputs sound</p>\n', 15313 type: 'Object', 15314 optional: true 15315 } 15316 ], 15317 class: 'p5.SoundRecorder', 15318 module: 'p5.sound' 15319 }, 15320 record: { 15321 name: 'record', 15322 params: [ 15323 { 15324 name: 'soundFile', 15325 description: '<p>p5.SoundFile</p>\n', 15326 type: 'p5.SoundFile' 15327 }, 15328 { 15329 name: 'duration', 15330 description: '<p>Time (in seconds)</p>\n', 15331 type: 'Number', 15332 optional: true 15333 }, 15334 { 15335 name: 'callback', 15336 description: 15337 '<p>The name of a function that will be\n called once the recording completes</p>\n', 15338 type: 'Function', 15339 optional: true 15340 } 15341 ], 15342 class: 'p5.SoundRecorder', 15343 module: 'p5.sound' 15344 }, 15345 stop: { 15346 name: 'stop', 15347 class: 'p5.SoundRecorder', 15348 module: 'p5.sound' 15349 } 15350 }, 15351 'p5.PeakDetect': { 15352 isDetected: { 15353 name: 'isDetected', 15354 class: 'p5.PeakDetect', 15355 module: 'p5.sound' 15356 }, 15357 update: { 15358 name: 'update', 15359 params: [ 15360 { 15361 name: 'fftObject', 15362 description: '<p>A p5.FFT object</p>\n', 15363 type: 'p5.FFT' 15364 } 15365 ], 15366 class: 'p5.PeakDetect', 15367 module: 'p5.sound' 15368 }, 15369 onPeak: { 15370 name: 'onPeak', 15371 params: [ 15372 { 15373 name: 'callback', 15374 description: 15375 '<p>Name of a function that will\n be called when a peak is\n detected.</p>\n', 15376 type: 'Function' 15377 }, 15378 { 15379 name: 'val', 15380 description: 15381 '<p>Optional value to pass\n into the function when\n a peak is detected.</p>\n', 15382 type: 'Object', 15383 optional: true 15384 } 15385 ], 15386 class: 'p5.PeakDetect', 15387 module: 'p5.sound' 15388 } 15389 }, 15390 'p5.Gain': { 15391 setInput: { 15392 name: 'setInput', 15393 params: [ 15394 { 15395 name: 'src', 15396 description: 15397 '<p>p5.sound / Web Audio object with a sound\n output.</p>\n', 15398 type: 'Object' 15399 } 15400 ], 15401 class: 'p5.Gain', 15402 module: 'p5.sound' 15403 }, 15404 connect: { 15405 name: 'connect', 15406 params: [ 15407 { 15408 name: 'unit', 15409 description: '', 15410 type: 'Object' 15411 } 15412 ], 15413 class: 'p5.Gain', 15414 module: 'p5.sound' 15415 }, 15416 disconnect: { 15417 name: 'disconnect', 15418 class: 'p5.Gain', 15419 module: 'p5.sound' 15420 }, 15421 amp: { 15422 name: 'amp', 15423 params: [ 15424 { 15425 name: 'volume', 15426 description: '<p>amplitude between 0 and 1.0</p>\n', 15427 type: 'Number' 15428 }, 15429 { 15430 name: 'rampTime', 15431 description: '<p>create a fade that lasts rampTime</p>\n', 15432 type: 'Number', 15433 optional: true 15434 }, 15435 { 15436 name: 'timeFromNow', 15437 description: 15438 '<p>schedule this event to happen\n seconds from now</p>\n', 15439 type: 'Number', 15440 optional: true 15441 } 15442 ], 15443 class: 'p5.Gain', 15444 module: 'p5.sound' 15445 } 15446 }, 15447 'p5.Distortion': { 15448 WaveShaperNode: { 15449 name: 'WaveShaperNode', 15450 class: 'p5.Distortion', 15451 module: 'p5.sound' 15452 }, 15453 process: { 15454 name: 'process', 15455 params: [ 15456 { 15457 name: 'amount', 15458 description: 15459 '<p>Unbounded distortion amount.\n Normal values range from 0-1.</p>\n', 15460 type: 'Number', 15461 optional: true, 15462 optdefault: '0.25' 15463 }, 15464 { 15465 name: 'oversample', 15466 description: "<p>'none', '2x', or '4x'.</p>\n", 15467 type: 'String', 15468 optional: true, 15469 optdefault: "'none'" 15470 } 15471 ], 15472 class: 'p5.Distortion', 15473 module: 'p5.sound' 15474 }, 15475 set: { 15476 name: 'set', 15477 params: [ 15478 { 15479 name: 'amount', 15480 description: 15481 '<p>Unbounded distortion amount.\n Normal values range from 0-1.</p>\n', 15482 type: 'Number', 15483 optional: true, 15484 optdefault: '0.25' 15485 }, 15486 { 15487 name: 'oversample', 15488 description: "<p>'none', '2x', or '4x'.</p>\n", 15489 type: 'String', 15490 optional: true, 15491 optdefault: "'none'" 15492 } 15493 ], 15494 class: 'p5.Distortion', 15495 module: 'p5.sound' 15496 }, 15497 getAmount: { 15498 name: 'getAmount', 15499 class: 'p5.Distortion', 15500 module: 'p5.sound' 15501 }, 15502 getOversample: { 15503 name: 'getOversample', 15504 class: 'p5.Distortion', 15505 module: 'p5.sound' 15506 } 15507 } 15508 }; 15509 }, 15510 {} 15511 ], 15512 2: [
15513 function(_dereq_, module, exports) { 15514 function _arrayWithHoles(arr) { 15515 if (Array.isArray(arr)) return arr; 15516 } 15517 15518 module.exports = _arrayWithHoles; 15519 }, 15520 {} 15521 ], 15522 3: [ 15523 function(_dereq_, module, exports) { 15524 function _arrayWithoutHoles(arr) { 15525 if (Array.isArray(arr)) { 15526 for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { 15527 arr2[i] = arr[i]; 15528 } 15529 15530 return arr2; 15531 } 15532 } 15533 15534 module.exports = _arrayWithoutHoles; 15535 }, 15536 {} 15537 ], 15538 4: [ 15539 function(_dereq_, module, exports) { 15540 function _assertThisInitialized(self) { 15541 if (self === void 0) { 15542 throw new ReferenceError( 15543 "this hasn't been initialised - super() hasn't been called" 15544 ); 15545 } 15546 15547 return self; 15548 } 15549 15550 module.exports = _assertThisInitialized; 15551 }, 15552 {} 15553 ], 15554 5: [ 15555 function(_dereq_, module, exports) { 15556 function _classCallCheck(instance, Constructor) { 15557 if (!(instance instanceof Constructor)) { 15558 throw new TypeError('Cannot call a class as a function'); 15559 } 15560 } 15561 15562 module.exports = _classCallCheck; 15563 }, 15564 {} 15565 ], 15566 6: [ 15567 function(_dereq_, module, exports) { 15568 function _defineProperties(target, props) { 15569 for (var i = 0; i < props.length; i++) { 15570 var descriptor = props[i]; 15571 descriptor.enumerable = descriptor.enumerable || false; 15572 descriptor.configurable = true; 15573 if ('value' in descriptor) descriptor.writable = true; 15574 Object.defineProperty(target, descriptor.key, descriptor); 15575 } 15576 } 15577 15578 function _createClass(Constructor, protoProps, staticProps) { 15579 if (protoProps) _defineProperties(Constructor.prototype, protoProps); 15580 if (staticProps) _defineProperties(Constructor, staticProps); 15581 return Constructor; 15582 } 15583 15584 module.exports = _createClass; 15585 }, 15586 {} 15587 ], 15588 7: [ 15589 function(_dereq_, module, exports) { 15590 function _defineProperty(obj, key, value) { 15591 if (key in obj) { 15592 Object.defineProperty(obj, key, { 15593 value: value, 15594 enumerable: true, 15595 configurable: true, 15596 writable: true 15597 }); 15598 } else { 15599 obj[key] = value; 15600 } 15601 15602 return obj; 15603 } 15604 15605 module.exports = _defineProperty; 15606 }, 15607 {} 15608 ], 15609 8: [ 15610 function(_dereq_, module, exports) { 15611 function _getPrototypeOf(o) { 15612 module.exports = _getPrototypeOf = Object.setPrototypeOf 15613 ? Object.getPrototypeOf 15614 : function _getPrototypeOf(o) { 15615 return o.__proto__ || Object.getPrototypeOf(o); 15616 }; 15617 return _getPrototypeOf(o); 15618 } 15619 15620 module.exports = _getPrototypeOf; 15621 }, 15622 {} 15623 ], 15624 9: [ 15625 function(_dereq_, module, exports) { 15626 var setPrototypeOf = _dereq_('./setPrototypeOf'); 15627 15628 function _inherits(subClass, superClass) { 15629 if (typeof superClass !== 'function' && superClass !== null) { 15630 throw new TypeError('Super expression must either be null or a function'); 15631 } 15632 15633 subClass.prototype = Object.create(superClass && superClass.prototype, { 15634 constructor: { 15635 value: subClass, 15636 writable: true, 15637 configurable: true 15638 } 15639 }); 15640 if (superClass) setPrototypeOf(subClass, superClass); 15641 } 15642 15643 module.exports = _inherits; 15644 }, 15645 { './setPrototypeOf': 16 } 15646 ], 15647 10: [ 15648 function(_dereq_, module, exports) { 15649 function _iterableToArray(iter) { 15650 if ( 15651 Symbol.iterator in Object(iter) || 15652 Object.prototype.toString.call(iter) === '[object Arguments]' 15653 ) 15654 return Array.from(iter); 15655 } 15656 15657 module.exports = _iterableToArray; 15658 }, 15659 {} 15660 ], 15661 11: [
15662 function(_dereq_, module, exports) { 15663 function _iterableToArrayLimit(arr, i) { 15664 var _arr = []; 15665 var _n = true; 15666 var _d = false; 15667 var _e = undefined; 15668 15669 try { 15670 for ( 15671 var _i = arr[Symbol.iterator](), _s; 15672 !(_n = (_s = _i.next()).done); 15673 _n = true 15674 ) { 15675 _arr.push(_s.value); 15676 15677 if (i && _arr.length === i) break; 15678 } 15679 } catch (err) { 15680 _d = true; 15681 _e = err; 15682 } finally { 15683 try { 15684 if (!_n && _i['return'] != null) _i['return'](); 15685 } finally { 15686 if (_d) throw _e; 15687 } 15688 } 15689 15690 return _arr; 15691 } 15692 15693 module.exports = _iterableToArrayLimit; 15694 }, 15695 {} 15696 ], 15697 12: [ 15698 function(_dereq_, module, exports) { 15699 function _nonIterableRest() { 15700 throw new TypeError('Invalid attempt to destructure non-iterable instance'); 15701 } 15702 15703 module.exports = _nonIterableRest; 15704 }, 15705 {} 15706 ], 15707 13: [ 15708 function(_dereq_, module, exports) { 15709 function _nonIterableSpread() { 15710 throw new TypeError('Invalid attempt to spread non-iterable instance'); 15711 } 15712 15713 module.exports = _nonIterableSpread; 15714 }, 15715 {} 15716 ], 15717 14: [ 15718 function(_dereq_, module, exports) { 15719 var defineProperty = _dereq_('./defineProperty'); 15720 15721 function _objectSpread(target) { 15722 for (var i = 1; i < arguments.length; i++) { 15723 var source = arguments[i] != null ? arguments[i] : {}; 15724 var ownKeys = Object.keys(source); 15725 15726 if (typeof Object.getOwnPropertySymbols === 'function') { 15727 ownKeys = ownKeys.concat( 15728 Object.getOwnPropertySymbols(source).filter(function(sym) { 15729 return Object.getOwnPropertyDescriptor(source, sym).enumerable; 15730 }) 15731 ); 15732 } 15733 15734 ownKeys.forEach(function(key) { 15735 defineProperty(target, key, source[key]); 15736 }); 15737 } 15738 15739 return target; 15740 } 15741 15742 module.exports = _objectSpread; 15743 }, 15744 { './defineProperty': 7 } 15745 ], 15746 15: [ 15747 function(_dereq_, module, exports) { 15748 var _typeof = _dereq_('../helpers/typeof'); 15749 15750 var assertThisInitialized = _dereq_('./assertThisInitialized'); 15751 15752 function _possibleConstructorReturn(self, call) { 15753 if (call && (_typeof(call) === 'object' || typeof call === 'function')) { 15754 return call; 15755 } 15756 15757 return assertThisInitialized(self); 15758 } 15759 15760 module.exports = _possibleConstructorReturn; 15761 }, 15762 { '../helpers/typeof': 19, './assertThisInitialized': 4 } 15763 ], 15764 16: [ 15765 function(_dereq_, module, exports) { 15766 function _setPrototypeOf(o, p) { 15767 module.exports = _setPrototypeOf = 15768 Object.setPrototypeOf || 15769 function _setPrototypeOf(o, p) { 15770 o.__proto__ = p; 15771 return o; 15772 }; 15773 15774 return _setPrototypeOf(o, p); 15775 } 15776 15777 module.exports = _setPrototypeOf; 15778 }, 15779 {} 15780 ], 15781 17: [ 15782 function(_dereq_, module, exports) { 15783 var arrayWithHoles = _dereq_('./arrayWithHoles'); 15784 15785 var iterableToArrayLimit = _dereq_('./iterableToArrayLimit'); 15786 15787 var nonIterableRest = _dereq_('./nonIterableRest'); 15788 15789 function _slicedToArray(arr, i) { 15790 return arrayWithHoles(arr) || iterableToArrayLimit(arr, i) || nonIterableRest(); 15791 } 15792 15793 module.exports = _slicedToArray; 15794 }, 15795 { './arrayWithHoles': 2, './iterableToArrayLimit': 11, './nonIterableRest': 12 } 15796 ], 15797 18: [ 15798 function(_dereq_, module, exports) { 15799 var arrayWithoutHoles = _dereq_('./arrayWithoutHoles'); 15800 15801 var iterableToArray = _dereq_('./iterableToArray'); 15802 15803 var nonIterableSpread = _dereq_('./nonIterableSpread'); 15804 15805 function _toConsumableArray(arr) { 15806 return arrayWithoutHoles(arr) || iterableToArray(arr) || nonIterableSpread(); 15807 } 15808 15809 module.exports = _toConsumableArray; 15810 }, 15811 { './arrayWithoutHoles': 3, './iterableToArray': 10, './nonIterableSpread': 13 } 15812 ], 15813 19: [
15814 function(_dereq_, module, exports) { 15815 function _typeof2(obj) { 15816 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') { 15817 _typeof2 = function _typeof2(obj) { 15818 return typeof obj; 15819 }; 15820 } else { 15821 _typeof2 = function _typeof2(obj) { 15822 return obj && 15823 typeof Symbol === 'function' && 15824 obj.constructor === Symbol && 15825 obj !== Symbol.prototype 15826 ? 'symbol' 15827 : typeof obj; 15828 }; 15829 } 15830 return _typeof2(obj); 15831 } 15832 15833 function _typeof(obj) { 15834 if (typeof Symbol === 'function' && _typeof2(Symbol.iterator) === 'symbol') { 15835 module.exports = _typeof = function _typeof(obj) { 15836 return _typeof2(obj); 15837 }; 15838 } else { 15839 module.exports = _typeof = function _typeof(obj) { 15840 return obj && 15841 typeof Symbol === 'function' && 15842 obj.constructor === Symbol && 15843 obj !== Symbol.prototype 15844 ? 'symbol' 15845 : _typeof2(obj); 15846 }; 15847 } 15848 15849 return _typeof(obj); 15850 } 15851 15852 module.exports = _typeof; 15853 }, 15854 {} 15855 ], 15856 20: [ 15857 function(_dereq_, module, exports) { 15858 'use strict'; 15859 15860 exports.byteLength = byteLength; 15861 exports.toByteArray = toByteArray; 15862 exports.fromByteArray = fromByteArray; 15863 15864 var lookup = []; 15865 var revLookup = []; 15866 var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array; 15867 15868 var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; 15869 for (var i = 0, len = code.length; i < len; ++i) { 15870 lookup[i] = code[i]; 15871 revLookup[code.charCodeAt(i)] = i; 15872 } 15873 15874 // Support decoding URL-safe base64 strings, as Node.js does. 15875 // See: https://en.wikipedia.org/wiki/Base64#URL_applications 15876 revLookup['-'.charCodeAt(0)] = 62; 15877 revLookup['_'.charCodeAt(0)] = 63; 15878 15879 function getLens(b64) { 15880 var len = b64.length; 15881 15882 if (len % 4 > 0) { 15883 throw new Error('Invalid string. Length must be a multiple of 4'); 15884 } 15885 15886 // Trim off extra bytes after placeholder bytes are found 15887 // See: https://github.com/beatgammit/base64-js/issues/42 15888 var validLen = b64.indexOf('='); 15889 if (validLen === -1) validLen = len; 15890 15891 var placeHoldersLen = validLen === len ? 0 : 4 - validLen % 4; 15892 15893 return [validLen, placeHoldersLen]; 15894 } 15895 15896 // base64 is 4/3 + up to two characters of the original data 15897 function byteLength(b64) { 15898 var lens = getLens(b64); 15899 var validLen = lens[0]; 15900 var placeHoldersLen = lens[1]; 15901 return (validLen + placeHoldersLen) * 3 / 4 - placeHoldersLen; 15902 } 15903 15904 function _byteLength(b64, validLen, placeHoldersLen) { 15905 return (validLen + placeHoldersLen) * 3 / 4 - placeHoldersLen; 15906 } 15907 15908 function toByteArray(b64) { 15909 var tmp; 15910 var lens = getLens(b64); 15911 var validLen = lens[0]; 15912 var placeHoldersLen = lens[1]; 15913 15914 var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen)); 15915 15916 var curByte = 0; 15917 15918 // if there are placeholders, only get up to the last complete 4 chars 15919 var len = placeHoldersLen > 0 ? validLen - 4 : validLen; 15920 15921 var i; 15922 for (i = 0; i < len; i += 4) { 15923 tmp = 15924 (revLookup[b64.charCodeAt(i)] << 18) | 15925 (revLookup[b64.charCodeAt(i + 1)] << 12) | 15926 (revLookup[b64.charCodeAt(i + 2)] << 6) | 15927 revLookup[b64.charCodeAt(i + 3)]; 15928 arr[curByte++] = (tmp >> 16) & 0xff; 15929 arr[curByte++] = (tmp >> 8) & 0xff;
15930 arr[curByte++] = tmp & 0xff; 15931 } 15932 15933 if (placeHoldersLen === 2) { 15934 tmp = 15935 (revLookup[b64.charCodeAt(i)] << 2) | 15936 (revLookup[b64.charCodeAt(i + 1)] >> 4); 15937 arr[curByte++] = tmp & 0xff; 15938 } 15939 15940 if (placeHoldersLen === 1) { 15941 tmp = 15942 (revLookup[b64.charCodeAt(i)] << 10) | 15943 (revLookup[b64.charCodeAt(i + 1)] << 4) | 15944 (revLookup[b64.charCodeAt(i + 2)] >> 2); 15945 arr[curByte++] = (tmp >> 8) & 0xff; 15946 arr[curByte++] = tmp & 0xff; 15947 } 15948 15949 return arr; 15950 } 15951 15952 function tripletToBase64(num) { 15953 return ( 15954 lookup[(num >> 18) & 0x3f] + 15955 lookup[(num >> 12) & 0x3f] + 15956 lookup[(num >> 6) & 0x3f] + 15957 lookup[num & 0x3f] 15958 ); 15959 } 15960 15961 function encodeChunk(uint8, start, end) { 15962 var tmp; 15963 var output = []; 15964 for (var i = start; i < end; i += 3) { 15965 tmp = 15966 ((uint8[i] << 16) & 0xff0000) + 15967 ((uint8[i + 1] << 8) & 0xff00) + 15968 (uint8[i + 2] & 0xff); 15969 output.push(tripletToBase64(tmp)); 15970 } 15971 return output.join(''); 15972 } 15973 15974 function fromByteArray(uint8) { 15975 var tmp; 15976 var len = uint8.length; 15977 var extraBytes = len % 3; // if we have 1 byte left, pad 2 bytes 15978 var parts = []; 15979 var maxChunkLength = 16383; // must be multiple of 3 15980 15981 // go through the array every three bytes, we'll deal with trailing stuff later 15982 for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) { 15983 parts.push( 15984 encodeChunk(uint8, i, i + maxChunkLength > len2 ? len2 : i + maxChunkLength) 15985 ); 15986 } 15987 15988 // pad the end with zeros, but make sure to not forget the extra bytes 15989 if (extraBytes === 1) { 15990 tmp = uint8[len - 1]; 15991 parts.push(lookup[tmp >> 2] + lookup[(tmp << 4) & 0x3f] + '=='); 15992 } else if (extraBytes === 2) { 15993 tmp = (uint8[len - 2] << 8) + uint8[len - 1]; 15994 parts.push( 15995 lookup[tmp >> 10] + 15996 lookup[(tmp >> 4) & 0x3f] + 15997 lookup[(tmp << 2) & 0x3f] + 15998 '=' 15999 ); 16000 } 16001 16002 return parts.join(''); 16003 } 16004 }, 16005 {} 16006 ], 16007 21: [function(_dereq_, module, exports) {}, {}], 16008 22: [ 16009 function(_dereq_, module, exports) { 16010 (function(Buffer) { 16011 /*! 16012 * The buffer module from node.js, for the browser. 16013 * 16014 * @author Feross Aboukhadijeh <https://feross.org> 16015 * @license MIT 16016 */ 16017 /* eslint-disable no-proto */ 16018 16019 'use strict'; 16020 16021 var base64 = _dereq_('base64-js'); 16022 var ieee754 = _dereq_('ieee754'); 16023 var customInspectSymbol = 16024 typeof Symbol === 'function' && typeof Symbol.for === 'function' 16025 ? Symbol.for('nodejs.util.inspect.custom') 16026 : null; 16027 16028 exports.Buffer = Buffer; 16029 exports.SlowBuffer = SlowBuffer; 16030 exports.INSPECT_MAX_BYTES = 50; 16031 16032 var K_MAX_LENGTH = 0x7fffffff; 16033 exports.kMaxLength = K_MAX_LENGTH; 16034 16035 /** 16036 * If `Buffer.TYPED_ARRAY_SUPPORT`: 16037 * === true Use Uint8Array implementation (fastest) 16038 * === false Print warning and recommend using `buffer` v4.x which has an Object 16039 * implementation (most compatible, even IE6) 16040 * 16041 * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, 16042 * Opera 11.6+, iOS 4.2+. 16043 * 16044 * We report that the browser does not support typed arrays if the are not subclassable 16045 * using __proto__. Firefox 4-29 lacks support for adding new properties to `Uint8Array` 16046 * (See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438). IE 10 lacks supp
vendor: 6,630 bytes, lines 16046-16224
16046ort 16047 * for __proto__ and has a buggy typed array implementation. 16048 */ 16049 Buffer.TYPED_ARRAY_SUPPORT = typedArraySupport(); 16050 16051 if ( 16052 !Buffer.TYPED_ARRAY_SUPPORT && 16053 typeof console !== 'undefined' && 16054 typeof console.error === 'function' 16055 ) { 16056 console.error( 16057 'This browser lacks typed array (Uint8Array) support which is required by ' + 16058 '`buffer` v5.x. Use `buffer` v4.x if you require old browser support.' 16059 ); 16060 } 16061 16062 function typedArraySupport() { 16063 // Can typed array instances can be augmented? 16064 try { 16065 var arr = new Uint8Array(1); 16066 var proto = { 16067 foo: function() { 16068 return 42; 16069 } 16070 }; 16071 Object.setPrototypeOf(proto, Uint8Array.prototype); 16072 Object.setPrototypeOf(arr, proto); 16073 return arr.foo() === 42; 16074 } catch (e) { 16075 return false; 16076 } 16077 } 16078 16079 Object.defineProperty(Buffer.prototype, 'parent', { 16080 enumerable: true, 16081 get: function() { 16082 if (!Buffer.isBuffer(this)) return undefined; 16083 return this.buffer; 16084 } 16085 }); 16086 16087 Object.defineProperty(Buffer.prototype, 'offset', { 16088 enumerable: true, 16089 get: function() { 16090 if (!Buffer.isBuffer(this)) return undefined; 16091 return this.byteOffset; 16092 } 16093 }); 16094 16095 function createBuffer(length) { 16096 if (length > K_MAX_LENGTH) { 16097 throw new RangeError( 16098 'The value "' + length + '" is invalid for option "size"' 16099 ); 16100 } 16101 // Return an augmented `Uint8Array` instance 16102 var buf = new Uint8Array(length); 16103 Object.setPrototypeOf(buf, Buffer.prototype); 16104 return buf; 16105 } 16106 16107 /** 16108 * The Buffer constructor returns instances of `Uint8Array` that have their 16109 * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of 16110 * `Uint8Array`, so the returned instances will have all the node `Buffer` methods 16111 * and the `Uint8Array` methods. Square bracket notation works as expected -- it 16112 * returns a single octet. 16113 * 16114 * The `Uint8Array` prototype remains unmodified. 16115 */ 16116 16117 function Buffer(arg, encodingOrOffset, length) { 16118 // Common case. 16119 if (typeof arg === 'number') { 16120 if (typeof encodingOrOffset === 'string') { 16121 throw new TypeError( 16122 'The "string" argument must be of type string. Received type number' 16123 ); 16124 } 16125 return allocUnsafe(arg); 16126 } 16127 return from(arg, encodingOrOffset, length); 16128 } 16129 16130 // Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97 16131 if ( 16132 typeof Symbol !== 'undefined' && 16133 Symbol.species != null && 16134 Buffer[Symbol.species] === Buffer 16135 ) { 16136 Object.defineProperty(Buffer, Symbol.species, { 16137 value: null, 16138 configurable: true, 16139 enumerable: false, 16140 writable: false 16141 }); 16142 } 16143 16144 Buffer.poolSize = 8192; // not used by this implementation 16145 16146 function from(value, encodingOrOffset, length) { 16147 if (typeof value === 'string') { 16148 return fromString(value, encodingOrOffset); 16149 } 16150 16151 if (ArrayBuffer.isView(value)) { 16152 return fromArrayLike(value); 16153 } 16154 16155 if (value == null) { 16156 throw new TypeError( 16157 'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' + 16158 'or Array-like Object. Received type ' + 16159 typeof value 16160 ); 16161 } 16162 16163 if ( 16164 isInstance(value, ArrayBuffer) || 16165 (value && isInstance(value.buffer, ArrayBuffer)) 16166 ) { 16167 return fromArrayBuffer(value, encodingOrOffset, length); 16168 } 16169 16170 if (typeof value === 'number') { 16171 throw new TypeError( 16172 'The "value" argument must not be of type number. Received type number' 16173 ); 16174 } 16175 16176 var valueOf = value.valueOf && value.valueOf(); 16177 if (valueOf != null && valueOf !== value) { 16178 return Buffer.from(valueOf, encodingOrOffset, length); 16179 } 16180 16181 var b = fromObject(value); 16182 if (b) return b; 16183 16184 if ( 16185 typeof Symbol !== 'undefined' && 16186 Symbol.toPrimitive != null && 16187 typeof value[Symbol.toPrimitive] === 'function' 16188 ) { 16189 return Buffer.from( 16190 value[Symbol.toPrimitive]('string'), 16191 encodingOrOffset, 16192 length 16193 ); 16194 } 16195 16196 throw new TypeError( 16197 'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' + 16198 'or Array-like Object. Received type ' + 16199 typeof value 16200 ); 16201 } 16202 16203 /** 16204 * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError 16205 * if value is a number. 16206 * Buffer.from(str[, encoding]) 16207 * Buffer.from(array) 16208 * Buffer.from(buffer) 16209 * Buffer.from(arrayBuffer[, byteOffset[, length]]) 16210 **/ 16211 Buffer.from = function(value, encodingOrOffset, length) { 16212 return from(value, encodingOrOffset, length); 16213 }; 16214 16215 // Note: Change prototype *after* Buffer.from is defined to workaround Chrome bug: 16216 // https://github.com/feross/buffer/pull/148 16217 Object.setPrototypeOf(Buffer.prototype, Uint8Array.prototype); 16218 Object.setPrototypeOf(Buffer, Uint8Array); 16219 16220 function assertSize(size) { 16221 if (typeof size !== 'number') { 16222 throw new TypeError('"size" argument must be of type number'); 16223 } else if (size < 0) { 16224 throw new RangeError(
vendor: 5,389 bytes, lines 16225-16377
16225 'The value "' + size + '" is invalid for option "size"' 16226 ); 16227 } 16228 } 16229 16230 function alloc(size, fill, encoding) { 16231 assertSize(size); 16232 if (size <= 0) { 16233 return createBuffer(size); 16234 } 16235 if (fill !== undefined) { 16236 // Only pay attention to encoding if it's a string. This 16237 // prevents accidentally sending in a number that would 16238 // be interpretted as a start offset. 16239 return typeof encoding === 'string' 16240 ? createBuffer(size).fill(fill, encoding) 16241 : createBuffer(size).fill(fill); 16242 } 16243 return createBuffer(size); 16244 } 16245 16246 /** 16247 * Creates a new filled Buffer instance. 16248 * alloc(size[, fill[, encoding]]) 16249 **/ 16250 Buffer.alloc = function(size, fill, encoding) { 16251 return alloc(size, fill, encoding); 16252 }; 16253 16254 function allocUnsafe(size) { 16255 assertSize(size); 16256 return createBuffer(size < 0 ? 0 : checked(size) | 0); 16257 } 16258 16259 /** 16260 * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance. 16261 * */ 16262 Buffer.allocUnsafe = function(size) { 16263 return allocUnsafe(size); 16264 }; 16265 /** 16266 * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance. 16267 */ 16268 Buffer.allocUnsafeSlow = function(size) { 16269 return allocUnsafe(size); 16270 }; 16271 16272 function fromString(string, encoding) { 16273 if (typeof encoding !== 'string' || encoding === '') { 16274 encoding = 'utf8'; 16275 } 16276 16277 if (!Buffer.isEncoding(encoding)) { 16278 throw new TypeError('Unknown encoding: ' + encoding); 16279 } 16280 16281 var length = byteLength(string, encoding) | 0; 16282 var buf = createBuffer(length); 16283 16284 var actual = buf.write(string, encoding); 16285 16286 if (actual !== length) { 16287 // Writing a hex string, for example, that contains invalid characters will 16288 // cause everything after the first invalid character to be ignored. (e.g. 16289 // 'abxxcd' will be treated as 'ab') 16290 buf = buf.slice(0, actual); 16291 } 16292 16293 return buf; 16294 } 16295 16296 function fromArrayLike(array) { 16297 var length = array.length < 0 ? 0 : checked(array.length) | 0; 16298 var buf = createBuffer(length); 16299 for (var i = 0; i < length; i += 1) { 16300 buf[i] = array[i] & 255; 16301 } 16302 return buf; 16303 } 16304 16305 function fromArrayBuffer(array, byteOffset, length) { 16306 if (byteOffset < 0 || array.byteLength < byteOffset) { 16307 throw new RangeError('"offset" is outside of buffer bounds'); 16308 } 16309 16310 if (array.byteLength < byteOffset + (length || 0)) { 16311 throw new RangeError('"length" is outside of buffer bounds'); 16312 } 16313 16314 var buf; 16315 if (byteOffset === undefined && length === undefined) { 16316 buf = new Uint8Array(array); 16317 } else if (length === undefined) { 16318 buf = new Uint8Array(array, byteOffset); 16319 } else { 16320 buf = new Uint8Array(array, byteOffset, length); 16321 } 16322 16323 // Return an augmented `Uint8Array` instance 16324 Object.setPrototypeOf(buf, Buffer.prototype); 16325 16326 return buf; 16327 } 16328 16329 function fromObject(obj) { 16330 if (Buffer.isBuffer(obj)) { 16331 var len = checked(obj.length) | 0; 16332 var buf = createBuffer(len); 16333 16334 if (buf.length === 0) { 16335 return buf; 16336 } 16337 16338 obj.copy(buf, 0, 0, len); 16339 return buf; 16340 } 16341 16342 if (obj.length !== undefined) { 16343 if (typeof obj.length !== 'number' || numberIsNaN(obj.length)) { 16344 return createBuffer(0); 16345 } 16346 return fromArrayLike(obj); 16347 } 16348 16349 if (obj.type === 'Buffer' && Array.isArray(obj.data)) { 16350 return fromArrayLike(obj.data); 16351 } 16352 } 16353 16354 function checked(length) { 16355 // Note: cannot use `length < K_MAX_LENGTH` here because that fails when 16356 // length is NaN (which is otherwise coerced to zero.) 16357 if (length >= K_MAX_LENGTH) { 16358 throw new RangeError( 16359 'Attempt to allocate Buffer larger than maximum ' + 16360 'size: 0x' + 16361 K_MAX_LENGTH.toString(16) + 16362 ' bytes' 16363 ); 16364 } 16365 return length | 0; 16366 } 16367 16368 function SlowBuffer(length) { 16369 if (+length != length) { 16370 // eslint-disable-line eqeqeq 16371 length = 0; 16372 } 16373 return Buffer.alloc(+length); 16374 } 16375 16376 Buffer.isBuffer = function isBuffer(b) { 16377 return b != null && b._isBuffer === true && b !== Buffer.prototype;
vendor: 4,569 bytes, lines 16377-16510
16377 // so Buffer.isBuffer(Buffer.prototype) will be false 16378 }; 16379 16380 Buffer.compare = function compare(a, b) { 16381 if (isInstance(a, Uint8Array)) a = Buffer.from(a, a.offset, a.byteLength); 16382 if (isInstance(b, Uint8Array)) b = Buffer.from(b, b.offset, b.byteLength); 16383 if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { 16384 throw new TypeError( 16385 'The "buf1", "buf2" arguments must be one of type Buffer or Uint8Array' 16386 ); 16387 } 16388 16389 if (a === b) return 0; 16390 16391 var x = a.length; 16392 var y = b.length; 16393 16394 for (var i = 0, len = Math.min(x, y); i < len; ++i) { 16395 if (a[i] !== b[i]) { 16396 x = a[i]; 16397 y = b[i]; 16398 break; 16399 } 16400 } 16401 16402 if (x < y) return -1; 16403 if (y < x) return 1; 16404 return 0; 16405 }; 16406 16407 Buffer.isEncoding = function isEncoding(encoding) { 16408 switch (String(encoding).toLowerCase()) { 16409 case 'hex': 16410 case 'utf8': 16411 case 'utf-8': 16412 case 'ascii': 16413 case 'latin1': 16414 case 'binary': 16415 case 'base64': 16416 case 'ucs2': 16417 case 'ucs-2': 16418 case 'utf16le': 16419 case 'utf-16le': 16420 return true; 16421 default: 16422 return false; 16423 } 16424 }; 16425 16426 Buffer.concat = function concat(list, length) { 16427 if (!Array.isArray(list)) { 16428 throw new TypeError('"list" argument must be an Array of Buffers'); 16429 } 16430 16431 if (list.length === 0) { 16432 return Buffer.alloc(0); 16433 } 16434 16435 var i; 16436 if (length === undefined) { 16437 length = 0; 16438 for (i = 0; i < list.length; ++i) { 16439 length += list[i].length; 16440 } 16441 } 16442 16443 var buffer = Buffer.allocUnsafe(length); 16444 var pos = 0; 16445 for (i = 0; i < list.length; ++i) { 16446 var buf = list[i]; 16447 if (isInstance(buf, Uint8Array)) { 16448 buf = Buffer.from(buf); 16449 } 16450 if (!Buffer.isBuffer(buf)) { 16451 throw new TypeError('"list" argument must be an Array of Buffers'); 16452 } 16453 buf.copy(buffer, pos); 16454 pos += buf.length; 16455 } 16456 return buffer; 16457 }; 16458 16459 function byteLength(string, encoding) { 16460 if (Buffer.isBuffer(string)) { 16461 return string.length; 16462 } 16463 if (ArrayBuffer.isView(string) || isInstance(string, ArrayBuffer)) { 16464 return string.byteLength; 16465 } 16466 if (typeof string !== 'string') { 16467 throw new TypeError( 16468 'The "string" argument must be one of type string, Buffer, or ArrayBuffer. ' + 16469 'Received type ' + 16470 typeof string 16471 ); 16472 } 16473 16474 var len = string.length; 16475 var mustMatch = arguments.length > 2 && arguments[2] === true; 16476 if (!mustMatch && len === 0) return 0; 16477 16478 // Use a for loop to avoid recursion 16479 var loweredCase = false; 16480 for (;;) { 16481 switch (encoding) { 16482 case 'ascii': 16483 case 'latin1': 16484 case 'binary': 16485 return len; 16486 case 'utf8': 16487 case 'utf-8': 16488 return utf8ToBytes(string).length; 16489 case 'ucs2': 16490 case 'ucs-2': 16491 case 'utf16le': 16492 case 'utf-16le': 16493 return len * 2; 16494 case 'hex': 16495 return len >>> 1; 16496 case 'base64': 16497 return base64ToBytes(string).length; 16498 default: 16499 if (loweredCase) { 16500 return mustMatch ? -1 : utf8ToBytes(string).length; // assume utf8 16501 } 16502 encoding = ('' + encoding).toLowerCase(); 16503 loweredCase = true; 16504 } 16505 } 16506 } 16507 Buffer.byteLength = byteLength; 16508 16509 function slowToString(encoding, start, end) { 16510 var loweredCase = false;
vendor: 4,552 bytes, lines 16511-16636
16511 16512 // No need to verify that "this.length <= MAX_UINT32" since it's a read-only 16513 // property of a typed array. 16514 16515 // This behaves neither like String nor Uint8Array in that we set start/end 16516 // to their upper/lower bounds if the value passed is out of range. 16517 // undefined is handled specially as per ECMA-262 6th Edition, 16518 // Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization. 16519 if (start === undefined || start < 0) { 16520 start = 0; 16521 } 16522 // Return early if start > this.length. Done here to prevent potential uint32 16523 // coercion fail below. 16524 if (start > this.length) { 16525 return ''; 16526 } 16527 16528 if (end === undefined || end > this.length) { 16529 end = this.length; 16530 } 16531 16532 if (end <= 0) { 16533 return ''; 16534 } 16535 16536 // Force coersion to uint32. This will also coerce falsey/NaN values to 0. 16537 end >>>= 0; 16538 start >>>= 0; 16539 16540 if (end <= start) { 16541 return ''; 16542 } 16543 16544 if (!encoding) encoding = 'utf8'; 16545 16546 while (true) { 16547 switch (encoding) { 16548 case 'hex': 16549 return hexSlice(this, start, end); 16550 16551 case 'utf8': 16552 case 'utf-8': 16553 return utf8Slice(this, start, end); 16554 16555 case 'ascii': 16556 return asciiSlice(this, start, end); 16557 16558 case 'latin1': 16559 case 'binary': 16560 return latin1Slice(this, start, end); 16561 16562 case 'base64': 16563 return base64Slice(this, start, end); 16564 16565 case 'ucs2': 16566 case 'ucs-2': 16567 case 'utf16le': 16568 case 'utf-16le': 16569 return utf16leSlice(this, start, end); 16570 16571 default: 16572 if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding); 16573 encoding = (encoding + '').toLowerCase(); 16574 loweredCase = true; 16575 } 16576 } 16577 } 16578 16579 // This property is used by `Buffer.isBuffer` (and the `is-buffer` npm package) 16580 // to detect a Buffer instance. It's not possible to use `instanceof Buffer` 16581 // reliably in a browserify context because there could be multiple different 16582 // copies of the 'buffer' package in use. This method works even for Buffer 16583 // instances that were created from another copy of the `buffer` package. 16584 // See: https://github.com/feross/buffer/issues/154 16585 Buffer.prototype._isBuffer = true; 16586 16587 function swap(b, n, m) { 16588 var i = b[n]; 16589 b[n] = b[m]; 16590 b[m] = i; 16591 } 16592 16593 Buffer.prototype.swap16 = function swap16() { 16594 var len = this.length; 16595 if (len % 2 !== 0) { 16596 throw new RangeError('Buffer size must be a multiple of 16-bits'); 16597 } 16598 for (var i = 0; i < len; i += 2) { 16599 swap(this, i, i + 1); 16600 } 16601 return this; 16602 }; 16603 16604 Buffer.prototype.swap32 = function swap32() { 16605 var len = this.length; 16606 if (len % 4 !== 0) { 16607 throw new RangeError('Buffer size must be a multiple of 32-bits'); 16608 } 16609 for (var i = 0; i < len; i += 4) { 16610 swap(this, i, i + 3); 16611 swap(this, i + 1, i + 2); 16612 } 16613 return this; 16614 }; 16615 16616 Buffer.prototype.swap64 = function swap64() { 16617 var len = this.length; 16618 if (len % 8 !== 0) { 16619 throw new RangeError('Buffer size must be a multiple of 64-bits'); 16620 } 16621 for (var i = 0; i < len; i += 8) { 16622 swap(this, i, i + 7); 16623 swap(this, i + 1, i + 6); 16624 swap(this, i + 2, i + 5); 16625 swap(this, i + 3, i + 4); 16626 } 16627 return this; 16628 }; 16629 16630 Buffer.prototype.toString = function toString() { 16631 var length = this.length; 16632 if (length === 0) return ''; 16633 if (arguments.length === 0) return utf8Slice(this, 0, length); 16634 return slowToString.apply(this, arguments); 16635 }; 16636
vendor: 12,005 bytes, lines 16637-16966
16637 Buffer.prototype.toLocaleString = Buffer.prototype.toString; 16638 16639 Buffer.prototype.equals = function equals(b) { 16640 if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer'); 16641 if (this === b) return true; 16642 return Buffer.compare(this, b) === 0; 16643 }; 16644 16645 Buffer.prototype.inspect = function inspect() { 16646 var str = ''; 16647 var max = exports.INSPECT_MAX_BYTES; 16648 str = this.toString('hex', 0, max) 16649 .replace(/(.{2})/g, '$1 ') 16650 .trim(); 16651 if (this.length > max) str += ' ... '; 16652 return '<Buffer ' + str + '>'; 16653 }; 16654 if (customInspectSymbol) { 16655 Buffer.prototype[customInspectSymbol] = Buffer.prototype.inspect; 16656 } 16657 16658 Buffer.prototype.compare = function compare( 16659 target, 16660 start, 16661 end, 16662 thisStart, 16663 thisEnd 16664 ) { 16665 if (isInstance(target, Uint8Array)) { 16666 target = Buffer.from(target, target.offset, target.byteLength); 16667 } 16668 if (!Buffer.isBuffer(target)) { 16669 throw new TypeError( 16670 'The "target" argument must be one of type Buffer or Uint8Array. ' + 16671 'Received type ' + 16672 typeof target 16673 ); 16674 } 16675 16676 if (start === undefined) { 16677 start = 0; 16678 } 16679 if (end === undefined) { 16680 end = target ? target.length : 0; 16681 } 16682 if (thisStart === undefined) { 16683 thisStart = 0; 16684 } 16685 if (thisEnd === undefined) { 16686 thisEnd = this.length; 16687 } 16688 16689 if ( 16690 start < 0 || 16691 end > target.length || 16692 thisStart < 0 || 16693 thisEnd > this.length 16694 ) { 16695 throw new RangeError('out of range index'); 16696 } 16697 16698 if (thisStart >= thisEnd && start >= end) { 16699 return 0; 16700 } 16701 if (thisStart >= thisEnd) { 16702 return -1; 16703 } 16704 if (start >= end) { 16705 return 1; 16706 } 16707 16708 start >>>= 0; 16709 end >>>= 0; 16710 thisStart >>>= 0; 16711 thisEnd >>>= 0; 16712 16713 if (this === target) return 0; 16714 16715 var x = thisEnd - thisStart; 16716 var y = end - start; 16717 var len = Math.min(x, y); 16718 16719 var thisCopy = this.slice(thisStart, thisEnd); 16720 var targetCopy = target.slice(start, end); 16721 16722 for (var i = 0; i < len; ++i) { 16723 if (thisCopy[i] !== targetCopy[i]) { 16724 x = thisCopy[i]; 16725 y = targetCopy[i]; 16726 break; 16727 } 16728 } 16729 16730 if (x < y) return -1; 16731 if (y < x) return 1; 16732 return 0; 16733 }; 16734 16735 // Finds either the first index of `val` in `buffer` at offset >= `byteOffset`, 16736 // OR the last index of `val` in `buffer` at offset <= `byteOffset`. 16737 // 16738 // Arguments: 16739 // - buffer - a Buffer to search 16740 // - val - a string, Buffer, or number 16741 // - byteOffset - an index into `buffer`; will be clamped to an int32 16742 // - encoding - an optional encoding, relevant is val is a string 16743 // - dir - true for indexOf, false for lastIndexOf 16744 function bidirectionalIndexOf(buffer, val, byteOffset, encoding, dir) { 16745 // Empty buffer means no match 16746 if (buffer.length === 0) return -1; 16747 16748 // Normalize byteOffset 16749 if (typeof byteOffset === 'string') { 16750 encoding = byteOffset; 16751 byteOffset = 0; 16752 } else if (byteOffset > 0x7fffffff) { 16753 byteOffset = 0x7fffffff; 16754 } else if (byteOffset < -0x80000000) { 16755 byteOffset = -0x80000000; 16756 } 16757 byteOffset = +byteOffset; // Coerce to Number. 16758 if (numberIsNaN(byteOffset)) { 16759 // byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer 16760 byteOffset = dir ? 0 : buffer.length - 1; 16761 } 16762 16763 // Normalize byteOffset: negative offsets start from the end of the buffer 16764 if (byteOffset < 0) byteOffset = buffer.length + byteOffset; 16765 if (byteOffset >= buffer.length) { 16766 if (dir) return -1; 16767 else byteOffset = buffer.length - 1; 16768 } else if (byteOffset < 0) { 16769 if (dir) byteOffset = 0; 16770 else return -1; 16771 } 16772 16773 // Normalize val 16774 if (typeof val === 'string') { 16775 val = Buffer.from(val, encoding); 16776 } 16777 16778 // Finally, search either indexOf (if dir is true) or lastIndexOf 16779 if (Buffer.isBuffer(val)) { 16780 // Special case: looking for empty string/buffer always fails 16781 if (val.length === 0) { 16782 return -1; 16783 } 16784 return arrayIndexOf(buffer, val, byteOffset, encoding, dir); 16785 } else if (typeof val === 'number') { 16786 val = val & 0xff; // Search for a byte value [0-255] 16787 if (typeof Uint8Array.prototype.indexOf === 'function') { 16788 if (dir) { 16789 return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset); 16790 } else { 16791 return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset); 16792 } 16793 } 16794 return arrayIndexOf(buffer, [val], byteOffset, encoding, dir); 16795 } 16796 16797 throw new TypeError('val must be string, number or Buffer'); 16798 } 16799 16800 function arrayIndexOf(arr, val, byteOffset, encoding, dir) { 16801 var indexSize = 1; 16802 var arrLength = arr.length; 16803 var valLength = val.length; 16804 16805 if (encoding !== undefined) { 16806 encoding = String(encoding).toLowerCase(); 16807 if ( 16808 encoding === 'ucs2' || 16809 encoding === 'ucs-2' || 16810 encoding === 'utf16le' || 16811 encoding === 'utf-16le' 16812 ) { 16813 if (arr.length < 2 || val.length < 2) { 16814 return -1; 16815 } 16816 indexSize = 2; 16817 arrLength /= 2; 16818 valLength /= 2; 16819 byteOffset /= 2; 16820 } 16821 } 16822 16823 function read(buf, i) { 16824 if (indexSize === 1) { 16825 return buf[i]; 16826 } else { 16827 return buf.readUInt16BE(i * indexSize); 16828 } 16829 } 16830 16831 var i; 16832 if (dir) { 16833 var foundIndex = -1; 16834 for (i = byteOffset; i < arrLength; i++) { 16835 if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) { 16836 if (foundIndex === -1) foundIndex = i; 16837 if (i - foundIndex + 1 === valLength) return foundIndex * indexSize; 16838 } else { 16839 if (foundIndex !== -1) i -= i - foundIndex; 16840 foundIndex = -1; 16841 } 16842 } 16843 } else { 16844 if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength; 16845 for (i = byteOffset; i >= 0; i--) { 16846 var found = true; 16847 for (var j = 0; j < valLength; j++) { 16848 if (read(arr, i + j) !== read(val, j)) { 16849 found = false; 16850 break; 16851 } 16852 } 16853 if (found) return i; 16854 } 16855 } 16856 16857 return -1; 16858 } 16859 16860 Buffer.prototype.includes = function includes(val, byteOffset, encoding) { 16861 return this.indexOf(val, byteOffset, encoding) !== -1; 16862 }; 16863 16864 Buffer.prototype.indexOf = function indexOf(val, byteOffset, encoding) { 16865 return bidirectionalIndexOf(this, val, byteOffset, encoding, true); 16866 }; 16867 16868 Buffer.prototype.lastIndexOf = function lastIndexOf(val, byteOffset, encoding) { 16869 return bidirectionalIndexOf(this, val, byteOffset, encoding, false); 16870 }; 16871 16872 function hexWrite(buf, string, offset, length) { 16873 offset = Number(offset) || 0; 16874 var remaining = buf.length - offset; 16875 if (!length) { 16876 length = remaining; 16877 } else { 16878 length = Number(length); 16879 if (length > remaining) { 16880 length = remaining; 16881 } 16882 } 16883 16884 var strLen = string.length; 16885 16886 if (length > strLen / 2) { 16887 length = strLen / 2; 16888 } 16889 for (var i = 0; i < length; ++i) { 16890 var parsed = parseInt(string.substr(i * 2, 2), 16); 16891 if (numberIsNaN(parsed)) return i; 16892 buf[offset + i] = parsed; 16893 } 16894 return i; 16895 } 16896 16897 function utf8Write(buf, string, offset, length) { 16898 return blitBuffer( 16899 utf8ToBytes(string, buf.length - offset), 16900 buf, 16901 offset, 16902 length 16903 ); 16904 } 16905 16906 function asciiWrite(buf, string, offset, length) { 16907 return blitBuffer(asciiToBytes(string), buf, offset, length); 16908 } 16909 16910 function latin1Write(buf, string, offset, length) { 16911 return asciiWrite(buf, string, offset, length); 16912 } 16913 16914 function base64Write(buf, string, offset, length) { 16915 return blitBuffer(base64ToBytes(string), buf, offset, length); 16916 } 16917 16918 function ucs2Write(buf, string, offset, length) { 16919 return blitBuffer( 16920 utf16leToBytes(string, buf.length - offset), 16921 buf, 16922 offset, 16923 length 16924 ); 16925 } 16926 16927 Buffer.prototype.write = function write(string, offset, length, encoding) { 16928 // Buffer#write(string) 16929 if (offset === undefined) { 16930 encoding = 'utf8'; 16931 length = this.length; 16932 offset = 0; 16933 // Buffer#write(string, encoding) 16934 } else if (length === undefined && typeof offset === 'string') { 16935 encoding = offset; 16936 length = this.length; 16937 offset = 0; 16938 // Buffer#write(string, offset[, length][, encoding]) 16939 } else if (isFinite(offset)) { 16940 offset = offset >>> 0; 16941 if (isFinite(length)) { 16942 length = length >>> 0; 16943 if (encoding === undefined) encoding = 'utf8'; 16944 } else { 16945 encoding = length; 16946 length = undefined; 16947 } 16948 } else { 16949 throw new Error( 16950 'Buffer.write(string, encoding, offset[, length]) is no longer supported' 16951 ); 16952 } 16953 16954 var remaining = this.length - offset; 16955 if (length === undefined || length > remaining) length = remaining; 16956 16957 if ( 16958 (string.length > 0 && (length < 0 || offset < 0)) || 16959 offset > this.length 16960 ) { 16961 throw new RangeError('Attempt to write outside buffer bounds'); 16962 } 16963 16964 if (!encoding) encoding = 'utf8'; 16965 16966 var loweredCase = false;
vendor: 20,195 bytes, lines 16967-17528
16967 for (;;) { 16968 switch (encoding) { 16969 case 'hex': 16970 return hexWrite(this, string, offset, length); 16971 16972 case 'utf8': 16973 case 'utf-8': 16974 return utf8Write(this, string, offset, length); 16975 16976 case 'ascii': 16977 return asciiWrite(this, string, offset, length); 16978 16979 case 'latin1': 16980 case 'binary': 16981 return latin1Write(this, string, offset, length); 16982 16983 case 'base64': 16984 // Warning: maxLength not taken into account in base64Write 16985 return base64Write(this, string, offset, length); 16986 16987 case 'ucs2': 16988 case 'ucs-2': 16989 case 'utf16le': 16990 case 'utf-16le': 16991 return ucs2Write(this, string, offset, length); 16992 16993 default: 16994 if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding); 16995 encoding = ('' + encoding).toLowerCase(); 16996 loweredCase = true; 16997 } 16998 } 16999 }; 17000 17001 Buffer.prototype.toJSON = function toJSON() { 17002 return { 17003 type: 'Buffer', 17004 data: Array.prototype.slice.call(this._arr || this, 0) 17005 }; 17006 }; 17007 17008 function base64Slice(buf, start, end) { 17009 if (start === 0 && end === buf.length) { 17010 return base64.fromByteArray(buf); 17011 } else { 17012 return base64.fromByteArray(buf.slice(start, end)); 17013 } 17014 } 17015 17016 function utf8Slice(buf, start, end) { 17017 end = Math.min(buf.length, end); 17018 var res = []; 17019 17020 var i = start; 17021 while (i < end) { 17022 var firstByte = buf[i]; 17023 var codePoint = null; 17024 var bytesPerSequence = 17025 firstByte > 0xef ? 4 : firstByte > 0xdf ? 3 : firstByte > 0xbf ? 2 : 1; 17026 17027 if (i + bytesPerSequence <= end) { 17028 var secondByte, thirdByte, fourthByte, tempCodePoint; 17029 17030 switch (bytesPerSequence) { 17031 case 1: 17032 if (firstByte < 0x80) { 17033 codePoint = firstByte; 17034 } 17035 break; 17036 case 2: 17037 secondByte = buf[i + 1]; 17038 if ((secondByte & 0xc0) === 0x80) { 17039 tempCodePoint = ((firstByte & 0x1f) << 0x6) | (secondByte & 0x3f); 17040 if (tempCodePoint > 0x7f) { 17041 codePoint = tempCodePoint; 17042 } 17043 } 17044 break; 17045 case 3: 17046 secondByte = buf[i + 1]; 17047 thirdByte = buf[i + 2]; 17048 if ((secondByte & 0xc0) === 0x80 && (thirdByte & 0xc0) === 0x80) { 17049 tempCodePoint = 17050 ((firstByte & 0xf) << 0xc) | 17051 ((secondByte & 0x3f) << 0x6) | 17052 (thirdByte & 0x3f); 17053 if ( 17054 tempCodePoint > 0x7ff && 17055 (tempCodePoint < 0xd800 || tempCodePoint > 0xdfff) 17056 ) { 17057 codePoint = tempCodePoint; 17058 } 17059 } 17060 break; 17061 case 4: 17062 secondByte = buf[i + 1]; 17063 thirdByte = buf[i + 2]; 17064 fourthByte = buf[i + 3]; 17065 if ( 17066 (secondByte & 0xc0) === 0x80 && 17067 (thirdByte & 0xc0) === 0x80 && 17068 (fourthByte & 0xc0) === 0x80 17069 ) { 17070 tempCodePoint = 17071 ((firstByte & 0xf) << 0x12) | 17072 ((secondByte & 0x3f) << 0xc) | 17073 ((thirdByte & 0x3f) << 0x6) | 17074 (fourthByte & 0x3f); 17075 if (tempCodePoint > 0xffff && tempCodePoint < 0x110000) { 17076 codePoint = tempCodePoint; 17077 } 17078 } 17079 } 17080 } 17081 17082 if (codePoint === null) { 17083 // we did not generate a valid codePoint so insert a 17084 // replacement char (U+FFFD) and advance only 1 byte 17085 codePoint = 0xfffd; 17086 bytesPerSequence = 1; 17087 } else if (codePoint > 0xffff) { 17088 // encode to utf16 (surrogate pair dance) 17089 codePoint -= 0x10000; 17090 res.push(((codePoint >>> 10) & 0x3ff) | 0xd800); 17091 codePoint = 0xdc00 | (codePoint & 0x3ff); 17092 } 17093 17094 res.push(codePoint); 17095 i += bytesPerSequence; 17096 } 17097 17098 return decodeCodePointsArray(res); 17099 } 17100 17101 // Based on http://stackoverflow.com/a/22747272/680742, the browser with 17102 // the lowest limit is Chrome, with 0x10000 args. 17103 // We go 1 magnitude less, for safety 17104 var MAX_ARGUMENTS_LENGTH = 0x1000; 17105 17106 function decodeCodePointsArray(codePoints) { 17107 var len = codePoints.length; 17108 if (len <= MAX_ARGUMENTS_LENGTH) { 17109 return String.fromCharCode.apply(String, codePoints); // avoid extra slice() 17110 } 17111 17112 // Decode in chunks to avoid "call stack size exceeded". 17113 var res = ''; 17114 var i = 0; 17115 while (i < len) { 17116 res += String.fromCharCode.apply( 17117 String, 17118 codePoints.slice(i, (i += MAX_ARGUMENTS_LENGTH)) 17119 ); 17120 } 17121 return res; 17122 } 17123 17124 function asciiSlice(buf, start, end) { 17125 var ret = ''; 17126 end = Math.min(buf.length, end); 17127 17128 for (var i = start; i < end; ++i) { 17129 ret += String.fromCharCode(buf[i] & 0x7f); 17130 } 17131 return ret; 17132 } 17133 17134 function latin1Slice(buf, start, end) { 17135 var ret = ''; 17136 end = Math.min(buf.length, end); 17137 17138 for (var i = start; i < end; ++i) { 17139 ret += String.fromCharCode(buf[i]); 17140 } 17141 return ret; 17142 } 17143 17144 function hexSlice(buf, start, end) { 17145 var len = buf.length; 17146 17147 if (!start || start < 0) start = 0; 17148 if (!end || end < 0 || end > len) end = len; 17149 17150 var out = ''; 17151 for (var i = start; i < end; ++i) { 17152 out += hexSliceLookupTable[buf[i]]; 17153 } 17154 return out; 17155 } 17156 17157 function utf16leSlice(buf, start, end) { 17158 var bytes = buf.slice(start, end); 17159 var res = ''; 17160 for (var i = 0; i < bytes.length; i += 2) { 17161 res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256); 17162 } 17163 return res; 17164 } 17165 17166 Buffer.prototype.slice = function slice(start, end) { 17167 var len = this.length; 17168 start = ~~start; 17169 end = end === undefined ? len : ~~end; 17170 17171 if (start < 0) { 17172 start += len; 17173 if (start < 0) start = 0; 17174 } else if (start > len) { 17175 start = len; 17176 } 17177 17178 if (end < 0) { 17179 end += len; 17180 if (end < 0) end = 0; 17181 } else if (end > len) { 17182 end = len; 17183 } 17184 17185 if (end < start) end = start; 17186 17187 var newBuf = this.subarray(start, end); 17188 // Return an augmented `Uint8Array` instance 17189 Object.setPrototypeOf(newBuf, Buffer.prototype); 17190 17191 return newBuf; 17192 }; 17193 17194 /* 17195 * Need to make sure that buffer isn't trying to write out of bounds. 17196 */ 17197 function checkOffset(offset, ext, length) { 17198 if (offset % 1 !== 0 || offset < 0) 17199 throw new RangeError('offset is not uint'); 17200 if (offset + ext > length) 17201 throw new RangeError('Trying to access beyond buffer length'); 17202 } 17203 17204 Buffer.prototype.readUIntLE = function readUIntLE( 17205 offset, 17206 byteLength, 17207 noAssert 17208 ) { 17209 offset = offset >>> 0; 17210 byteLength = byteLength >>> 0; 17211 if (!noAssert) checkOffset(offset, byteLength, this.length); 17212 17213 var val = this[offset]; 17214 var mul = 1; 17215 var i = 0; 17216 while (++i < byteLength && (mul *= 0x100)) { 17217 val += this[offset + i] * mul; 17218 } 17219 17220 return val; 17221 }; 17222 17223 Buffer.prototype.readUIntBE = function readUIntBE( 17224 offset, 17225 byteLength, 17226 noAssert 17227 ) { 17228 offset = offset >>> 0; 17229 byteLength = byteLength >>> 0; 17230 if (!noAssert) { 17231 checkOffset(offset, byteLength, this.length); 17232 } 17233 17234 var val = this[offset + --byteLength]; 17235 var mul = 1; 17236 while (byteLength > 0 && (mul *= 0x100)) { 17237 val += this[offset + --byteLength] * mul; 17238 } 17239 17240 return val; 17241 }; 17242 17243 Buffer.prototype.readUInt8 = function readUInt8(offset, noAssert) { 17244 offset = offset >>> 0; 17245 if (!noAssert) checkOffset(offset, 1, this.length); 17246 return this[offset]; 17247 }; 17248 17249 Buffer.prototype.readUInt16LE = function readUInt16LE(offset, noAssert) { 17250 offset = offset >>> 0; 17251 if (!noAssert) checkOffset(offset, 2, this.length); 17252 return this[offset] | (this[offset + 1] << 8); 17253 }; 17254 17255 Buffer.prototype.readUInt16BE = function readUInt16BE(offset, noAssert) { 17256 offset = offset >>> 0; 17257 if (!noAssert) checkOffset(offset, 2, this.length); 17258 return (this[offset] << 8) | this[offset + 1]; 17259 }; 17260 17261 Buffer.prototype.readUInt32LE = function readUInt32LE(offset, noAssert) { 17262 offset = offset >>> 0; 17263 if (!noAssert) checkOffset(offset, 4, this.length); 17264 17265 return ( 17266 (this[offset] | (this[offset + 1] << 8) | (this[offset + 2] << 16)) + 17267 this[offset + 3] * 0x1000000 17268 ); 17269 }; 17270 17271 Buffer.prototype.readUInt32BE = function readUInt32BE(offset, noAssert) { 17272 offset = offset >>> 0; 17273 if (!noAssert) checkOffset(offset, 4, this.length); 17274 17275 return ( 17276 this[offset] * 0x1000000 + 17277 ((this[offset + 1] << 16) | (this[offset + 2] << 8) | this[offset + 3]) 17278 ); 17279 }; 17280 17281 Buffer.prototype.readIntLE = function readIntLE(offset, byteLength, noAssert) { 17282 offset = offset >>> 0; 17283 byteLength = byteLength >>> 0; 17284 if (!noAssert) checkOffset(offset, byteLength, this.length); 17285 17286 var val = this[offset]; 17287 var mul = 1; 17288 var i = 0; 17289 while (++i < byteLength && (mul *= 0x100)) { 17290 val += this[offset + i] * mul; 17291 } 17292 mul *= 0x80; 17293 17294 if (val >= mul) val -= Math.pow(2, 8 * byteLength); 17295 17296 return val; 17297 }; 17298 17299 Buffer.prototype.readIntBE = function readIntBE(offset, byteLength, noAssert) { 17300 offset = offset >>> 0; 17301 byteLength = byteLength >>> 0; 17302 if (!noAssert) checkOffset(offset, byteLength, this.length); 17303 17304 var i = byteLength; 17305 var mul = 1; 17306 var val = this[offset + --i]; 17307 while (i > 0 && (mul *= 0x100)) { 17308 val += this[offset + --i] * mul; 17309 } 17310 mul *= 0x80; 17311 17312 if (val >= mul) val -= Math.pow(2, 8 * byteLength); 17313 17314 return val; 17315 }; 17316 17317 Buffer.prototype.readInt8 = function readInt8(offset, noAssert) { 17318 offset = offset >>> 0; 17319 if (!noAssert) checkOffset(offset, 1, this.length); 17320 if (!(this[offset] & 0x80)) return this[offset]; 17321 return (0xff - this[offset] + 1) * -1; 17322 }; 17323 17324 Buffer.prototype.readInt16LE = function readInt16LE(offset, noAssert) { 17325 offset = offset >>> 0; 17326 if (!noAssert) checkOffset(offset, 2, this.length); 17327 var val = this[offset] | (this[offset + 1] << 8); 17328 return val & 0x8000 ? val | 0xffff0000 : val; 17329 }; 17330 17331 Buffer.prototype.readInt16BE = function readInt16BE(offset, noAssert) { 17332 offset = offset >>> 0; 17333 if (!noAssert) checkOffset(offset, 2, this.length); 17334 var val = this[offset + 1] | (this[offset] << 8); 17335 return val & 0x8000 ? val | 0xffff0000 : val; 17336 }; 17337 17338 Buffer.prototype.readInt32LE = function readInt32LE(offset, noAssert) { 17339 offset = offset >>> 0; 17340 if (!noAssert) checkOffset(offset, 4, this.length); 17341 17342 return ( 17343 this[offset] | 17344 (this[offset + 1] << 8) | 17345 (this[offset + 2] << 16) | 17346 (this[offset + 3] << 24) 17347 ); 17348 }; 17349 17350 Buffer.prototype.readInt32BE = function readInt32BE(offset, noAssert) { 17351 offset = offset >>> 0; 17352 if (!noAssert) checkOffset(offset, 4, this.length); 17353 17354 return ( 17355 (this[offset] << 24) | 17356 (this[offset + 1] << 16) | 17357 (this[offset + 2] << 8) | 17358 this[offset + 3] 17359 ); 17360 }; 17361 17362 Buffer.prototype.readFloatLE = function readFloatLE(offset, noAssert) { 17363 offset = offset >>> 0; 17364 if (!noAssert) checkOffset(offset, 4, this.length); 17365 return ieee754.read(this, offset, true, 23, 4); 17366 }; 17367 17368 Buffer.prototype.readFloatBE = function readFloatBE(offset, noAssert) { 17369 offset = offset >>> 0; 17370 if (!noAssert) checkOffset(offset, 4, this.length); 17371 return ieee754.read(this, offset, false, 23, 4); 17372 }; 17373 17374 Buffer.prototype.readDoubleLE = function readDoubleLE(offset, noAssert) { 17375 offset = offset >>> 0; 17376 if (!noAssert) checkOffset(offset, 8, this.length); 17377 return ieee754.read(this, offset, true, 52, 8); 17378 }; 17379 17380 Buffer.prototype.readDoubleBE = function readDoubleBE(offset, noAssert) { 17381 offset = offset >>> 0; 17382 if (!noAssert) checkOffset(offset, 8, this.length); 17383 return ieee754.read(this, offset, false, 52, 8); 17384 }; 17385 17386 function checkInt(buf, value, offset, ext, max, min) { 17387 if (!Buffer.isBuffer(buf)) 17388 throw new TypeError('"buffer" argument must be a Buffer instance'); 17389 if (value > max || value < min) 17390 throw new RangeError('"value" argument is out of bounds'); 17391 if (offset + ext > buf.length) throw new RangeError('Index out of range'); 17392 } 17393 17394 Buffer.prototype.writeUIntLE = function writeUIntLE( 17395 value, 17396 offset, 17397 byteLength, 17398 noAssert 17399 ) { 17400 value = +value; 17401 offset = offset >>> 0; 17402 byteLength = byteLength >>> 0; 17403 if (!noAssert) { 17404 var maxBytes = Math.pow(2, 8 * byteLength) - 1; 17405 checkInt(this, value, offset, byteLength, maxBytes, 0); 17406 } 17407 17408 var mul = 1; 17409 var i = 0; 17410 this[offset] = value & 0xff; 17411 while (++i < byteLength && (mul *= 0x100)) { 17412 this[offset + i] = (value / mul) & 0xff; 17413 } 17414 17415 return offset + byteLength; 17416 }; 17417 17418 Buffer.prototype.writeUIntBE = function writeUIntBE( 17419 value, 17420 offset, 17421 byteLength, 17422 noAssert 17423 ) { 17424 value = +value; 17425 offset = offset >>> 0; 17426 byteLength = byteLength >>> 0; 17427 if (!noAssert) { 17428 var maxBytes = Math.pow(2, 8 * byteLength) - 1; 17429 checkInt(this, value, offset, byteLength, maxBytes, 0); 17430 } 17431 17432 var i = byteLength - 1; 17433 var mul = 1; 17434 this[offset + i] = value & 0xff; 17435 while (--i >= 0 && (mul *= 0x100)) { 17436 this[offset + i] = (value / mul) & 0xff; 17437 } 17438 17439 return offset + byteLength; 17440 }; 17441 17442 Buffer.prototype.writeUInt8 = function writeUInt8(value, offset, noAssert) { 17443 value = +value; 17444 offset = offset >>> 0; 17445 if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0); 17446 this[offset] = value & 0xff; 17447 return offset + 1; 17448 }; 17449 17450 Buffer.prototype.writeUInt16LE = function writeUInt16LE( 17451 value, 17452 offset, 17453 noAssert 17454 ) { 17455 value = +value; 17456 offset = offset >>> 0; 17457 if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0); 17458 this[offset] = value & 0xff; 17459 this[offset + 1] = value >>> 8; 17460 return offset + 2; 17461 }; 17462 17463 Buffer.prototype.writeUInt16BE = function writeUInt16BE( 17464 value, 17465 offset, 17466 noAssert 17467 ) { 17468 value = +value; 17469 offset = offset >>> 0; 17470 if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0); 17471 this[offset] = value >>> 8; 17472 this[offset + 1] = value & 0xff; 17473 return offset + 2; 17474 }; 17475 17476 Buffer.prototype.writeUInt32LE = function writeUInt32LE( 17477 value, 17478 offset, 17479 noAssert 17480 ) { 17481 value = +value; 17482 offset = offset >>> 0; 17483 if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0); 17484 this[offset + 3] = value >>> 24; 17485 this[offset + 2] = value >>> 16; 17486 this[offset + 1] = value >>> 8; 17487 this[offset] = value & 0xff; 17488 return offset + 4; 17489 }; 17490 17491 Buffer.prototype.writeUInt32BE = function writeUInt32BE( 17492 value, 17493 offset, 17494 noAssert 17495 ) { 17496 value = +value; 17497 offset = offset >>> 0; 17498 if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0); 17499 this[offset] = value >>> 24; 17500 this[offset + 1] = value >>> 16; 17501 this[offset + 2] = value >>> 8; 17502 this[offset + 3] = value & 0xff; 17503 return offset + 4; 17504 }; 17505 17506 Buffer.prototype.writeIntLE = function writeIntLE( 17507 value, 17508 offset, 17509 byteLength, 17510 noAssert 17511 ) { 17512 value = +value; 17513 offset = offset >>> 0; 17514 if (!noAssert) { 17515 var limit = Math.pow(2, 8 * byteLength - 1); 17516 17517 checkInt(this, value, offset, byteLength, limit - 1, -limit); 17518 } 17519 17520 var i = 0; 17521 var mul = 1; 17522 var sub = 0; 17523 this[offset] = value & 0xff; 17524 while (++i < byteLength && (mul *= 0x100)) { 17525 if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) { 17526 sub = 1; 17527 } 17528 this[offset + i] = (((value / mul) >> 0) - sub) & 0xff;
vendor: 9,736 bytes, lines 17529-17784
17529 } 17530 17531 return offset + byteLength; 17532 }; 17533 17534 Buffer.prototype.writeIntBE = function writeIntBE( 17535 value, 17536 offset, 17537 byteLength, 17538 noAssert 17539 ) { 17540 value = +value; 17541 offset = offset >>> 0; 17542 if (!noAssert) { 17543 var limit = Math.pow(2, 8 * byteLength - 1); 17544 17545 checkInt(this, value, offset, byteLength, limit - 1, -limit); 17546 } 17547 17548 var i = byteLength - 1; 17549 var mul = 1; 17550 var sub = 0; 17551 this[offset + i] = value & 0xff; 17552 while (--i >= 0 && (mul *= 0x100)) { 17553 if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) { 17554 sub = 1; 17555 } 17556 this[offset + i] = (((value / mul) >> 0) - sub) & 0xff; 17557 } 17558 17559 return offset + byteLength; 17560 }; 17561 17562 Buffer.prototype.writeInt8 = function writeInt8(value, offset, noAssert) { 17563 value = +value; 17564 offset = offset >>> 0; 17565 if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80); 17566 if (value < 0) value = 0xff + value + 1; 17567 this[offset] = value & 0xff; 17568 return offset + 1; 17569 }; 17570 17571 Buffer.prototype.writeInt16LE = function writeInt16LE(value, offset, noAssert) { 17572 value = +value; 17573 offset = offset >>> 0; 17574 if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); 17575 this[offset] = value & 0xff; 17576 this[offset + 1] = value >>> 8; 17577 return offset + 2; 17578 }; 17579 17580 Buffer.prototype.writeInt16BE = function writeInt16BE(value, offset, noAssert) { 17581 value = +value; 17582 offset = offset >>> 0; 17583 if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); 17584 this[offset] = value >>> 8; 17585 this[offset + 1] = value & 0xff; 17586 return offset + 2; 17587 }; 17588 17589 Buffer.prototype.writeInt32LE = function writeInt32LE(value, offset, noAssert) { 17590 value = +value; 17591 offset = offset >>> 0; 17592 if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); 17593 this[offset] = value & 0xff; 17594 this[offset + 1] = value >>> 8; 17595 this[offset + 2] = value >>> 16; 17596 this[offset + 3] = value >>> 24; 17597 return offset + 4; 17598 }; 17599 17600 Buffer.prototype.writeInt32BE = function writeInt32BE(value, offset, noAssert) { 17601 value = +value; 17602 offset = offset >>> 0; 17603 if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); 17604 if (value < 0) value = 0xffffffff + value + 1; 17605 this[offset] = value >>> 24; 17606 this[offset + 1] = value >>> 16; 17607 this[offset + 2] = value >>> 8; 17608 this[offset + 3] = value & 0xff; 17609 return offset + 4; 17610 }; 17611 17612 function checkIEEE754(buf, value, offset, ext, max, min) { 17613 if (offset + ext > buf.length) throw new RangeError('Index out of range'); 17614 if (offset < 0) throw new RangeError('Index out of range'); 17615 } 17616 17617 function writeFloat(buf, value, offset, littleEndian, noAssert) { 17618 value = +value; 17619 offset = offset >>> 0; 17620 if (!noAssert) { 17621 checkIEEE754( 17622 buf, 17623 value, 17624 offset, 17625 4, 17626 3.4028234663852886e38, 17627 -3.4028234663852886e38 17628 ); 17629 } 17630 ieee754.write(buf, value, offset, littleEndian, 23, 4); 17631 return offset + 4; 17632 } 17633 17634 Buffer.prototype.writeFloatLE = function writeFloatLE(value, offset, noAssert) { 17635 return writeFloat(this, value, offset, true, noAssert); 17636 }; 17637 17638 Buffer.prototype.writeFloatBE = function writeFloatBE(value, offset, noAssert) { 17639 return writeFloat(this, value, offset, false, noAssert); 17640 }; 17641 17642 function writeDouble(buf, value, offset, littleEndian, noAssert) { 17643 value = +value; 17644 offset = offset >>> 0; 17645 if (!noAssert) { 17646 checkIEEE754( 17647 buf, 17648 value, 17649 offset, 17650 8, 17651 1.7976931348623157e308, 17652 -1.7976931348623157e308 17653 ); 17654 } 17655 ieee754.write(buf, value, offset, littleEndian, 52, 8); 17656 return offset + 8; 17657 } 17658 17659 Buffer.prototype.writeDoubleLE = function writeDoubleLE( 17660 value, 17661 offset, 17662 noAssert 17663 ) { 17664 return writeDouble(this, value, offset, true, noAssert); 17665 }; 17666 17667 Buffer.prototype.writeDoubleBE = function writeDoubleBE( 17668 value, 17669 offset, 17670 noAssert 17671 ) { 17672 return writeDouble(this, value, offset, false, noAssert); 17673 }; 17674 17675 // copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) 17676 Buffer.prototype.copy = function copy(target, targetStart, start, end) { 17677 if (!Buffer.isBuffer(target)) 17678 throw new TypeError('argument should be a Buffer'); 17679 if (!start) start = 0; 17680 if (!end && end !== 0) end = this.length; 17681 if (targetStart >= target.length) targetStart = target.length; 17682 if (!targetStart) targetStart = 0; 17683 if (end > 0 && end < start) end = start; 17684 17685 // Copy 0 bytes; we're done 17686 if (end === start) return 0; 17687 if (target.length === 0 || this.length === 0) return 0; 17688 17689 // Fatal error conditions 17690 if (targetStart < 0) { 17691 throw new RangeError('targetStart out of bounds'); 17692 } 17693 if (start < 0 || start >= this.length) 17694 throw new RangeError('Index out of range'); 17695 if (end < 0) throw new RangeError('sourceEnd out of bounds'); 17696 17697 // Are we oob? 17698 if (end > this.length) end = this.length; 17699 if (target.length - targetStart < end - start) { 17700 end = target.length - targetStart + start; 17701 } 17702 17703 var len = end - start; 17704 17705 if ( 17706 this === target && 17707 typeof Uint8Array.prototype.copyWithin === 'function' 17708 ) { 17709 // Use built-in when available, missing from IE11 17710 this.copyWithin(targetStart, start, end); 17711 } else if (this === target && start < targetStart && targetStart < end) { 17712 // descending copy from end 17713 for (var i = len - 1; i >= 0; --i) { 17714 target[i + targetStart] = this[i + start]; 17715 } 17716 } else { 17717 Uint8Array.prototype.set.call( 17718 target, 17719 this.subarray(start, end), 17720 targetStart 17721 ); 17722 } 17723 17724 return len; 17725 }; 17726 17727 // Usage: 17728 // buffer.fill(number[, offset[, end]]) 17729 // buffer.fill(buffer[, offset[, end]]) 17730 // buffer.fill(string[, offset[, end]][, encoding]) 17731 Buffer.prototype.fill = function fill(val, start, end, encoding) { 17732 // Handle string cases: 17733 if (typeof val === 'string') { 17734 if (typeof start === 'string') { 17735 encoding = start; 17736 start = 0; 17737 end = this.length; 17738 } else if (typeof end === 'string') { 17739 encoding = end; 17740 end = this.length; 17741 } 17742 if (encoding !== undefined && typeof encoding !== 'string') { 17743 throw new TypeError('encoding must be a string'); 17744 } 17745 if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) { 17746 throw new TypeError('Unknown encoding: ' + encoding); 17747 } 17748 if (val.length === 1) { 17749 var code = val.charCodeAt(0); 17750 if ((encoding === 'utf8' && code < 128) || encoding === 'latin1') { 17751 // Fast path: If `val` fits into a single byte, use that numeric value. 17752 val = code; 17753 } 17754 } 17755 } else if (typeof val === 'number') { 17756 val = val & 255; 17757 } else if (typeof val === 'boolean') { 17758 val = Number(val); 17759 } 17760 17761 // Invalid ranges are not set to a default, so can range check early. 17762 if (start < 0 || this.length < start || this.length < end) { 17763 throw new RangeError('Out of range index'); 17764 } 17765 17766 if (end <= start) { 17767 return this; 17768 } 17769 17770 start = start >>> 0; 17771 end = end === undefined ? this.length : end >>> 0; 17772 17773 if (!val) val = 0; 17774 17775 var i; 17776 if (typeof val === 'number') { 17777 for (i = start; i < end; ++i) { 17778 this[i] = val; 17779 } 17780 } else { 17781 var bytes = Buffer.isBuffer(val) ? val : Buffer.from(val, encoding); 17782 var len = bytes.length; 17783 if (len === 0) { 17784 throw new TypeError(
vendor: 6,256 bytes, lines 17785-17954
17785 'The value "' + val + '" is invalid for argument "value"' 17786 ); 17787 } 17788 for (i = 0; i < end - start; ++i) { 17789 this[i + start] = bytes[i % len]; 17790 } 17791 } 17792 17793 return this; 17794 }; 17795 17796 // HELPER FUNCTIONS 17797 // ================ 17798 17799 var INVALID_BASE64_RE = /[^+/0-9A-Za-z-_]/g; 17800 17801 function base64clean(str) { 17802 // Node takes equal signs as end of the Base64 encoding 17803 str = str.split('=')[0]; 17804 // Node strips out invalid characters like \n and \t from the string, base64-js does not 17805 str = str.trim().replace(INVALID_BASE64_RE, ''); 17806 // Node converts strings with length < 2 to '' 17807 if (str.length < 2) return ''; 17808 // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not 17809 while (str.length % 4 !== 0) { 17810 str = str + '='; 17811 } 17812 return str; 17813 } 17814 17815 function utf8ToBytes(string, units) { 17816 units = units || Infinity; 17817 var codePoint; 17818 var length = string.length; 17819 var leadSurrogate = null; 17820 var bytes = []; 17821 17822 for (var i = 0; i < length; ++i) { 17823 codePoint = string.charCodeAt(i); 17824 17825 // is surrogate component 17826 if (codePoint > 0xd7ff && codePoint < 0xe000) { 17827 // last char was a lead 17828 if (!leadSurrogate) { 17829 // no lead yet 17830 if (codePoint > 0xdbff) { 17831 // unexpected trail 17832 if ((units -= 3) > -1) bytes.push(0xef, 0xbf, 0xbd); 17833 continue; 17834 } else if (i + 1 === length) { 17835 // unpaired lead 17836 if ((units -= 3) > -1) bytes.push(0xef, 0xbf, 0xbd); 17837 continue; 17838 } 17839 17840 // valid lead 17841 leadSurrogate = codePoint; 17842 17843 continue; 17844 } 17845 17846 // 2 leads in a row 17847 if (codePoint < 0xdc00) { 17848 if ((units -= 3) > -1) bytes.push(0xef, 0xbf, 0xbd); 17849 leadSurrogate = codePoint; 17850 continue; 17851 } 17852 17853 // valid surrogate pair 17854 codePoint = 17855 (((leadSurrogate - 0xd800) << 10) | (codePoint - 0xdc00)) + 0x10000; 17856 } else if (leadSurrogate) { 17857 // valid bmp char, but last char was a lead 17858 if ((units -= 3) > -1) bytes.push(0xef, 0xbf, 0xbd); 17859 } 17860 17861 leadSurrogate = null; 17862 17863 // encode utf8 17864 if (codePoint < 0x80) { 17865 if ((units -= 1) < 0) break; 17866 bytes.push(codePoint); 17867 } else if (codePoint < 0x800) { 17868 if ((units -= 2) < 0) break; 17869 bytes.push((codePoint >> 0x6) | 0xc0, (codePoint & 0x3f) | 0x80); 17870 } else if (codePoint < 0x10000) { 17871 if ((units -= 3) < 0) break; 17872 bytes.push( 17873 (codePoint >> 0xc) | 0xe0, 17874 ((codePoint >> 0x6) & 0x3f) | 0x80, 17875 (codePoint & 0x3f) | 0x80 17876 ); 17877 } else if (codePoint < 0x110000) { 17878 if ((units -= 4) < 0) break; 17879 bytes.push( 17880 (codePoint >> 0x12) | 0xf0, 17881 ((codePoint >> 0xc) & 0x3f) | 0x80, 17882 ((codePoint >> 0x6) & 0x3f) | 0x80, 17883 (codePoint & 0x3f) | 0x80 17884 ); 17885 } else { 17886 throw new Error('Invalid code point'); 17887 } 17888 } 17889 17890 return bytes; 17891 } 17892 17893 function asciiToBytes(str) { 17894 var byteArray = []; 17895 for (var i = 0; i < str.length; ++i) { 17896 // Node's code seems to be doing this and not & 0x7F.. 17897 byteArray.push(str.charCodeAt(i) & 0xff); 17898 } 17899 return byteArray; 17900 } 17901 17902 function utf16leToBytes(str, units) { 17903 var c, hi, lo; 17904 var byteArray = []; 17905 for (var i = 0; i < str.length; ++i) { 17906 if ((units -= 2) < 0) break; 17907 17908 c = str.charCodeAt(i); 17909 hi = c >> 8; 17910 lo = c % 256; 17911 byteArray.push(lo); 17912 byteArray.push(hi); 17913 } 17914 17915 return byteArray; 17916 } 17917 17918 function base64ToBytes(str) { 17919 return base64.toByteArray(base64clean(str)); 17920 } 17921 17922 function blitBuffer(src, dst, offset, length) { 17923 for (var i = 0; i < length; ++i) { 17924 if (i + offset >= dst.length || i >= src.length) break; 17925 dst[i + offset] = src[i]; 17926 } 17927 return i; 17928 } 17929 17930 // ArrayBuffer or Uint8Array objects from other contexts (i.e. iframes) do not pass 17931 // the `instanceof` check but they should be treated as of that type. 17932 // See: https://github.com/feross/buffer/issues/166 17933 function isInstance(obj, type) { 17934 return ( 17935 obj instanceof type || 17936 (obj != null && 17937 obj.constructor != null && 17938 obj.constructor.name != null && 17939 obj.constructor.name === type.name) 17940 ); 17941 } 17942 function numberIsNaN(obj) { 17943 // For IE11 support 17944 return obj !== obj; // eslint-disable-line no-self-compare 17945 } 17946 17947 // Create lookup table for `toString('hex')` 17948 // See: https://github.com/feross/buffer/issues/219 17949 var hexSliceLookupTable = (function() { 17950 var alphabet = '0123456789abcdef'; 17951 var table = new Array(256); 17952 for (var i = 0; i < 16; ++i) { 17953 var i16 = i * 16; 17954 for (var j = 0; j < 16; ++j) {
vendor: 6,584 bytes, lines 17955-18136
17955 table[i16 + j] = alphabet[i] + alphabet[j]; 17956 } 17957 } 17958 return table; 17959 })(); 17960 }.call(this, _dereq_('buffer').Buffer)); 17961 }, 17962 { 'base64-js': 20, buffer: 22, ieee754: 31 } 17963 ], 17964 23: [ 17965 function(_dereq_, module, exports) { 17966 // This file can be required in Browserify and Node.js for automatic polyfill 17967 // To use it: require('es6-promise/auto'); 17968 'use strict'; 17969 module.exports = _dereq_('./').polyfill(); 17970 }, 17971 { './': 24 } 17972 ], 17973 24: [ 17974 function(_dereq_, module, exports) { 17975 (function(process, global) { 17976 /*! 17977 * @overview es6-promise - a tiny implementation of Promises/A+. 17978 * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald) 17979 * @license Licensed under MIT license 17980 * See https://raw.githubusercontent.com/stefanpenner/es6-promise/master/LICENSE 17981 * @version v4.2.8+1e68dce6 17982 */ 17983 17984 (function(global, factory) { 17985 typeof exports === 'object' && typeof module !== 'undefined' 17986 ? (module.exports = factory()) 17987 : typeof define === 'function' && define.amd 17988 ? define(factory) 17989 : (global.ES6Promise = factory()); 17990 })(this, function() { 17991 'use strict'; 17992 17993 function objectOrFunction(x) { 17994 var type = typeof x; 17995 return x !== null && (type === 'object' || type === 'function'); 17996 } 17997 17998 function isFunction(x) { 17999 return typeof x === 'function'; 18000 } 18001 18002 var _isArray = void 0; 18003 if (Array.isArray) { 18004 _isArray = Array.isArray; 18005 } else { 18006 _isArray = function(x) { 18007 return Object.prototype.toString.call(x) === '[object Array]'; 18008 }; 18009 } 18010 18011 var isArray = _isArray; 18012 18013 var len = 0; 18014 var vertxNext = void 0; 18015 var customSchedulerFn = void 0; 18016 18017 var asap = function asap(callback, arg) { 18018 queue[len] = callback; 18019 queue[len + 1] = arg; 18020 len += 2; 18021 if (len === 2) { 18022 // If len is 2, that means that we need to schedule an async flush. 18023 // If additional callbacks are queued before the queue is flushed, they 18024 // will be processed by this flush that we are scheduling. 18025 if (customSchedulerFn) { 18026 customSchedulerFn(flush); 18027 } else { 18028 scheduleFlush(); 18029 } 18030 } 18031 }; 18032 18033 function setScheduler(scheduleFn) { 18034 customSchedulerFn = scheduleFn; 18035 } 18036 18037 function setAsap(asapFn) { 18038 asap = asapFn; 18039 } 18040 18041 var browserWindow = typeof window !== 'undefined' ? window : undefined; 18042 var browserGlobal = browserWindow || {}; 18043 var BrowserMutationObserver = 18044 browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver; 18045 var isNode = 18046 typeof self === 'undefined' && 18047 typeof process !== 'undefined' && 18048 {}.toString.call(process) === '[object process]'; 18049 18050 // test for web worker but not in IE10 18051 var isWorker = 18052 typeof Uint8ClampedArray !== 'undefined' && 18053 typeof importScripts !== 'undefined' && 18054 typeof MessageChannel !== 'undefined'; 18055 18056 // node 18057 function useNextTick() { 18058 // node version 0.10.x displays a deprecation warning when nextTick is used recursively 18059 // see https://github.com/cujojs/when/issues/410 for details 18060 return function() { 18061 return process.nextTick(flush); 18062 }; 18063 } 18064 18065 // vertx 18066 function useVertxTimer() { 18067 if (typeof vertxNext !== 'undefined') { 18068 return function() { 18069 vertxNext(flush); 18070 }; 18071 } 18072 18073 return useSetTimeout(); 18074 } 18075 18076 function useMutationObserver() { 18077 var iterations = 0; 18078 var observer = new BrowserMutationObserver(flush); 18079 var node = document.createTextNode(''); 18080 observer.observe(node, { characterData: true }); 18081 18082 return function() { 18083 node.data = iterations = ++iterations % 2; 18084 }; 18085 } 18086 18087 // web worker 18088 function useMessageChannel() { 18089 var channel = new MessageChannel(); 18090 channel.port1.onmessage = flush; 18091 return function() { 18092 return channel.port2.postMessage(0); 18093 }; 18094 } 18095 18096 function useSetTimeout() { 18097 // Store setTimeout reference so es6-promise will be unaffected by 18098 // other code modifying setTimeout (like sinon.useFakeTimers()) 18099 var globalSetTimeout = setTimeout; 18100 return function() { 18101 return globalSetTimeout(flush, 1); 18102 }; 18103 } 18104 18105 var queue = new Array(1000); 18106 function flush() { 18107 for (var i = 0; i < len; i += 2) { 18108 var callback = queue[i]; 18109 var arg = queue[i + 1]; 18110 18111 callback(arg); 18112 18113 queue[i] = undefined; 18114 queue[i + 1] = undefined; 18115 } 18116 18117 len = 0; 18118 } 18119 18120 function attemptVertx() { 18121 try { 18122 var vertx = Function('return this')().require('vertx'); 18123 vertxNext = vertx.runOnLoop || vertx.runOnContext; 18124 return useVertxTimer(); 18125 } catch (e) { 18126 return useSetTimeout(); 18127 } 18128 } 18129 18130 var scheduleFlush = void 0; 18131 // Decide what async method to use to triggering processing of queued callbacks: 18132 if (isNode) { 18133 scheduleFlush = useNextTick(); 18134 } else if (BrowserMutationObserver) { 18135 scheduleFlush = useMutationObserver(); 18136 } else if (isWorker) {
vendor: 6,310 bytes, lines 18137-18333
18137 scheduleFlush = useMessageChannel(); 18138 } else if (browserWindow === undefined && typeof _dereq_ === 'function') { 18139 scheduleFlush = attemptVertx(); 18140 } else { 18141 scheduleFlush = useSetTimeout(); 18142 } 18143 18144 function then(onFulfillment, onRejection) { 18145 var parent = this; 18146 18147 var child = new this.constructor(noop); 18148 18149 if (child[PROMISE_ID] === undefined) { 18150 makePromise(child); 18151 } 18152 18153 var _state = parent._state; 18154 18155 if (_state) { 18156 var callback = arguments[_state - 1]; 18157 asap(function() { 18158 return invokeCallback(_state, child, callback, parent._result); 18159 }); 18160 } else { 18161 subscribe(parent, child, onFulfillment, onRejection); 18162 } 18163 18164 return child; 18165 } 18166 18167 /** 18168 `Promise.resolve` returns a promise that will become resolved with the 18169 passed `value`. It is shorthand for the following: 18170 18171 ```javascript 18172 let promise = new Promise(function(resolve, reject){ 18173 resolve(1); 18174 }); 18175 18176 promise.then(function(value){ 18177 // value === 1 18178 }); 18179 ``` 18180 18181 Instead of writing the above, your code now simply becomes the following: 18182 18183 ```javascript 18184 let promise = Promise.resolve(1); 18185 18186 promise.then(function(value){ 18187 // value === 1 18188 }); 18189 ``` 18190 18191 @method resolve 18192 @static 18193 @param {Any} value value that the returned promise will be resolved with 18194 Useful for tooling. 18195 @return {Promise} a promise that will become fulfilled with the given 18196 `value` 18197*/ 18198 function resolve$1(object) { 18199 /*jshint validthis:true */ 18200 var Constructor = this; 18201 18202 if ( 18203 object && 18204 typeof object === 'object' && 18205 object.constructor === Constructor 18206 ) { 18207 return object; 18208 } 18209 18210 var promise = new Constructor(noop); 18211 resolve(promise, object); 18212 return promise; 18213 } 18214 18215 var PROMISE_ID = Math.random() 18216 .toString(36) 18217 .substring(2); 18218 18219 function noop() {} 18220 18221 var PENDING = void 0; 18222 var FULFILLED = 1; 18223 var REJECTED = 2; 18224 18225 function selfFulfillment() { 18226 return new TypeError('You cannot resolve a promise with itself'); 18227 } 18228 18229 function cannotReturnOwn() { 18230 return new TypeError( 18231 'A promises callback cannot return that same promise.' 18232 ); 18233 } 18234 18235 function tryThen(then$$1, value, fulfillmentHandler, rejectionHandler) { 18236 try { 18237 then$$1.call(value, fulfillmentHandler, rejectionHandler); 18238 } catch (e) { 18239 return e; 18240 } 18241 } 18242 18243 function handleForeignThenable(promise, thenable, then$$1) { 18244 asap(function(promise) { 18245 var sealed = false; 18246 var error = tryThen( 18247 then$$1, 18248 thenable, 18249 function(value) { 18250 if (sealed) { 18251 return; 18252 } 18253 sealed = true; 18254 if (thenable !== value) { 18255 resolve(promise, value); 18256 } else { 18257 fulfill(promise, value); 18258 } 18259 }, 18260 function(reason) { 18261 if (sealed) { 18262 return; 18263 } 18264 sealed = true; 18265 18266 reject(promise, reason); 18267 }, 18268 'Settle: ' + (promise._label || ' unknown promise') 18269 ); 18270 18271 if (!sealed && error) { 18272 sealed = true; 18273 reject(promise, error); 18274 } 18275 }, promise); 18276 } 18277 18278 function handleOwnThenable(promise, thenable) { 18279 if (thenable._state === FULFILLED) { 18280 fulfill(promise, thenable._result); 18281 } else if (thenable._state === REJECTED) { 18282 reject(promise, thenable._result); 18283 } else { 18284 subscribe( 18285 thenable, 18286 undefined, 18287 function(value) { 18288 return resolve(promise, value); 18289 }, 18290 function(reason) { 18291 return reject(promise, reason); 18292 } 18293 ); 18294 } 18295 } 18296 18297 function handleMaybeThenable(promise, maybeThenable, then$$1) { 18298 if ( 18299 maybeThenable.constructor === promise.constructor && 18300 then$$1 === then && 18301 maybeThenable.constructor.resolve === resolve$1 18302 ) { 18303 handleOwnThenable(promise, maybeThenable); 18304 } else { 18305 if (then$$1 === undefined) { 18306 fulfill(promise, maybeThenable); 18307 } else if (isFunction(then$$1)) { 18308 handleForeignThenable(promise, maybeThenable, then$$1); 18309 } else { 18310 fulfill(promise, maybeThenable); 18311 } 18312 } 18313 } 18314 18315 function resolve(promise, value) { 18316 if (promise === value) { 18317 reject(promise, selfFulfillment()); 18318 } else if (objectOrFunction(value)) { 18319 var then$$1 = void 0; 18320 try { 18321 then$$1 = value.then; 18322 } catch (error) { 18323 reject(promise, error); 18324 return; 18325 } 18326 handleMaybeThenable(promise, value, then$$1); 18327 } else { 18328 fulfill(promise, value); 18329 } 18330 } 18331 18332 function publishRejection(promise) { 18333 if (promise._onerror) {
vendor: 11,219 bytes, lines 18334-18679
18334 promise._onerror(promise._result); 18335 } 18336 18337 publish(promise); 18338 } 18339 18340 function fulfill(promise, value) { 18341 if (promise._state !== PENDING) { 18342 return; 18343 } 18344 18345 promise._result = value; 18346 promise._state = FULFILLED; 18347 18348 if (promise._subscribers.length !== 0) { 18349 asap(publish, promise); 18350 } 18351 } 18352 18353 function reject(promise, reason) { 18354 if (promise._state !== PENDING) { 18355 return; 18356 } 18357 promise._state = REJECTED; 18358 promise._result = reason; 18359 18360 asap(publishRejection, promise); 18361 } 18362 18363 function subscribe(parent, child, onFulfillment, onRejection) { 18364 var _subscribers = parent._subscribers; 18365 var length = _subscribers.length; 18366 18367 parent._onerror = null; 18368 18369 _subscribers[length] = child; 18370 _subscribers[length + FULFILLED] = onFulfillment; 18371 _subscribers[length + REJECTED] = onRejection; 18372 18373 if (length === 0 && parent._state) { 18374 asap(publish, parent); 18375 } 18376 } 18377 18378 function publish(promise) { 18379 var subscribers = promise._subscribers; 18380 var settled = promise._state; 18381 18382 if (subscribers.length === 0) { 18383 return; 18384 } 18385 18386 var child = void 0, 18387 callback = void 0, 18388 detail = promise._result; 18389 18390 for (var i = 0; i < subscribers.length; i += 3) { 18391 child = subscribers[i]; 18392 callback = subscribers[i + settled]; 18393 18394 if (child) { 18395 invokeCallback(settled, child, callback, detail); 18396 } else { 18397 callback(detail); 18398 } 18399 } 18400 18401 promise._subscribers.length = 0; 18402 } 18403 18404 function invokeCallback(settled, promise, callback, detail) { 18405 var hasCallback = isFunction(callback), 18406 value = void 0, 18407 error = void 0, 18408 succeeded = true; 18409 18410 if (hasCallback) { 18411 try { 18412 value = callback(detail); 18413 } catch (e) { 18414 succeeded = false; 18415 error = e; 18416 } 18417 18418 if (promise === value) { 18419 reject(promise, cannotReturnOwn()); 18420 return; 18421 } 18422 } else { 18423 value = detail; 18424 } 18425 18426 if (promise._state !== PENDING) { 18427 // noop 18428 } else if (hasCallback && succeeded) { 18429 resolve(promise, value); 18430 } else if (succeeded === false) { 18431 reject(promise, error); 18432 } else if (settled === FULFILLED) { 18433 fulfill(promise, value); 18434 } else if (settled === REJECTED) { 18435 reject(promise, value); 18436 } 18437 } 18438 18439 function initializePromise(promise, resolver) { 18440 try { 18441 resolver( 18442 function resolvePromise(value) { 18443 resolve(promise, value); 18444 }, 18445 function rejectPromise(reason) { 18446 reject(promise, reason); 18447 } 18448 ); 18449 } catch (e) { 18450 reject(promise, e); 18451 } 18452 } 18453 18454 var id = 0; 18455 function nextId() { 18456 return id++; 18457 } 18458 18459 function makePromise(promise) { 18460 promise[PROMISE_ID] = id++; 18461 promise._state = undefined; 18462 promise._result = undefined; 18463 promise._subscribers = []; 18464 } 18465 18466 function validationError() { 18467 return new Error('Array Methods must be provided an Array'); 18468 } 18469 18470 var Enumerator = (function() { 18471 function Enumerator(Constructor, input) { 18472 this._instanceConstructor = Constructor; 18473 this.promise = new Constructor(noop); 18474 18475 if (!this.promise[PROMISE_ID]) { 18476 makePromise(this.promise); 18477 } 18478 18479 if (isArray(input)) { 18480 this.length = input.length; 18481 this._remaining = input.length; 18482 18483 this._result = new Array(this.length); 18484 18485 if (this.length === 0) { 18486 fulfill(this.promise, this._result); 18487 } else { 18488 this.length = this.length || 0; 18489 this._enumerate(input); 18490 if (this._remaining === 0) { 18491 fulfill(this.promise, this._result); 18492 } 18493 } 18494 } else { 18495 reject(this.promise, validationError()); 18496 } 18497 } 18498 18499 Enumerator.prototype._enumerate = function _enumerate(input) { 18500 for (var i = 0; this._state === PENDING && i < input.length; i++) { 18501 this._eachEntry(input[i], i); 18502 } 18503 }; 18504 18505 Enumerator.prototype._eachEntry = function _eachEntry(entry, i) { 18506 var c = this._instanceConstructor; 18507 var resolve$$1 = c.resolve; 18508 18509 if (resolve$$1 === resolve$1) { 18510 var _then = void 0; 18511 var error = void 0; 18512 var didError = false; 18513 try { 18514 _then = entry.then; 18515 } catch (e) { 18516 didError = true; 18517 error = e; 18518 } 18519 18520 if (_then === then && entry._state !== PENDING) { 18521 this._settledAt(entry._state, i, entry._result); 18522 } else if (typeof _then !== 'function') { 18523 this._remaining--; 18524 this._result[i] = entry; 18525 } else if (c === Promise$1) { 18526 var promise = new c(noop); 18527 if (didError) { 18528 reject(promise, error); 18529 } else { 18530 handleMaybeThenable(promise, entry, _then); 18531 } 18532 this._willSettleAt(promise, i); 18533 } else { 18534 this._willSettleAt( 18535 new c(function(resolve$$1) { 18536 return resolve$$1(entry); 18537 }), 18538 i 18539 ); 18540 } 18541 } else { 18542 this._willSettleAt(resolve$$1(entry), i); 18543 } 18544 }; 18545 18546 Enumerator.prototype._settledAt = function _settledAt(state, i, value) { 18547 var promise = this.promise; 18548 18549 if (promise._state === PENDING) { 18550 this._remaining--; 18551 18552 if (state === REJECTED) { 18553 reject(promise, value); 18554 } else { 18555 this._result[i] = value; 18556 } 18557 } 18558 18559 if (this._remaining === 0) { 18560 fulfill(promise, this._result); 18561 } 18562 }; 18563 18564 Enumerator.prototype._willSettleAt = function _willSettleAt(promise, i) { 18565 var enumerator = this; 18566 18567 subscribe( 18568 promise, 18569 undefined, 18570 function(value) { 18571 return enumerator._settledAt(FULFILLED, i, value); 18572 }, 18573 function(reason) { 18574 return enumerator._settledAt(REJECTED, i, reason); 18575 } 18576 ); 18577 }; 18578 18579 return Enumerator; 18580 })(); 18581 18582 /** 18583 `Promise.all` accepts an array of promises, and returns a new promise which 18584 is fulfilled with an array of fulfillment values for the passed promises, or 18585 rejected with the reason of the first passed promise to be rejected. It casts all 18586 elements of the passed iterable to promises as it runs this algorithm. 18587 18588 Example: 18589 18590 ```javascript 18591 let promise1 = resolve(1); 18592 let promise2 = resolve(2); 18593 let promise3 = resolve(3); 18594 let promises = [ promise1, promise2, promise3 ]; 18595 18596 Promise.all(promises).then(function(array){ 18597 // The array here would be [ 1, 2, 3 ]; 18598 }); 18599 ``` 18600 18601 If any of the `promises` given to `all` are rejected, the first promise 18602 that is rejected will be given as an argument to the returned promises's 18603 rejection handler. For example: 18604 18605 Example: 18606 18607 ```javascript 18608 let promise1 = resolve(1); 18609 let promise2 = reject(new Error("2")); 18610 let promise3 = reject(new Error("3")); 18611 let promises = [ promise1, promise2, promise3 ]; 18612 18613 Promise.all(promises).then(function(array){ 18614 // Code here never runs because there are rejected promises! 18615 }, function(error) { 18616 // error.message === "2" 18617 }); 18618 ``` 18619 18620 @method all 18621 @static 18622 @param {Array} entries array of promises 18623 @param {String} label optional string for labeling the promise. 18624 Useful for tooling. 18625 @return {Promise} promise that is fulfilled when all `promises` have been 18626 fulfilled, or rejected if any of them become rejected. 18627 @static 18628*/ 18629 function all(entries) { 18630 return new Enumerator(this, entries).promise; 18631 } 18632 18633 /** 18634 `Promise.race` returns a new promise which is settled in the same way as the 18635 first passed promise to settle. 18636 18637 Example: 18638 18639 ```javascript 18640 let promise1 = new Promise(function(resolve, reject){ 18641 setTimeout(function(){ 18642 resolve('promise 1'); 18643 }, 200); 18644 }); 18645 18646 let promise2 = new Promise(function(resolve, reject){ 18647 setTimeout(function(){ 18648 resolve('promise 2'); 18649 }, 100); 18650 }); 18651 18652 Promise.race([promise1, promise2]).then(function(result){ 18653 // result === 'promise 2' because it was resolved before promise1 18654 // was resolved. 18655 }); 18656 ``` 18657 18658 `Promise.race` is deterministic in that only the state of the first 18659 settled promise matters. For example, even if other promises given to the 18660 `promises` array argument are resolved, but the first settled promise has 18661 become rejected before the other promises became fulfilled, the returned 18662 promise will become rejected: 18663 18664 ```javascript 18665 let promise1 = new Promise(function(resolve, reject){ 18666 setTimeout(function(){ 18667 resolve('promise 1'); 18668 }, 200); 18669 }); 18670 18671 let promise2 = new Promise(function(resolve, reject){ 18672 setTimeout(function(){ 18673 reject(new Error('promise 2')); 18674 }, 100); 18675 }); 18676 18677 Promise.race([promise1, promise2]).then(function(result){ 18678 // Code here never runs 18679 }, function(reason){
18680 // reason.message === 'promise 2' because promise 2 became rejected before 18681 // promise 1 became fulfilled 18682 }); 18683 ``` 18684 18685 An example real-world use case is implementing timeouts: 18686 18687 ```javascript 18688 Promise.race([ajax('foo.json'), timeout(5000)]) 18689 ``` 18690 18691 @method race 18692 @static 18693 @param {Array} promises array of promises to observe 18694 Useful for tooling. 18695 @return {Promise} a promise which settles in the same way as the first passed 18696 promise to settle. 18697*/ 18698 function race(entries) { 18699 /*jshint validthis:true */ 18700 var Constructor = this; 18701 18702 if (!isArray(entries)) { 18703 return new Constructor(function(_, reject) { 18704 return reject(new TypeError('You must pass an array to race.')); 18705 }); 18706 } else { 18707 return new Constructor(function(resolve, reject) { 18708 var length = entries.length; 18709 for (var i = 0; i < length; i++) { 18710 Constructor.resolve(entries[i]).then(resolve, reject); 18711 } 18712 }); 18713 } 18714 } 18715 18716 /** 18717 `Promise.reject` returns a promise rejected with the passed `reason`. 18718 It is shorthand for the following: 18719 18720 ```javascript 18721 let promise = new Promise(function(resolve, reject){ 18722 reject(new Error('WHOOPS')); 18723 }); 18724 18725 promise.then(function(value){ 18726 // Code here doesn't run because the promise is rejected! 18727 }, function(reason){ 18728 // reason.message === 'WHOOPS' 18729 }); 18730 ``` 18731 18732 Instead of writing the above, your code now simply becomes the following: 18733 18734 ```javascript 18735 let promise = Promise.reject(new Error('WHOOPS')); 18736 18737 promise.then(function(value){ 18738 // Code here doesn't run because the promise is rejected! 18739 }, function(reason){ 18740 // reason.message === 'WHOOPS' 18741 }); 18742 ``` 18743 18744 @method reject 18745 @static 18746 @param {Any} reason value that the returned promise will be rejected with. 18747 Useful for tooling. 18748 @return {Promise} a promise rejected with the given `reason`. 18749*/ 18750 function reject$1(reason) { 18751 /*jshint validthis:true */ 18752 var Constructor = this; 18753 var promise = new Constructor(noop); 18754 reject(promise, reason); 18755 return promise; 18756 } 18757 18758 function needsResolver() { 18759 throw new TypeError( 18760 'You must pass a resolver function as the first argument to the promise constructor' 18761 ); 18762 } 18763 18764 function needsNew() { 18765 throw new TypeError( 18766 "Failed to construct 'Promise': Please use the 'new' operator, this object c
18766onstructor cannot be called as a function." 18767 ); 18768 } 18769 18770 /** 18771 Promise objects represent the eventual result of an asynchronous operation. The 18772 primary way of interacting with a promise is through its `then` method, which 18773 registers callbacks to receive either a promise's eventual value or the reason 18774 why the promise cannot be fulfilled. 18775 18776 Terminology 18777 ----------- 18778 18779 - `promise` is an object or function with a `then` method whose behavior conforms to this specification. 18780 - `thenable` is an object or function that defines a `then` method. 18781 - `value` is any legal JavaScript value (including undefined, a thenable, or a promise). 18782 - `exception` is a value that is thrown using the throw statement. 18783 - `reason` is a value that indicates why a promise was rejected. 18784 - `settled` the final resting state of a promise, fulfilled or rejected. 18785 18786 A promise can be in one of three states: pending, fulfilled, or rejected. 18787 18788 Promises that are fulfilled have a fulfillment value and are in the fulfilled 18789 state. Promises that are rejected have a rejection reason and are in the 18790 rejected state. A fulfillment value is never a thenable. 18791 18792 Promises can also be said to *resolve* a value. If this value is also a 18793 promise, then the original promise's settled state will match the value's 18794 settled state. So a promise that *resolves* a promise that rejects will 18795 itself reject, and a promise that *resolves* a promise that fulfills will 18796 itself fulfill. 18797 18798 18799 Basic Usage: 18800 ------------ 18801 18802 ```js 18803 let promise = new Promise(function(resolve, reject) { 18804 // on success 18805 resolve(value); 18806 18807 // on failure 18808 reject(reason); 18809 }); 18810 18811 promise.then(function(value) { 18812 // on fulfillment 18813 }, function(reason) { 18814 // on rejection 18815 }); 18816 ``` 18817 18818 Advanced Usage: 18819 --------------- 18820 18821 Promises shine when abstracting away asynchronous interactions such as 18822 `XMLHttpRequest`s. 18823 18824 ```js 18825 function getJSON(url) { 18826 return new Promise(function(resolve, reject){ 18827 let xhr = new XMLHttpRequest(); 18828 18829 xhr.open('GET', url); 18830 xhr.onreadystatechange = handler; 18831 xhr.responseType = 'json'; 18832 xhr.setRequestHeader('Accept', 'application/json'); 18833 xhr.send(); 18834 18835 function handler() { 18836 if (this.readyState === this.DONE) { 18837 if (this.status === 200) { 18838 resolve(this.response); 18839 } else { 18840 reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']')); 18841 } 18842 } 18843 }; 18844 }); 18845 } 18846 18847 getJSON('/posts.json').then(function(json) { 18848 // on fulfillment 18849 }, function(reason) { 18850 // on rejection 18851 }); 18852 ``` 18853 18854 Unlike callbacks, promises are great composable primitives. 18855 18856 ```js 18857 Promise.all([ 18858 getJSON('/posts'), 18859 getJSON('/comments') 18860 ]).then(function(values){ 18861 values[0] // => postsJSON 18862 values[1] // => commentsJSON 18863 18864 return values; 18865 }); 18866 ``` 18867 18868 @class Promise 18869 @param {Function} resolver 18870 Useful for tooling. 18871 @constructor 18872*/ 18873 18874 var Promise$1 = (function() { 18875 function Promise(resolver) { 18876 this[PROMISE_ID] = nextId(); 18877 this._result = this._state = undefined; 18878 this._subscribers = []; 18879 18880 if (noop !== resolver) { 18881 typeof resolver !== 'function' && needsResolver(); 18882 this instanceof Promise 18883 ? initializePromise(this, resolver) 18884 : needsNew(); 18885 } 18886 } 18887 18888 /** 18889 The primary way of interacting with a promise is through its `then` method, 18890 which registers callbacks to receive either a promise's eventual value or the 18891 reason why the promise cannot be fulfilled. 18892 ```js 18893 findUser().then(function(user){ 18894 // user is available 18895 }, function(reason){ 18896 // user is unavailable, and you are given the reason why 18897 }); 18898 ``` 18899 Chaining 18900 -------- 18901 The return value of `then` is itself a promise. This second, 'downstream' 18902 promise is resolved with the return value of the first promise's fulfillment 18903 or rejection handler, or rejected if the handler throws an exception. 18904 ```js 18905 findUser().then(function (user) { 18906 return user.name; 18907 }, function (reason) { 18908 return 'default name'; 18909 }).then(function (userName) { 18910 // If `findUser` fulfilled, `userName` will be the user's name, otherwise it 18911 // will be `'default name'` 18912 }); 18913 findUser().then(function (user) { 18914 throw new Error('Found user, but still unhappy'); 18915 }, function (reason) { 18916 throw new Error('`findUser` rejected and we're unhappy'); 18917 }).then(function (value) { 18918 // never reached 18919 }, function (reason) { 18920 // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'. 18921 // If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'. 18922 }); 18923 ``` 18924 If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream. 18925 ```js 18926 findUser().then(function (user) { 18927 throw new PedagogicalException('Upstream error'); 18928 }).then(function (value) { 18929 // never reached 18930 }).then(function (value) { 18931 // never reached 18932 }, function (reason) { 18933 // The `PedgagocialException` is propagated all the way down to here 18934 }); 18935 ``` 18936 Assimilation 18937 ------------ 18938 Sometimes the value you want to propagate to a downstream promise can only be 18939 retrieved asynchronously. This can be achieved by returning a promise in the 18940 fulfillment or rejection handler. The downstream promise will then be pending 18941 until the returned promise is settled. This is called *assimilation*. 18942 ```js 18943 findUser().then(function (user) { 18944 return findCommentsByAuthor(user); 18945 }).then(function (comments) { 18946 // The user's comments are now available 18947 }); 18948 ``` 18949 If the assimliated promise rejects, then the downstream promise will also reject. 18950 ```js 18951 findUser().then(function (user) { 18952 return findCommentsByAuthor(user); 18953 }).then(function (comments) { 18954 // If `findCommentsByAuthor` fulfills, we'll have the value here 18955 }, function (reason) { 18956 // If `findCommentsByAuthor` rejects, we'll have the reason here 18957 }); 18958 ```
18959 Simple Example 18960 -------------- 18961 Synchronous Example 18962 ```javascript 18963 let result; 18964 try { 18965 result = findResult(); 18966 // success 18967 } catch(reason) { 18968 // failure 18969 } 18970 ``` 18971 Errback Example 18972 ```js 18973 findResult(function(result, err){ 18974 if (err) { 18975 // failure 18976 } else { 18977 // success 18978 } 18979 }); 18980 ``` 18981 Promise Example; 18982 ```javascript 18983 findResult().then(function(result){ 18984 // success 18985 }, function(reason){ 18986 // failure 18987 }); 18988 ``` 18989 Advanced Example 18990 -------------- 18991 Synchronous Example 18992 ```javascript 18993 let author, books; 18994 try { 18995 author = findAuthor(); 18996 books = findBooksByAuthor(author); 18997 // success 18998 } catch(reason) { 18999 // failure 19000 } 19001 ``` 19002 Errback Example 19003 ```js 19004 function foundBooks(books) { 19005 } 19006 function failure(reason) { 19007 } 19008 findAuthor(function(author, err){ 19009 if (err) { 19010 failure(err); 19011 // failure 19012 } else { 19013 try { 19014 findBoooksByAuthor(author, function(books, err) { 19015 if (err) { 19016 failure(err); 19017 } else { 19018 try { 19019 foundBooks(books); 19020 } catch(reason) { 19021 failure(reason); 19022 } 19023 } 19024 }); 19025 } catch(error) { 19026 failure(err); 19027 } 19028 // success 19029 } 19030 }); 19031 ``` 19032 Promise Example; 19033 ```javascript 19034 findAuthor(). 19035 then(findBooksByAuthor). 19036 then(function(books){ 19037 // found books 19038 }).catch(function(reason){ 19039 // something went wrong 19040 }); 19041 ``` 19042 @method then 19043 @param {Function} onFulfilled 19044 @param {Function} onRejected 19045 Useful for tooling. 19046 @return {Promise} 19047 */ 19048 19049 /** 19050 `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same 19051 as the catch block of a try/catch statement. 19052 ```js 19053 function findAuthor(){ 19054 throw new Error('couldn't find that author'); 19055 } 19056 // synchronous 19057 try { 19058 findAuthor(); 19059 } catch(reason) { 19060 // something went wrong 19061 } 19062 // async with promises 19063 findAuthor().catch(function(reason){ 19064 // something went wrong 19065 }); 19066 ``` 19067 @method catch 19068 @param {Function} onRejection 19069 Useful for tooling. 19070 @return {Promise} 19071 */ 19072 19073 Promise.prototype.catch = function _catch(onRejection) { 19074 return this.then(null, onRejection); 19075 }; 19076 19077 /** 19078 `finally` will be invoked regardless of the promise's fate just as native 19079 try/catch/finally behaves 19080 19081 Synchronous example: 19082 19083 ```js 19084 findAuthor() { 19085 if (Math.random() > 0.5) { 19086 throw new Error(); 19087 } 19088 return new Author(); 19089 } 19090 19091 try { 19092 return findAuthor(); // succeed or fail 19093 } catch(error) { 19094 return findOtherAuther(); 19095 } finally { 19096 // always runs 19097 // doesn't affect the return value 19098 } 19099 ``` 19100 19101 Asynchronous example: 19102 19103 ```js 19104 findAuthor().catch(function(reason){ 19105 return findOtherAuther(); 19106 }).finally(function(){ 19107 // author was either found, or not 19108 }); 19109 ``` 19110 19111 @method finally 19112 @param {Function} callback 19113 @return {Promise} 19114 */ 19115 19116 Promise.prototype.finally = function _finally(callback) { 19117 var promise = this; 19118 var constructor = promise.constructor; 19119 19120 if (isFunction(callback)) { 19121 return promise.then( 19122 function(value) { 19123 return constructor.resolve(callback()).then(function() { 19124 return value; 19125 }); 19126 }, 19127 function(reason) { 19128 return constructor.resolve(callback()).then(function() { 19129 throw reason; 19130 }); 19131 } 19132 ); 19133 } 19134 19135 return promise.then(callback, callback); 19136 }; 19137 19138 return Promise; 19139 })(); 19140 19141 Promise$1.prototype.then = then; 19142 Promise$1.all = all; 19143 Promise$1.race = race; 19144 Promise$1.resolve = resolve$1; 19145 Promise$1.reject = reject$1; 19146 Promise$1._setScheduler = setScheduler; 19147 Promise$1._setAsap = setAsap; 19148 Promise$1._asap = asap; 19149 19150 /*global self*/ 19151 function polyfill() { 19152 var local = void 0; 19153 19154 if (typeof global !== 'undefined') { 19155 local = global; 19156 } else if (typeof self !== 'undefined') { 19157 local = self; 19158 } else { 19159 try { 19160 local = Function('return this')(); 19161 } catch (e) { 19162 throw new Error( 19163 'polyfill failed because global object is unavailable in this environment' 19164 ); 19165 } 19166 } 19167 19168 var P = local.Promise; 19169 19170 if (P) { 19171 var promiseToString = null; 19172 try { 19173 promiseToString = Object.prototype.toString.call(P.resolve()); 19174 } catch (e) { 19175 // silently ignored 19176 } 19177 19178 if (promiseToString === '[object Promise]' && !P.cast) { 19179 return; 19180 } 19181 } 19182 19183 local.Promise = Promise$1; 19184 } 19185 19186 // Strange compat.. 19187 Promise$1.polyfill = polyfill; 19188 Promise$1.Promise = Promise$1; 19189 19190 return Promise$1; 19191 }); 19192 }.call( 19193 this, 19194 _dereq_('_process'), 19195 typeof global !== 'undefined' 19196 ? global 19197 : typeof self !== 'undefined' 19198 ? self 19199 : typeof window !== 'undefined' ? window : {} 19200 )); 19201 }, 19202 { _process: 36 } 19203 ], 19204 25: [
vendor: 4,623 bytes, lines 19205-19337
19205 function(_dereq_, module, exports) { 19206 (function(global, factory) { 19207 if (typeof define === 'function' && define.amd) { 19208 define(['exports', 'module'], factory); 19209 } else if (typeof exports !== 'undefined' && typeof module !== 'undefined') { 19210 factory(exports, module); 19211 } else { 19212 var mod = { 19213 exports: {} 19214 }; 19215 factory(mod.exports, mod); 19216 global.fetchJsonp = mod.exports; 19217 } 19218 })(this, function(exports, module) { 19219 'use strict'; 19220 19221 var defaultOptions = { 19222 timeout: 5000, 19223 jsonpCallback: 'callback', 19224 jsonpCallbackFunction: null 19225 }; 19226 19227 function generateCallbackFunction() { 19228 return 'jsonp_' + Date.now() + '_' + Math.ceil(Math.random() * 100000); 19229 } 19230 19231 function clearFunction(functionName) { 19232 // IE8 throws an exception when you try to delete a property on window 19233 // http://stackoverflow.com/a/1824228/751089 19234 try { 19235 delete window[functionName]; 19236 } catch (e) { 19237 window[functionName] = undefined; 19238 } 19239 } 19240 19241 function removeScript(scriptId) { 19242 var script = document.getElementById(scriptId); 19243 if (script) { 19244 document.getElementsByTagName('head')[0].removeChild(script); 19245 } 19246 } 19247 19248 function fetchJsonp(_url) { 19249 var options = 19250 arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; 19251 19252 // to avoid param reassign 19253 var url = _url; 19254 var timeout = options.timeout || defaultOptions.timeout; 19255 var jsonpCallback = options.jsonpCallback || defaultOptions.jsonpCallback; 19256 19257 var timeoutId = undefined; 19258 19259 return new Promise(function(resolve, reject) { 19260 var callbackFunction = 19261 options.jsonpCallbackFunction || generateCallbackFunction(); 19262 var scriptId = jsonpCallback + '_' + callbackFunction; 19263 19264 window[callbackFunction] = function(response) { 19265 resolve({ 19266 ok: true, 19267 // keep consistent with fetch API 19268 json: function json() { 19269 return Promise.resolve(response); 19270 } 19271 }); 19272 19273 if (timeoutId) clearTimeout(timeoutId); 19274 19275 removeScript(scriptId); 19276 19277 clearFunction(callbackFunction); 19278 }; 19279 19280 // Check if the user set their own params, and if not add a ? to start a list of params 19281 url += url.indexOf('?') === -1 ? '?' : '&'; 19282 19283 var jsonpScript = document.createElement('script'); 19284 jsonpScript.setAttribute( 19285 'src', 19286 '' + url + jsonpCallback + '=' + callbackFunction 19287 ); 19288 if (options.charset) { 19289 jsonpScript.setAttribute('charset', options.charset); 19290 } 19291 jsonpScript.id = scriptId; 19292 document.getElementsByTagName('head')[0].appendChild(jsonpScript); 19293 19294 timeoutId = setTimeout(function() { 19295 reject(new Error('JSONP request to ' + _url + ' timed out')); 19296 19297 clearFunction(callbackFunction); 19298 removeScript(scriptId); 19299 window[callbackFunction] = function() { 19300 clearFunction(callbackFunction); 19301 }; 19302 }, timeout); 19303 19304 // Caught if got 404/500 19305 jsonpScript.onerror = function() { 19306 reject(new Error('JSONP request to ' + _url + ' failed')); 19307 19308 clearFunction(callbackFunction); 19309 removeScript(scriptId); 19310 if (timeoutId) clearTimeout(timeoutId); 19311 }; 19312 }); 19313 } 19314 19315 // export as global function 19316 /* 19317 let local; 19318 if (typeof global !== 'undefined') { 19319 local = global; 19320 } else if (typeof self !== 'undefined') { 19321 local = self; 19322 } else { 19323 try { 19324 local = Function('return this')(); 19325 } catch (e) { 19326 throw new Error('polyfill failed because global object is unavailable in this environment'); 19327 } 19328 } 19329 local.fetchJsonp = fetchJsonp; 19330 */ 19331 19332 module.exports = fetchJsonp; 19333 }); 19334 }, 19335 {} 19336 ], 19337 26: [
vendor: 6,694 bytes, lines 19338-19483
19338 function(_dereq_, module, exports) { 19339 /* FileSaver.js 19340 * A saveAs() FileSaver implementation. 19341 * 1.3.2 19342 * 2016-06-16 18:25:19 19343 * 19344 * By Eli Grey, http://eligrey.com 19345 * License: MIT 19346 * See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md 19347 */ 19348 19349 /*global self */ 19350 /*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */ 19351 19352 /*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */ 19353 19354 var saveAs = 19355 saveAs || 19356 (function(view) { 19357 'use strict'; 19358 // IE <10 is explicitly unsupported 19359 if ( 19360 typeof view === 'undefined' || 19361 (typeof navigator !== 'undefined' && 19362 /MSIE [1-9]\./.test(navigator.userAgent)) 19363 ) { 19364 return; 19365 } 19366 var doc = view.document, 19367 // only get URL when necessary in case Blob.js hasn't overridden it yet 19368 get_URL = function() { 19369 return view.URL || view.webkitURL || view; 19370 }, 19371 save_link = doc.createElementNS('http://www.w3.org/1999/xhtml', 'a'), 19372 can_use_save_link = 'download' in save_link, 19373 click = function(node) { 19374 var event = new MouseEvent('click'); 19375 node.dispatchEvent(event); 19376 }, 19377 is_safari = /constructor/i.test(view.HTMLElement) || view.safari, 19378 is_chrome_ios = /CriOS\/[\d]+/.test(navigator.userAgent), 19379 throw_outside = function(ex) { 19380 (view.setImmediate || view.setTimeout)(function() { 19381 throw ex; 19382 }, 0); 19383 }, 19384 force_saveable_type = 'application/octet-stream', 19385 // the Blob API is fundamentally broken as there is no "downloadfinished" event to subscribe to 19386 arbitrary_revoke_timeout = 1000 * 40, // in ms 19387 revoke = function(file) { 19388 var revoker = function() { 19389 if (typeof file === 'string') { 19390 // file is an object URL 19391 get_URL().revokeObjectURL(file); 19392 } else { 19393 // file is a File 19394 file.remove(); 19395 } 19396 }; 19397 setTimeout(revoker, arbitrary_revoke_timeout); 19398 }, 19399 dispatch = function(filesaver, event_types, event) { 19400 event_types = [].concat(event_types); 19401 var i = event_types.length; 19402 while (i--) { 19403 var listener = filesaver['on' + event_types[i]]; 19404 if (typeof listener === 'function') { 19405 try { 19406 listener.call(filesaver, event || filesaver); 19407 } catch (ex) { 19408 throw_outside(ex); 19409 } 19410 } 19411 } 19412 }, 19413 auto_bom = function(blob) { 19414 // prepend BOM for UTF-8 XML and text/* types (including HTML) 19415 // note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF 19416 if ( 19417 /^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test( 19418 blob.type 19419 ) 19420 ) { 19421 return new Blob([String.fromCharCode(0xfeff), blob], { 19422 type: blob.type 19423 }); 19424 } 19425 return blob; 19426 }, 19427 FileSaver = function(blob, name, no_auto_bom) { 19428 if (!no_auto_bom) { 19429 blob = auto_bom(blob); 19430 } 19431 // First try a.download, then web filesystem, then object URLs 19432 var filesaver = this, 19433 type = blob.type, 19434 force = type === force_saveable_type, 19435 object_url, 19436 dispatch_all = function() { 19437 dispatch(filesaver, 'writestart progress write writeend'.split(' ')); 19438 }, 19439 // on any filesys errors revert to saving with object URLs 19440 fs_error = function() { 19441 if ((is_chrome_ios || (force && is_safari)) && view.FileReader) { 19442 // Safari doesn't allow downloading of blob urls 19443 var reader = new FileReader(); 19444 reader.onloadend = function() { 19445 var url = is_chrome_ios 19446 ? reader.result 19447 : reader.result.replace( 19448 /^data:[^;]*;/, 19449 'data:attachment/file;' 19450 ); 19451 var popup = view.open(url, '_blank'); 19452 if (!popup) view.location.href = url; 19453 url = undefined; // release reference before dispatching 19454 filesaver.readyState = filesaver.DONE; 19455 dispatch_all(); 19456 }; 19457 reader.readAsDataURL(blob); 19458 filesaver.readyState = filesaver.INIT; 19459 return; 19460 } 19461 // don't create more object URLs than needed 19462 if (!object_url) { 19463 object_url = get_URL().createObjectURL(blob); 19464 } 19465 if (force) { 19466 view.location.href = object_url; 19467 } else { 19468 var opened = view.open(object_url, '_blank'); 19469 if (!opened) { 19470 // Apple does not allow window.open, see https://developer.apple.com/library/safari/documentation/Tools/Conceptual/SafariExtensionGuide/WorkingwithWindowsandTabs/WorkingwithWindowsandTabs.html 19471 view.location.href = object_url; 19472 } 19473 } 19474 filesaver.readyState = filesaver.DONE; 19475 dispatch_all(); 19476 revoke(object_url); 19477 }; 19478 filesaver.readyState = filesaver.INIT; 19479 19480 if (can_use_save_link) { 19481 object_url = get_URL().createObjectURL(blob); 19482 setTimeout(function() { 19483 save_link.href = object_url;
19484 save_link.download = name; 19485 click(save_link); 19486 dispatch_all(); 19487 revoke(object_url); 19488 filesaver.readyState = filesaver.DONE; 19489 }); 19490 return; 19491 } 19492 19493 fs_error(); 19494 }, 19495 FS_proto = FileSaver.prototype, 19496 saveAs = function(blob, name, no_auto_bom) { 19497 return new FileSaver(blob, name || blob.name || 'download', no_auto_bom); 19498 }; 19499 // IE 10+ (native saveAs) 19500 if (typeof navigator !== 'undefined' && navigator.msSaveOrOpenBlob) { 19501 return function(blob, name, no_auto_bom) { 19502 name = name || blob.name || 'download'; 19503 19504 if (!no_auto_bom) { 19505 blob = auto_bom(blob); 19506 } 19507 return navigator.msSaveOrOpenBlob(blob, name); 19508 }; 19509 } 19510 19511 FS_proto.abort = function() {}; 19512 FS_proto.readyState = FS_proto.INIT = 0; 19513 FS_proto.WRITING = 1; 19514 FS_proto.DONE = 2; 19515 19516 FS_proto.error = FS_proto.onwritestart = FS_proto.onprogress = FS_proto.onwrite = FS_proto.onabort = FS_proto.onerror = FS_proto.onwriteend = null; 19517 19518 return saveAs; 19519 })( 19520 (typeof self !== 'undefined' && self) || 19521 (typeof window !== 'undefined' && window) || 19522 this.content 19523 ); 19524 // `self` is undefined in Firefox for Android content script context 19525 // while `this` is nsIContentFrameMessageManager 19526 // with an attribute `content` that corresponds to the window 19527 19528 if (typeof module !== 'undefined' && module.exports) { 19529 module.exports.saveAs = saveAs; 19530 } else if ( 19531 typeof define !== 'undefined' && 19532 define !== null && 19533 define.amd !== null 19534 ) { 19535 define('FileSaver.js', function() { 19536 return saveAs; 19537 }); 19538 } 19539 }, 19540 {} 19541 ], 19542 27: [ 19543 function(_dereq_, module, exports) { 19544 'use strict'; 19545 19546 function _interopDefault(ex) { 19547 return ex && typeof ex === 'object' && 'default' in ex ? ex['default'] : ex; 19548 } 19549 19550 var _classCallCheck = _interopDefault( 19551 _dereq_('@babel/runtime/helpers/classCallCheck') 19552 ); 19553 var _createClass = _interopDefault(_dereq_('@babel/runtime/helpers/createClass')); 19554 19555 var arr = []; 19556 var each = arr.forEach; 19557 var slice = arr.slice; 19558 function defaults(obj) { 19559 each.call(slice.call(arguments, 1), function(source) { 19560 if (source) { 19561 for (var prop in source) { 19562 if (obj[prop] === undefined) obj[prop] = source[prop]; 19563 } 19564 } 19565 }); 19566 return obj; 19567 } 19568 19569 var cookie = { 19570 create: function create(name, value, minutes, domain) { 19571 var expires; 19572 19573 if (minutes) { 19574 var date = new Date(); 19575 date.setTime(date.getTime() + minutes * 60 * 1000); 19576 expires = '; expires=' + date.toGMTString(); 19577 } else expires = ''; 19578 19579 domain = domain ? 'domain=' + domain + ';' : ''; 19580 document.cookie = name + '=' + value + expires + ';' + domain + 'path=/'; 19581 }, 19582 read: function read(name) { 19583 var nameEQ = name + '='; 19584 var ca = document.cookie.split(';'); 19585 19586 for (var i = 0; i < ca.length; i++) { 19587 var c = ca[i]; 19588 19589 while (c.charAt(0) === ' ') { 19590 c = c.substring(1, c.length); 19591 } 19592 19593 if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length, c.length); 19594 } 19595 19596 return null; 19597 }, 19598 remove: function remove(name) { 19599 this.create(name, '', -1); 19600 } 19601 }; 19602 var cookie$1 = { 19603 name: 'cookie', 19604 lookup: function lookup(options) { 19605 var found; 19606 19607 if (options.lookupCookie && typeof document !== 'undefined') { 19608 var c = cookie.read(options.lookupCookie); 19609 if (c) found = c; 19610 } 19611 19612 return found; 19613 }, 19614 cacheUserLanguage: function cacheUserLanguage(lng, options) { 19615 if (options.lookupCookie && typeof document !== 'undefined') { 19616 cookie.create( 19617 options.lookupCookie, 19618 lng, 19619 options.cookieMinutes, 19620 options.cookieDomain 19621 ); 19622 } 19623 } 19624 }; 19625 19626 var querystring = { 19627 name: 'querystring', 19628 lookup: function lookup(options) { 19629 var found; 19630 19631 if (typeof window !== 'undefined') { 19632 var query = window.location.search.substring(1); 19633 var params = query.split('&'); 19634 19635 for (var i = 0; i < params.length; i++) { 19636 var pos = params[i].indexOf('='); 19637 19638 if (pos > 0) { 19639 var key = params[i].substring(0, pos); 19640 19641 if (key === options.lookupQuerystring) { 19642 found = params[i].substring(pos + 1); 19643 } 19644 } 19645 } 19646 } 19647 19648 return found; 19649 } 19650 }; 19651 19652 var hasLocalStorageSupport; 19653 19654 try { 19655 hasLocalStorageSupport = window !== 'undefined' && window.localStorage !== null; 19656 var testKey = 'i18next.translate.boo'; 19657 window.localStorage.setItem(testKey, 'foo'); 19658 window.localStorage.removeItem(testKey); 19659 } catch (e) { 19660 hasLocalStorageSupport = false;
vendor: 6,234 bytes, lines 19661-19841
19661 } 19662 19663 var localStorage = { 19664 name: 'localStorage', 19665 lookup: function lookup(options) { 19666 var found; 19667 19668 if (options.lookupLocalStorage && hasLocalStorageSupport) { 19669 var lng = window.localStorage.getItem(options.lookupLocalStorage); 19670 if (lng) found = lng; 19671 } 19672 19673 return found; 19674 }, 19675 cacheUserLanguage: function cacheUserLanguage(lng, options) { 19676 if (options.lookupLocalStorage && hasLocalStorageSupport) { 19677 window.localStorage.setItem(options.lookupLocalStorage, lng); 19678 } 19679 } 19680 }; 19681 19682 var navigator$1 = { 19683 name: 'navigator', 19684 lookup: function lookup(options) { 19685 var found = []; 19686 19687 if (typeof navigator !== 'undefined') { 19688 if (navigator.languages) { 19689 // chrome only; not an array, so can't use .push.apply instead of iterating 19690 for (var i = 0; i < navigator.languages.length; i++) { 19691 found.push(navigator.languages[i]); 19692 } 19693 } 19694 19695 if (navigator.userLanguage) { 19696 found.push(navigator.userLanguage); 19697 } 19698 19699 if (navigator.language) { 19700 found.push(navigator.language); 19701 } 19702 } 19703 19704 return found.length > 0 ? found : undefined; 19705 } 19706 }; 19707 19708 var htmlTag = { 19709 name: 'htmlTag', 19710 lookup: function lookup(options) { 19711 var found; 19712 var htmlTag = 19713 options.htmlTag || 19714 (typeof document !== 'undefined' ? document.documentElement : null); 19715 19716 if (htmlTag && typeof htmlTag.getAttribute === 'function') { 19717 found = htmlTag.getAttribute('lang'); 19718 } 19719 19720 return found; 19721 } 19722 }; 19723 19724 var path = { 19725 name: 'path', 19726 lookup: function lookup(options) { 19727 var found; 19728 19729 if (typeof window !== 'undefined') { 19730 var language = window.location.pathname.match(/\/([a-zA-Z-]*)/g); 19731 19732 if (language instanceof Array) { 19733 if (typeof options.lookupFromPathIndex === 'number') { 19734 if (typeof language[options.lookupFromPathIndex] !== 'string') { 19735 return undefined; 19736 } 19737 19738 found = language[options.lookupFromPathIndex].replace('/', ''); 19739 } else { 19740 found = language[0].replace('/', ''); 19741 } 19742 } 19743 } 19744 19745 return found; 19746 } 19747 }; 19748 19749 var subdomain = { 19750 name: 'subdomain', 19751 lookup: function lookup(options) { 19752 var found; 19753 19754 if (typeof window !== 'undefined') { 19755 var language = window.location.href.match( 19756 /(?:http[s]*\:\/\/)*(.*?)\.(?=[^\/]*\..{2,5})/gi 19757 ); 19758 19759 if (language instanceof Array) { 19760 if (typeof options.lookupFromSubdomainIndex === 'number') { 19761 found = language[options.lookupFromSubdomainIndex] 19762 .replace('http://', '') 19763 .replace('https://', '') 19764 .replace('.', ''); 19765 } else { 19766 found = language[0] 19767 .replace('http://', '') 19768 .replace('https://', '') 19769 .replace('.', ''); 19770 } 19771 } 19772 } 19773 19774 return found; 19775 } 19776 }; 19777 19778 function getDefaults() { 19779 return { 19780 order: ['querystring', 'cookie', 'localStorage', 'navigator', 'htmlTag'], 19781 lookupQuerystring: 'lng', 19782 lookupCookie: 'i18next', 19783 lookupLocalStorage: 'i18nextLng', 19784 // cache user language 19785 caches: ['localStorage'], 19786 excludeCacheFor: ['cimode'], 19787 //cookieMinutes: 10, 19788 //cookieDomain: 'myDomain' 19789 checkWhitelist: true 19790 }; 19791 } 19792 19793 var Browser = 19794 /*#__PURE__*/ 19795 (function() { 19796 function Browser(services) { 19797 var options = 19798 arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; 19799 19800 _classCallCheck(this, Browser); 19801 19802 this.type = 'languageDetector'; 19803 this.detectors = {}; 19804 this.init(services, options); 19805 } 19806 19807 _createClass(Browser, [ 19808 { 19809 key: 'init', 19810 value: function init(services) { 19811 var options = 19812 arguments.length > 1 && arguments[1] !== undefined 19813 ? arguments[1] 19814 : {}; 19815 var i18nOptions = 19816 arguments.length > 2 && arguments[2] !== undefined 19817 ? arguments[2] 19818 : {}; 19819 this.services = services; 19820 this.options = defaults(options, this.options || {}, getDefaults()); // backwards compatibility 19821 19822 if (this.options.lookupFromUrlIndex) 19823 this.options.lookupFromPathIndex = this.options.lookupFromUrlIndex; 19824 this.i18nOptions = i18nOptions; 19825 this.addDetector(cookie$1); 19826 this.addDetector(querystring); 19827 this.addDetector(localStorage); 19828 this.addDetector(navigator$1); 19829 this.addDetector(htmlTag); 19830 this.addDetector(path); 19831 this.addDetector(subdomain); 19832 } 19833 }, 19834 { 19835 key: 'addDetector', 19836 value: function addDetector(detector) { 19837 this.detectors[detector.name] = detector; 19838 } 19839 }, 19840 { 19841 key: 'detect',
19842 value: function detect(detectionOrder) { 19843 var _this = this; 19844 19845 if (!detectionOrder) detectionOrder = this.options.order; 19846 var detected = []; 19847 detectionOrder.forEach(function(detectorName) { 19848 if (_this.detectors[detectorName]) { 19849 var lookup = _this.detectors[detectorName].lookup(_this.options); 19850 19851 if (lookup && typeof lookup === 'string') lookup = [lookup]; 19852 if (lookup) detected = detected.concat(lookup); 19853 } 19854 }); 19855 var found; 19856 detected.forEach(function(lng) { 19857 if (found) return; 19858 19859 var cleanedLng = _this.services.languageUtils.formatLanguageCode(lng); 19860 19861 if ( 19862 !_this.options.checkWhitelist || 19863 _this.services.languageUtils.isWhitelisted(cleanedLng) 19864 ) 19865 found = cleanedLng; 19866 }); 19867 19868 if (!found) { 19869 var fallbacks = this.i18nOptions.fallbackLng; 19870 if (typeof fallbacks === 'string') fallbacks = [fallbacks]; 19871 if (!fallbacks) fallbacks = []; 19872 19873 if (Object.prototype.toString.apply(fallbacks) === '[object Array]') { 19874 found = fallbacks[0]; 19875 } else { 19876 found = 19877 fallbacks[0] || (fallbacks['default'] && fallbacks['default'][0]); 19878 } 19879 } 19880 19881 return found; 19882 } 19883 }, 19884 { 19885 key: 'cacheUserLanguage', 19886 value: function cacheUserLanguage(lng, caches) { 19887 var _this2 = this; 19888 19889 if (!caches) caches = this.options.caches; 19890 if (!caches) return; 19891 if ( 19892 this.options.excludeCacheFor && 19893 this.options.excludeCacheFor.indexOf(lng) > -1 19894 ) 19895 return; 19896 caches.forEach(function(cacheName) { 19897 if (_this2.detectors[cacheName]) 19898 _this2.detectors[cacheName].cacheUserLanguage(lng, _this2.options); 19899 }); 19900 } 19901 } 19902 ]); 19903 19904 return Browser; 19905 })(); 19906 19907 Browser.type = 'languageDetector'; 19908 19909 module.exports = Browser; 19910 }, 19911 { 19912 '@babel/runtime/helpers/classCallCheck': 28, 19913 '@babel/runtime/helpers/createClass': 29 19914 } 19915 ], 19916 28: [ 19917 function(_dereq_, module, exports) { 19918 arguments[4][5][0].apply(exports, arguments); 19919 }, 19920 { dup: 5 } 19921 ], 19922 29: [ 19923 function(_dereq_, module, exports) { 19924 arguments[4][6][0].apply(exports, arguments); 19925 }, 19926 { dup: 6 } 19927 ], 19928 30: [ 19929 function(_dereq_, module, exports) { 19930 'use strict'; 19931 19932 function _interopDefault(ex) { 19933 return ex && typeof ex === 'object' && 'default' in ex ? ex['default'] : ex; 19934 } 19935 19936 var _typeof = _interopDefault(_dereq_('@babel/runtime/helpers/typeof')); 19937 var _objectSpread = _interopDefault( 19938 _dereq_('@babel/runtime/helpers/objectSpread') 19939 ); 19940 var _classCallCheck = _interopDefault( 19941 _dereq_('@babel/runtime/helpers/classCallCheck') 19942 ); 19943 var _createClass = _interopDefault(_dereq_('@babel/runtime/helpers/createClass')); 19944 var _possibleConstructorReturn = _interopDefault( 19945 _dereq_('@babel/runtime/helpers/possibleConstructorReturn') 19946 ); 19947 var _getPrototypeOf = _interopDefault( 19948 _dereq_('@babel/runtime/helpers/getPrototypeOf') 19949 ); 19950 var _assertThisInitialized = _interopDefault( 19951 _dereq_('@babel/runtime/helpers/assertThisInitialized') 19952 ); 19953 var _inherits = _interopDefault(_dereq_('@babel/runtime/helpers/inherits')); 19954 var _toConsumableArray = _interopDefault( 19955 _dereq_('@babel/runtime/helpers/toConsumableArray') 19956 ); 19957 var _slicedToArray = _interopDefault( 19958 _dereq_('@babel/runtime/helpers/slicedToArray') 19959 ); 19960 19961 var consoleLogger = { 19962 type: 'logger', 19963 log: function log(args) { 19964 this.output('log', args); 19965 }, 19966 warn: function warn(args) { 19967 this.output('warn', args); 19968 }, 19969 error: function error(args) { 19970 this.output('error', args); 19971 }, 19972 output: function output(type, args) { 19973 var _console; 19974 19975 /* eslint no-console: 0 */ 19976 if (console && console[type]) 19977 (_console = console)[type].apply(_console, _toConsumableArray(args)); 19978 } 19979 }; 19980 19981 var Logger = 19982 /*#__PURE__*/ 19983 (function() { 19984 function Logger(concreteLogger) { 19985 var options = 19986 arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; 19987 19988 _classCallCheck(this, Logger); 19989 19990 this.init(concreteLogger, options); 19991 } 19992 19993 _createClass(Logger, [ 19994 { 19995 key: 'init', 19996 value: function init(concreteLogger) { 19997 var options = 19998 arguments.length > 1 && arguments[1] !== undefined 19999 ? arguments[1] 20000 : {}; 20001 this.prefix = options.prefix || 'i18next:'; 20002 this.logger = concreteLogger || consoleLogger; 20003 this.options = options; 20004 this.debug = options.debug; 20005 } 20006 }, 20007 { 20008 key: 'setDebug', 20009 value: function setDebug(bool) { 20010 this.debug = bool; 20011 } 20012 }, 20013 { 20014 key: 'log', 20015 value: function log() { 20016 for ( 20017 var _len = arguments.length, args = new Array(_len), _key = 0; 20018 _key < _len; 20019 _key++ 20020 ) { 20021 args[_key] = arguments[_key]; 20022 } 20023 20024 return this.forward(args, 'log', '', true); 20025 } 20026 }, 20027 { 20028 key: 'warn', 20029 value: function warn() { 20030 for ( 20031 var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; 20032 _key2 < _len2; 20033 _key2++ 20034 ) { 20035 args[_key2] = arguments[_key2]; 20036 } 20037 20038 return this.forward(args, 'warn', '', true); 20039 } 20040 }, 20041 { 20042 key: 'error', 20043 value: function error() { 20044 for ( 20045 var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; 20046 _key3 < _len3; 20047 _key3++ 20048 ) { 20049 args[_key3] = arguments[_key3]; 20050 } 20051 20052 return this.forward(args, 'error', ''); 20053 } 20054 }, 20055 { 20056 key: 'deprecate', 20057 value: function deprecate() { 20058 for ( 20059 var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; 20060 _key4 < _len4; 20061 _key4++ 20062 ) {
vendor: 6,649 bytes, lines 20063-20261
20063 args[_key4] = arguments[_key4]; 20064 } 20065 20066 return this.forward(args, 'warn', 'WARNING DEPRECATED: ', true); 20067 } 20068 }, 20069 { 20070 key: 'forward', 20071 value: function forward(args, lvl, prefix, debugOnly) { 20072 if (debugOnly && !this.debug) return null; 20073 if (typeof args[0] === 'string') 20074 args[0] = '' 20075 .concat(prefix) 20076 .concat(this.prefix, ' ') 20077 .concat(args[0]); 20078 return this.logger[lvl](args); 20079 } 20080 }, 20081 { 20082 key: 'create', 20083 value: function create(moduleName) { 20084 return new Logger( 20085 this.logger, 20086 _objectSpread( 20087 {}, 20088 { 20089 prefix: ''.concat(this.prefix, ':').concat(moduleName, ':') 20090 }, 20091 this.options 20092 ) 20093 ); 20094 } 20095 } 20096 ]); 20097 20098 return Logger; 20099 })(); 20100 20101 var baseLogger = new Logger(); 20102 20103 var EventEmitter = 20104 /*#__PURE__*/ 20105 (function() { 20106 function EventEmitter() { 20107 _classCallCheck(this, EventEmitter); 20108 20109 this.observers = {}; 20110 } 20111 20112 _createClass(EventEmitter, [ 20113 { 20114 key: 'on', 20115 value: function on(events, listener) { 20116 var _this = this; 20117 20118 events.split(' ').forEach(function(event) { 20119 _this.observers[event] = _this.observers[event] || []; 20120 20121 _this.observers[event].push(listener); 20122 }); 20123 return this; 20124 } 20125 }, 20126 { 20127 key: 'off', 20128 value: function off(event, listener) { 20129 if (!this.observers[event]) return; 20130 20131 if (!listener) { 20132 delete this.observers[event]; 20133 return; 20134 } 20135 20136 this.observers[event] = this.observers[event].filter(function(l) { 20137 return l !== listener; 20138 }); 20139 } 20140 }, 20141 { 20142 key: 'emit', 20143 value: function emit(event) { 20144 for ( 20145 var _len = arguments.length, 20146 args = new Array(_len > 1 ? _len - 1 : 0), 20147 _key = 1; 20148 _key < _len; 20149 _key++ 20150 ) { 20151 args[_key - 1] = arguments[_key]; 20152 } 20153 20154 if (this.observers[event]) { 20155 var cloned = [].concat(this.observers[event]); 20156 cloned.forEach(function(observer) { 20157 observer.apply(void 0, args); 20158 }); 20159 } 20160 20161 if (this.observers['*']) { 20162 var _cloned = [].concat(this.observers['*']); 20163 20164 _cloned.forEach(function(observer) { 20165 observer.apply(observer, [event].concat(args)); 20166 }); 20167 } 20168 } 20169 } 20170 ]); 20171 20172 return EventEmitter; 20173 })(); 20174 20175 // http://lea.verou.me/2016/12/resolve-promises-externally-with-this-one-weird-trick/ 20176 function defer() { 20177 var res; 20178 var rej; 20179 var promise = new Promise(function(resolve, reject) { 20180 res = resolve; 20181 rej = reject; 20182 }); 20183 promise.resolve = res; 20184 promise.reject = rej; 20185 return promise; 20186 } 20187 function makeString(object) { 20188 if (object == null) return ''; 20189 /* eslint prefer-template: 0 */ 20190 20191 return '' + object; 20192 } 20193 function copy(a, s, t) { 20194 a.forEach(function(m) { 20195 if (s[m]) t[m] = s[m]; 20196 }); 20197 } 20198 20199 function getLastOfPath(object, path, Empty) { 20200 function cleanKey(key) { 20201 return key && key.indexOf('###') > -1 ? key.replace(/###/g, '.') : key; 20202 } 20203 20204 function canNotTraverseDeeper() { 20205 return !object || typeof object === 'string'; 20206 } 20207 20208 var stack = typeof path !== 'string' ? [].concat(path) : path.split('.'); 20209 20210 while (stack.length > 1) { 20211 if (canNotTraverseDeeper()) return {}; 20212 var key = cleanKey(stack.shift()); 20213 if (!object[key] && Empty) object[key] = new Empty(); 20214 object = object[key]; 20215 } 20216 20217 if (canNotTraverseDeeper()) return {}; 20218 return { 20219 obj: object, 20220 k: cleanKey(stack.shift()) 20221 }; 20222 } 20223 20224 function setPath(object, path, newValue) { 20225 var _getLastOfPath = getLastOfPath(object, path, Object), 20226 obj = _getLastOfPath.obj, 20227 k = _getLastOfPath.k; 20228 20229 obj[k] = newValue; 20230 } 20231 function pushPath(object, path, newValue, concat) { 20232 var _getLastOfPath2 = getLastOfPath(object, path, Object), 20233 obj = _getLastOfPath2.obj, 20234 k = _getLastOfPath2.k; 20235 20236 obj[k] = obj[k] || []; 20237 if (concat) obj[k] = obj[k].concat(newValue); 20238 if (!concat) obj[k].push(newValue); 20239 } 20240 function getPath(object, path) { 20241 var _getLastOfPath3 = getLastOfPath(object, path), 20242 obj = _getLastOfPath3.obj, 20243 k = _getLastOfPath3.k; 20244 20245 if (!obj) return undefined; 20246 return obj[k]; 20247 } 20248 function getPathWithDefaults(data, defaultData, key) { 20249 var value = getPath(data, key); 20250 20251 if (value !== undefined) { 20252 return value; 20253 } // Fallback to default values 20254 20255 return getPath(defaultData, key); 20256 } 20257 function deepExtend(target, source, overwrite) { 20258 /* eslint no-restricted-syntax: 0 */ 20259 for (var prop in source) { 20260 if (prop in target) { 20261 // If we reached a leaf string in target or source then replace with source or skip depen
20261ding on the 'overwrite' switch 20262 if ( 20263 typeof target[prop] === 'string' || 20264 target[prop] instanceof String || 20265 typeof source[prop] === 'string' || 20266 source[prop] instanceof String 20267 ) { 20268 if (overwrite) target[prop] = source[prop]; 20269 } else { 20270 deepExtend(target[prop], source[prop], overwrite); 20271 } 20272 } else { 20273 target[prop] = source[prop]; 20274 } 20275 } 20276 20277 return target; 20278 } 20279 function regexEscape(str) { 20280 /* eslint no-useless-escape: 0 */ 20281 return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&'); 20282 } 20283 /* eslint-disable */ 20284 20285 var _entityMap = { 20286 '&': '&', 20287 '<': '<', 20288 '>': '>', 20289 '"': '"', 20290 "'": ''', 20291 '/': '/' 20292 }; 20293 /* eslint-enable */ 20294 20295 function escape(data) { 20296 if (typeof data === 'string') { 20297 return data.replace(/[&<>"'\/]/g, function(s) { 20298 return _entityMap[s]; 20299 }); 20300 } 20301 20302 return data; 20303 } 20304 20305 var ResourceStore = 20306 /*#__PURE__*/ 20307 (function(_EventEmitter) { 20308 _inherits(ResourceStore, _EventEmitter); 20309 20310 function ResourceStore(data) { 20311 var _this; 20312 20313 var options = 20314 arguments.length > 1 && arguments[1] !== undefined 20315 ? arguments[1] 20316 : { 20317 ns: ['translation'], 20318 defaultNS: 'translation' 20319 }; 20320 20321 _classCallCheck(this, ResourceStore); 20322 20323 _this = _possibleConstructorReturn( 20324 this, 20325 _getPrototypeOf(ResourceStore).call(this) 20326 ); 20327 EventEmitter.call(_assertThisInitialized(_this)); // <=IE10 fix (unable to call parent constructor) 20328 20329 _this.data = data || {}; 20330 _this.options = options; 20331 20332 if (_this.options.keySeparator === undefined) { 20333 _this.options.keySeparator = '.'; 20334 } 20335 20336 return _this; 20337 } 20338 20339 _createClass(ResourceStore, [ 20340 { 20341 key: 'addNamespaces', 20342 value: function addNamespaces(ns) { 20343 if (this.options.ns.indexOf(ns) < 0) { 20344 this.options.ns.push(ns); 20345 } 20346 } 20347 }, 20348 { 20349 key: 'removeNamespaces', 20350 value: function removeNamespaces(ns) { 20351 var index = this.options.ns.indexOf(ns); 20352 20353 if (index > -1) { 20354 this.options.ns.splice(index, 1); 20355 } 20356 } 20357 }, 20358 { 20359 key: 'getResource', 20360 value: function getResource(lng, ns, key) { 20361 var options = 20362 arguments.length > 3 && arguments[3] !== undefined 20363 ? arguments[3] 20364 : {}; 20365 var keySeparator = 20366 options.keySeparator !== undefined 20367 ? options.keySeparator 20368 : this.options.keySeparator; 20369 var path = [lng, ns]; 20370 if (key && typeof key !== 'string') path = path.concat(key); 20371 if (key && typeof key === 'string') 20372 path = path.concat(keySeparator ? key.split(keySeparator) : key); 20373 20374 if (lng.indexOf('.') > -1) { 20375 path = lng.split('.'); 20376 } 20377 20378 return getPath(this.data, path); 20379 } 20380 }, 20381 { 20382 key: 'addResource', 20383 value: function addResource(lng, ns, key, value) { 20384 var options = 20385 arguments.length > 4 && arguments[4] !== undefined 20386 ? arguments[4] 20387 : { 20388 silent: false 20389 }; 20390 var keySeparator = this.options.keySeparator; 20391 if (keySeparator === undefined) keySeparator = '.'; 20392 var path = [lng, ns]; 20393 if (key) 20394 path = path.concat(keySeparator ? key.split(keySeparator) : key); 20395 20396 if (lng.indexOf('.') > -1) { 20397 path = lng.split('.'); 20398 value = ns; 20399 ns = path[1]; 20400 } 20401 20402 this.addNamespaces(ns); 20403 setPath(this.data, path, value);
vendor: 4,105 bytes, lines 20404-20513
20404 if (!options.silent) this.emit('added', lng, ns, key, value); 20405 } 20406 }, 20407 { 20408 key: 'addResources', 20409 value: function addResources(lng, ns, resources) { 20410 var options = 20411 arguments.length > 3 && arguments[3] !== undefined 20412 ? arguments[3] 20413 : { 20414 silent: false 20415 }; 20416 20417 /* eslint no-restricted-syntax: 0 */ 20418 for (var m in resources) { 20419 if ( 20420 typeof resources[m] === 'string' || 20421 Object.prototype.toString.apply(resources[m]) === '[object Array]' 20422 ) 20423 this.addResource(lng, ns, m, resources[m], { 20424 silent: true 20425 }); 20426 } 20427 20428 if (!options.silent) this.emit('added', lng, ns, resources); 20429 } 20430 }, 20431 { 20432 key: 'addResourceBundle', 20433 value: function addResourceBundle(lng, ns, resources, deep, overwrite) { 20434 var options = 20435 arguments.length > 5 && arguments[5] !== undefined 20436 ? arguments[5] 20437 : { 20438 silent: false 20439 }; 20440 var path = [lng, ns]; 20441 20442 if (lng.indexOf('.') > -1) { 20443 path = lng.split('.'); 20444 deep = resources; 20445 resources = ns; 20446 ns = path[1]; 20447 } 20448 20449 this.addNamespaces(ns); 20450 var pack = getPath(this.data, path) || {}; 20451 20452 if (deep) { 20453 deepExtend(pack, resources, overwrite); 20454 } else { 20455 pack = _objectSpread({}, pack, resources); 20456 } 20457 20458 setPath(this.data, path, pack); 20459 if (!options.silent) this.emit('added', lng, ns, resources); 20460 } 20461 }, 20462 { 20463 key: 'removeResourceBundle', 20464 value: function removeResourceBundle(lng, ns) { 20465 if (this.hasResourceBundle(lng, ns)) { 20466 delete this.data[lng][ns]; 20467 } 20468 20469 this.removeNamespaces(ns); 20470 this.emit('removed', lng, ns); 20471 } 20472 }, 20473 { 20474 key: 'hasResourceBundle', 20475 value: function hasResourceBundle(lng, ns) { 20476 return this.getResource(lng, ns) !== undefined; 20477 } 20478 }, 20479 { 20480 key: 'getResourceBundle', 20481 value: function getResourceBundle(lng, ns) { 20482 if (!ns) ns = this.options.defaultNS; // COMPATIBILITY: remove extend in v2.1.0 20483 20484 if (this.options.compatibilityAPI === 'v1') 20485 return _objectSpread({}, {}, this.getResource(lng, ns)); 20486 return this.getResource(lng, ns); 20487 } 20488 }, 20489 { 20490 key: 'getDataByLanguage', 20491 value: function getDataByLanguage(lng) { 20492 return this.data[lng]; 20493 } 20494 }, 20495 { 20496 key: 'toJSON', 20497 value: function toJSON() { 20498 return this.data; 20499 } 20500 } 20501 ]); 20502 20503 return ResourceStore; 20504 })(EventEmitter); 20505 20506 var postProcessor = { 20507 processors: {}, 20508 addPostProcessor: function addPostProcessor(module) { 20509 this.processors[module.name] = module; 20510 }, 20511 handle: function handle(processors, value, key, options, translator) { 20512 var _this = this; 20513
20514 processors.forEach(function(processor) { 20515 if (_this.processors[processor]) 20516 value = _this.processors[processor].process( 20517 value, 20518 key, 20519 options, 20520 translator 20521 ); 20522 }); 20523 return value; 20524 } 20525 }; 20526 20527 var checkedLoadedFor = {}; 20528 20529 var Translator = 20530 /*#__PURE__*/ 20531 (function(_EventEmitter) { 20532 _inherits(Translator, _EventEmitter); 20533 20534 function Translator(services) { 20535 var _this; 20536 20537 var options = 20538 arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; 20539 20540 _classCallCheck(this, Translator); 20541 20542 _this = _possibleConstructorReturn( 20543 this, 20544 _getPrototypeOf(Translator).call(this) 20545 ); 20546 EventEmitter.call(_assertThisInitialized(_this)); // <=IE10 fix (unable to call parent constructor) 20547 20548 copy( 20549 [ 20550 'resourceStore', 20551 'languageUtils', 20552 'pluralResolver', 20553 'interpolator', 20554 'backendConnector', 20555 'i18nFormat', 20556 'utils' 20557 ], 20558 services, 20559 _assertThisInitialized(_this) 20560 ); 20561 _this.options = options; 20562 20563 if (_this.options.keySeparator === undefined) { 20564 _this.options.keySeparator = '.'; 20565 } 20566 20567 _this.logger = baseLogger.create('translator'); 20568 return _this; 20569 } 20570 20571 _createClass(Translator, [ 20572 { 20573 key: 'changeLanguage', 20574 value: function changeLanguage(lng) { 20575 if (lng) this.language = lng; 20576 } 20577 }, 20578 { 20579 key: 'exists', 20580 value: function exists(key) { 20581 var options = 20582 arguments.length > 1 && arguments[1] !== undefined 20583 ? arguments[1] 20584 : { 20585 interpolation: {} 20586 }; 20587 var resolved = this.resolve(key, options); 20588 return resolved && resolved.res !== undefined; 20589 } 20590 }, 20591 { 20592 key: 'extractFromKey', 20593 value: function extractFromKey(key, options) { 20594 var nsSeparator = options.nsSeparator || this.options.nsSeparator; 20595 if (nsSeparator === undefined) nsSeparator = ':'; 20596 var keySeparator = 20597 options.keySeparator !== undefined 20598 ? options.keySeparator 20599 : this.options.keySeparator; 20600 var namespaces = options.ns || this.options.defaultNS; 20601 20602 if (nsSeparator && key.indexOf(nsSeparator) > -1) { 20603 var parts = key.split(nsSeparator); 20604 if ( 20605 nsSeparator !== keySeparator || 20606 (nsSeparator === keySeparator && 20607 this.options.ns.indexOf(parts[0]) > -1) 20608 ) 20609 namespaces = parts.shift(); 20610 key = parts.join(keySeparator); 20611 } 20612 20613 if (typeof namespaces === 'string') namespaces = [namespaces]; 20614 return { 20615 key: key, 20616 namespaces: namespaces 20617 }; 20618 } 20619 }, 20620 { 20621 key: 'translate', 20622 value: function translate(keys, options) { 20623 var _this2 = this; 20624 20625 if ( 20626 _typeof(options) !== 'object' && 20627 this.options.overloadTranslationOptionHandler 20628 ) { 20629 /* eslint prefer-rest-params: 0 */ 20630 options = this.options.overloadTranslationOptionHandler(arguments); 20631 } 20632 20633 if (!options) options = {}; // non valid keys handling 20634 20635 if ( 20636 keys === undefined || 20637 keys === null 20638 /* || keys === ''*/ 20639 ) 20640 return ''; 20641 if (!Array.isArray(keys)) keys = [String(keys)]; // separators 20642 20643 var keySeparator = 20644 options.keySeparator !== undefined 20645 ? options.keySeparator 20646 : this.options.keySeparator; // get namespace(s) 20647 20648 var _this$extractFromKey = this.extractFromKey( 20649 keys[keys.length - 1], 20650 options 20651 ), 20652 key = _this$extractFromKey.key, 20653 namespaces = _this$extractFromKey.namespaces; 20654 20655 var namespace = namespaces[namespaces.length - 1]; // return key on CIMode 20656 20657 var lng = options.lng || this.language; 20658 var appendNamespaceToCIMode = 20659 options.appendNamespaceToCIMode || 20660 this.options.appendNamespaceToCIMode; 20661 20662 if (lng && lng.toLowerCase() === 'cimode') { 20663 if (appendNamespaceToCIMode) { 20664 var nsSeparator = options.nsSeparator || this.options.nsSeparator; 20665 return namespace + nsSeparator + key; 20666 } 20667 20668 return key; 20669 } // resolve from store 20670 20671 var resolved = this.resolve(keys, options); 20672 var res = resolved && resolved.res; 20673 var resUsedKey = (resolved && resolved.usedKey) || key; 20674 var resExactUsedKey = (resolved && resolved.exactUsedKey) || key; 20675 var resType = Object.prototype.toString.apply(res); 20676 var noObject = [ 20677 '[object Number]', 20678 '[object Function]', 20679 '[object RegExp]' 20680 ]; 20681 var joinArrays = 20682 options.joinArrays !== undefined 20683 ? options.joinArrays 20684 : this.options.joinArrays; // object 20685 20686 var handleAsObjectInI18nFormat = 20687 !this.i18nFormat || this.i18nFormat.handleAsObject; 20688 var handleAsObject = 20689 typeof res !== 'string' && 20690 typeof res !== 'boolean' && 20691 typeof res !== 'number'; 20692 20693 if ( 20694 handleAsObjectInI18nFormat && 20695 res && 20696 handleAsObject && 20697 noObject.indexOf(resType) < 0 && 20698 !(typeof joinArrays === 'string' && resType === '[object Array]') 20699 ) { 20700 if (!options.returnObjects && !this.options.returnObjects) { 20701 this.logger.warn( 20702 'accessing an object - but returnObjects options is not enabled!' 20703 ); 20704 return this.options.returnedObjectHandler 20705 ? this.options.returnedObjectHandler(resUsedKey, res, options) 20706 : "key '" 20707 .concat(key, ' (') 20708 .concat( 20709 this.language, 20710 ")' returned an object instead of string." 20711 ); 20712 } // if we got a separator we loop over children - else we just return object as is 20713 // as having it set to false means no hierarchy so no lookup for nested values 20714 20715 if (keySeparator) { 20716 var resTypeIsArray = resType === '[object Array]'; 20717 var copy$$1 = resTypeIsArray ? [] : {}; // apply child translation on a copy 20718 20719 /* eslint no-restricted-syntax: 0 */ 20720 20721 var newKeyToUse = resTypeIsArray ? resExactUsedKey : resUsedKey; 20722 20723 for (var m in res) { 20724 if (Object.prototype.hasOwnProperty.call(res, m)) { 20725 var deepKey = '' 20726 .concat(newKeyToUse) 20727 .concat(keySeparator) 20728 .concat(m); 20729 copy$$1[m] = this.translate( 20730 deepKey, 20731 _objectSpread({}, options, {
20732 joinArrays: false, 20733 ns: namespaces 20734 }) 20735 ); 20736 if (copy$$1[m] === deepKey) copy$$1[m] = res[m]; // if nothing found use orginal value as fallback 20737 } 20738 } 20739 20740 res = copy$$1; 20741 } 20742 } else if ( 20743 handleAsObjectInI18nFormat && 20744 typeof joinArrays === 'string' && 20745 resType === '[object Array]' 20746 ) { 20747 // array special treatment 20748 res = res.join(joinArrays); 20749 if (res) res = this.extendTranslation(res, keys, options); 20750 } else { 20751 // string, empty or null 20752 var usedDefault = false; 20753 var usedKey = false; // fallback value 20754 20755 if (!this.isValidLookup(res) && options.defaultValue !== undefined) { 20756 usedDefault = true; 20757 20758 if (options.count !== undefined) { 20759 var suffix = this.pluralResolver.getSuffix(lng, options.count); 20760 res = options['defaultValue'.concat(suffix)]; 20761 } 20762 20763 if (!res) res = options.defaultValue; 20764 } 20765 20766 if (!this.isValidLookup(res)) { 20767 usedKey = true; 20768 res = key; 20769 } // save missing 20770 20771 var updateMissing = 20772 options.defaultValue && 20773 options.defaultValue !== res && 20774 this.options.updateMissing; 20775 20776 if (usedKey || usedDefault || updateMissing) { 20777 this.logger.log( 20778 updateMissing ? 'updateKey' : 'missingKey', 20779 lng, 20780 namespace, 20781 key, 20782 updateMissing ? options.defaultValue : res 20783 ); 20784 var lngs = []; 20785 var fallbackLngs = this.languageUtils.getFallbackCodes( 20786 this.options.fallbackLng, 20787 options.lng || this.language 20788 ); 20789 20790 if ( 20791 this.options.saveMissingTo === 'fallback' && 20792 fallbackLngs && 20793 fallbackLngs[0] 20794 ) { 20795 for (var i = 0; i < fallbackLngs.length; i++) { 20796 lngs.push(fallbackLngs[i]); 20797 } 20798 } else if (this.options.saveMissingTo === 'all') { 20799 lngs = this.languageUtils.toResolveHierarchy( 20800 options.lng || this.language 20801 ); 20802 } else { 20803 lngs.push(options.lng || this.language); 20804 } 20805 20806 var send = function send(l, k) { 20807 if (_this2.options.missingKeyHandler) { 20808 _this2.options.missingKeyHandler( 20809 l, 20810 namespace, 20811 k, 20812 updateMissing ? options.defaultValue : res, 20813 updateMissing, 20814 options 20815 ); 20816 } else if ( 20817 _this2.backendConnector && 20818 _this2.backendConnector.saveMissing 20819 ) { 20820 _this2.backendConnector.saveMissing( 20821 l, 20822 namespace, 20823 k, 20824 updateMissing ? options.defaultValue : res, 20825 updateMissing, 20826 options 20827 ); 20828 } 20829 20830 _this2.emit('missingKey', l, namespace, k, res); 20831 }; 20832 20833 if (this.options.saveMissing) { 20834 var needsPluralHandling = 20835 options.count !== undefined && 20836 typeof options.count !== 'string'; 20837 20838 if (this.options.saveMissingPlurals && needsPluralHandling) {
20839 lngs.forEach(function(l) { 20840 var plurals = _this2.pluralResolver.getPluralFormsOfKey( 20841 l, 20842 key 20843 ); 20844 20845 plurals.forEach(function(p) { 20846 return send([l], p); 20847 }); 20848 }); 20849 } else { 20850 send(lngs, key); 20851 } 20852 } 20853 } // extend 20854 20855 res = this.extendTranslation(res, keys, options, resolved); // append namespace if still key 20856 20857 if ( 20858 usedKey && 20859 res === key && 20860 this.options.appendNamespaceToMissingKey 20861 ) 20862 res = ''.concat(namespace, ':').concat(key); // parseMissingKeyHandler 20863 20864 if (usedKey && this.options.parseMissingKeyHandler) 20865 res = this.options.parseMissingKeyHandler(res); 20866 } // return 20867 20868 return res; 20869 } 20870 }, 20871 { 20872 key: 'extendTranslation', 20873 value: function extendTranslation(res, key, options, resolved) { 20874 var _this3 = this; 20875 20876 if (this.i18nFormat && this.i18nFormat.parse) { 20877 res = this.i18nFormat.parse( 20878 res, 20879 options, 20880 resolved.usedLng, 20881 resolved.usedNS, 20882 resolved.usedKey, 20883 { 20884 resolved: resolved 20885 } 20886 ); 20887 } else if (!options.skipInterpolation) { 20888 // i18next.parsing 20889 if (options.interpolation) 20890 this.interpolator.init( 20891 _objectSpread({}, options, { 20892 interpolation: _objectSpread( 20893 {}, 20894 this.options.interpolation, 20895 options.interpolation 20896 ) 20897 }) 20898 ); // interpolate 20899 20900 var data = 20901 options.replace && typeof options.replace !== 'string' 20902 ? options.replace 20903 : options; 20904 if (this.options.interpolation.defaultVariables) 20905 data = _objectSpread( 20906 {}, 20907 this.options.interpolation.defaultVariables, 20908 data 20909 ); 20910 res = this.interpolator.interpolate( 20911 res, 20912 data, 20913 options.lng || this.language, 20914 options 20915 ); // nesting 20916 20917 if (options.nest !== false) 20918 res = this.interpolator.nest( 20919 res, 20920 function() { 20921 return _this3.translate.apply(_this3, arguments); 20922 }, 20923 options 20924 ); 20925 if (options.interpolation) this.interpolator.reset(); 20926 } // post process 20927 20928 var postProcess = options.postProcess || this.options.postProcess; 20929 var postProcessorNames = 20930 typeof postProcess === 'string' ? [postProcess] : postProcess; 20931 20932 if ( 20933 res !== undefined && 20934 res !== null && 20935 postProcessorNames && 20936 postProcessorNames.length && 20937 options.applyPostProcessor !== false 20938 ) { 20939 res = postProcessor.handle( 20940 postProcessorNames, 20941 res, 20942 key, 20943 this.options && this.options.postProcessPassResolved 20944 ? _objectSpread( 20945 { 20946 i18nResolved: resolved 20947 }, 20948 options 20949 ) 20950 : options, 20951 this 20952 ); 20953 } 20954 20955 return res; 20956 } 20957 }, 20958 { 20959 key: 'resolve', 20960 value: function resolve(keys) { 20961 var _this4 = this; 20962 20963 var options = 20964 arguments.length > 1 && arguments[1] !== undefined 20965 ? arguments[1] 20966 : {}; 20967 var found; 20968 var usedKey; // plain key 20969 20970 var exactUsedKey; // key with context / plural 20971 20972 var usedLng; 20973 var usedNS; 20974 if (typeof keys === 'string') keys = [keys]; // forEach possible key 20975 20976 keys.forEach(function(k) { 20977 if (_this4.isValidLookup(found)) return; 20978 20979 var extracted = _this4.extractFromKey(k, options); 20980 20981 var key = extracted.key; 20982 usedKey = key; 20983 var namespaces = extracted.namespaces; 20984 if (_this4.options.fallbackNS) 20985 namespaces = namespaces.concat(_this4.options.fallbackNS); 20986 var needsPluralHandling = 20987 options.count !== undefined && typeof options.count !== 'string'; 20988 var needsContextHandling = 20989 options.context !== undefined && 20990 typeof options.context === 'string' && 20991 options.context !== ''; 20992 var codes = options.lngs 20993 ? options.lngs 20994 : _this4.languageUtils.toResolveHierarchy( 20995 options.lng || _this4.language, 20996 options.fallbackLng 20997 );
20998 namespaces.forEach(function(ns) { 20999 if (_this4.isValidLookup(found)) return; 21000 usedNS = ns; 21001 21002 if ( 21003 !checkedLoadedFor[''.concat(codes[0], '-').concat(ns)] && 21004 _this4.utils && 21005 _this4.utils.hasLoadedNamespace && 21006 !_this4.utils.hasLoadedNamespace(usedNS) 21007 ) { 21008 checkedLoadedFor[''.concat(codes[0], '-').concat(ns)] = true; 21009 21010 _this4.logger.warn( 21011 'key "' 21012 .concat(usedKey, '" for namespace "') 21013 .concat(usedNS, '" for languages "') 21014 .concat( 21015 codes.join(', '), 21016 '" won\'t get resolved as namespace was not yet loaded' 21017 ), 21018 '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!!!' 21019 ); 21020 } 21021 21022 codes.forEach(function(code) { 21023 if (_this4.isValidLookup(found)) return; 21024 usedLng = code; 21025 var finalKey = key; 21026 var finalKeys = [finalKey]; 21027 21028 if (_this4.i18nFormat && _this4.i18nFormat.addLookupKeys) { 21029 _this4.i18nFormat.addLookupKeys( 21030 finalKeys, 21031 key, 21032 code, 21033 ns, 21034 options 21035 ); 21036 } else { 21037 var pluralSuffix; 21038 if (needsPluralHandling) 21039 pluralSuffix = _this4.pluralResolver.getSuffix( 21040 code, 21041 options.count 21042 ); // fallback for plural if context not found 21043 21044 if (needsPluralHandling && needsContextHandling) 21045 finalKeys.push(finalKey + pluralSuffix); // get key for context if needed 21046 21047 if (needsContextHandling) 21048 finalKeys.push( 21049 (finalKey += '' 21050 .concat(_this4.options.contextSeparator) 21051 .concat(options.context)) 21052 ); // get key for plural if needed 21053 21054 if (needsPluralHandling) 21055 finalKeys.push((finalKey += pluralSuffix)); 21056 } // iterate over finalKeys starting with most specific pluralkey (-> contextkey only) -> singularkey only 21057 21058 var possibleKey; 21059 /* eslint no-cond-assign: 0 */ 21060 21061 while ((possibleKey = finalKeys.pop())) { 21062 if (!_this4.isValidLookup(found)) { 21063 exactUsedKey = possibleKey; 21064 found = _this4.getResource(code, ns, possibleKey, options); 21065 } 21066 } 21067 }); 21068 }); 21069 }); 21070 return { 21071 res: found, 21072 usedKey: usedKey, 21073 exactUsedKey: exactUsedKey, 21074 usedLng: usedLng, 21075 usedNS: usedNS 21076 }; 21077 } 21078 }, 21079 { 21080 key: 'isValidLookup', 21081 value: function isValidLookup(res) { 21082 return ( 21083 res !== undefined && 21084 !(!this.options.returnNull && res === null) && 21085 !(!this.options.returnEmptyString && res === '') 21086 ); 21087 } 21088 }, 21089 { 21090 key: 'getResource', 21091 value: function getResource(code, ns, key) { 21092 var options = 21093 arguments.length > 3 && arguments[3] !== undefined 21094 ? arguments[3] 21095 : {}; 21096 if (this.i18nFormat && this.i18nFormat.getResource) 21097 return this.i18nFormat.getResource(code, ns, key, options); 21098 return this.resourceStore.getResource(code, ns, key, options); 21099 } 21100 } 21101 ]); 21102 21103 return Translator; 21104 })(EventEmitter); 21105 21106 function capitalize(string) { 21107 return string.charAt(0).toUpperCase() + string.slice(1); 21108 } 21109 21110 var LanguageUtil = 21111 /*#__PURE__*/ 21112 (function() { 21113 function LanguageUtil(options) { 21114 _classCallCheck(this, LanguageUtil); 21115 21116 this.options = options; 21117 this.whitelist = this.options.whitelist || false;
vendor: 10,268 bytes, lines 21118-21450
21118 this.logger = baseLogger.create('languageUtils'); 21119 } 21120 21121 _createClass(LanguageUtil, [ 21122 { 21123 key: 'getScriptPartFromCode', 21124 value: function getScriptPartFromCode(code) { 21125 if (!code || code.indexOf('-') < 0) return null; 21126 var p = code.split('-'); 21127 if (p.length === 2) return null; 21128 p.pop(); 21129 return this.formatLanguageCode(p.join('-')); 21130 } 21131 }, 21132 { 21133 key: 'getLanguagePartFromCode', 21134 value: function getLanguagePartFromCode(code) { 21135 if (!code || code.indexOf('-') < 0) return code; 21136 var p = code.split('-'); 21137 return this.formatLanguageCode(p[0]); 21138 } 21139 }, 21140 { 21141 key: 'formatLanguageCode', 21142 value: function formatLanguageCode(code) { 21143 // http://www.iana.org/assignments/language-tags/language-tags.xhtml 21144 if (typeof code === 'string' && code.indexOf('-') > -1) { 21145 var specialCases = [ 21146 'hans', 21147 'hant', 21148 'latn', 21149 'cyrl', 21150 'cans', 21151 'mong', 21152 'arab' 21153 ]; 21154 var p = code.split('-'); 21155 21156 if (this.options.lowerCaseLng) { 21157 p = p.map(function(part) { 21158 return part.toLowerCase(); 21159 }); 21160 } else if (p.length === 2) { 21161 p[0] = p[0].toLowerCase(); 21162 p[1] = p[1].toUpperCase(); 21163 if (specialCases.indexOf(p[1].toLowerCase()) > -1) 21164 p[1] = capitalize(p[1].toLowerCase()); 21165 } else if (p.length === 3) { 21166 p[0] = p[0].toLowerCase(); // if lenght 2 guess it's a country 21167 21168 if (p[1].length === 2) p[1] = p[1].toUpperCase(); 21169 if (p[0] !== 'sgn' && p[2].length === 2) p[2] = p[2].toUpperCase(); 21170 if (specialCases.indexOf(p[1].toLowerCase()) > -1) 21171 p[1] = capitalize(p[1].toLowerCase()); 21172 if (specialCases.indexOf(p[2].toLowerCase()) > -1) 21173 p[2] = capitalize(p[2].toLowerCase()); 21174 } 21175 21176 return p.join('-'); 21177 } 21178 21179 return this.options.cleanCode || this.options.lowerCaseLng 21180 ? code.toLowerCase() 21181 : code; 21182 } 21183 }, 21184 { 21185 key: 'isWhitelisted', 21186 value: function isWhitelisted(code) { 21187 if ( 21188 this.options.load === 'languageOnly' || 21189 this.options.nonExplicitWhitelist 21190 ) { 21191 code = this.getLanguagePartFromCode(code); 21192 } 21193 21194 return ( 21195 !this.whitelist || 21196 !this.whitelist.length || 21197 this.whitelist.indexOf(code) > -1 21198 ); 21199 } 21200 }, 21201 { 21202 key: 'getFallbackCodes', 21203 value: function getFallbackCodes(fallbacks, code) { 21204 if (!fallbacks) return []; 21205 if (typeof fallbacks === 'string') fallbacks = [fallbacks]; 21206 if (Object.prototype.toString.apply(fallbacks) === '[object Array]') 21207 return fallbacks; 21208 if (!code) return fallbacks['default'] || []; // asume we have an object defining fallbacks 21209 21210 var found = fallbacks[code]; 21211 if (!found) found = fallbacks[this.getScriptPartFromCode(code)]; 21212 if (!found) found = fallbacks[this.formatLanguageCode(code)]; 21213 if (!found) found = fallbacks['default']; 21214 return found || []; 21215 } 21216 }, 21217 { 21218 key: 'toResolveHierarchy', 21219 value: function toResolveHierarchy(code, fallbackCode) { 21220 var _this = this; 21221 21222 var fallbackCodes = this.getFallbackCodes( 21223 fallbackCode || this.options.fallbackLng || [], 21224 code 21225 ); 21226 var codes = []; 21227 21228 var addCode = function addCode(c) { 21229 if (!c) return; 21230 21231 if (_this.isWhitelisted(c)) { 21232 codes.push(c); 21233 } else { 21234 _this.logger.warn( 21235 'rejecting non-whitelisted language code: '.concat(c) 21236 ); 21237 } 21238 }; 21239 21240 if (typeof code === 'string' && code.indexOf('-') > -1) { 21241 if (this.options.load !== 'languageOnly') 21242 addCode(this.formatLanguageCode(code)); 21243 if ( 21244 this.options.load !== 'languageOnly' && 21245 this.options.load !== 'currentOnly' 21246 ) 21247 addCode(this.getScriptPartFromCode(code)); 21248 if (this.options.load !== 'currentOnly') 21249 addCode(this.getLanguagePartFromCode(code)); 21250 } else if (typeof code === 'string') { 21251 addCode(this.formatLanguageCode(code)); 21252 } 21253 21254 fallbackCodes.forEach(function(fc) { 21255 if (codes.indexOf(fc) < 0) addCode(_this.formatLanguageCode(fc)); 21256 }); 21257 return codes; 21258 } 21259 } 21260 ]); 21261 21262 return LanguageUtil; 21263 })(); 21264 21265 /* eslint-disable */ 21266 21267 var sets = [ 21268 { 21269 lngs: [ 21270 'ach', 21271 'ak', 21272 'am', 21273 'arn', 21274 'br', 21275 'fil', 21276 'gun', 21277 'ln', 21278 'mfe', 21279 'mg', 21280 'mi', 21281 'oc', 21282 'pt', 21283 'pt-BR', 21284 'tg', 21285 'ti', 21286 'tr', 21287 'uz', 21288 'wa' 21289 ], 21290 nr: [1, 2], 21291 fc: 1 21292 }, 21293 { 21294 lngs: [ 21295 'af', 21296 'an', 21297 'ast', 21298 'az', 21299 'bg', 21300 'bn', 21301 'ca', 21302 'da', 21303 'de', 21304 'dev', 21305 'el', 21306 'en', 21307 'eo', 21308 'es', 21309 'et', 21310 'eu', 21311 'fi', 21312 'fo', 21313 'fur', 21314 'fy', 21315 'gl', 21316 'gu', 21317 'ha', 21318 'hi', 21319 'hu', 21320 'hy', 21321 'ia', 21322 'it', 21323 'kn', 21324 'ku', 21325 'lb', 21326 'mai', 21327 'ml', 21328 'mn', 21329 'mr', 21330 'nah', 21331 'nap', 21332 'nb', 21333 'ne', 21334 'nl', 21335 'nn', 21336 'no', 21337 'nso', 21338 'pa', 21339 'pap', 21340 'pms', 21341 'ps', 21342 'pt-PT', 21343 'rm', 21344 'sco', 21345 'se', 21346 'si', 21347 'so', 21348 'son', 21349 'sq', 21350 'sv', 21351 'sw', 21352 'ta', 21353 'te', 21354 'tk', 21355 'ur', 21356 'yo' 21357 ], 21358 nr: [1, 2], 21359 fc: 2 21360 }, 21361 { 21362 lngs: [ 21363 'ay', 21364 'bo', 21365 'cgg', 21366 'fa', 21367 'id', 21368 'ja', 21369 'jbo', 21370 'ka', 21371 'kk', 21372 'km', 21373 'ko', 21374 'ky', 21375 'lo', 21376 'ms', 21377 'sah', 21378 'su', 21379 'th', 21380 'tt', 21381 'ug', 21382 'vi', 21383 'wo', 21384 'zh' 21385 ], 21386 nr: [1], 21387 fc: 3 21388 }, 21389 { 21390 lngs: ['be', 'bs', 'cnr', 'dz', 'hr', 'ru', 'sr', 'uk'], 21391 nr: [1, 2, 5], 21392 fc: 4 21393 }, 21394 { 21395 lngs: ['ar'], 21396 nr: [0, 1, 2, 3, 11, 100], 21397 fc: 5 21398 }, 21399 { 21400 lngs: ['cs', 'sk'], 21401 nr: [1, 2, 5], 21402 fc: 6 21403 }, 21404 { 21405 lngs: ['csb', 'pl'], 21406 nr: [1, 2, 5], 21407 fc: 7 21408 }, 21409 { 21410 lngs: ['cy'], 21411 nr: [1, 2, 3, 8], 21412 fc: 8 21413 }, 21414 { 21415 lngs: ['fr'], 21416 nr: [1, 2], 21417 fc: 9 21418 }, 21419 { 21420 lngs: ['ga'], 21421 nr: [1, 2, 3, 7, 11], 21422 fc: 10 21423 }, 21424 { 21425 lngs: ['gd'], 21426 nr: [1, 2, 3, 20], 21427 fc: 11 21428 }, 21429 { 21430 lngs: ['is'], 21431 nr: [1, 2], 21432 fc: 12 21433 }, 21434 { 21435 lngs: ['jv'], 21436 nr: [0, 1], 21437 fc: 13 21438 }, 21439 { 21440 lngs: ['kw'], 21441 nr: [1, 2, 3, 4], 21442 fc: 14 21443 }, 21444 { 21445 lngs: ['lt'], 21446 nr: [1, 2, 10], 21447 fc: 15 21448 }, 21449 { 21450 lngs: ['lv'],
vendor: 4,273 bytes, lines 21451-21591
21451 nr: [1, 2, 0], 21452 fc: 16 21453 }, 21454 { 21455 lngs: ['mk'], 21456 nr: [1, 2], 21457 fc: 17 21458 }, 21459 { 21460 lngs: ['mnk'], 21461 nr: [0, 1, 2], 21462 fc: 18 21463 }, 21464 { 21465 lngs: ['mt'], 21466 nr: [1, 2, 11, 20], 21467 fc: 19 21468 }, 21469 { 21470 lngs: ['or'], 21471 nr: [2, 1], 21472 fc: 2 21473 }, 21474 { 21475 lngs: ['ro'], 21476 nr: [1, 2, 20], 21477 fc: 20 21478 }, 21479 { 21480 lngs: ['sl'], 21481 nr: [5, 1, 2, 3], 21482 fc: 21 21483 }, 21484 { 21485 lngs: ['he'], 21486 nr: [1, 2, 20, 21], 21487 fc: 22 21488 } 21489 ]; 21490 var _rulesPluralsTypes = { 21491 1: function _(n) { 21492 return Number(n > 1); 21493 }, 21494 2: function _(n) { 21495 return Number(n != 1); 21496 }, 21497 3: function _(n) { 21498 return 0; 21499 }, 21500 4: function _(n) { 21501 return Number( 21502 n % 10 == 1 && n % 100 != 11 21503 ? 0 21504 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2 21505 ); 21506 }, 21507 5: function _(n) { 21508 return Number( 21509 n === 0 21510 ? 0 21511 : n == 1 21512 ? 1 21513 : n == 2 ? 2 : n % 100 >= 3 && n % 100 <= 10 ? 3 : n % 100 >= 11 ? 4 : 5 21514 ); 21515 }, 21516 6: function _(n) { 21517 return Number(n == 1 ? 0 : n >= 2 && n <= 4 ? 1 : 2); 21518 }, 21519 7: function _(n) { 21520 return Number( 21521 n == 1 21522 ? 0 21523 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2 21524 ); 21525 }, 21526 8: function _(n) { 21527 return Number(n == 1 ? 0 : n == 2 ? 1 : n != 8 && n != 11 ? 2 : 3); 21528 }, 21529 9: function _(n) { 21530 return Number(n >= 2); 21531 }, 21532 10: function _(n) { 21533 return Number(n == 1 ? 0 : n == 2 ? 1 : n < 7 ? 2 : n < 11 ? 3 : 4); 21534 }, 21535 11: function _(n) { 21536 return Number( 21537 n == 1 || n == 11 ? 0 : n == 2 || n == 12 ? 1 : n > 2 && n < 20 ? 2 : 3 21538 ); 21539 }, 21540 12: function _(n) { 21541 return Number(n % 10 != 1 || n % 100 == 11); 21542 }, 21543 13: function _(n) { 21544 return Number(n !== 0); 21545 }, 21546 14: function _(n) { 21547 return Number(n == 1 ? 0 : n == 2 ? 1 : n == 3 ? 2 : 3); 21548 }, 21549 15: function _(n) { 21550 return Number( 21551 n % 10 == 1 && n % 100 != 11 21552 ? 0 21553 : n % 10 >= 2 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2 21554 ); 21555 }, 21556 16: function _(n) { 21557 return Number(n % 10 == 1 && n % 100 != 11 ? 0 : n !== 0 ? 1 : 2); 21558 }, 21559 17: function _(n) { 21560 return Number(n == 1 || n % 10 == 1 ? 0 : 1); 21561 }, 21562 18: function _(n) { 21563 return Number(n == 0 ? 0 : n == 1 ? 1 : 2); 21564 }, 21565 19: function _(n) { 21566 return Number( 21567 n == 1 21568 ? 0 21569 : n === 0 || (n % 100 > 1 && n % 100 < 11) 21570 ? 1 21571 : n % 100 > 10 && n % 100 < 20 ? 2 : 3 21572 ); 21573 }, 21574 20: function _(n) { 21575 return Number(n == 1 ? 0 : n === 0 || (n % 100 > 0 && n % 100 < 20) ? 1 : 2); 21576 }, 21577 21: function _(n) { 21578 return Number( 21579 n % 100 == 1 ? 1 : n % 100 == 2 ? 2 : n % 100 == 3 || n % 100 == 4 ? 3 : 0 21580 ); 21581 }, 21582 22: function _(n) { 21583 return Number( 21584 n === 1 ? 0 : n === 2 ? 1 : (n < 0 || n > 10) && n % 10 == 0 ? 2 : 3 21585 ); 21586 } 21587 }; 21588 /* eslint-enable */ 21589 21590 function createRules() { 21591 var rules = {};
21592 sets.forEach(function(set) { 21593 set.lngs.forEach(function(l) { 21594 rules[l] = { 21595 numbers: set.nr, 21596 plurals: _rulesPluralsTypes[set.fc] 21597 }; 21598 }); 21599 }); 21600 return rules; 21601 } 21602 21603 var PluralResolver = 21604 /*#__PURE__*/ 21605 (function() { 21606 function PluralResolver(languageUtils) { 21607 var options = 21608 arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; 21609 21610 _classCallCheck(this, PluralResolver); 21611 21612 this.languageUtils = languageUtils; 21613 this.options = options; 21614 this.logger = baseLogger.create('pluralResolver'); 21615 this.rules = createRules(); 21616 } 21617 21618 _createClass(PluralResolver, [ 21619 { 21620 key: 'addRule', 21621 value: function addRule(lng, obj) { 21622 this.rules[lng] = obj; 21623 } 21624 }, 21625 { 21626 key: 'getRule', 21627 value: function getRule(code) { 21628 return ( 21629 this.rules[code] || 21630 this.rules[this.languageUtils.getLanguagePartFromCode(code)] 21631 ); 21632 } 21633 }, 21634 { 21635 key: 'needsPlural', 21636 value: function needsPlural(code) { 21637 var rule = this.getRule(code); 21638 return rule && rule.numbers.length > 1; 21639 } 21640 }, 21641 { 21642 key: 'getPluralFormsOfKey', 21643 value: function getPluralFormsOfKey(code, key) { 21644 var _this = this; 21645 21646 var ret = []; 21647 var rule = this.getRule(code); 21648 if (!rule) return ret; 21649 rule.numbers.forEach(function(n) { 21650 var suffix = _this.getSuffix(code, n); 21651 21652 ret.push(''.concat(key).concat(suffix)); 21653 }); 21654 return ret; 21655 } 21656 }, 21657 { 21658 key: 'getSuffix', 21659 value: function getSuffix(code, count) { 21660 var _this2 = this; 21661 21662 var rule = this.getRule(code); 21663 21664 if (rule) { 21665 // if (rule.numbers.length === 1) return ''; // only singular 21666 var idx = rule.noAbs 21667 ? rule.plurals(count) 21668 : rule.plurals(Math.abs(count)); 21669 var suffix = rule.numbers[idx]; // special treatment for lngs only having singular and plural 21670 21671 if ( 21672 this.options.simplifyPluralSuffix && 21673 rule.numbers.length === 2 && 21674 rule.numbers[0] === 1 21675 ) { 21676 if (suffix === 2) { 21677 suffix = 'plural'; 21678 } else if (suffix === 1) { 21679 suffix = ''; 21680 } 21681 } 21682 21683 var returnSuffix = function returnSuffix() { 21684 return _this2.options.prepend && suffix.toString() 21685 ? _this2.options.prepend + suffix.toString() 21686 : suffix.toString(); 21687 }; // COMPATIBILITY JSON 21688 // v1 21689 21690 if (this.options.compatibilityJSON === 'v1') { 21691 if (suffix === 1) return ''; 21692 if (typeof suffix === 'number') 21693 return '_plural_'.concat(suffix.toString()); 21694 return returnSuffix(); 21695 } else if ( 21696 /* v2 */ 21697 this.options.compatibilityJSON === 'v2' 21698 ) { 21699 return returnSuffix(); 21700 } else if ( 21701 /* v3 - gettext index */ 21702 this.options.simplifyPluralSuffix && 21703 rule.numbers.length === 2 &&
vendor: 4,196 bytes, lines 21704-21806
21704 rule.numbers[0] === 1 21705 ) { 21706 return returnSuffix(); 21707 } 21708 21709 return this.options.prepend && idx.toString() 21710 ? this.options.prepend + idx.toString() 21711 : idx.toString(); 21712 } 21713 21714 this.logger.warn('no plural rule found for: '.concat(code)); 21715 return ''; 21716 } 21717 } 21718 ]); 21719 21720 return PluralResolver; 21721 })(); 21722 21723 var Interpolator = 21724 /*#__PURE__*/ 21725 (function() { 21726 function Interpolator() { 21727 var options = 21728 arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; 21729 21730 _classCallCheck(this, Interpolator); 21731 21732 this.logger = baseLogger.create('interpolator'); 21733 this.options = options; 21734 21735 this.format = 21736 (options.interpolation && options.interpolation.format) || 21737 function(value) { 21738 return value; 21739 }; 21740 21741 this.init(options); 21742 } 21743 /* eslint no-param-reassign: 0 */ 21744 21745 _createClass(Interpolator, [ 21746 { 21747 key: 'init', 21748 value: function init() { 21749 var options = 21750 arguments.length > 0 && arguments[0] !== undefined 21751 ? arguments[0] 21752 : {}; 21753 if (!options.interpolation) 21754 options.interpolation = { 21755 escapeValue: true 21756 }; 21757 var iOpts = options.interpolation; 21758 this.escape = iOpts.escape !== undefined ? iOpts.escape : escape; 21759 this.escapeValue = 21760 iOpts.escapeValue !== undefined ? iOpts.escapeValue : true; 21761 this.useRawValueToEscape = 21762 iOpts.useRawValueToEscape !== undefined 21763 ? iOpts.useRawValueToEscape 21764 : false; 21765 this.prefix = iOpts.prefix 21766 ? regexEscape(iOpts.prefix) 21767 : iOpts.prefixEscaped || '{{'; 21768 this.suffix = iOpts.suffix 21769 ? regexEscape(iOpts.suffix) 21770 : iOpts.suffixEscaped || '}}'; 21771 this.formatSeparator = iOpts.formatSeparator 21772 ? iOpts.formatSeparator 21773 : iOpts.formatSeparator || ','; 21774 this.unescapePrefix = iOpts.unescapeSuffix 21775 ? '' 21776 : iOpts.unescapePrefix || '-'; 21777 this.unescapeSuffix = this.unescapePrefix 21778 ? '' 21779 : iOpts.unescapeSuffix || ''; 21780 this.nestingPrefix = iOpts.nestingPrefix 21781 ? regexEscape(iOpts.nestingPrefix) 21782 : iOpts.nestingPrefixEscaped || regexEscape('$t('); 21783 this.nestingSuffix = iOpts.nestingSuffix 21784 ? regexEscape(iOpts.nestingSuffix) 21785 : iOpts.nestingSuffixEscaped || regexEscape(')'); 21786 this.maxReplaces = iOpts.maxReplaces ? iOpts.maxReplaces : 1000; // the regexp 21787 21788 this.resetRegExp(); 21789 } 21790 }, 21791 { 21792 key: 'reset', 21793 value: function reset() { 21794 if (this.options) this.init(this.options); 21795 } 21796 }, 21797 { 21798 key: 'resetRegExp', 21799 value: function resetRegExp() { 21800 // the regexp 21801 var regexpStr = ''.concat(this.prefix, '(.+?)').concat(this.suffix); 21802 this.regexp = new RegExp(regexpStr, 'g'); 21803 var regexpUnescapeStr = '' 21804 .concat(this.prefix) 21805 .concat(this.unescapePrefix, '(.+?)') 21806 .concat(this.unescapeSuffix)
21807 .concat(this.suffix); 21808 this.regexpUnescape = new RegExp(regexpUnescapeStr, 'g'); 21809 var nestingRegexpStr = '' 21810 .concat(this.nestingPrefix, '(.+?)') 21811 .concat(this.nestingSuffix); 21812 this.nestingRegexp = new RegExp(nestingRegexpStr, 'g'); 21813 } 21814 }, 21815 { 21816 key: 'interpolate', 21817 value: function interpolate(str, data, lng, options) { 21818 var _this = this; 21819 21820 var match; 21821 var value; 21822 var replaces; 21823 var defaultData = 21824 (this.options && 21825 this.options.interpolation && 21826 this.options.interpolation.defaultVariables) || 21827 {}; 21828 21829 function regexSafe(val) { 21830 return val.replace(/\$/g, '$$$$'); 21831 } 21832 21833 var handleFormat = function handleFormat(key) { 21834 if (key.indexOf(_this.formatSeparator) < 0) { 21835 return getPathWithDefaults(data, defaultData, key); 21836 } 21837 21838 var p = key.split(_this.formatSeparator); 21839 var k = p.shift().trim(); 21840 var f = p.join(_this.formatSeparator).trim(); 21841 return _this.format( 21842 getPathWithDefaults(data, defaultData, k), 21843 f, 21844 lng 21845 ); 21846 }; 21847 21848 this.resetRegExp(); 21849 var missingInterpolationHandler = 21850 (options && options.missingInterpolationHandler) || 21851 this.options.missingInterpolationHandler; 21852 replaces = 0; // unescape if has unescapePrefix/Suffix 21853 21854 /* eslint no-cond-assign: 0 */ 21855 21856 while ((match = this.regexpUnescape.exec(str))) { 21857 value = handleFormat(match[1].trim()); 21858 21859 if (value === undefined) { 21860 if (typeof missingInterpolationHandler === 'function') { 21861 var temp = missingInterpolationHandler(str, match, options); 21862 value = typeof temp === 'string' ? temp : ''; 21863 } else { 21864 this.logger.warn( 21865 'missed to pass in variable ' 21866 .concat(match[1], ' for interpolating ') 21867 .concat(str) 21868 ); 21869 value = ''; 21870 } 21871 } else if (typeof value !== 'string' && !this.useRawValueToEscape) { 21872 value = makeString(value); 21873 } 21874 21875 str = str.replace(match[0], regexSafe(value)); 21876 this.regexpUnescape.lastIndex = 0; 21877 replaces++; 21878 21879 if (replaces >= this.maxReplaces) { 21880 break; 21881 } 21882 } 21883 21884 replaces = 0; // regular escape on demand 21885 21886 while ((match = this.regexp.exec(str))) { 21887 value = handleFormat(match[1].trim()); 21888 21889 if (value === undefined) { 21890 if (typeof missingInterpolationHandler === 'function') { 21891 var _temp = missingInterpolationHandler(str, match, options); 21892 21893 value = typeof _temp === 'string' ? _temp : ''; 21894 } else { 21895 this.logger.warn( 21896 'missed to pass in variable ' 21897 .concat(match[1], ' for interpolating ') 21898 .concat(str) 21899 ); 21900 value = ''; 21901 } 21902 } else if (typeof value !== 'string' && !this.useRawValueToEscape) { 21903 value = makeString(value); 21904 } 21905 21906 value = this.escapeValue 21907 ? regexSafe(this.escape(value)) 21908 : regexSafe(value); 21909 str = str.replace(match[0], value); 21910 this.regexp.lastIndex = 0; 21911 replaces++; 21912 21913 if (replaces >= this.maxReplaces) { 21914 break; 21915 } 21916 } 21917 21918 return str; 21919 } 21920 }, 21921 { 21922 key: 'nest', 21923 value: function nest(str, fc) { 21924 var options = 21925 arguments.length > 2 && arguments[2] !== undefined 21926 ? arguments[2] 21927 : {}; 21928 var match; 21929 var value; 21930 21931 var clonedOptions = _objectSpread({}, options); 21932 21933 clonedOptions.applyPostProcessor = false; // avoid post processing on nested lookup 21934 21935 delete clonedOptions.defaultValue; // assert we do not get a endless loop on interpolating defaultValue again and again 21936 // if value is something like "myKey": "lorem $(anotherKey, { "count": {{aValueInOptions}} })"
21937 21938 function handleHasOptions(key, inheritedOptions) { 21939 if (key.indexOf(',') < 0) return key; 21940 var p = key.split(','); 21941 key = p.shift(); 21942 var optionsString = p.join(','); 21943 optionsString = this.interpolate(optionsString, clonedOptions); 21944 optionsString = optionsString.replace(/'/g, '"'); 21945 21946 try { 21947 clonedOptions = JSON.parse(optionsString); 21948 if (inheritedOptions) 21949 clonedOptions = _objectSpread( 21950 {}, 21951 inheritedOptions, 21952 clonedOptions 21953 ); 21954 } catch (e) { 21955 this.logger.error( 21956 'failed parsing options string in nesting for key '.concat(key), 21957 e 21958 ); 21959 } // assert we do not get a endless loop on interpolating defaultValue again and again 21960 21961 delete clonedOptions.defaultValue; 21962 return key; 21963 } // regular escape on demand 21964 21965 while ((match = this.nestingRegexp.exec(str))) { 21966 value = fc( 21967 handleHasOptions.call(this, match[1].trim(), clonedOptions), 21968 clonedOptions 21969 ); // is only the nesting key (key1 = '$(key2)') return the value without stringify 21970 21971 if (value && match[0] === str && typeof value !== 'string') 21972 return value; // no string to include or empty 21973 21974 if (typeof value !== 'string') value = makeString(value); 21975 21976 if (!value) { 21977 this.logger.warn( 21978 'missed to resolve '.concat(match[1], ' for nesting ').concat(str) 21979 ); 21980 value = ''; 21981 } // Nested keys should not be escaped by default #854 21982 // value = this.escapeValue ? regexSafe(utils.escape(value)) : regexSafe(value); 21983 21984 str = str.replace(match[0], value); 21985 this.regexp.lastIndex = 0; 21986 } 21987 21988 return str; 21989 } 21990 } 21991 ]); 21992 21993 return Interpolator; 21994 })(); 21995 21996 function remove(arr, what) { 21997 var found = arr.indexOf(what); 21998 21999 while (found !== -1) { 22000 arr.splice(found, 1); 22001 found = arr.indexOf(what); 22002 } 22003 } 22004 22005 var Connector = 22006 /*#__PURE__*/ 22007 (function(_EventEmitter) { 22008 _inherits(Connector, _EventEmitter); 22009 22010 function Connector(backend, store, services) { 22011 var _this; 22012 22013 var options = 22014 arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; 22015 22016 _classCallCheck(this, Connector); 22017 22018 _this = _possibleConstructorReturn( 22019 this, 22020 _getPrototypeOf(Connector).call(this) 22021 ); 22022 EventEmitter.call(_assertThisInitialized(_this)); // <=IE10 fix (unable to call parent constructor) 22023 22024 _this.backend = backend; 22025 _this.store = store; 22026 _this.services = services; 22027 _this.languageUtils = services.languageUtils; 22028 _this.options = options; 22029 _this.logger = baseLogger.create('backendConnector'); 22030 _this.state = {}; 22031 _this.queue = []; 22032 22033 if (_this.backend && _this.backend.init) { 22034 _this.backend.init(services, options.backend, options); 22035 } 22036 22037 return _this; 22038 } 22039 22040 _createClass(Connector, [ 22041 { 22042 key: 'queueLoad', 22043 value: function queueLoad(languages, namespaces, options, callback) { 22044 var _this2 = this; 22045 22046 // find what needs to be loaded 22047 var toLoad = []; 22048 var pending = []; 22049 var toLoadLanguages = []; 22050 var toLoadNamespaces = [];
22051 languages.forEach(function(lng) { 22052 var hasAllNamespaces = true; 22053 namespaces.forEach(function(ns) { 22054 var name = ''.concat(lng, '|').concat(ns); 22055 22056 if (!options.reload && _this2.store.hasResourceBundle(lng, ns)) { 22057 _this2.state[name] = 2; // loaded 22058 } else if (_this2.state[name] < 0); 22059 else if (_this2.state[name] === 1) { 22060 if (pending.indexOf(name) < 0) pending.push(name); 22061 } else { 22062 _this2.state[name] = 1; // pending 22063 22064 hasAllNamespaces = false; 22065 if (pending.indexOf(name) < 0) pending.push(name); 22066 if (toLoad.indexOf(name) < 0) toLoad.push(name); 22067 if (toLoadNamespaces.indexOf(ns) < 0) toLoadNamespaces.push(ns); 22068 } 22069 }); 22070 if (!hasAllNamespaces) toLoadLanguages.push(lng); 22071 }); 22072 22073 if (toLoad.length || pending.length) { 22074 this.queue.push({ 22075 pending: pending, 22076 loaded: {}, 22077 errors: [], 22078 callback: callback 22079 }); 22080 } 22081 22082 return { 22083 toLoad: toLoad, 22084 pending: pending, 22085 toLoadLanguages: toLoadLanguages, 22086 toLoadNamespaces: toLoadNamespaces 22087 }; 22088 } 22089 }, 22090 { 22091 key: 'loaded', 22092 value: function loaded(name, err, data) { 22093 var _name$split = name.split('|'), 22094 _name$split2 = _slicedToArray(_name$split, 2), 22095 lng = _name$split2[0], 22096 ns = _name$split2[1]; 22097 22098 if (err) this.emit('failedLoading', lng, ns, err); 22099 22100 if (data) { 22101 this.store.addResourceBundle(lng, ns, data); 22102 } // set loaded 22103 22104 this.state[name] = err ? -1 : 2; // consolidated loading done in this run - only emit once for a loaded namespace 22105 22106 var loaded = {}; // callback if ready 22107 22108 this.queue.forEach(function(q) { 22109 pushPath(q.loaded, [lng], ns); 22110 remove(q.pending, name); 22111 if (err) q.errors.push(err); 22112 22113 if (q.pending.length === 0 && !q.done) { 22114 // only do once per loaded -> this.emit('loaded', q.loaded); 22115 Object.keys(q.loaded).forEach(function(l) { 22116 if (!loaded[l]) loaded[l] = []; 22117 22118 if (q.loaded[l].length) { 22119 q.loaded[l].forEach(function(ns) { 22120 if (loaded[l].indexOf(ns) < 0) loaded[l].push(ns); 22121 }); 22122 } 22123 }); 22124 /* eslint no-param-reassign: 0 */ 22125 22126 q.done = true; 22127 22128 if (q.errors.length) { 22129 q.callback(q.errors); 22130 } else { 22131 q.callback(); 22132 } 22133 } 22134 }); // emit consolidated loaded event 22135 22136 this.emit('loaded', loaded); // remove done load requests 22137 22138 this.queue = this.queue.filter(function(q) { 22139 return !q.done; 22140 }); 22141 } 22142 }, 22143 { 22144 key: 'read', 22145 value: function read(lng, ns, fcName) { 22146 var _this3 = this; 22147 22148 var tried = 22149 arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0; 22150 var wait = 22151 arguments.length > 4 && arguments[4] !== undefined 22152 ? arguments[4] 22153 : 250; 22154 var callback = arguments.length > 5 ? arguments[5] : undefined; 22155 if (!lng.length) return callback(null, {}); // noting to load 22156 22157 return this.backend[fcName](lng, ns, function(err, data) { 22158 if ( 22159 err && 22160 data && 22161 /* = retryFlag */ 22162 tried < 5 22163 ) { 22164 setTimeout(function() { 22165 _this3.read.call( 22166 _this3, 22167 lng, 22168 ns, 22169 fcName, 22170 tried + 1, 22171 wait * 2, 22172 callback 22173 ); 22174 }, wait); 22175 return; 22176 } 22177 22178 callback(err, data); 22179 }); 22180 } 22181 /* eslint consistent-return: 0 */ 22182 }, 22183 { 22184 key: 'prepareLoading', 22185 value: function prepareLoading(languages, namespaces) { 22186 var _this4 = this; 22187 22188 var options = 22189 arguments.length > 2 && arguments[2] !== undefined 22190 ? arguments[2] 22191 : {}; 22192 var callback = arguments.length > 3 ? arguments[3] : undefined; 22193 22194 if (!this.backend) { 22195 this.logger.warn(
vendor: 27,572 bytes, lines 22196-22895
22196 'No backend was added via i18next.use. Will not load resources.' 22197 ); 22198 return callback && callback(); 22199 } 22200 22201 if (typeof languages === 'string') 22202 languages = this.languageUtils.toResolveHierarchy(languages); 22203 if (typeof namespaces === 'string') namespaces = [namespaces]; 22204 var toLoad = this.queueLoad(languages, namespaces, options, callback); 22205 22206 if (!toLoad.toLoad.length) { 22207 if (!toLoad.pending.length) callback(); // nothing to load and no pendings...callback now 22208 22209 return null; // pendings will trigger callback 22210 } 22211 22212 toLoad.toLoad.forEach(function(name) { 22213 _this4.loadOne(name); 22214 }); 22215 } 22216 }, 22217 { 22218 key: 'load', 22219 value: function load(languages, namespaces, callback) { 22220 this.prepareLoading(languages, namespaces, {}, callback); 22221 } 22222 }, 22223 { 22224 key: 'reload', 22225 value: function reload(languages, namespaces, callback) { 22226 this.prepareLoading( 22227 languages, 22228 namespaces, 22229 { 22230 reload: true 22231 }, 22232 callback 22233 ); 22234 } 22235 }, 22236 { 22237 key: 'loadOne', 22238 value: function loadOne(name) { 22239 var _this5 = this; 22240 22241 var prefix = 22242 arguments.length > 1 && arguments[1] !== undefined 22243 ? arguments[1] 22244 : ''; 22245 22246 var _name$split3 = name.split('|'), 22247 _name$split4 = _slicedToArray(_name$split3, 2), 22248 lng = _name$split4[0], 22249 ns = _name$split4[1]; 22250 22251 this.read(lng, ns, 'read', null, null, function(err, data) { 22252 if (err) 22253 _this5.logger.warn( 22254 '' 22255 .concat(prefix, 'loading namespace ') 22256 .concat(ns, ' for language ') 22257 .concat(lng, ' failed'), 22258 err 22259 ); 22260 if (!err && data) 22261 _this5.logger.log( 22262 '' 22263 .concat(prefix, 'loaded namespace ') 22264 .concat(ns, ' for language ') 22265 .concat(lng), 22266 data 22267 ); 22268 22269 _this5.loaded(name, err, data); 22270 }); 22271 } 22272 }, 22273 { 22274 key: 'saveMissing', 22275 value: function saveMissing( 22276 languages, 22277 namespace, 22278 key, 22279 fallbackValue, 22280 isUpdate 22281 ) { 22282 var options = 22283 arguments.length > 5 && arguments[5] !== undefined 22284 ? arguments[5] 22285 : {}; 22286 22287 if ( 22288 this.services.utils && 22289 this.services.utils.hasLoadedNamespace && 22290 !this.services.utils.hasLoadedNamespace(namespace) 22291 ) { 22292 this.logger.warn( 22293 'did not save key "' 22294 .concat(key, '" for namespace "') 22295 .concat(namespace, '" as the namespace was not yet loaded'), 22296 '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!!!' 22297 ); 22298 return; 22299 } // ignore non valid keys 22300 22301 if (key === undefined || key === null || key === '') return; 22302 22303 if (this.backend && this.backend.create) { 22304 this.backend.create( 22305 languages, 22306 namespace, 22307 key, 22308 fallbackValue, 22309 null, 22310 /* unused callback */ 22311 _objectSpread({}, options, { 22312 isUpdate: isUpdate 22313 }) 22314 ); 22315 } // write to store to avoid resending 22316 22317 if (!languages || !languages[0]) return; 22318 this.store.addResource(languages[0], namespace, key, fallbackValue); 22319 } 22320 } 22321 ]); 22322 22323 return Connector; 22324 })(EventEmitter); 22325 22326 function get() { 22327 return { 22328 debug: false, 22329 initImmediate: true, 22330 ns: ['translation'], 22331 defaultNS: ['translation'], 22332 fallbackLng: ['dev'], 22333 fallbackNS: false, 22334 // string or array of namespaces 22335 whitelist: false, 22336 // array with whitelisted languages 22337 nonExplicitWhitelist: false, 22338 load: 'all', 22339 // | currentOnly | languageOnly 22340 preload: false, 22341 // array with preload languages 22342 simplifyPluralSuffix: true, 22343 keySeparator: '.', 22344 nsSeparator: ':', 22345 pluralSeparator: '_', 22346 contextSeparator: '_', 22347 partialBundledLanguages: false, 22348 // allow bundling certain languages that are not remotely fetched 22349 saveMissing: false, 22350 // enable to send missing values 22351 updateMissing: false, 22352 // enable to update default values if different from translated value (only useful on initial development, or when keeping code as source of truth) 22353 saveMissingTo: 'fallback', 22354 // 'current' || 'all' 22355 saveMissingPlurals: true, 22356 // will save all forms not only singular key 22357 missingKeyHandler: false, 22358 // function(lng, ns, key, fallbackValue) -> override if prefer on handling 22359 missingInterpolationHandler: false, 22360 // function(str, match) 22361 postProcess: false, 22362 // string or array of postProcessor names 22363 postProcessPassResolved: false, 22364 // pass resolved object into 'options.i18nResolved' for postprocessor 22365 returnNull: true, 22366 // allows null value as valid translation 22367 returnEmptyString: true, 22368 // allows empty string value as valid translation 22369 returnObjects: false, 22370 joinArrays: false, 22371 // or string to join array 22372 returnedObjectHandler: false, 22373 // function(key, value, options) triggered if key returns object but returnObjects is set to false 22374 parseMissingKeyHandler: false, 22375 // function(key) parsed a key that was not found in t() before returning 22376 appendNamespaceToMissingKey: false, 22377 appendNamespaceToCIMode: false, 22378 overloadTranslationOptionHandler: function handle(args) { 22379 var ret = {}; 22380 if (_typeof(args[1]) === 'object') ret = args[1]; 22381 if (typeof args[1] === 'string') ret.defaultValue = args[1]; 22382 if (typeof args[2] === 'string') ret.tDescription = args[2]; 22383 22384 if (_typeof(args[2]) === 'object' || _typeof(args[3]) === 'object') { 22385 var options = args[3] || args[2]; 22386 Object.keys(options).forEach(function(key) { 22387 ret[key] = options[key]; 22388 }); 22389 } 22390 22391 return ret; 22392 }, 22393 interpolation: { 22394 escapeValue: true, 22395 format: function format(value, _format, lng) { 22396 return value; 22397 }, 22398 prefix: '{{', 22399 suffix: '}}', 22400 formatSeparator: ',', 22401 // prefixEscaped: '{{', 22402 // suffixEscaped: '}}', 22403 // unescapeSuffix: '', 22404 unescapePrefix: '-', 22405 nestingPrefix: '$t(', 22406 nestingSuffix: ')', 22407 // nestingPrefixEscaped: '$t(', 22408 // nestingSuffixEscaped: ')', 22409 // defaultVariables: undefined // object that can have values to interpolate on - extends passed in interpolation data 22410 maxReplaces: 1000 // max replaces to prevent endless loop 22411 } 22412 }; 22413 } 22414 /* eslint no-param-reassign: 0 */ 22415 22416 function transformOptions(options) { 22417 // create namespace object if namespace is passed in as string 22418 if (typeof options.ns === 'string') options.ns = [options.ns]; 22419 if (typeof options.fallbackLng === 'string') 22420 options.fallbackLng = [options.fallbackLng]; 22421 if (typeof options.fallbackNS === 'string') 22422 options.fallbackNS = [options.fallbackNS]; // extend whitelist with cimode 22423 22424 if (options.whitelist && options.whitelist.indexOf('cimode') < 0) { 22425 options.whitelist = options.whitelist.concat(['cimode']); 22426 } 22427 22428 return options; 22429 } 22430 22431 function noop() {} 22432 22433 var I18n = 22434 /*#__PURE__*/ 22435 (function(_EventEmitter) { 22436 _inherits(I18n, _EventEmitter); 22437 22438 function I18n() { 22439 var _this; 22440 22441 var options = 22442 arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; 22443 var callback = arguments.length > 1 ? arguments[1] : undefined; 22444 22445 _classCallCheck(this, I18n); 22446 22447 _this = _possibleConstructorReturn(this, _getPrototypeOf(I18n).call(this)); 22448 EventEmitter.call(_assertThisInitialized(_this)); // <=IE10 fix (unable to call parent constructor) 22449 22450 _this.options = transformOptions(options); 22451 _this.services = {}; 22452 _this.logger = baseLogger; 22453 _this.modules = { 22454 external: [] 22455 }; 22456 22457 if (callback && !_this.isInitialized && !options.isClone) { 22458 // https://github.com/i18next/i18next/issues/879 22459 if (!_this.options.initImmediate) { 22460 _this.init(options, callback); 22461 22462 return _possibleConstructorReturn(_this, _assertThisInitialized(_this)); 22463 } 22464 22465 setTimeout(function() { 22466 _this.init(options, callback); 22467 }, 0); 22468 } 22469 22470 return _this; 22471 } 22472 22473 _createClass(I18n, [ 22474 { 22475 key: 'init', 22476 value: function init() { 22477 var _this2 = this; 22478 22479 var options = 22480 arguments.length > 0 && arguments[0] !== undefined 22481 ? arguments[0] 22482 : {}; 22483 var callback = arguments.length > 1 ? arguments[1] : undefined; 22484 22485 if (typeof options === 'function') { 22486 callback = options; 22487 options = {}; 22488 } 22489 22490 this.options = _objectSpread( 22491 {}, 22492 get(), 22493 this.options, 22494 transformOptions(options) 22495 ); 22496 this.format = this.options.interpolation.format; 22497 if (!callback) callback = noop; 22498 22499 function createClassOnDemand(ClassOrObject) { 22500 if (!ClassOrObject) return null; 22501 if (typeof ClassOrObject === 'function') return new ClassOrObject(); 22502 return ClassOrObject; 22503 } // init services 22504 22505 if (!this.options.isClone) { 22506 if (this.modules.logger) { 22507 baseLogger.init( 22508 createClassOnDemand(this.modules.logger), 22509 this.options 22510 ); 22511 } else { 22512 baseLogger.init(null, this.options); 22513 } 22514 22515 var lu = new LanguageUtil(this.options); 22516 this.store = new ResourceStore(this.options.resources, this.options); 22517 var s = this.services; 22518 s.logger = baseLogger; 22519 s.resourceStore = this.store; 22520 s.languageUtils = lu; 22521 s.pluralResolver = new PluralResolver(lu, { 22522 prepend: this.options.pluralSeparator, 22523 compatibilityJSON: this.options.compatibilityJSON, 22524 simplifyPluralSuffix: this.options.simplifyPluralSuffix 22525 }); 22526 s.interpolator = new Interpolator(this.options); 22527 s.utils = { 22528 hasLoadedNamespace: this.hasLoadedNamespace.bind(this) 22529 }; 22530 s.backendConnector = new Connector( 22531 createClassOnDemand(this.modules.backend), 22532 s.resourceStore, 22533 s, 22534 this.options 22535 ); // pipe events from backendConnector 22536 22537 s.backendConnector.on('*', function(event) { 22538 for ( 22539 var _len = arguments.length, 22540 args = new Array(_len > 1 ? _len - 1 : 0), 22541 _key = 1; 22542 _key < _len; 22543 _key++ 22544 ) { 22545 args[_key - 1] = arguments[_key]; 22546 } 22547 22548 _this2.emit.apply(_this2, [event].concat(args)); 22549 }); 22550 22551 if (this.modules.languageDetector) { 22552 s.languageDetector = createClassOnDemand( 22553 this.modules.languageDetector 22554 ); 22555 s.languageDetector.init(s, this.options.detection, this.options); 22556 } 22557 22558 if (this.modules.i18nFormat) { 22559 s.i18nFormat = createClassOnDemand(this.modules.i18nFormat); 22560 if (s.i18nFormat.init) s.i18nFormat.init(this); 22561 } 22562 22563 this.translator = new Translator(this.services, this.options); // pipe events from translator 22564 22565 this.translator.on('*', function(event) { 22566 for ( 22567 var _len2 = arguments.length, 22568 args = new Array(_len2 > 1 ? _len2 - 1 : 0), 22569 _key2 = 1; 22570 _key2 < _len2; 22571 _key2++ 22572 ) { 22573 args[_key2 - 1] = arguments[_key2]; 22574 } 22575 22576 _this2.emit.apply(_this2, [event].concat(args)); 22577 }); 22578 this.modules.external.forEach(function(m) { 22579 if (m.init) m.init(_this2); 22580 }); 22581 } // append api 22582 22583 var storeApi = [ 22584 'getResource', 22585 'addResource', 22586 'addResources', 22587 'addResourceBundle', 22588 'removeResourceBundle', 22589 'hasResourceBundle', 22590 'getResourceBundle', 22591 'getDataByLanguage' 22592 ]; 22593 storeApi.forEach(function(fcName) { 22594 _this2[fcName] = function() { 22595 var _this2$store; 22596 22597 return (_this2$store = _this2.store)[fcName].apply( 22598 _this2$store, 22599 arguments 22600 ); 22601 }; 22602 }); 22603 var deferred = defer(); 22604 22605 var load = function load() { 22606 _this2.changeLanguage(_this2.options.lng, function(err, t) { 22607 _this2.isInitialized = true; 22608 22609 _this2.logger.log('initialized', _this2.options); 22610 22611 _this2.emit('initialized', _this2.options); 22612 22613 deferred.resolve(t); // not rejecting on err (as err is only a loading translation failed warning) 22614 22615 callback(err, t); 22616 }); 22617 }; 22618 22619 if (this.options.resources || !this.options.initImmediate) { 22620 load(); 22621 } else { 22622 setTimeout(load, 0); 22623 } 22624 22625 return deferred; 22626 } 22627 /* eslint consistent-return: 0 */ 22628 }, 22629 { 22630 key: 'loadResources', 22631 value: function loadResources(language) { 22632 var _this3 = this; 22633 22634 var callback = 22635 arguments.length > 1 && arguments[1] !== undefined 22636 ? arguments[1] 22637 : noop; 22638 var usedCallback = callback; 22639 var usedLng = typeof language === 'string' ? language : this.language; 22640 if (typeof language === 'function') usedCallback = language; 22641 22642 if (!this.options.resources || this.options.partialBundledLanguages) { 22643 if (usedLng && usedLng.toLowerCase() === 'cimode') 22644 return usedCallback(); // avoid loading resources for cimode 22645 22646 var toLoad = []; 22647 22648 var append = function append(lng) { 22649 if (!lng) return; 22650 22651 var lngs = _this3.services.languageUtils.toResolveHierarchy(lng); 22652 22653 lngs.forEach(function(l) { 22654 if (toLoad.indexOf(l) < 0) toLoad.push(l); 22655 }); 22656 }; 22657 22658 if (!usedLng) { 22659 // at least load fallbacks in this case 22660 var fallbacks = this.services.languageUtils.getFallbackCodes( 22661 this.options.fallbackLng 22662 ); 22663 fallbacks.forEach(function(l) { 22664 return append(l); 22665 }); 22666 } else { 22667 append(usedLng); 22668 } 22669 22670 if (this.options.preload) { 22671 this.options.preload.forEach(function(l) { 22672 return append(l); 22673 }); 22674 } 22675 22676 this.services.backendConnector.load( 22677 toLoad, 22678 this.options.ns, 22679 usedCallback 22680 ); 22681 } else { 22682 usedCallback(null); 22683 } 22684 } 22685 }, 22686 { 22687 key: 'reloadResources', 22688 value: function reloadResources(lngs, ns, callback) { 22689 var deferred = defer(); 22690 if (!lngs) lngs = this.languages; 22691 if (!ns) ns = this.options.ns; 22692 if (!callback) callback = noop; 22693 this.services.backendConnector.reload(lngs, ns, function(err) { 22694 deferred.resolve(); // not rejecting on err (as err is only a loading translation failed warning) 22695 22696 callback(err); 22697 }); 22698 return deferred; 22699 } 22700 }, 22701 { 22702 key: 'use', 22703 value: function use(module) { 22704 if (module.type === 'backend') { 22705 this.modules.backend = module; 22706 } 22707 22708 if ( 22709 module.type === 'logger' || 22710 (module.log && module.warn && module.error) 22711 ) { 22712 this.modules.logger = module; 22713 } 22714 22715 if (module.type === 'languageDetector') { 22716 this.modules.languageDetector = module; 22717 } 22718 22719 if (module.type === 'i18nFormat') { 22720 this.modules.i18nFormat = module; 22721 } 22722 22723 if (module.type === 'postProcessor') { 22724 postProcessor.addPostProcessor(module); 22725 } 22726 22727 if (module.type === '3rdParty') { 22728 this.modules.external.push(module); 22729 } 22730 22731 return this; 22732 } 22733 }, 22734 { 22735 key: 'changeLanguage', 22736 value: function changeLanguage(lng, callback) { 22737 var _this4 = this; 22738 22739 this.isLanguageChangingTo = lng; 22740 var deferred = defer(); 22741 this.emit('languageChanging', lng); 22742 22743 var done = function done(err, l) { 22744 if (l) { 22745 _this4.language = l; 22746 _this4.languages = _this4.services.languageUtils.toResolveHierarchy( 22747 l 22748 ); 22749 22750 _this4.translator.changeLanguage(l); 22751 22752 _this4.isLanguageChangingTo = undefined; 22753 22754 _this4.emit('languageChanged', l); 22755 22756 _this4.logger.log('languageChanged', l); 22757 } else { 22758 _this4.isLanguageChangingTo = undefined; 22759 } 22760 22761 deferred.resolve(function() { 22762 return _this4.t.apply(_this4, arguments); 22763 }); 22764 if (callback) 22765 callback(err, function() { 22766 return _this4.t.apply(_this4, arguments); 22767 }); 22768 }; 22769 22770 var setLng = function setLng(l) { 22771 if (l) { 22772 if (!_this4.language) { 22773 _this4.language = l; 22774 _this4.languages = _this4.services.languageUtils.toResolveHierarchy( 22775 l 22776 ); 22777 } 22778 22779 if (!_this4.translator.language) 22780 _this4.translator.changeLanguage(l); 22781 if (_this4.services.languageDetector) 22782 _this4.services.languageDetector.cacheUserLanguage(l); 22783 } 22784 22785 _this4.loadResources(l, function(err) { 22786 done(err, l); 22787 }); 22788 }; 22789 22790 if ( 22791 !lng && 22792 this.services.languageDetector && 22793 !this.services.languageDetector.async 22794 ) { 22795 setLng(this.services.languageDetector.detect()); 22796 } else if ( 22797 !lng && 22798 this.services.languageDetector && 22799 this.services.languageDetector.async 22800 ) { 22801 this.services.languageDetector.detect(setLng); 22802 } else { 22803 setLng(lng); 22804 } 22805 22806 return deferred; 22807 } 22808 }, 22809 { 22810 key: 'getFixedT', 22811 value: function getFixedT(lng, ns) { 22812 var _this5 = this; 22813 22814 var fixedT = function fixedT(key, opts) { 22815 var options; 22816 22817 if (_typeof(opts) !== 'object') { 22818 for ( 22819 var _len3 = arguments.length, 22820 rest = new Array(_len3 > 2 ? _len3 - 2 : 0), 22821 _key3 = 2; 22822 _key3 < _len3; 22823 _key3++ 22824 ) { 22825 rest[_key3 - 2] = arguments[_key3]; 22826 } 22827 22828 options = _this5.options.overloadTranslationOptionHandler( 22829 [key, opts].concat(rest) 22830 ); 22831 } else { 22832 options = _objectSpread({}, opts); 22833 } 22834 22835 options.lng = options.lng || fixedT.lng; 22836 options.lngs = options.lngs || fixedT.lngs; 22837 options.ns = options.ns || fixedT.ns; 22838 return _this5.t(key, options); 22839 }; 22840 22841 if (typeof lng === 'string') { 22842 fixedT.lng = lng; 22843 } else { 22844 fixedT.lngs = lng; 22845 } 22846 22847 fixedT.ns = ns; 22848 return fixedT; 22849 } 22850 }, 22851 { 22852 key: 't', 22853 value: function t() { 22854 var _this$translator; 22855 22856 return ( 22857 this.translator && 22858 (_this$translator = this.translator).translate.apply( 22859 _this$translator, 22860 arguments 22861 ) 22862 ); 22863 } 22864 }, 22865 { 22866 key: 'exists', 22867 value: function exists() { 22868 var _this$translator2; 22869 22870 return ( 22871 this.translator && 22872 (_this$translator2 = this.translator).exists.apply( 22873 _this$translator2, 22874 arguments 22875 ) 22876 ); 22877 } 22878 }, 22879 { 22880 key: 'setDefaultNamespace', 22881 value: function setDefaultNamespace(ns) { 22882 this.options.defaultNS = ns; 22883 } 22884 }, 22885 { 22886 key: 'hasLoadedNamespace', 22887 value: function hasLoadedNamespace(ns) { 22888 var _this6 = this; 22889 22890 if (!this.isInitialized) { 22891 this.logger.warn( 22892 'hasLoadedNamespace: i18next was not initialized', 22893 this.languages 22894 ); 22895 return false;
vendor: 5,423 bytes, lines 22896-23045
22896 } 22897 22898 if (!this.languages || !this.languages.length) { 22899 this.logger.warn( 22900 'hasLoadedNamespace: i18n.languages were undefined or empty', 22901 this.languages 22902 ); 22903 return false; 22904 } 22905 22906 var lng = this.languages[0]; 22907 var fallbackLng = this.options ? this.options.fallbackLng : false; 22908 var lastLng = this.languages[this.languages.length - 1]; // we're in cimode so this shall pass 22909 22910 if (lng.toLowerCase() === 'cimode') return true; 22911 22912 var loadNotPending = function loadNotPending(l, n) { 22913 var loadState = 22914 _this6.services.backendConnector.state[''.concat(l, '|').concat(n)]; 22915 22916 return loadState === -1 || loadState === 2; 22917 }; // loaded -> SUCCESS 22918 22919 if (this.hasResourceBundle(lng, ns)) return true; // were not loading at all -> SEMI SUCCESS 22920 22921 if (!this.services.backendConnector.backend) return true; // failed loading ns - but at least fallback is not pending -> SEMI SUCCESS 22922 22923 if ( 22924 loadNotPending(lng, ns) && 22925 (!fallbackLng || loadNotPending(lastLng, ns)) 22926 ) 22927 return true; 22928 return false; 22929 } 22930 }, 22931 { 22932 key: 'loadNamespaces', 22933 value: function loadNamespaces(ns, callback) { 22934 var _this7 = this; 22935 22936 var deferred = defer(); 22937 22938 if (!this.options.ns) { 22939 callback && callback(); 22940 return Promise.resolve(); 22941 } 22942 22943 if (typeof ns === 'string') ns = [ns]; 22944 ns.forEach(function(n) { 22945 if (_this7.options.ns.indexOf(n) < 0) _this7.options.ns.push(n); 22946 }); 22947 this.loadResources(function(err) { 22948 deferred.resolve(); 22949 if (callback) callback(err); 22950 }); 22951 return deferred; 22952 } 22953 }, 22954 { 22955 key: 'loadLanguages', 22956 value: function loadLanguages(lngs, callback) { 22957 var deferred = defer(); 22958 if (typeof lngs === 'string') lngs = [lngs]; 22959 var preloaded = this.options.preload || []; 22960 var newLngs = lngs.filter(function(lng) { 22961 return preloaded.indexOf(lng) < 0; 22962 }); // Exit early if all given languages are already preloaded 22963 22964 if (!newLngs.length) { 22965 if (callback) callback(); 22966 return Promise.resolve(); 22967 } 22968 22969 this.options.preload = preloaded.concat(newLngs); 22970 this.loadResources(function(err) { 22971 deferred.resolve(); 22972 if (callback) callback(err); 22973 }); 22974 return deferred; 22975 } 22976 }, 22977 { 22978 key: 'dir', 22979 value: function dir(lng) { 22980 if (!lng) 22981 lng = 22982 this.languages && this.languages.length > 0 22983 ? this.languages[0] 22984 : this.language; 22985 if (!lng) return 'rtl'; 22986 var rtlLngs = [ 22987 'ar', 22988 'shu', 22989 'sqr', 22990 'ssh', 22991 'xaa', 22992 'yhd', 22993 'yud', 22994 'aao', 22995 'abh', 22996 'abv', 22997 'acm', 22998 'acq', 22999 'acw', 23000 'acx', 23001 'acy', 23002 'adf', 23003 'ads', 23004 'aeb', 23005 'aec', 23006 'afb', 23007 'ajp', 23008 'apc', 23009 'apd', 23010 'arb', 23011 'arq', 23012 'ars', 23013 'ary', 23014 'arz', 23015 'auz', 23016 'avl', 23017 'ayh', 23018 'ayl', 23019 'ayn', 23020 'ayp', 23021 'bbz', 23022 'pga', 23023 'he', 23024 'iw', 23025 'ps', 23026 'pbt', 23027 'pbu', 23028 'pst', 23029 'prp', 23030 'prd', 23031 'ur', 23032 'ydd', 23033 'yds', 23034 'yih', 23035 'ji', 23036 'yi', 23037 'hbo', 23038 'men', 23039 'xmn', 23040 'fa', 23041 'jpr', 23042 'peo', 23043 'pes', 23044 'prs', 23045 'dv',
23046 'sam' 23047 ]; 23048 return rtlLngs.indexOf( 23049 this.services.languageUtils.getLanguagePartFromCode(lng) 23050 ) >= 0 23051 ? 'rtl' 23052 : 'ltr'; 23053 } 23054 /* eslint class-methods-use-this: 0 */ 23055 }, 23056 { 23057 key: 'createInstance', 23058 value: function createInstance() { 23059 var options = 23060 arguments.length > 0 && arguments[0] !== undefined 23061 ? arguments[0] 23062 : {}; 23063 var callback = arguments.length > 1 ? arguments[1] : undefined; 23064 return new I18n(options, callback); 23065 } 23066 }, 23067 { 23068 key: 'cloneInstance', 23069 value: function cloneInstance() { 23070 var _this8 = this; 23071 23072 var options = 23073 arguments.length > 0 && arguments[0] !== undefined 23074 ? arguments[0] 23075 : {}; 23076 var callback = 23077 arguments.length > 1 && arguments[1] !== undefined 23078 ? arguments[1] 23079 : noop; 23080 23081 var mergedOptions = _objectSpread({}, this.options, options, { 23082 isClone: true 23083 }); 23084 23085 var clone = new I18n(mergedOptions); 23086 var membersToCopy = ['store', 'services', 'language']; 23087 membersToCopy.forEach(function(m) { 23088 clone[m] = _this8[m]; 23089 }); 23090 clone.translator = new Translator(clone.services, clone.options); 23091 clone.translator.on('*', function(event) { 23092 for ( 23093 var _len4 = arguments.length, 23094 args = new Array(_len4 > 1 ? _len4 - 1 : 0), 23095 _key4 = 1; 23096 _key4 < _len4; 23097 _key4++ 23098 ) { 23099 args[_key4 - 1] = arguments[_key4]; 23100 } 23101 23102 clone.emit.apply(clone, [event].concat(args)); 23103 }); 23104 clone.init(mergedOptions, callback); 23105 clone.translator.options = clone.options; // sync options 23106 23107 return clone; 23108 } 23109 } 23110 ]); 23111 23112 return I18n; 23113 })(EventEmitter); 23114 23115 var i18next = new I18n(); 23116 23117 module.exports = i18next; 23118 }, 23119 { 23120 '@babel/runtime/helpers/assertThisInitialized': 4, 23121 '@babel/runtime/helpers/classCallCheck': 5, 23122 '@babel/runtime/helpers/createClass': 6, 23123 '@babel/runtime/helpers/getPrototypeOf': 8, 23124 '@babel/runtime/helpers/inherits': 9, 23125 '@babel/runtime/helpers/objectSpread': 14, 23126 '@babel/runtime/helpers/possibleConstructorReturn': 15, 23127 '@babel/runtime/helpers/slicedToArray': 17, 23128 '@babel/runtime/helpers/toConsumableArray': 18, 23129 '@babel/runtime/helpers/typeof': 19 23130 } 23131 ], 23132 31: [ 23133 function(_dereq_, module, exports) { 23134 exports.read = function(buffer, offset, isLE, mLen, nBytes) { 23135 var e, m; 23136 var eLen = nBytes * 8 - mLen - 1; 23137 var eMax = (1 << eLen) - 1; 23138 var eBias = eMax >> 1; 23139 var nBits = -7; 23140 var i = isLE ? nBytes - 1 : 0; 23141 var d = isLE ? -1 : 1; 23142 var s = buffer[offset + i]; 23143 23144 i += d; 23145 23146 e = s & ((1 << -nBits) - 1); 23147 s >>= -nBits; 23148 nBits += eLen; 23149 for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {} 23150 23151 m = e & ((1 << -nBits) - 1); 23152 e >>= -nBits; 23153 nBits += mLen; 23154 for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {} 23155 23156 if (e === 0) { 23157 e = 1 - eBias; 23158 } else if (e === eMax) { 23159 return m ? NaN : (s ? -1 : 1) * Infinity; 23160 } else { 23161 m = m + Math.pow(2, mLen); 23162 e = e - eBias; 23163 } 23164 return (s ? -1 : 1) * m * Math.pow(2, e - mLen); 23165 }; 23166 23167 exports.write = function(buffer, value, offset, isLE, mLen, nBytes) { 23168 var e, m, c; 23169 var eLen = nBytes * 8 - mLen - 1; 23170 var eMax = (1 << eLen) - 1; 23171 var eBias = eMax >> 1; 23172 var rt = mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0; 23173 var i = isLE ? 0 : nBytes - 1; 23174 var d = isLE ? 1 : -1; 23175 var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0; 23176 23177 value = Math.abs(value); 23178 23179 if (isNaN(value) || value === Infinity) { 23180 m = isNaN(value) ? 1 : 0; 23181 e = eMax; 23182 } else { 23183 e = Math.floor(Math.log(value) / Math.LN2); 23184 if (value * (c = Math.pow(2, -e)) < 1) { 23185 e--; 23186 c *= 2; 23187 } 23188 if (e + eBias >= 1) { 23189 value += rt / c; 23190 } else { 23191 value += rt * Math.pow(2, 1 - eBias); 23192 } 23193 if (value * c >= 2) { 23194 e++; 23195 c /= 2; 23196 } 23197 23198 if (e + eBias >= eMax) { 23199 m = 0; 23200 e = eMax; 23201 } else if (e + eBias >= 1) { 23202 m = (value * c - 1) * Math.pow(2, mLen); 23203 e = e + eBias; 23204 } else { 23205 m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen); 23206 e = 0; 23207 } 23208 } 23209 23210 for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {} 23211 23212 e = (e << mLen) | m; 23213 eLen += mLen; 23214 for (; eLen > 0;
23214 buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {} 23215 23216 buffer[offset + i - d] |= s * 128; 23217 }; 23218 }, 23219 {} 23220 ], 23221 32: [ 23222 function(_dereq_, module, exports) { 23223 /* 23224 23225 Copyright 2000, Silicon Graphics, Inc. All Rights Reserved. 23226 Copyright 2015, Google Inc. All Rights Reserved. 23227 23228 Permission is hereby granted, free of charge, to any person obtaining a copy 23229 of this software and associated documentation files (the "Software"), to 23230 deal in the Software without restriction, including without limitation the 23231 rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 23232 sell copies of the Software, and to permit persons to whom the Software is 23233 furnished to do so, subject to the following conditions: 23234 23235 The above copyright notice including the dates of first publication and 23236 either this permission notice or a reference to http://oss.sgi.com/projects/FreeB/ 23237 shall be included in all copies or substantial portions of the Software. 23238 23239 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23240 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23241 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 23242 SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23243 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 23244 IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23245 23246 Original Code. The Original Code is: OpenGL Sample Implementation, 23247 Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, 23248 Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. 23249 Copyright in any portions created by third parties is as indicated 23250 elsewhere herein. All Rights Reserved. 23251*/ 23252 'use strict'; 23253 var n; 23254 function t(a, b) { 23255 return a.b === b.b && a.a === b.a; 23256 } 23257 function u(a, b) { 23258 return a.b < b.b || (a.b === b.b && a.a <= b.a); 23259 } 23260 function v(a, b, c) { 23261 var d = b.b - a.b, 23262 e = c.b - b.b; 23263 return 0 < d + e 23264 ? d < e 23265 ? b.a - a.a + d / (d + e) * (a.a - c.a) 23266 : b.a - c.a + e / (d + e) * (c.a - a.a) 23267 : 0; 23268 } 23269 function x(a, b, c) { 23270 var d = b.b - a.b, 23271 e = c.b - b.b; 23272 return 0 < d + e ? (b.a - c.a) * d + (b.a - a.a) * e : 0; 23273 } 23274 function z(a, b) { 23275 return a.a < b.a || (a.a === b.a && a.b <= b.b); 23276 } 23277 function aa(a, b, c) { 23278 var d = b.a - a.a, 23279 e = c.a - b.a; 23280 return 0 < d + e 23281 ? d < e 23282 ? b.b - a.b + d / (d + e) * (a.b - c.b) 23283 : b.b - c.b + e / (d + e) * (c.b - a.b) 23284 : 0; 23285 } 23286 function ba(a, b, c) { 23287 var d = b.a - a.a, 23288 e = c.a - b.a; 23289 return 0 < d + e ? (b.b - c.b) * d + (b.b - a.b) * e : 0; 23290 } 23291 function ca(a) { 23292 return u(a.b.a, a.a); 23293 } 23294 function da(a) { 23295 return u(a.a, a.b.a); 23296 } 23297 function A(a, b, c, d) { 23298 a = 0 > a ? 0 : a; 23299 c = 0 > c ? 0 : c; 23300 return a <= c 23301 ? 0 === c ? (b + d) / 2 : b + a / (a + c) * (d - b) 23302 : d + c / (a + c) * (b - d); 23303 } 23304 function ea(a) { 23305 var b = B(a.b); 23306 C(b, a.c); 23307 C(b.b, a.c); 23308 D(b, a.a); 23309 return b; 23310 } 23311 function E(a, b) { 23312 var c = !1, 23313 d = !1; 23314 a !== b && 23315 (b.a !== a.a && ((d = !0), F(b.a, a.a)), 23316 b.d !== a.d && ((c = !0), G(b.d, a.d)), 23317 H(b, a), 23318 d || (C(b, a.a), (a.a.c = a)), 23319 c || (D(b, a.d), (a.d.a = a))); 23320 } 23321 function I(a) { 23322 var b = a.b, 23323 c = !1; 23324 a.d !== a.b.d && ((c = !0), G(a.d, a.b.d)); 23325 a.c === a 23326 ? F(a.a, null)
23327 : ((a.b.d.a = J(a)), (a.a.c = a.c), H(a, J(a)), c || D(a, a.d)); 23328 b.c === b 23329 ? (F(b.a, null), G(b.d, null)) 23330 : ((a.d.a = J(b)), (b.a.c = b.c), H(b, J(b))); 23331 fa(a); 23332 } 23333 function K(a) { 23334 var b = B(a), 23335 c = b.b; 23336 H(b, a.e); 23337 b.a = a.b.a; 23338 C(c, b.a); 23339 b.d = c.d = a.d; 23340 b = b.b; 23341 H(a.b, J(a.b)); 23342 H(a.b, b); 23343 a.b.a = b.a; 23344 b.b.a.c = b.b; 23345 b.b.d = a.b.d; 23346 b.f = a.f; 23347 b.b.f = a.b.f; 23348 return b; 23349 } 23350 function L(a, b) { 23351 var c = !1, 23352 d = B(a), 23353 e = d.b; 23354 b.d !== a.d && ((c = !0), G(b.d, a.d)); 23355 H(d, a.e); 23356 H(e, b); 23357 d.a = a.b.a; 23358 e.a = b.a; 23359 d.d = e.d = a.d; 23360 a.d.a = e; 23361 c || D(d, a.d); 23362 return d; 23363 } 23364 function B(a) { 23365 var b = new M(), 23366 c = new M(), 23367 d = a.b.h; 23368 c.h = d; 23369 d.b.h = b; 23370 b.h = a; 23371 a.b.h = c; 23372 b.b = c; 23373 b.c = b; 23374 b.e = c; 23375 c.b = b; 23376 c.c = c; 23377 return (c.e = b); 23378 } 23379 function H(a, b) { 23380 var c = a.c, 23381 d = b.c; 23382 c.b.e = b; 23383 d.b.e = a; 23384 a.c = d; 23385 b.c = c; 23386 } 23387 function C(a, b) { 23388 var c = b.f, 23389 d = new N(b, c); 23390 c.e = d; 23391 b.f = d; 23392 c = d.c = a; 23393 do (c.a = d), (c = c.c); 23394 while (c !== a); 23395 } 23396 function D(a, b) { 23397 var c = b.d, 23398 d = new ga(b, c); 23399 c.b = d; 23400 b.d = d; 23401 d.a = a; 23402 d.c = b.c; 23403 c = a; 23404 do (c.d = d), (c = c.e); 23405 while (c !== a); 23406 } 23407 function fa(a) { 23408 var b = a.h; 23409 a = a.b.h; 23410 b.b.h = a; 23411 a.b.h = b; 23412 } 23413 function F(a, b) { 23414 var c = a.c, 23415 d = c; 23416 do (d.a = b), (d = d.c); 23417 while (d !== c); 23418 c = a.f; 23419 d = a.e; 23420 d.f = c; 23421 c.e = d; 23422 } 23423 function G(a, b) { 23424 var c = a.a, 23425 d = c; 23426 do (d.d = b), (d = d.e); 23427 while (d !== c); 23428 c = a.d; 23429 d = a.b; 23430 d.d = c; 23431 c.b = d; 23432 } 23433 function ha(a) { 23434 var b = 0; 23435 Math.abs(a[1]) > Math.abs(a[0]) && (b = 1); 23436 Math.abs(a[2]) > Math.abs(a[b]) && (b = 2); 23437 return b; 23438 } 23439 var O = 4 * 1e150; 23440 function P(a, b) { 23441 a.f += b.f; 23442 a.b.f += b.b.f; 23443 } 23444 function ia(a, b, c) { 23445 a = a.a; 23446 b = b.a; 23447 c = c.a; 23448 if (b.b.a === a) 23449 return c.b.a === a 23450 ? u(b.a, c.a) ? 0 >= x(c.b.a, b.a, c.a) : 0 <= x(b.b.a, c.a, b.a) 23451 : 0 >= x(c.b.a, a, c.a); 23452 if (c.b.a === a) return 0 <= x(b.b.a, a, b.a); 23453 b = v(b.b.a, a, b.a); 23454 a = v(c.b.a, a, c.a); 23455 return b >= a; 23456 } 23457 function Q(a) { 23458 a.a.i = null; 23459 var b = a.e; 23460 b.a.c = b.c; 23461 b.c.a = b.a; 23462 a.e = null; 23463 } 23464 function ja(a, b) { 23465 I(a.a); 23466 a.c = !1; 23467 a.a = b; 23468 b.i = a; 23469 } 23470 function ka(a) { 23471 var b = a.a.a; 23472 do a = R(a); 23473 while (a.a.a === b); 23474 a.c && ((b = L(S(a).a.b, a.a.e)), ja(a, b), (a = R(a))); 23475 return a; 23476 } 23477 function la(a, b, c) { 23478 var d = new ma(); 23479 d.a = c; 23480 d.e = na(a.f, b.e, d); 23481 return (c.i = d); 23482 } 23483 function oa(a, b) { 23484 switch (a.s) { 23485 case 100130: 23486 return 0 !== (b & 1); 23487 case 100131: 23488 return 0 !== b; 23489 case 100132: 23490 return 0 < b; 23491 case 100133: 23492 return 0 > b; 23493 case 100134: 23494 return 2 <= b || -2 >= b; 23495 } 23496 return !1; 23497 } 23498 function pa(a) { 23499 var b = a.a, 23500 c = b.d; 23501 c.c = a.d; 23502 c.a = b; 23503 Q(a); 23504 } 23505 function T(a, b, c) { 23506 a = b; 23507 for (b = b.a; a !== c; ) { 23508 a.c = !1; 23509 var d = S(a), 23510 e = d.a; 23511 if (e.a !== b.a) { 23512 if (!d.c) { 23513 pa(a); 23514 break; 23515 } 23516 e = L(b.c.b, e.b); 23517 ja(d, e); 23518 } 23519 b.c !== e && (E(J(e), e), E(b, e)); 23520 pa(a); 23521 b = d.a; 23522 a = d; 23523 } 23524 return b; 23525 } 23526 function U(a, b, c, d, e, f) { 23527 var g = !0; 23528 do la(a, b, c.b), (c = c.c); 23529 while (c !== d); 23530 for (null === e && (e = S(b).a.b.c); ; ) { 23531 d = S(b); 23532 c = d.a.b; 23533 if (c.a !== e.a) break; 23534 c.c !== e && (E(J(c), c), E(J(e), c)); 23535 d.f = b.f - c.f; 23536 d.d = oa(a, d.f); 23537 b.b = !0; 23538 !g && qa(a, b) && (P(c, e), Q(b), I(e)); 23539 g = !1; 23540 b = d; 23541 e = c; 23542 } 23543 b.b = !0; 23544 f && ra(a, b); 23545 } 23546 function sa(a, b, c, d, e) { 23547 var f = [b.g[0], b.g[1], b.g[2]]; 23548 b.d = null; 23549 b.d = a.o ? a.o(f, c, d, a.c) || null : null; 23550 null === b.d && (e ? a.n || (V(a, 100156), (a.n = !0)) : (b.d = c[0])); 23551 } 23552 function ta(a, b, c) { 23553 var d = [null, null, null, null]; 23554 d[0] = b.a.d; 23555 d[1] = c.a.d; 23556 sa(a, b.a, d, [0.5, 0.5, 0, 0], !1); 23557 E(b, c); 23558 } 23559 function ua(a, b, c, d, e) { 23560 var f = Math.abs(b.b - a.b) + Math.abs(b.a - a.a), 23561 g = Math.abs(c.b - a.b) + Math.abs(c.a - a.a), 23562 h = e + 1; 23563 d[e] = 0.5 * g / (f + g); 23564 d[h] = 0.5 * f / (f + g); 23565 a.g[0] += d[e] * b.g[0] + d[h] * c.g[0]; 23566 a.g[1] += d[e] * b.g[1] + d[h] * c.g[1]; 23567 a.g[2] += d[e] * b.g[2] + d[h] * c.g[2]; 23568 } 23569 function qa(a, b) { 23570 var c = S(b), 23571 d = b.a, 23572 e = c.a; 23573 if (u(d.a, e.a)) { 23574 if (0 < x(e.b.a, d.a, e.a)) return !1; 23575 if (!t(d.a, e.a)) K(e.b), E(d, J(e)), (b.b = c.b = !0); 23576 else if (d.a !== e.a) { 23577 var c = a.e, 23578 f = d.a.h; 23579 if (0 <= f) { 23580 var c = c.b, 23581 g = c.d, 23582 h = c.e, 23583 k = c.c, 23584 l = k[f]; 23585 g[l] = g[c.a]; 23586 k[g[l]] = l; 23587 l <= --c.a && 23588 (1 >= l ? W(c, l) : u(h[g[l >> 1]], h[g[l]]) ? W(c, l) : va(c, l)); 23589 h[f] = null; 23590 k[f] = c.b; 23591 c.b = f; 23592 } else 23593 for (c.c[-(f + 1)] = null; 0 < c.a && null === c.c[c.d[c.a - 1]]; ) --c.a; 23594 ta(a, J(e), d); 23595 } 23596 } else { 23597 if (0 > x(d.b.a, e.a, d.a)) return !1; 23598 R(b).b = b.b = !0; 23599 K(d.b); 23600 E(J(e), d); 23601 } 23602 return !0; 23603 } 23604 function wa(a, b) { 23605 var c = S(b), 23606 d = b.a, 23607 e = c.a, 23608 f = d.a, 23609 g = e.a, 23610 h = d.b.a, 23611 k = e.b.a,
23612 l = new N(); 23613 x(h, a.a, f); 23614 x(k, a.a, g); 23615 if (f === g || Math.min(f.a, h.a) > Math.max(g.a, k.a)) return !1; 23616 if (u(f, g)) { 23617 if (0 < x(k, f, g)) return !1; 23618 } else if (0 > x(h, g, f)) return !1; 23619 var r = h, 23620 p = f, 23621 q = k, 23622 y = g, 23623 m, 23624 w; 23625 u(r, p) || ((m = r), (r = p), (p = m)); 23626 u(q, y) || ((m = q), (q = y), (y = m)); 23627 u(r, q) || ((m = r), (r = q), (q = m), (m = p), (p = y), (y = m)); 23628 u(q, p) 23629 ? u(p, y) 23630 ? ((m = v(r, q, p)), 23631 (w = v(q, p, y)), 23632 0 > m + w && ((m = -m), (w = -w)), 23633 (l.b = A(m, q.b, w, p.b))) 23634 : ((m = x(r, q, p)), 23635 (w = -x(r, y, p)), 23636 0 > m + w && ((m = -m), (w = -w)), 23637 (l.b = A(m, q.b, w, y.b))) 23638 : (l.b = (q.b + p.b) / 2); 23639 z(r, p) || ((m = r), (r = p), (p = m)); 23640 z(q, y) || ((m = q), (q = y), (y = m)); 23641 z(r, q) || ((m = r), (r = q), (q = m), (m = p), (p = y), (y = m)); 23642 z(q, p) 23643 ? z(p, y) 23644 ? ((m = aa(r, q, p)), 23645 (w = aa(q, p, y)), 23646 0 > m + w && ((m = -m), (w = -w)), 23647 (l.a = A(m, q.a, w, p.a))) 23648 : ((m = ba(r, q, p)), 23649 (w = -ba(r, y, p)), 23650 0 > m + w && ((m = -m), (w = -w)), 23651 (l.a = A(m, q.a, w, y.a))) 23652 : (l.a = (q.a + p.a) / 2); 23653 u(l, a.a) && ((l.b = a.a.b), (l.a = a.a.a)); 23654 r = u(f, g) ? f : g; 23655 u(r, l) && ((l.b = r.b), (l.a = r.a)); 23656 if (t(l, f) || t(l, g)) return qa(a, b), !1; 23657 if ((!t(h, a.a) && 0 <= x(h, a.a, l)) || (!t(k, a.a) && 0 >= x(k, a.a, l))) { 23658 if (k === a.a) 23659 return ( 23660 K(d.b), 23661 E(e.b, d), 23662 (b = ka(b)), 23663 (d = S(b).a), 23664 T(a, S(b), c), 23665 U(a, b, J(d), d, d, !0), 23666 !0 23667 ); 23668 if (h === a.a) { 23669 K(e.b); 23670 E(d.e, J(e)); 23671 f = c = b; 23672 g = f.a.b.a; 23673 do f = R(f); 23674 while (f.a.b.a === g); 23675 b = f; 23676 f = S(b).a.b.c; 23677 c.a = J(e); 23678 e = T(a, c, null); 23679 U(a, b, e.c, d.b.c, f, !0); 23680 return !0; 23681 } 23682 0 <= x(h, a.a, l) && 23683 ((R(b).b = b.b = !0), K(d.b), (d.a.b = a.a.b), (d.a.a = a.a.a)); 23684 0 >= x(k, a.a, l) && 23685 ((b.b = c.b = !0), K(e.b), (e.a.b = a.a.b), (e.a.a = a.a.a)); 23686 return !1; 23687 } 23688 K(d.b); 23689 K(e.b); 23690 E(J(e), d); 23691 d.a.b = l.b; 23692 d.a.a = l.a; 23693 d.a.h = xa(a.e, d.a); 23694 d = d.a; 23695 e = [0, 0, 0, 0]; 23696 l = [f.d, h.d, g.d, k.d]; 23697 d.g[0] = d.g[1] = d.g[2] = 0; 23698 ua(d, f, h, e, 0); 23699 ua(d, g, k, e, 2); 23700 sa(a, d, l, e, !0); 23701 R(b).b = b.b = c.b = !0; 23702 return !1; 23703 } 23704 function ra(a, b) { 23705 for (var c = S(b); ; ) { 23706 for (; c.b; ) (b = c), (c = S(c)); 23707 if (!b.b && ((c = b), (b = R(b)), null === b || !b.b)) break; 23708 b.b = !1; 23709 var d = b.a, 23710 e = c.a, 23711 f; 23712 if ((f = d.b.a !== e.b.a)) 23713 a: { 23714 f = b; 23715 var g = S(f), 23716 h = f.a, 23717 k = g.a, 23718 l = void 0; 23719 if (u(h.b.a, k.b.a)) { 23720 if (0 > x(h.b.a, k.b.a, h.a)) { 23721 f = !1; 23722 break a; 23723 } 23724 R(f).b = f.b = !0; 23725 l = K(h); 23726 E(k.b, l); 23727 l.d.c = f.d; 23728 } else { 23729 if (0 < x(k.b.a, h.b.a, k.a)) { 23730 f = !1; 23731 break a; 23732 } 23733 f.b = g.b = !0; 23734 l = K(k); 23735 E(h.e, k.b); 23736 l.b.d.c = f.d; 23737 } 23738 f = !0; 23739 } 23740 f && 23741 (c.c 23742 ? (Q(c), I(e), (c = S(b)), (e = c.a)) 23743 : b.c && (Q(b), I(d), (b = R(c)), (d = b.a))); 23744 if (d.a !== e.a) 23745 if (d.b.a === e.b.a || b.c || c.c || (d.b.a !== a.a && e.b.a !== a.a)) 23746 qa(a, b); 23747 else if (wa(a, b)) break; 23748 d.a === e.a && d.b.a === e.b.a && (P(e, d), Q(b), I(d), (b = R(c))); 23749 } 23750 } 23751 function ya(a, b) { 23752 a.a = b; 23753 for (var c = b.c; null === c.i; ) 23754 if (((c = c.c), c === b.c)) { 23755 var c = a, 23756 d = b, 23757 e = new ma(); 23758 e.a = d.c.b; 23759 var f = c.f, 23760 g = f.a; 23761 do g = g.a; 23762 while (null !== g.b && !f.c(f.b, e, g.b)); 23763 var f = g.b, 23764 h = S(f), 23765 e = f.a, 23766 g = h.a; 23767 if (0 === x(e.b.a, d, e.a)) 23768 (e = f.a), 23769 t(e.a, d) || 23770 t(e.b.a, d) || 23771 (K(e.b), f.c && (I(e.c), (f.c = !1)), E(d.c, e), ya(c, d)); 23772 else { 23773 var k = u(g.b.a, e.b.a) ? f : h, 23774 h = void 0; 23775 f.d || k.c 23776 ? (k === f ? (h = L(d.c.b, e.e)) : (h = L(g.b.c.b, d.c).b), 23777 k.c 23778 ? ja(k, h) 23779 : ((e = c), 23780 (f = la(c, f, h)), 23781 (f.f = R(f).f + f.a.f), 23782 (f.d = oa(e, f.f))), 23783 ya(c, d)) 23784 : U(c, f, d.c, d.c, null, !0); 23785 } 23786 return; 23787 } 23788 c = ka(c.i); 23789 e = S(c); 23790 f = e.a; 23791 e = T(a, e, null); 23792 if (e.c === f) { 23793 var f = e, 23794 e = f.c, 23795 g = S(c), 23796 h = c.a, 23797 k = g.a, 23798 l = !1; 23799 h.b.a !== k.b.a && wa(a, c); 23800 t(h.a, a.a) && 23801 (E(J(e), h), (c = ka(c)), (e = S(c).a), T(a, S(c), g), (l = !0)); 23802 t(k.a, a.a) && (E(f, J(k)), (f = T(a, g, null)), (l = !0)); 23803 l 23804 ? U(a, c, f.c, e, e, !0) 23805 : (u(k.a, h.a) ? (d = J(k)) : (d = h), 23806 (d = L(f.c.b, d)), 23807 U(a, c, d, d.c, d.c, !1), 23808 (d.b.i.c = !0), 23809 ra(a, c)); 23810 } else U(a, c, e.c, f, f, !0); 23811 } 23812 function za(a, b) { 23813 var c = new ma(), 23814 d = ea(a.b); 23815 d.a.b = O; 23816 d.a.a = b; 23817 d.b.a.b = -O; 23818 d.b.a.a = b; 23819 a.a = d.b.a; 23820 c.a = d; 23821 c.f = 0; 23822 c.d = !1; 23823 c.c = !1; 23824 c.h = !0; 23825 c.b = !1; 23826 d = a.f; 23827 d = na(d, d.a, c); 23828 c.e = d; 23829 } 23830 function Aa(a) { 23831 this.a = new Ba(); 23832 this.b = a; 23833 this.c = ia; 23834 } 23835 function na(a, b, c) { 23836 do b = b.c; 23837 while (null !== b.b && !a.c(a.b, b.b, c)); 23838 a = new Ba(c, b.a, b); 23839 b.a.c = a; 23840 return (b.a = a); 23841 } 23842 function Ba(a, b, c) { 23843 this.b = a || null; 23844 this.a = b || this; 23845 this.c = c || this; 23846 } 23847 function X() { 23848 this.d = Y; 23849 this.p = this.b = this.q = null; 23850 this.j = [0, 0, 0]; 23851 this.s = 100130; 23852 this.n = !1; 23853 this.o = this.a = this.e = this.f = null; 23854 this.m = !1; 23855 this.c = this.r = this.i = this.k = this.l = this.h = null; 23856 } 23857 var Y = 0; 23858 n = X.prototype; 23859 n.x = function() { 23860 Z(this, Y); 23861 }; 23862 n.B = function(a, b) { 23863 switch (a) { 23864 case 100142: 23865 return; 23866 case 100140: 23867 switch (b) { 23868 case 100130: 23869 case 100131: 23870 case 100132: 23871 case 100133: 23872 case 100134: 23873 this.s = b; 23874 return; 23875 } 23876 break; 23877 case 100141: 23878 this.m = !!b; 23879 return; 23880 default: 23881 V(this, 100900); 23882 return; 23883 } 23884 V(this, 100901); 23885 }; 23886 n.y = function(a) { 23887 switch (a) { 23888 case 100142: 23889 return 0; 23890 case 100140: 23891 return this.s; 23892 case 100141: 23893 return this.m; 23894 default: 23895 V(this, 100900); 23896 } 23897 return !1; 23898 }; 23899 n.A = function(a, b, c) { 23900 this.j[0] = a; 23901 this.j[1] = b; 23902 this.j[2] = c; 23903 }; 23904 n.z = function(a, b) { 23905 var c = b ? b : null; 23906 switch (a) { 23907 case 100100: 23908 case 100106: 23909 this.h = c; 23910 break; 23911 case 100104: 23912 case 100110: 23913 this.l = c; 23914 break; 23915 case 100101: 23916 case 100107: 23917 this.k = c; 23918 break; 23919 case 100102: 23920 case 100108: 23921 this.i = c; 23922 break; 23923 case 100103: 23924 case 100109: 23925 this.p = c; 23926 break; 23927 case 100105: 23928 case 100111: 23929 this.o = c; 23930 break; 23931 case 100112: 23932 this.r = c; 23933 break; 23934 default: 23935 V(this, 100900); 23936 } 23937 }; 23938 n.C = function(a, b) { 23939 var c = !1, 23940 d = [0, 0, 0]; 23941 Z(this, 2); 23942 for (var e = 0; 3 > e; ++e) { 23943 var f = a[e]; 23944 -1e150 > f && ((f = -1e150), (c = !0)); 23945 1e150 < f && ((f = 1e150), (c = !0)); 23946 d[e] = f; 23947 } 23948 c && V(this, 100155); 23949 c = this.q; 23950 null === c ? ((c = ea(this.b)), E(c, c.b)) : (K(c), (c = c.e)); 23951 c.a.d = b; 23952 c.a.g[0] = d[0]; 23953 c.a.g[1] = d[1]; 23954 c.a.g[2] = d[2]; 23955 c.f = 1; 23956 c.b.f = -1; 23957 this.q = c; 23958 }; 23959 n.u = function(a) { 23960 Z(this, Y); 23961 this.d = 1; 23962 this.b = new Ca(); 23963 this.c = a; 23964 }; 23965 n.t = function() { 23966 Z(this, 1); 23967 this.d = 2; 23968 this.q = null; 23969 }; 23970 n.v = function() { 23971 Z(this, 2); 23972 this.d = 1; 23973 }; 23974 n.w = function() { 23975 Z(this, 1); 23976 this.d = Y; 23977 var a = this.j[0], 23978 b = this.j[1], 23979 c = this.j[2], 23980 d = !1, 23981 e = [a, b, c]; 23982 if (0 === a && 0 === b && 0 === c) { 23983 for ( 23984 var b = [-2 * 1e150, -2 * 1e150, -2 * 1e150], 23985 f = [2 * 1e150, 2 * 1e150, 2 * 1e150], 23986 c = [], 23987 g = [], 23988 d = this.b.c, 23989 a = d.e; 23990 a !== d; 23991 a = a.e 23992 ) 23993 for (var h = 0; 3 > h; ++h) { 23994 var k = a.g[h]; 23995 k < f[h] && ((f[h] = k), (g[h] = a)); 23996 k > b[h] && ((b[h] = k), (c[h] = a)); 23997 } 23998 a = 0; 23999 b[1] - f[1] > b[0] - f[0] && (a = 1); 24000 b[2] - f[2] > b[a] - f[a] && (a = 2); 24001 if (f[a] >= b[a]) (e[0] = 0), (e[1] = 0), (e[2] = 1); 24002 else { 24003 b = 0; 24004 f = g[a]; 24005 c = c[a]; 24006 g = [0, 0, 0]; 24007 f = [f.g[0] - c.g[0], f.g[1] - c.g[1], f.g[2] - c.g[2]]; 24008 h = [0, 0, 0]; 24009 for (a = d.e; a !== d; a = a.e) 24010 (h[0] = a.g[0] - c.g[0]), 24011 (h[1] = a.g[1] - c.g[1]), 24012 (h[2] = a.g[2] - c.g[2]), 24013 (g[0] = f[1] * h[2] - f[2] * h[1]), 24014 (g[1] = f[2] * h[0] - f[0] * h[2]), 24015 (g[2] = f[0] * h[1] - f[1] * h[0]), 24016 (k = g[0] * g[0] + g[1] * g[1] + g[2] * g[2]), 24017 k > b && ((b = k), (e[0] = g[0]), (e[1] = g[1]), (e[2] = g[2])); 24018 0 >= b && ((e[0] = e[1] = e[2] = 0), (e[ha(f)] = 1)); 24019 } 24020 d = !0; 24021 } 24022 g = ha(e); 24023 a = this.b.c; 24024 b = (g + 1) % 3; 24025 c = (g + 2) % 3; 24026 g = 0 < e[g] ? 1 : -1; 24027 for (e = a.e; e !== a; e = e.e) (e.b = e.g[b]), (e.a = g * e.g[c]); 24028 if (d) { 24029 e = 0; 24030 d = this.b.a; 24031 for (a = d.b; a !== d; a = a.b) 24032 if (((b = a.a), !(0 >= b.f))) { 24033 do (e += (b.a.b - b.b.a.b) * (b.a.a + b.b.a.a)), (b = b.e); 24034 while (b !== a.a); 24035 } 24036 if (0 > e) for (e = this.b.c, d = e.e; d !== e; d = d.e) d.a = -d.a; 24037 } 24038 this.n = !1; 24039 e = this.b.b; 24040 for (a = e.h; a !== e; a = d) 24041 if ( 24042 ((d = a.h), 24043 (b = a.e),
24044 t(a.a, a.b.a) && a.e.e !== a && (ta(this, b, a), I(a), (a = b), (b = a.e)), 24045 b.e === a) 24046 ) { 24047 if (b !== a) { 24048 if (b === d || b === d.b) d = d.h; 24049 I(b); 24050 } 24051 if (a === d || a === d.b) d = d.h; 24052 I(a); 24053 } 24054 this.e = e = new Da(); 24055 d = this.b.c; 24056 for (a = d.e; a !== d; a = a.e) a.h = xa(e, a); 24057 Ea(e); 24058 this.f = new Aa(this); 24059 za(this, -O); 24060 for (za(this, O); null !== (e = Fa(this.e)); ) { 24061 for (;;) { 24062 a: if (((a = this.e), 0 === a.a)) d = Ga(a.b); 24063 else if ( 24064 ((d = a.c[a.d[a.a - 1]]), 0 !== a.b.a && ((a = Ga(a.b)), u(a, d))) 24065 ) { 24066 d = a; 24067 break a; 24068 } 24069 if (null === d || !t(d, e)) break; 24070 d = Fa(this.e); 24071 ta(this, e.c, d.c); 24072 } 24073 ya(this, e); 24074 } 24075 this.a = this.f.a.a.b.a.a; 24076 for (e = 0; null !== (d = this.f.a.a.b); ) d.h || ++e, Q(d); 24077 this.f = null; 24078 e = this.e; 24079 e.b = null; 24080 e.d = null; 24081 this.e = e.c = null; 24082 e = this.b; 24083 for (a = e.a.b; a !== e.a; a = d) 24084 (d = a.b), (a = a.a), a.e.e === a && (P(a.c, a), I(a)); 24085 if (!this.n) { 24086 e = this.b; 24087 if (this.m) 24088 for (a = e.b.h; a !== e.b; a = d) 24089 (d = a.h), a.b.d.c !== a.d.c ? (a.f = a.d.c ? 1 : -1) : I(a); 24090 else 24091 for (a = e.a.b; a !== e.a; a = d) 24092 if (((d = a.b), a.c)) { 24093 for (a = a.a; u(a.b.a, a.a); a = a.c.b); 24094 for (; u(a.a, a.b.a); a = a.e); 24095 b = a.c.b; 24096 for (c = void 0; a.e !== b; ) 24097 if (u(a.b.a, b.a)) { 24098 for (; b.e !== a && (ca(b.e) || 0 >= x(b.a, b.b.a, b.e.b.a)); ) 24099 (c = L(b.e, b)), (b = c.b); 24100 b = b.c.b; 24101 } else { 24102 for (; b.e !== a && (da(a.c.b) || 0 <= x(a.b.a, a.a, a.c.b.a)); ) 24103 (c = L(a, a.c.b)), (a = c.b); 24104 a = a.e; 24105 } 24106 for (; b.e.e !== a; ) (c = L(b.e, b)), (b = c.b); 24107 } 24108 if (this.h || this.i || this.k || this.l) 24109 if (this.m) 24110 for (e = this.b, d = e.a.b; d !== e.a; d = d.b) { 24111 if (d.c) { 24112 this.h && this.h(2, this.c); 24113 a = d.a; 24114 do this.k && this.k(a.a.d, this.c), (a = a.e); 24115 while (a !== d.a); 24116 this.i && this.i(this.c); 24117 } 24118 } 24119 else { 24120 e = this.b; 24121 d = !!this.l; 24122 a = !1; 24123 b = -1; 24124 for (c = e.a.d; c !== e.a; c = c.d) 24125 if (c.c) { 24126 a || (this.h && this.h(4, this.c), (a = !0)); 24127 g = c.a; 24128 do 24129 d && 24130 ((f = g.b.d.c ? 0 : 1), 24131 b !== f && ((b = f), this.l && this.l(!!b, this.c))), 24132 this.k && this.k(g.a.d, this.c), 24133 (g = g.e); 24134 while (g !== c.a); 24135 } 24136 a && this.i && this.i(this.c); 24137 } 24138 if (this.r) { 24139 e = this.b; 24140 for (a = e.a.b; a !== e.a; a = d) 24141 if (((d = a.b), !a.c)) { 24142 b = a.a; 24143 c = b.e; 24144 g = void 0; 24145 do 24146 (g = c), 24147 (c = g.e), 24148 (g.d = null), 24149 null === g.b.d && 24150 (g.c === g ? F(g.a, null) : ((g.a.c = g.c), H(g, J(g))), 24151 (f = g.b), 24152 f.c === f ? F(f.a, null) : ((f.a.c = f.c), H(f, J(f))), 24153 fa(g)); 24154 while (g !== b); 24155 b = a.d; 24156 a = a.b; 24157 a.d = b; 24158 b.b = a; 24159 } 24160 this.r(this.b); 24161 this.c = this.b = null; 24162 return; 24163 } 24164 } 24165 this.b = this.c = null; 24166 }; 24167 function Z(a, b) { 24168 if (a.d !== b) 24169 for (; a.d !== b; ) 24170 if (a.d < b) 24171 switch (a.d) { 24172 case Y: 24173 V(a, 100151); 24174 a.u(null); 24175 break; 24176 case 1: 24177 V(a, 100152), a.t(); 24178 } 24179 else 24180 switch (a.d) { 24181 case 2: 24182 V(a, 100154); 24183 a.v(); 24184 break; 24185 case 1: 24186 V(a, 100153), a.w(); 24187 } 24188 } 24189 function V(a, b) { 24190 a.p && a.p(b, a.c); 24191 } 24192 function ga(a, b) { 24193 this.b = a || this; 24194 this.d = b || this; 24195 this.a = null; 24196 this.c = !1; 24197 } 24198 function M() { 24199 this.h = this; 24200 this.i = this.d = this.a = this.e = this.c = this.b = null; 24201 this.f = 0; 24202 } 24203 function J(a) { 24204 return a.b.e; 24205 } 24206 function Ca() { 24207 this.c = new N(); 24208 this.a = new ga(); 24209 this.b = new M(); 24210 this.d = new M(); 24211 this.b.b = this.d; 24212 this.d.b = this.b; 24213 } 24214 function N(a, b) { 24215 this.e = a || this; 24216 this.f = b || this; 24217 this.d = this.c = null; 24218 this.g = [0, 0, 0]; 24219 this.h = this.a = this.b = 0; 24220 } 24221 function Da() { 24222 this.c = []; 24223 this.d = null; 24224 this.a = 0; 24225 this.e = !1; 24226 this.b = new Ha(); 24227 } 24228 function Ea(a) { 24229 a.d = []; 24230 for (var b = 0; b < a.a; b++) a.d[b] = b; 24231 a.d.sort( 24232 (function(a) { 24233 return function(b, e) { 24234 return u(a[b], a[e]) ? 1 : -1; 24235 }; 24236 })(a.c) 24237 ); 24238 a.e = !0; 24239 Ia(a.b); 24240 } 24241 function xa(a, b) { 24242 if (a.e) { 24243 var c = a.b, 24244 d = ++c.a; 24245 2 * d > c.f && ((c.f *= 2), (c.c = Ja(c.c, c.f + 1))); 24246 var e; 24247 0 === c.b ? (e = d) : ((e = c.b), (c.b = c.c[c.b])); 24248 c.e[e] = b; 24249 c.c[e] = d; 24250 c.d[d] = e; 24251 c.h && va(c, d); 24252 return e; 24253 } 24254 c = a.a++; 24255 a.c[c] = b; 24256 return -(c + 1); 24257 } 24258 function Fa(a) { 24259 if (0 === a.a) return Ka(a.b); 24260 var b = a.c[a.d[a.a - 1]]; 24261 if (0 !== a.b.a && u(Ga(a.b), b)) return Ka(a.b); 24262 do --a.a; 24263 while (0 < a.a && null === a.c[a.d[a.a - 1]]); 24264 return b; 24265 } 24266 function Ha() { 24267 this.d = Ja([0], 33); 24268 this.e = [null, null]; 24269 this.c = [0, 0]; 24270 this.a = 0; 24271 this.f = 32; 24272 this.b = 0; 24273 this.h = !1; 24274 this.d[1] = 1; 24275 } 24276 function Ja(a, b) { 24277 for (var c = Array(b), d = 0; d < a.length; d++) c[d] = a[d]; 24278 for (; d < b; d++) c[d] = 0; 24279 return c; 24280 } 24281 function Ia(a) { 24282 for (var b = a.a; 1 <= b; --b) W(a, b); 24283 a.h = !0; 24284 } 24285 function Ga(a) { 24286 return a.e[a.d[1]]; 24287 } 24288 function Ka(a) { 24289 var b = a.d, 24290 c = a.e, 24291 d = a.c, 24292 e = b[1], 24293 f = c[e]; 24294 0 < a.a && 24295 ((b[1] = b[a.a]), 24296 (d[b[1]] = 1), 24297 (c[e] = null),
24298 (d[e] = a.b), 24299 (a.b = e), 24300 0 < --a.a && W(a, 1)); 24301 return f; 24302 } 24303 function W(a, b) { 24304 for (var c = a.d, d = a.e, e = a.c, f = b, g = c[f]; ; ) { 24305 var h = f << 1; 24306 h < a.a && u(d[c[h + 1]], d[c[h]]) && (h += 1); 24307 var k = c[h]; 24308 if (h > a.a || u(d[g], d[k])) { 24309 c[f] = g; 24310 e[g] = f; 24311 break; 24312 } 24313 c[f] = k; 24314 e[k] = f; 24315 f = h; 24316 } 24317 } 24318 function va(a, b) { 24319 for (var c = a.d, d = a.e, e = a.c, f = b, g = c[f]; ; ) { 24320 var h = f >> 1, 24321 k = c[h]; 24322 if (0 === h || u(d[k], d[g])) { 24323 c[f] = g; 24324 e[g] = f; 24325 break; 24326 } 24327 c[f] = k; 24328 e[k] = f; 24329 f = h; 24330 } 24331 } 24332 function ma() { 24333 this.e = this.a = null; 24334 this.f = 0; 24335 this.c = this.b = this.h = this.d = !1; 24336 } 24337 function S(a) { 24338 return a.e.c.b; 24339 } 24340 function R(a) { 24341 return a.e.a.b; 24342 } 24343 this.libtess = { 24344 GluTesselator: X, 24345 windingRule: { 24346 GLU_TESS_WINDING_ODD: 100130, 24347 GLU_TESS_WINDING_NONZERO: 100131, 24348 GLU_TESS_WINDING_POSITIVE: 100132, 24349 GLU_TESS_WINDING_NEGATIVE: 100133, 24350 GLU_TESS_WINDING_ABS_GEQ_TWO: 100134 24351 }, 24352 primitiveType: { 24353 GL_LINE_LOOP: 2, 24354 GL_TRIANGLES: 4, 24355 GL_TRIANGLE_STRIP: 5, 24356 GL_TRIANGLE_FAN: 6 24357 }, 24358 errorType: { 24359 GLU_TESS_MISSING_BEGIN_POLYGON: 100151, 24360 GLU_TESS_MISSING_END_POLYGON: 100153, 24361 GLU_TESS_MISSING_BEGIN_CONTOUR: 100152, 24362 GLU_TESS_MISSING_END_CONTOUR: 100154, 24363 GLU_TESS_COORD_TOO_LARGE: 100155, 24364 GLU_TESS_NEED_COMBINE_CALLBACK: 100156 24365 }, 24366 gluEnum: { 24367 GLU_TESS_MESH: 100112, 24368 GLU_TESS_TOLERANCE: 100142, 24369 GLU_TESS_WINDING_RULE: 100140, 24370 GLU_TESS_BOUNDARY_ONLY: 100141, 24371 GLU_INVALID_ENUM: 100900, 24372 GLU_INVALID_VALUE: 100901, 24373 GLU_TESS_BEGIN: 100100, 24374 GLU_TESS_VERTEX: 100101, 24375 GLU_TESS_END: 100102, 24376 GLU_TESS_ERROR: 100103, 24377 GLU_TESS_EDGE_FLAG: 100104, 24378 GLU_TESS_COMBINE: 100105, 24379 GLU_TESS_BEGIN_DATA: 100106, 24380 GLU_TESS_VERTEX_DATA: 100107, 24381 GLU_TESS_END_DATA: 100108, 24382 GLU_TESS_ERROR_DATA: 100109, 24383 GLU_TESS_EDGE_FLAG_DATA: 100110, 24384 GLU_TESS_COMBINE_DATA: 100111 24385 } 24386 }; 24387 X.prototype.gluDeleteTess = X.prototype.x; 24388 X.prototype.gluTessProperty = X.prototype.B; 24389 X.prototype.gluGetTessProperty = X.prototype.y; 24390 X.prototype.gluTessNormal = X.prototype.A; 24391 X.prototype.gluTessCallback = X.prototype.z; 24392 X.prototype.gluTessVertex = X.prototype.C; 24393 X.prototype.gluTessBeginPolygon = X.prototype.u; 24394 X.prototype.gluTessBeginContour = X.prototype.t; 24395 X.prototype.gluTessEndContour = X.prototype.v; 24396 X.prototype.gluTessEndPolygon = X.prototype.w; 24397 if (typeof module !== 'undefined') { 24398 module.exports = this.libtess; 24399 } 24400 }, 24401 {} 24402 ], 24403 33: [ 24404 function(_dereq_, module, exports) { 24405 // (c) Dean McNamee <[email protected]>, 2013. 24406 // 24407 // https://github.com/deanm/omggif 24408 // 24409 // Permission is hereby granted, free of charge, to any person obtaining a copy 24410 // of this software and associated documentation files (the "Software"), to 24411 // deal in the Software without restriction, including without limitation the 24412 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 24413 // sell copies of the Software, and to permit persons to whom the Software is 24414 // furnished to do so, subject to the following conditions: 24415 // 24416 // The above copyright notice and this permission notice shall be included in 24417 // all copies or substantial portions of the Software. 24418 // 24419 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24420 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24421 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24422 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24423 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24424 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 24425 // IN THE SOFTWARE. 24426 // 24427 // omggif is a JavaScript implementation of a GIF 89a encoder and decoder, 24428 // including animation and compression. It does not rely on any specific 24429 // underlying system, so should run in the browser, Node, or Plask. 24430 24431 'use strict'; 24432 24433 function GifWriter(buf, width, height, gopts) { 24434 var p = 0; 24435 24436 var gopts = gopts === undefined ? {} : gopts; 24437 var loop_count = gopts.loop === undefined ? null : gopts.loop; 24438 var global_palette = gopts.palette === undefined ? null : gopts.palette; 24439 24440 if (width <= 0 || height <= 0 || width > 65535 || height > 65535) 24441 throw new Error('Width/Height invalid.'); 24442 24443 function check_palette_and_num_colors(palette) { 24444 var num_colors = palette.length; 24445 if (num_colors < 2 || num_colors > 256 || num_colors & (num_colors - 1)) { 24446 throw new Error( 24447 'Invalid code/color length, must be power of 2 and 2 .. 256.' 24448 ); 24449 } 24450 return num_colors; 24451 } 24452 24453 // - Header. 24454 buf[p++] = 0x47; 24455 buf[p++] = 0x49; 24456 buf[p++] = 0x46; // GIF 24457 buf[p++] = 0x38; 24458 buf[p++] = 0x39; 24459 buf[p++] = 0x61; // 89a 24460 24461 // Handling of Global Color Table (palette) and background index. 24462 var gp_num_colors_pow2 = 0; 24463 var background = 0; 24464 if (global_palette !== null) { 24465 var gp_num_colors = check_palette_and_num_colors(global_palette); 24466 while ((gp_num_colors >>= 1)) ++gp_num_colors_pow2; 24467 gp_num_colors = 1 << gp_num_colors_pow2;
24468 --gp_num_colors_pow2; 24469 if (gopts.background !== undefined) { 24470 background = gopts.background; 24471 if (background >= gp_num_colors) 24472 throw new Error('Background index out of range.'); 24473 // The GIF spec states that a background index of 0 should be ignored, so 24474 // this is probably a mistake and you really want to set it to another 24475 // slot in the palette. But actually in the end most browsers, etc end 24476 // up ignoring this almost completely (including for dispose background). 24477 if (background === 0) 24478 throw new Error('Background index explicitly passed as 0.'); 24479 } 24480 } 24481 24482 // - Logical Screen Descriptor. 24483 // NOTE(deanm): w/h apparently ignored by implementations, but set anyway. 24484 buf[p++] = width & 0xff; 24485 buf[p++] = (width >> 8) & 0xff; 24486 buf[p++] = height & 0xff; 24487 buf[p++] = (height >> 8) & 0xff;
24488 // NOTE: Indicates 0-bpp original color resolution (unused?). 24489 buf[p++] = 24490 (global_palette !== null ? 0x80 : 0) | gp_num_colors_pow2; // Global Color Table Flag. // NOTE: No sort flag (unused?). 24491 buf[p++] = background; // Background Color Index. 24492 buf[p++] = 0; // Pixel aspect ratio (unused?). 24493 24494 // - Global Color Table 24495 if (global_palette !== null) { 24496 for (var i = 0, il = global_palette.length; i < il; ++i) { 24497 var rgb = global_palette[i]; 24498 buf[p++] = (rgb >> 16) & 0xff; 24499 buf[p++] = (rgb >> 8) & 0xff; 24500 buf[p++] = rgb & 0xff; 24501 } 24502 } 24503 24504 if (loop_count !== null) { 24505 // Netscape block for looping. 24506 if (loop_count < 0 || loop_count > 65535) 24507 throw new Error('Loop count invalid.'); 24508 // Extension code, label, and length. 24509 buf[p++] = 0x21; 24510 buf[p++] = 0xff; 24511 buf[p++] = 0x0b; 24512 // NETSCAPE2.0 24513 buf[p++] = 0x4e; 24514 buf[p++] = 0x45; 24515 buf[p++] = 0x54; 24516 buf[p++] = 0x53; 24517 buf[p++] = 0x43; 24518 buf[p++] = 0x41; 24519 buf[p++] = 0x50; 24520 buf[p++] = 0x45; 24521 buf[p++] = 0x32; 24522 buf[p++] = 0x2e; 24523 buf[p++] = 0x30; 24524 // Sub-block 24525 buf[p++] = 0x03; 24526 buf[p++] = 0x01; 24527 buf[p++] = loop_count & 0xff; 24528 buf[p++] = (loop_count >> 8) & 0xff;
24529 buf[p++] = 0x00; // Terminator. 24530 } 24531 24532 var ended = false; 24533 24534 this.addFrame = function(x, y, w, h, indexed_pixels, opts) { 24535 if (ended === true) { 24536 --p; 24537 ended = false; 24538 } // Un-end. 24539 24540 opts = opts === undefined ? {} : opts; 24541 24542 // TODO(deanm): Bounds check x, y. Do they need to be within the virtual 24543 // canvas width/height, I imagine? 24544 if (x < 0 || y < 0 || x > 65535 || y > 65535) throw new Error('x/y invalid.'); 24545 24546 if (w <= 0 || h <= 0 || w > 65535 || h > 65535) 24547 throw new Error('Width/Height invalid.'); 24548 24549 if (indexed_pixels.length < w * h) 24550 throw new Error('Not enough pixels for the frame size.'); 24551 24552 var using_local_palette = true; 24553 var palette = opts.palette; 24554 if (palette === undefined || palette === null) { 24555 using_local_palette = false; 24556 palette = global_palette; 24557 } 24558 24559 if (palette === undefined || palette === null) 24560 throw new Error('Must supply either a local or global palette.'); 24561 24562 var num_colors = check_palette_and_num_colors(palette); 24563 24564 // Compute the min_code_size (power of 2), destroying num_colors. 24565 var min_code_size = 0; 24566 while ((num_colors >>= 1)) ++min_code_size; 24567 num_colors = 1 << min_code_size; // Now we can easily get it back. 24568 24569 var delay = opts.delay === undefined ? 0 : opts.delay; 24570 24571 // From the spec: 24572 // 0 - No disposal specified. The decoder is 24573 // not required to take any action. 24574 // 1 - Do not dispose. The graphic is to be left 24575 // in place. 24576 // 2 - Restore to background color. The area used by the 24577 // graphic must be restored to the background color. 24578 // 3 - Restore to previous. The decoder is required to 24579 // restore the area overwritten by the graphic with 24580 // what was there prior to rendering the graphic. 24581 // 4-7 - To be defined. 24582 // NOTE(deanm): Dispose background doesn't really work, apparently most 24583 // browsers ignore the background palette index and clear to transparency. 24584 var disposal = opts.disposal === undefined ? 0 : opts.disposal; 24585 if (disposal < 0 || disposal > 3) 24586 // 4-7 is reserved. 24587 throw new Error('Disposal out of range.'); 24588 24589 var use_transparency = false; 24590 var transparent_index = 0; 24591 if (opts.transparent !== undefined && opts.transparent !== null) { 24592 use_transparency = true; 24593 transparent_index = opts.transparent; 24594 if (transparent_index < 0 || transparent_index >= num_colors) 24595 throw new Error('Transparent color index.'); 24596 } 24597 24598 if (disposal !== 0 || use_transparency || delay !== 0) { 24599 // - Graphics Control Extension 24600 buf[p++] = 0x21; 24601 buf[p++] = 0xf9; // Extension / Label. 24602 buf[p++] = 4; // Byte size. 24603 24604 buf[p++] = (disposal << 2) | (use_transparency === true ? 1 : 0); 24605 buf[p++] = delay & 0xff; 24606 buf[p++] = (delay >> 8) & 0xff;
vendor: 5,225 bytes, lines 24607-24726
24607 buf[p++] = transparent_index; // Transparent color index. 24608 buf[p++] = 0; // Block Terminator. 24609 } 24610 24611 // - Image Descriptor 24612 buf[p++] = 0x2c; // Image Seperator. 24613 buf[p++] = x & 0xff; 24614 buf[p++] = (x >> 8) & 0xff; // Left. 24615 buf[p++] = y & 0xff; 24616 buf[p++] = (y >> 8) & 0xff; // Top. 24617 buf[p++] = w & 0xff; 24618 buf[p++] = (w >> 8) & 0xff; 24619 buf[p++] = h & 0xff; 24620 buf[p++] = (h >> 8) & 0xff; 24621 // NOTE: No sort flag (unused?). 24622 // TODO(deanm): Support interlace. 24623 buf[p++] = using_local_palette === true ? 0x80 | (min_code_size - 1) : 0; 24624 24625 // - Local Color Table 24626 if (using_local_palette === true) { 24627 for (var i = 0, il = palette.length; i < il; ++i) { 24628 var rgb = palette[i]; 24629 buf[p++] = (rgb >> 16) & 0xff; 24630 buf[p++] = (rgb >> 8) & 0xff; 24631 buf[p++] = rgb & 0xff; 24632 } 24633 } 24634 24635 p = GifWriterOutputLZWCodeStream( 24636 buf, 24637 p, 24638 min_code_size < 2 ? 2 : min_code_size, 24639 indexed_pixels 24640 ); 24641 24642 return p; 24643 }; 24644 24645 this.end = function() { 24646 if (ended === false) { 24647 buf[p++] = 0x3b; // Trailer. 24648 ended = true; 24649 } 24650 return p; 24651 }; 24652 24653 this.getOutputBuffer = function() { 24654 return buf; 24655 }; 24656 this.setOutputBuffer = function(v) { 24657 buf = v; 24658 }; 24659 this.getOutputBufferPosition = function() { 24660 return p; 24661 }; 24662 this.setOutputBufferPosition = function(v) { 24663 p = v; 24664 }; 24665 } 24666 24667 // Main compression routine, palette indexes -> LZW code stream. 24668 // |index_stream| must have at least one entry. 24669 function GifWriterOutputLZWCodeStream(buf, p, min_code_size, index_stream) { 24670 buf[p++] = min_code_size; 24671 var cur_subblock = p++; // Pointing at the length field. 24672 24673 var clear_code = 1 << min_code_size; 24674 var code_mask = clear_code - 1; 24675 var eoi_code = clear_code + 1; 24676 var next_code = eoi_code + 1; 24677 24678 var cur_code_size = min_code_size + 1; // Number of bits per code. 24679 var cur_shift = 0; 24680 // We have at most 12-bit codes, so we should have to hold a max of 19 24681 // bits here (and then we would write out). 24682 var cur = 0; 24683 24684 function emit_bytes_to_buffer(bit_block_size) { 24685 while (cur_shift >= bit_block_size) { 24686 buf[p++] = cur & 0xff; 24687 cur >>= 8; 24688 cur_shift -= 8; 24689 if (p === cur_subblock + 256) { 24690 // Finished a subblock. 24691 buf[cur_subblock] = 255; 24692 cur_subblock = p++; 24693 } 24694 } 24695 } 24696 24697 function emit_code(c) { 24698 cur |= c << cur_shift; 24699 cur_shift += cur_code_size; 24700 emit_bytes_to_buffer(8); 24701 } 24702 24703 // I am not an expert on the topic, and I don't want to write a thesis. 24704 // However, it is good to outline here the basic algorithm and the few data 24705 // structures and optimizations here that make this implementation fast. 24706 // The basic idea behind LZW is to build a table of previously seen runs 24707 // addressed by a short id (herein called output code). All data is 24708 // referenced by a code, which represents one or more values from the 24709 // original input stream. All input bytes can be referenced as the same 24710 // value as an output code. So if you didn't want any compression, you 24711 // could more or less just output the original bytes as codes (there are 24712 // some details to this, but it is the idea). In order to achieve 24713 // compression, values greater then the input range (codes can be up to 24714 // 12-bit while input only 8-bit) represent a sequence of previously seen 24715 // inputs. The decompressor is able to build the same mapping while 24716 // decoding, so there is always a shared common knowledge between the 24717 // encoding and decoder, which is also important for "timing" aspects like 24718 // how to handle variable bit width code encoding. 24719 // 24720 // One obvious but very important consequence of the table system is there 24721 // is always a unique id (at most 12-bits) to map the runs. 'A' might be 24722 // 4, then 'AA' might be 10, 'AAA' 11, 'AAAA' 12, etc. This relationship 24723 // can be used for an effecient lookup strategy for the code mapping. We 24724 // need to know if a run has been seen before, and be able to map that run 24725 // to the output code. Since we start with known unique ids (input bytes), 24726 // and then from those build more unique ids (table entr
24726ies), we can 24727 // continue this chain (almost like a linked list) to always have small 24728 // integer values that represent the current byte chains in the encoder. 24729 // This means instead of tracking the input bytes (AAAABCD) to know our 24730 // current state, we can track the table entry for AAAABC (it is guaranteed 24731 // to exist by the nature of the algorithm) and the next character D. 24732 // Therefor the tuple of (table_entry, byte) is guaranteed to also be 24733 // unique. This allows us to create a simple lookup key for mapping input 24734 // sequences to codes (table indices) without having to store or search 24735 // any of the code sequences. So if 'AAAA' has a table entry of 12, the 24736 // tuple of ('AAAA', K) for any input byte K will be unique, and can be our 24737 // key. This leads to a integer value at most 20-bits, which can always 24738 // fit in an SMI value and be used as a fast sparse array / object key. 24739 24740 // Output code for the current contents of the index buffer. 24741 var ib_code = index_stream[0] & code_mask; // Load first input index. 24742 var code_table = {}; // Key'd on our 20-bit "tuple". 24743 24744 emit_code(clear_code); // Spec says first code should be a clear code. 24745 24746 // First index already loaded, process the rest of the stream. 24747 for (var i = 1, il = index_stream.length; i < il; ++i) { 24748 var k = index_stream[i] & code_mask; 24749 var cur_key = (ib_code << 8) | k; // (prev, k) unique tuple. 24750 var cur_code = code_table[cur_key]; // buffer + k. 24751 24752 // Check if we have to create a new code table entry. 24753 if (cur_code === undefined) { 24754 // We don't have buffer + k. 24755 // Emit index buffer (without k). 24756 // This is an inline version of emit_code, because this is the core 24757 // writing routine of the compressor (and V8 cannot inline emit_code 24758 // because it is a closure here in a different context). Additionally 24759 // we can call emit_byte_to_buffer less often, because we can have 24760 // 30-bits (from our 31-bit signed SMI), and we know our codes will only 24761 // be 12-bits, so can safely have 18-bits there without overflow. 24762 // emit_code(ib_code); 24763 cur |= ib_code << cur_shift; 24764 cur_shift += cur_code_size; 24765 while (cur_shift >= 8) { 24766 buf[p++] = cur & 0xff; 24767 cur >>= 8; 24768 cur_shift -= 8; 24769 if (p === cur_subblock + 256) { 24770 // Finished a subblock. 24771 buf[cur_subblock] = 255; 24772 cur_subblock = p++; 24773 } 24774 } 24775 24776 if (next_code === 4096) { 24777 // Table full, need a clear. 24778 emit_code(clear_code); 24779 next_code = eoi_code + 1; 24780 cur_code_size = min_code_size + 1; 24781 code_table = {}; 24782 } else { 24783 // Table not full, insert a new entry. 24784 // Increase our variable bit code sizes if necessary. This is a bit 24785 // tricky as it is based on "timing" between the encoding and 24786 // decoder. From the encoders perspective this should happen after 24787 // we've already emitted the index buffer and are about to create the 24788 // first table entry that would overflow our current code bit size. 24789 if (next_code >= 1 << cur_code_size) ++cur_code_size; 24790 code_table[cur_key] = next_code++; // Insert into code table. 24791 } 24792 24793 ib_code = k; // Index buffer to single input k. 24794 } else { 24795 ib_code = cur_code; // Index buffer to sequence in code table. 24796 } 24797 } 24798 24799 emit_code(ib_code); // There will still be something in the index buffer. 24800 emit_code(eoi_code); // End Of Information. 24801 24802 // Flush / finalize the sub-blocks stream to the buffer. 24803 emit_bytes_to_buffer(1); 24804
vendor: 10,715 bytes, lines 24805-25058
24805 // Finish the sub-blocks, writing out any unfinished lengths and 24806 // terminating with a sub-block of length 0. If we have already started 24807 // but not yet used a sub-block it can just become the terminator. 24808 if (cur_subblock + 1 === p) { 24809 // Started but unused. 24810 buf[cur_subblock] = 0; 24811 } else { 24812 // Started and used, write length and additional terminator block. 24813 buf[cur_subblock] = p - cur_subblock - 1; 24814 buf[p++] = 0; 24815 } 24816 return p; 24817 } 24818 24819 function GifReader(buf) { 24820 var p = 0; 24821 24822 // - Header (GIF87a or GIF89a). 24823 if ( 24824 buf[p++] !== 0x47 || 24825 buf[p++] !== 0x49 || 24826 buf[p++] !== 0x46 || 24827 buf[p++] !== 0x38 || 24828 ((buf[p++] + 1) & 0xfd) !== 0x38 || 24829 buf[p++] !== 0x61 24830 ) { 24831 throw new Error('Invalid GIF 87a/89a header.'); 24832 } 24833 24834 // - Logical Screen Descriptor. 24835 var width = buf[p++] | (buf[p++] << 8); 24836 var height = buf[p++] | (buf[p++] << 8); 24837 var pf0 = buf[p++]; // <Packed Fields>. 24838 var global_palette_flag = pf0 >> 7; 24839 var num_global_colors_pow2 = pf0 & 0x7; 24840 var num_global_colors = 1 << (num_global_colors_pow2 + 1); 24841 var background = buf[p++]; 24842 buf[p++]; // Pixel aspect ratio (unused?). 24843 24844 var global_palette_offset = null; 24845 var global_palette_size = null; 24846 24847 if (global_palette_flag) { 24848 global_palette_offset = p; 24849 global_palette_size = num_global_colors; 24850 p += num_global_colors * 3; // Seek past palette. 24851 } 24852 24853 var no_eof = true; 24854 24855 var frames = []; 24856 24857 var delay = 0; 24858 var transparent_index = null; 24859 var disposal = 0; // 0 - No disposal specified. 24860 var loop_count = null; 24861 24862 this.width = width; 24863 this.height = height; 24864 24865 while (no_eof && p < buf.length) { 24866 switch (buf[p++]) { 24867 case 0x21: // Graphics Control Extension Block 24868 switch (buf[p++]) { 24869 case 0xff: // Application specific block 24870 // Try if it's a Netscape block (with animation loop counter). 24871 if ( 24872 buf[p] !== 0x0b || // 21 FF already read, check block size. 24873 // NETSCAPE2.0 24874 (buf[p + 1] == 0x4e && 24875 buf[p + 2] == 0x45 && 24876 buf[p + 3] == 0x54 && 24877 buf[p + 4] == 0x53 && 24878 buf[p + 5] == 0x43 && 24879 buf[p + 6] == 0x41 && 24880 buf[p + 7] == 0x50 && 24881 buf[p + 8] == 0x45 && 24882 buf[p + 9] == 0x32 && 24883 buf[p + 10] == 0x2e && 24884 buf[p + 11] == 0x30 && 24885 // Sub-block 24886 buf[p + 12] == 0x03 && 24887 buf[p + 13] == 0x01 && 24888 buf[p + 16] == 0) 24889 ) { 24890 p += 14; 24891 loop_count = buf[p++] | (buf[p++] << 8); 24892 p++; // Skip terminator. 24893 } else { 24894 // We don't know what it is, just try to get past it. 24895 p += 12; 24896 while (true) { 24897 // Seek through subblocks. 24898 var block_size = buf[p++]; 24899 // Bad block size (ex: undefined from an out of bounds read). 24900 if (!(block_size >= 0)) throw Error('Invalid block size'); 24901 if (block_size === 0) break; // 0 size is terminator 24902 p += block_size; 24903 } 24904 } 24905 break; 24906 24907 case 0xf9: // Graphics Control Extension 24908 if (buf[p++] !== 0x4 || buf[p + 4] !== 0) 24909 throw new Error('Invalid graphics extension block.'); 24910 var pf1 = buf[p++]; 24911 delay = buf[p++] | (buf[p++] << 8); 24912 transparent_index = buf[p++]; 24913 if ((pf1 & 1) === 0) transparent_index = null; 24914 disposal = (pf1 >> 2) & 0x7; 24915 p++; // Skip terminator. 24916 break; 24917 24918 case 0xfe: // Comment Extension. 24919 while (true) { 24920 // Seek through subblocks. 24921 var block_size = buf[p++]; 24922 // Bad block size (ex: undefined from an out of bounds read). 24923 if (!(block_size >= 0)) throw Error('Invalid block size'); 24924 if (block_size === 0) break; // 0 size is terminator 24925 // console.log(buf.slice(p, p+block_size).toString('ascii')); 24926 p += block_size; 24927 } 24928 break; 24929 24930 default: 24931 throw new Error( 24932 'Unknown graphic control label: 0x' + buf[p - 1].toString(16) 24933 ); 24934 } 24935 break; 24936 24937 case 0x2c: // Image Descriptor. 24938 var x = buf[p++] | (buf[p++] << 8); 24939 var y = buf[p++] | (buf[p++] << 8); 24940 var w = buf[p++] | (buf[p++] << 8); 24941 var h = buf[p++] | (buf[p++] << 8); 24942 var pf2 = buf[p++]; 24943 var local_palette_flag = pf2 >> 7; 24944 var interlace_flag = (pf2 >> 6) & 1; 24945 var num_local_colors_pow2 = pf2 & 0x7; 24946 var num_local_colors = 1 << (num_local_colors_pow2 + 1); 24947 var palette_offset = global_palette_offset; 24948 var palette_size = global_palette_size; 24949 var has_local_palette = false; 24950 if (local_palette_flag) { 24951 var has_local_palette = true; 24952 palette_offset = p; // Override with local palette. 24953 palette_size = num_local_colors; 24954 p += num_local_colors * 3; // Seek past palette. 24955 } 24956 24957 var data_offset = p; 24958 24959 p++; // codesize 24960 while (true) { 24961 var block_size = buf[p++]; 24962 // Bad block size (ex: undefined from an out of bounds read). 24963 if (!(block_size >= 0)) throw Error('Invalid block size'); 24964 if (block_size === 0) break; // 0 size is terminator 24965 p += block_size; 24966 } 24967 24968 frames.push({ 24969 x: x, 24970 y: y, 24971 width: w, 24972 height: h, 24973 has_local_palette: has_local_palette, 24974 palette_offset: palette_offset, 24975 palette_size: palette_size, 24976 data_offset: data_offset, 24977 data_length: p - data_offset, 24978 transparent_index: transparent_index, 24979 interlaced: !!interlace_flag, 24980 delay: delay, 24981 disposal: disposal 24982 }); 24983 break; 24984 24985 case 0x3b: // Trailer Marker (end of file). 24986 no_eof = false; 24987 break; 24988 24989 default: 24990 throw new Error('Unknown gif block: 0x' + buf[p - 1].toString(16)); 24991 break; 24992 } 24993 } 24994 24995 this.numFrames = function() { 24996 return frames.length; 24997 }; 24998 24999 this.loopCount = function() { 25000 return loop_count; 25001 }; 25002 25003 this.frameInfo = function(frame_num) { 25004 if (frame_num < 0 || frame_num >= frames.length) 25005 throw new Error('Frame index out of range.'); 25006 return frames[frame_num]; 25007 }; 25008 25009 this.decodeAndBlitFrameBGRA = function(frame_num, pixels) { 25010 var frame = this.frameInfo(frame_num); 25011 var num_pixels = frame.width * frame.height; 25012 var index_stream = new Uint8Array(num_pixels); // At most 8-bit indices. 25013 GifReaderLZWOutputIndexStream( 25014 buf, 25015 frame.data_offset, 25016 index_stream, 25017 num_pixels 25018 ); 25019 var palette_offset = frame.palette_offset; 25020 25021 // NOTE(deanm): It seems to be much faster to compare index to 256 than 25022 // to === null. Not sure why, but CompareStub_EQ_STRICT shows up high in 25023 // the profile, not sure if it's related to using a Uint8Array. 25024 var trans = frame.transparent_index; 25025 if (trans === null) trans = 256; 25026 25027 // We are possibly just blitting to a portion of the entire frame. 25028 // That is a subrect within the framerect, so the additional pixels 25029 // must be skipped over after we finished a scanline. 25030 var framewidth = frame.width; 25031 var framestride = width - framewidth; 25032 var xleft = framewidth; // Number of subrect pixels left in scanline. 25033 25034 // Output indicies of the top left and bottom right corners of the subrect. 25035 var opbeg = (frame.y * width + frame.x) * 4; 25036 var opend = ((frame.y + frame.height) * width + frame.x) * 4; 25037 var op = opbeg; 25038 25039 var scanstride = framestride * 4; 25040 25041 // Use scanstride to skip past the rows when interlacing. This is skipping 25042 // 7 rows for the first two passes, then 3 then 1. 25043 if (frame.interlaced === true) { 25044 scanstride += width * 4 * 7; // Pass 1. 25045 } 25046 25047 var interlaceskip = 8; // Tracking the row interval in the current pass. 25048 25049 for (var i = 0, il = index_stream.length; i < il; ++i) { 25050 var index = index_stream[i]; 25051 25052 if (xleft === 0) { 25053 // Beginning of new scan line 25054 op += scanstride; 25055 xleft = framewidth; 25056 if (op >= opend) { 25057 // Catch the wrap to switch passes when interlacing. 25058 scanstride = framestride * 4 + width * 4 * (interlaceskip - 1);
vendor: 5,704 bytes, lines 25059-25195
25059 // interlaceskip / 2 * 4 is interlaceskip << 1. 25060 op = opbeg + (framewidth + framestride) * (interlaceskip << 1); 25061 interlaceskip >>= 1; 25062 } 25063 } 25064 25065 if (index === trans) { 25066 op += 4; 25067 } else { 25068 var r = buf[palette_offset + index * 3]; 25069 var g = buf[palette_offset + index * 3 + 1]; 25070 var b = buf[palette_offset + index * 3 + 2]; 25071 pixels[op++] = b; 25072 pixels[op++] = g; 25073 pixels[op++] = r; 25074 pixels[op++] = 255; 25075 } 25076 --xleft; 25077 } 25078 }; 25079 25080 // I will go to copy and paste hell one day... 25081 this.decodeAndBlitFrameRGBA = function(frame_num, pixels) { 25082 var frame = this.frameInfo(frame_num); 25083 var num_pixels = frame.width * frame.height; 25084 var index_stream = new Uint8Array(num_pixels); // At most 8-bit indices. 25085 GifReaderLZWOutputIndexStream( 25086 buf, 25087 frame.data_offset, 25088 index_stream, 25089 num_pixels 25090 ); 25091 var palette_offset = frame.palette_offset; 25092 25093 // NOTE(deanm): It seems to be much faster to compare index to 256 than 25094 // to === null. Not sure why, but CompareStub_EQ_STRICT shows up high in 25095 // the profile, not sure if it's related to using a Uint8Array. 25096 var trans = frame.transparent_index; 25097 if (trans === null) trans = 256; 25098 25099 // We are possibly just blitting to a portion of the entire frame. 25100 // That is a subrect within the framerect, so the additional pixels 25101 // must be skipped over after we finished a scanline. 25102 var framewidth = frame.width; 25103 var framestride = width - framewidth; 25104 var xleft = framewidth; // Number of subrect pixels left in scanline. 25105 25106 // Output indicies of the top left and bottom right corners of the subrect. 25107 var opbeg = (frame.y * width + frame.x) * 4; 25108 var opend = ((frame.y + frame.height) * width + frame.x) * 4; 25109 var op = opbeg; 25110 25111 var scanstride = framestride * 4; 25112 25113 // Use scanstride to skip past the rows when interlacing. This is skipping 25114 // 7 rows for the first two passes, then 3 then 1. 25115 if (frame.interlaced === true) { 25116 scanstride += width * 4 * 7; // Pass 1. 25117 } 25118 25119 var interlaceskip = 8; // Tracking the row interval in the current pass. 25120 25121 for (var i = 0, il = index_stream.length; i < il; ++i) { 25122 var index = index_stream[i]; 25123 25124 if (xleft === 0) { 25125 // Beginning of new scan line 25126 op += scanstride; 25127 xleft = framewidth; 25128 if (op >= opend) { 25129 // Catch the wrap to switch passes when interlacing. 25130 scanstride = framestride * 4 + width * 4 * (interlaceskip - 1); 25131 // interlaceskip / 2 * 4 is interlaceskip << 1. 25132 op = opbeg + (framewidth + framestride) * (interlaceskip << 1); 25133 interlaceskip >>= 1; 25134 } 25135 } 25136 25137 if (index === trans) { 25138 op += 4; 25139 } else { 25140 var r = buf[palette_offset + index * 3]; 25141 var g = buf[palette_offset + index * 3 + 1]; 25142 var b = buf[palette_offset + index * 3 + 2]; 25143 pixels[op++] = r; 25144 pixels[op++] = g; 25145 pixels[op++] = b; 25146 pixels[op++] = 255; 25147 } 25148 --xleft; 25149 } 25150 }; 25151 } 25152 25153 function GifReaderLZWOutputIndexStream(code_stream, p, output, output_length) { 25154 var min_code_size = code_stream[p++]; 25155 25156 var clear_code = 1 << min_code_size; 25157 var eoi_code = clear_code + 1; 25158 var next_code = eoi_code + 1; 25159 25160 var cur_code_size = min_code_size + 1; // Number of bits per code. 25161 // NOTE: This shares the same name as the encoder, but has a different 25162 // meaning here. Here this masks each code coming from the code stream. 25163 var code_mask = (1 << cur_code_size) - 1; 25164 var cur_shift = 0; 25165 var cur = 0; 25166 25167 var op = 0; // Output pointer. 25168 25169 var subblock_size = code_stream[p++]; 25170 25171 // TODO(deanm): Would using a TypedArray be any faster? At least it would 25172 // solve the fast mode / backing store uncertainty. 25173 // var code_table = Array(4096); 25174 var code_table = new Int32Array(4096); // Can be signed, we only use 20 bits. 25175 25176 var prev_code = null; // Track code-1. 25177 25178 while (true) { 25179 // Read up to two bytes, making sure we always 12-bits for max sized code. 25180 while (cur_shift < 16) { 25181 if (subblock_size === 0) break; // No more data to be read. 25182 25183 cur |= code_stream[p++] << cur_shift; 25184 cur_shift += 8; 25185 25186 if (subblock_size === 1) { 25187 // Never let it get to 0 to hold logic above. 25188 subblock_size = code_stream[p++]; // Next subblock. 25189 } else { 25190 --subblock_size; 25191 } 25192 } 25193 25194 // TODO(deanm): We should never really get here, we should have received 25195 // and EOI.
vendor: 4,418 bytes, lines 25196-25282
25196 if (cur_shift < cur_code_size) break; 25197 25198 var code = cur & code_mask; 25199 cur >>= cur_code_size; 25200 cur_shift -= cur_code_size; 25201 25202 // TODO(deanm): Maybe should check that the first code was a clear code, 25203 // at least this is what you're supposed to do. But actually our encoder 25204 // now doesn't emit a clear code first anyway. 25205 if (code === clear_code) { 25206 // We don't actually have to clear the table. This could be a good idea 25207 // for greater error checking, but we don't really do any anyway. We 25208 // will just track it with next_code and overwrite old entries. 25209 25210 next_code = eoi_code + 1; 25211 cur_code_size = min_code_size + 1; 25212 code_mask = (1 << cur_code_size) - 1; 25213 25214 // Don't update prev_code ? 25215 prev_code = null; 25216 continue; 25217 } else if (code === eoi_code) { 25218 break; 25219 } 25220 25221 // We have a similar situation as the decoder, where we want to store 25222 // variable length entries (code table entries), but we want to do in a 25223 // faster manner than an array of arrays. The code below stores sort of a 25224 // linked list within the code table, and then "chases" through it to 25225 // construct the dictionary entries. When a new entry is created, just the 25226 // last byte is stored, and the rest (prefix) of the entry is only 25227 // referenced by its table entry. Then the code chases through the 25228 // prefixes until it reaches a single byte code. We have to chase twice, 25229 // first to compute the length, and then to actually copy the data to the 25230 // output (backwards, since we know the length). The alternative would be 25231 // storing something in an intermediate stack, but that doesn't make any 25232 // more sense. I implemented an approach where it also stored the length 25233 // in the code table, although it's a bit tricky because you run out of 25234 // bits (12 + 12 + 8), but I didn't measure much improvements (the table 25235 // entries are generally not the long). Even when I created benchmarks for 25236 // very long table entries the complexity did not seem worth it. 25237 // The code table stores the prefix entry in 12 bits and then the suffix 25238 // byte in 8 bits, so each entry is 20 bits. 25239 25240 var chase_code = code < next_code ? code : prev_code; 25241 25242 // Chase what we will output, either {CODE} or {CODE-1}. 25243 var chase_length = 0; 25244 var chase = chase_code; 25245 while (chase > clear_code) { 25246 chase = code_table[chase] >> 8; 25247 ++chase_length; 25248 } 25249 25250 var k = chase; 25251 25252 var op_end = op + chase_length + (chase_code !== code ? 1 : 0); 25253 if (op_end > output_length) { 25254 console.log('Warning, gif stream longer than expected.'); 25255 return; 25256 } 25257 25258 // Already have the first byte from the chase, might as well write it fast. 25259 output[op++] = k; 25260 25261 op += chase_length; 25262 var b = op; // Track pointer, writing backwards. 25263 25264 if (chase_code !== code) 25265 // The case of emitting {CODE-1} + k. 25266 output[op++] = k; 25267 25268 chase = chase_code; 25269 while (chase_length--) { 25270 chase = code_table[chase]; 25271 output[--b] = chase & 0xff; // Write backwards. 25272 chase >>= 8; // Pull down to the prefix code. 25273 } 25274 25275 if (prev_code !== null && next_code < 4096) { 25276 code_table[next_code++] = (prev_code << 8) | k; 25277 // TODO(deanm): Figure out this clearing vs code growth logic better. I 25278 // have an feeling that it should just happen somewhere else, for now it 25279 // is awkward between when we grow past the max and then hit a clear code. 25280 // For now just check if we hit the max 12-bits (then a clear code should 25281 // follow, also of course encoded in 12-bits). 25282 if (next_code >= code_mask + 1 && cur_code_size < 12) {
25283 ++cur_code_size; 25284 code_mask = (code_mask << 1) | 1; 25285 } 25286 } 25287 25288 prev_code = code; 25289 } 25290 25291 if (op !== output_length) { 25292 console.log('Warning, gif stream shorter than expected.'); 25293 } 25294 25295 return output; 25296 } 25297 25298 // CommonJS. 25299 try { 25300 exports.GifWriter = GifWriter; 25301 exports.GifReader = GifReader; 25302 } catch (e) {} 25303 }, 25304 {} 25305 ], 25306 34: [ 25307 function(_dereq_, module, exports) { 25308 (function(Buffer) { 25309 /** 25310 * 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 25311 */ 25312 25313 (function(global, factory) { 25314 typeof exports === 'object' && typeof module !== 'undefined' 25315 ? factory(exports) 25316 : typeof define === 'function' && define.amd 25317 ? define(['exports'], factory) 25318 : factory((global.opentype = {})); 25319 })(this, function(exports) { 25320 'use strict'; 25321 25322 /*! https://mths.be/codepointat v0.2.0 by @mathias */ 25323 if (!String.prototype.codePointAt) { 25324 (function() { 25325 var defineProperty = (function() { 25326 // IE 8 only supports `Object.defineProperty` on DOM elements 25327 try { 25328 var object = {}; 25329 var $defineProperty = Object.defineProperty; 25330 var result = 25331 $defineProperty(object, object, object) && $defineProperty; 25332 } catch (error) {} 25333 return result; 25334 })(); 25335 var codePointAt = function(position) { 25336 if (this == null) { 25337 throw TypeError(); 25338 } 25339 var string = String(this); 25340 var size = string.length; 25341 // `ToInteger` 25342 var index = position ? Number(position) : 0; 25343 if (index != index) { 25344 // better `isNaN` 25345 index = 0; 25346 } 25347 // Account for out-of-bounds indices: 25348 if (index < 0 || index >= size) { 25349 return undefined; 25350 } 25351 // Get the first code unit 25352 var first = string.charCodeAt(index); 25353 var second; 25354 if ( 25355 // check if itâs the start of a surrogate pair 25356 first >= 0xd800 && 25357 first <= 0xdbff && // high surrogate 25358 size > index + 1 // there is a next code unit 25359 ) { 25360 second = string.charCodeAt(index + 1); 25361 if (second >= 0xdc00 && second <= 0xdfff) { 25362 // low surrogate 25363 // https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae 25364 return (first - 0xd800) * 0x400 + second - 0xdc00 + 0x10000; 25365 } 25366 } 25367 return first; 25368 }; 25369 if (defineProperty) { 25370 defineProperty(String.prototype, 'codePointAt', { 25371 value: codePointAt, 25372 configurable: true, 25373 writable: true 25374 }); 25375 } else { 25376 String.prototype.codePointAt = codePointAt; 25377 } 25378 })(); 25379 } 25380 25381 var TINF_OK = 0; 25382 var TINF_DATA_ERROR = -3; 25383 25384 function Tree() { 25385 this.table = new Uint16Array(16); /* table of code length counts */ 25386 this.trans = new Uint16Array(288); /* code -> symbol translation table */ 25387 } 25388 25389 function Data(source, dest) { 25390 this.source = source; 25391 this.sourceIndex = 0; 25392 this.tag = 0; 25393 this.bitcount = 0; 25394 25395 this.dest = dest; 25396 this.destLen = 0; 25397 25398 this.ltree = new Tree(); /* dynamic length/symbol tree */ 25399 this.dtree = new Tree(); /* dynamic distance tree */ 25400 } 25401 25402 /* --------------------------------------------------- *
vendor: 11,225 bytes, lines 25403-25746
25403 * -- uninitialized global data (static structures) -- * 25404 * --------------------------------------------------- */ 25405 25406 var sltree = new Tree(); 25407 var sdtree = new Tree(); 25408 25409 /* extra bits and base tables for length codes */ 25410 var length_bits = new Uint8Array(30); 25411 var length_base = new Uint16Array(30); 25412 25413 /* extra bits and base tables for distance codes */ 25414 var dist_bits = new Uint8Array(30); 25415 var dist_base = new Uint16Array(30); 25416 25417 /* special ordering of code length codes */ 25418 var clcidx = new Uint8Array([ 25419 16, 25420 17, 25421 18, 25422 0, 25423 8, 25424 7, 25425 9, 25426 6, 25427 10, 25428 5, 25429 11, 25430 4, 25431 12, 25432 3, 25433 13, 25434 2, 25435 14, 25436 1, 25437 15 25438 ]); 25439 25440 /* used by tinf_decode_trees, avoids allocations every call */ 25441 var code_tree = new Tree(); 25442 var lengths = new Uint8Array(288 + 32); 25443 25444 /* ----------------------- * 25445 * -- utility functions -- * 25446 * ----------------------- */ 25447 25448 /* build extra bits and base tables */ 25449 function tinf_build_bits_base(bits, base, delta, first) { 25450 var i, sum; 25451 25452 /* build bits table */ 25453 for (i = 0; i < delta; ++i) { 25454 bits[i] = 0; 25455 } 25456 for (i = 0; i < 30 - delta; ++i) { 25457 bits[i + delta] = (i / delta) | 0; 25458 } 25459 25460 /* build base table */ 25461 for (sum = first, i = 0; i < 30; ++i) { 25462 base[i] = sum; 25463 sum += 1 << bits[i]; 25464 } 25465 } 25466 25467 /* build the fixed huffman trees */ 25468 function tinf_build_fixed_trees(lt, dt) { 25469 var i; 25470 25471 /* build fixed length tree */ 25472 for (i = 0; i < 7; ++i) { 25473 lt.table[i] = 0; 25474 } 25475 25476 lt.table[7] = 24; 25477 lt.table[8] = 152; 25478 lt.table[9] = 112; 25479 25480 for (i = 0; i < 24; ++i) { 25481 lt.trans[i] = 256 + i; 25482 } 25483 for (i = 0; i < 144; ++i) { 25484 lt.trans[24 + i] = i; 25485 } 25486 for (i = 0; i < 8; ++i) { 25487 lt.trans[24 + 144 + i] = 280 + i; 25488 } 25489 for (i = 0; i < 112; ++i) { 25490 lt.trans[24 + 144 + 8 + i] = 144 + i; 25491 } 25492 25493 /* build fixed distance tree */ 25494 for (i = 0; i < 5; ++i) { 25495 dt.table[i] = 0; 25496 } 25497 25498 dt.table[5] = 32; 25499 25500 for (i = 0; i < 32; ++i) { 25501 dt.trans[i] = i; 25502 } 25503 } 25504 25505 /* given an array of code lengths, build a tree */ 25506 var offs = new Uint16Array(16); 25507 25508 function tinf_build_tree(t, lengths, off, num) { 25509 var i, sum; 25510 25511 /* clear code length count table */ 25512 for (i = 0; i < 16; ++i) { 25513 t.table[i] = 0; 25514 } 25515 25516 /* scan symbol lengths, and sum code length counts */ 25517 for (i = 0; i < num; ++i) { 25518 t.table[lengths[off + i]]++; 25519 } 25520 25521 t.table[0] = 0; 25522 25523 /* compute offset table for distribution sort */ 25524 for (sum = 0, i = 0; i < 16; ++i) { 25525 offs[i] = sum; 25526 sum += t.table[i]; 25527 } 25528 25529 /* create code->symbol translation table (symbols sorted by code) */ 25530 for (i = 0; i < num; ++i) { 25531 if (lengths[off + i]) { 25532 t.trans[offs[lengths[off + i]]++] = i; 25533 } 25534 } 25535 } 25536 25537 /* ---------------------- * 25538 * -- decode functions -- * 25539 * ---------------------- */ 25540 25541 /* get one bit from source stream */ 25542 function tinf_getbit(d) { 25543 /* check if tag is empty */ 25544 if (!d.bitcount--) { 25545 /* load next tag */ 25546 d.tag = d.source[d.sourceIndex++]; 25547 d.bitcount = 7; 25548 } 25549 25550 /* shift bit out of tag */ 25551 var bit = d.tag & 1; 25552 d.tag >>>= 1; 25553 25554 return bit; 25555 } 25556 25557 /* read a num bit value from a stream and add base */ 25558 function tinf_read_bits(d, num, base) { 25559 if (!num) { 25560 return base; 25561 } 25562 25563 while (d.bitcount < 24) { 25564 d.tag |= d.source[d.sourceIndex++] << d.bitcount; 25565 d.bitcount += 8; 25566 } 25567 25568 var val = d.tag & (0xffff >>> (16 - num)); 25569 d.tag >>>= num; 25570 d.bitcount -= num; 25571 return val + base; 25572 } 25573 25574 /* given a data stream and a tree, decode a symbol */ 25575 function tinf_decode_symbol(d, t) { 25576 while (d.bitcount < 24) { 25577 d.tag |= d.source[d.sourceIndex++] << d.bitcount; 25578 d.bitcount += 8; 25579 } 25580 25581 var sum = 0, 25582 cur = 0, 25583 len = 0; 25584 var tag = d.tag; 25585 25586 /* get more bits while code value is above sum */ 25587 do { 25588 cur = 2 * cur + (tag & 1); 25589 tag >>>= 1; 25590 ++len; 25591 25592 sum += t.table[len]; 25593 cur -= t.table[len]; 25594 } while (cur >= 0); 25595 25596 d.tag = tag; 25597 d.bitcount -= len; 25598 25599 return t.trans[sum + cur]; 25600 } 25601 25602 /* given a data stream, decode dynamic trees from it */ 25603 function tinf_decode_trees(d, lt, dt) { 25604 var hlit, hdist, hclen; 25605 var i, num, length; 25606 25607 /* get 5 bits HLIT (257-286) */ 25608 hlit = tinf_read_bits(d, 5, 257); 25609 25610 /* get 5 bits HDIST (1-32) */ 25611 hdist = tinf_read_bits(d, 5, 1); 25612 25613 /* get 4 bits HCLEN (4-19) */ 25614 hclen = tinf_read_bits(d, 4, 4); 25615 25616 for (i = 0; i < 19; ++i) { 25617 lengths[i] = 0; 25618 } 25619 25620 /* read code lengths for code length alphabet */ 25621 for (i = 0; i < hclen; ++i) { 25622 /* get 3 bits code length (0-7) */ 25623 var clen = tinf_read_bits(d, 3, 0); 25624 lengths[clcidx[i]] = clen; 25625 } 25626 25627 /* build code length tree */ 25628 tinf_build_tree(code_tree, lengths, 0, 19); 25629 25630 /* decode code lengths for the dynamic trees */ 25631 for (num = 0; num < hlit + hdist; ) { 25632 var sym = tinf_decode_symbol(d, code_tree); 25633 25634 switch (sym) { 25635 case 16: 25636 /* copy previous code length 3-6 times (read 2 bits) */ 25637 var prev = lengths[num - 1]; 25638 for (length = tinf_read_bits(d, 2, 3); length; --length) { 25639 lengths[num++] = prev; 25640 } 25641 break; 25642 case 17: 25643 /* repeat code length 0 for 3-10 times (read 3 bits) */ 25644 for (length = tinf_read_bits(d, 3, 3); length; --length) { 25645 lengths[num++] = 0; 25646 } 25647 break; 25648 case 18: 25649 /* repeat code length 0 for 11-138 times (read 7 bits) */ 25650 for (length = tinf_read_bits(d, 7, 11); length; --length) { 25651 lengths[num++] = 0; 25652 } 25653 break; 25654 default: 25655 /* values 0-15 represent the actual code lengths */ 25656 lengths[num++] = sym; 25657 break; 25658 } 25659 } 25660 25661 /* build dynamic trees */ 25662 tinf_build_tree(lt, lengths, 0, hlit); 25663 tinf_build_tree(dt, lengths, hlit, hdist); 25664 } 25665 25666 /* ----------------------------- * 25667 * -- block inflate functions -- * 25668 * ----------------------------- */ 25669 25670 /* given a stream and two trees, inflate a block of data */ 25671 function tinf_inflate_block_data(d, lt, dt) { 25672 while (1) { 25673 var sym = tinf_decode_symbol(d, lt); 25674 25675 /* check for end of block */ 25676 if (sym === 256) { 25677 return TINF_OK; 25678 } 25679 25680 if (sym < 256) { 25681 d.dest[d.destLen++] = sym; 25682 } else { 25683 var length, dist, offs; 25684 var i; 25685 25686 sym -= 257; 25687 25688 /* possibly get more bits from length code */ 25689 length = tinf_read_bits(d, length_bits[sym], length_base[sym]); 25690 25691 dist = tinf_decode_symbol(d, dt); 25692 25693 /* possibly get more bits from distance code */ 25694 offs = d.destLen - tinf_read_bits(d, dist_bits[dist], dist_base[dist]); 25695 25696 /* copy match */ 25697 for (i = offs; i < offs + length; ++i) { 25698 d.dest[d.destLen++] = d.dest[i]; 25699 } 25700 } 25701 } 25702 } 25703 25704 /* inflate an uncompressed block of data */ 25705 function tinf_inflate_uncompressed_block(d) { 25706 var length, invlength; 25707 var i; 25708 25709 /* unread from bitbuffer */ 25710 while (d.bitcount > 8) { 25711 d.sourceIndex--; 25712 d.bitcount -= 8; 25713 } 25714 25715 /* get length */ 25716 length = d.source[d.sourceIndex + 1]; 25717 length = 256 * length + d.source[d.sourceIndex]; 25718 25719 /* get one's complement of length */ 25720 invlength = d.source[d.sourceIndex + 3]; 25721 invlength = 256 * invlength + d.source[d.sourceIndex + 2]; 25722 25723 /* check length */ 25724 if (length !== (~invlength & 0x0000ffff)) { 25725 return TINF_DATA_ERROR; 25726 } 25727 25728 d.sourceIndex += 4; 25729 25730 /* copy block */ 25731 for (i = length; i; --i) { 25732 d.dest[d.destLen++] = d.source[d.sourceIndex++]; 25733 } 25734 25735 /* make sure we start next block on a byte boundary */ 25736 d.bitcount = 0; 25737 25738 return TINF_OK; 25739 } 25740 25741 /* inflate stream from source to dest */ 25742 function tinf_uncompress(source, dest) { 25743 var d = new Data(source, dest); 25744 var bfinal, btype, res; 25745 25746 do {
25747 /* read final block flag */ 25748 bfinal = tinf_getbit(d); 25749 25750 /* read block type (2 bits) */ 25751 btype = tinf_read_bits(d, 2, 0); 25752 25753 /* decompress block */ 25754 switch (btype) { 25755 case 0: 25756 /* decompress uncompressed block */ 25757 res = tinf_inflate_uncompressed_block(d); 25758 break; 25759 case 1: 25760 /* decompress block with fixed huffman trees */ 25761 res = tinf_inflate_block_data(d, sltree, sdtree); 25762 break; 25763 case 2: 25764 /* decompress block with dynamic huffman trees */ 25765 tinf_decode_trees(d, d.ltree, d.dtree); 25766 res = tinf_inflate_block_data(d, d.ltree, d.dtree); 25767 break; 25768 default: 25769 res = TINF_DATA_ERROR; 25770 } 25771 25772 if (res !== TINF_OK) { 25773 throw new Error('Data error'); 25774 } 25775 } while (!bfinal); 25776 25777 if (d.destLen < d.dest.length) { 25778 if (typeof d.dest.slice === 'function') { 25779 return d.dest.slice(0, d.destLen); 25780 } else { 25781 return d.dest.subarray(0, d.destLen); 25782 } 25783 } 25784 25785 return d.dest; 25786 } 25787 25788 /* -------------------- * 25789 * -- initialization -- * 25790 * -------------------- */ 25791 25792 /* build fixed huffman trees */ 25793 tinf_build_fixed_trees(sltree, sdtree); 25794 25795 /* build extra bits and base tables */ 25796 tinf_build_bits_base(length_bits, length_base, 4, 3); 25797 tinf_build_bits_base(dist_bits, dist_base, 2, 1); 25798 25799 /* fix a special case */ 25800 length_bits[28] = 0; 25801 length_base[28] = 258; 25802 25803 var tinyInflate = tinf_uncompress; 25804 25805 // The Bounding Box object 25806 25807 function derive(v0, v1, v2, v3, t) { 25808 return ( 25809 Math.pow(1 - t, 3) * v0 + 25810 3 * Math.pow(1 - t, 2) * t * v1 + 25811 3 * (1 - t) * Math.pow(t, 2) * v2 + 25812 Math.pow(t, 3) * v3 25813 ); 25814 } 25815 /** 25816 * A bounding box is an enclosing box that describes the smallest measure within which all the points lie. 25817 * It is used to calculate the bounding box of a glyph or text path. 25818 * 25819 * On initialization, x1/y1/x2/y2 will be NaN. Check if the bounding box is empty using `isEmpty()`. 25820 * 25821 * @exports opentype.BoundingBox 25822 * @class 25823 * @constructor 25824 */ 25825 function BoundingBox() { 25826 this.x1 = Number.NaN; 25827 this.y1 = Number.NaN; 25828 this.x2 = Number.NaN; 25829 this.y2 = Number.NaN; 25830 } 25831 25832 /** 25833 * Returns true if the bounding box is empty, that is, no points have been added to the box yet. 25834 */ 25835 BoundingBox.prototype.isEmpty = function() { 25836 return isNaN(this.x1) || isNaN(this.y1) || isNaN(this.x2) || isNaN(this.y2); 25837 }; 25838 25839 /** 25840 * Add the point to the bounding box. 25841 * The x1/y1/x2/y2 coordinates of the bounding box will now encompass the given point. 25842 * @param {number} x - The X coordinate of the point. 25843 * @param {number} y - The Y coordinate of the point. 25844 */ 25845 BoundingBox.prototype.addPoint = function(x, y) { 25846 if (typeof x === 'number') { 25847 if (isNaN(this.x1) || isNaN(this.x2)) { 25848 this.x1 = x; 25849 this.x2 = x; 25850 } 25851 if (x < this.x1) { 25852 this.x1 = x; 25853 } 25854 if (x > this.x2) { 25855 this.x2 = x; 25856 } 25857 } 25858 if (typeof y === 'number') { 25859 if (isNaN(this.y1) || isNaN(this.y2)) { 25860 this.y1 = y; 25861 this.y2 = y; 25862 } 25863 if (y < this.y1) { 25864 this.y1 = y; 25865 } 25866 if (y > this.y2) { 25867 this.y2 = y; 25868 } 25869 } 25870 }; 25871 25872 /** 25873 * Add a X coordinate to the bounding box. 25874 * This extends the bounding box to include the X coordinate. 25875 * This function is used internally inside of addBezier. 25876 * @param {number} x - The X coordinate of the point. 25877 */ 25878 BoundingBox.prototype.addX = function(x) { 25879 this.addPoint(x, null); 25880 }; 25881 25882 /** 25883 * Add a Y coordinate to the bounding box. 25884 * This extends the bounding box to include the Y coordinate. 25885 * This function is used internally inside of addBezier. 25886 * @param {number} y - The Y coordinate of the point. 25887 */ 25888 BoundingBox.prototype.addY = function(y) { 25889 this.addPoint(null, y); 25890 }; 25891 25892 /** 25893 * Add a Bézier curve to the bounding box. 25894 * This extends the bounding box to include the entire Bézier. 25895 * @param {number} x0 - The starting X coordinate. 25896 * @param {number} y0 - The starting Y coordinate. 25897 * @param {number} x1 - The X coordinate of the first control point. 25898 * @param {number} y1 - The Y coordinate of the first control point. 25899 * @param {number} x2 - The X coordinate of the second control point. 25900 * @param {number} y2 - The Y coordinate of the second control point. 25901 * @param {number} x - The ending X coordinate. 25902 * @param {number} y - The ending Y coordinate. 25903 */ 25904 BoundingBox.prototype.addBezier = function(x0, y0, x1, y1, x2, y2, x, y) { 25905 var this$1 = this; 25906 25907 // This code is based on http://nishiohirokazu.blogspot.com/2009/06/how-to-calculate-bezier-curves-bounding.html 25908 // and https://github.com/icons8/svg-path-bounding-box 25909 25910 var p0 = [x0, y0]; 25911 var p1 = [x1, y1]; 25912 var p2 = [x2, y2]; 25913 var p3 = [x, y]; 25914 25915 this.addPoint(x0, y0); 25916 this.addPoint(x, y); 25917 25918 for (var i = 0; i <= 1; i++) { 25919 var b = 6 * p0[i] - 12 * p1[i] + 6 * p2[i]; 25920 var a = -3 * p0[i] + 9 * p1[i] - 9 * p2[i] + 3 * p3[i]; 25921 var c = 3 * p1[i] - 3 * p0[i]; 25922 25923 if (a === 0) { 25924 if (b === 0) { 25925 continue; 25926 } 25927 var t = -c / b; 25928 if (0 < t && t < 1) { 25929 if (i === 0) { 25930 this$1.addX(derive(p0[i], p1[i], p2[i], p3[
25930i], t)); 25931 } 25932 if (i === 1) { 25933 this$1.addY(derive(p0[i], p1[i], p2[i], p3[i], t)); 25934 } 25935 } 25936 continue; 25937 } 25938 25939 var b2ac = Math.pow(b, 2) - 4 * c * a; 25940 if (b2ac < 0) { 25941 continue; 25942 } 25943 var t1 = (-b + Math.sqrt(b2ac)) / (2 * a); 25944 if (0 < t1 && t1 < 1) { 25945 if (i === 0) { 25946 this$1.addX(derive(p0[i], p1[i], p2[i], p3[i], t1)); 25947 } 25948 if (i === 1) { 25949 this$1.addY(derive(p0[i], p1[i], p2[i], p3[i], t1)); 25950 } 25951 } 25952 var t2 = (-b - Math.sqrt(b2ac)) / (2 * a); 25953 if (0 < t2 && t2 < 1) { 25954 if (i === 0) { 25955 this$1.addX(derive(p0[i], p1[i], p2[i], p3[i], t2)); 25956 } 25957 if (i === 1) { 25958 this$1.addY(derive(p0[i], p1[i], p2[i], p3[i], t2)); 25959 } 25960 } 25961 } 25962 }; 25963 25964 /** 25965 * Add a quadratic curve to the bounding box. 25966 * This extends the bounding box to include the entire quadratic curve. 25967 * @param {number} x0 - The starting X coordinate. 25968 * @param {number} y0 - The starting Y coordinate. 25969 * @param {number} x1 - The X coordinate of the control point. 25970 * @param {number} y1 - The Y coordinate of the control point. 25971 * @param {number} x - The ending X coordinate. 25972 * @param {number} y - The ending Y coordinate. 25973 */ 25974 BoundingBox.prototype.addQuad = function(x0, y0, x1, y1, x, y) { 25975 var cp1x = x0 + 2 / 3 * (x1 - x0); 25976 var cp1y = y0 + 2 / 3 * (y1 - y0); 25977 var cp2x = cp1x + 1 / 3 * (x - x0); 25978 var cp2y = cp1y + 1 / 3 * (y - y0); 25979 this.addBezier(x0, y0, cp1x, cp1y, cp2x, cp2y, x, y); 25980 }; 25981 25982 // Geometric objects 25983 25984 /** 25985 * A bézier path containing a set of path commands similar to a SVG path. 25986 * Paths can be drawn on a context using `draw`. 25987 * @exports opentype.Path 25988 * @class 25989 * @constructor 25990 */ 25991 function Path() { 25992 this.commands = []; 25993 this.fill = 'black'; 25994 this.stroke = null; 25995 this.strokeWidth = 1; 25996 } 25997 25998 /** 25999 * @param {number} x 26000 * @param {number} y 26001 */ 26002 Path.prototype.moveTo = function(x, y) { 26003 this.commands.push({ 26004 type: 'M', 26005 x: x, 26006 y: y 26007 }); 26008 }; 26009 26010 /** 26011 * @param {number} x 26012 * @param {number} y 26013 */ 26014 Path.prototype.lineTo = function(x, y) { 26015 this.commands.push({ 26016 type: 'L', 26017 x: x, 26018 y: y 26019 }); 26020 }; 26021 26022 /** 26023 * Draws cubic curve 26024 * @function 26025 * curveTo 26026 * @memberof opentype.Path.prototype 26027 * @param {number} x1 - x of control 1 26028 * @param {number} y1 - y of control 1 26029 * @param {number} x2 - x of control 2 26030 * @param {number} y2 - y of control 2 26031 * @param {number} x - x of path point 26032 * @param {number} y - y of path point 26033 */ 26034 26035 /** 26036 * Draws cubic curve 26037 * @function 26038 * bezierCurveTo 26039 * @memberof opentype.Path.prototype 26040 * @param {number} x1 - x of control 1 26041 * @param {number} y1 - y of control 1 26042 * @param {number} x2 - x of control 2 26043 * @param {number} y2 - y of control 2 26044 * @param {number} x - x of path point 26045 * @param {number} y - y of path point 26046 * @see curveTo 26047 */ 26048 Path.prototype.curveTo = Path.prototype.bezierCurveTo = function( 26049 x1, 26050 y1, 26051 x2, 26052 y2, 26053 x, 26054 y 26055 ) { 26056 this.commands.push({ 26057 type: 'C', 26058 x1: x1, 26059 y1: y1, 26060 x2: x2, 26061 y2: y2, 26062 x: x, 26063 y: y 26064 }); 26065 }; 26066 26067 /** 26068 * Draws quadratic curve 26069 * @function 26070 * quadraticCurveTo 26071 * @memberof opentype.Path.prototype 26072 * @param {number} x1 - x of control 26073 * @param {number} y1 - y of control 26074 * @param {number} x - x of path point 26075 * @param {number} y - y of path point 26076 */ 26077 26078 /** 26079 * Draws quadratic curve 26080 * @function 26081 * quadTo 26082 * @memberof opentype.Path.prototype 26083 * @param {number} x1 - x of control 26084 * @param {number} y1 - y of control 26085 * @param {number} x - x of path point 26086 * @param {number} y - y of path point 26087 */ 26088 Path.prototype.quadTo = Path.prototype.quadraticCurveTo = function( 26089 x1, 26090 y1, 26091 x, 26092 y 26093 ) { 26094 this.commands.push({ 26095 type: 'Q', 26096 x1: x1, 26097 y1: y1, 26098 x: x, 26099 y: y 26100 }); 26101 }; 26102 26103 /** 26104 * Closes the path 26105 * @function closePath 26106 * @memberof opentype.Path.prototype 26107 */ 26108 26109 /** 26110 * Close the path 26111 * @function close 26112 * @memberof opentype.Path.prototype 26113 */ 26114 Path.prototype.close = Path.prototype.closePath = function() { 26115 this.commands.push({ 26116 type: 'Z' 26117 }); 26118 }; 26119 26120 /** 26121 * Add the given path or list of commands to the commands of this path. 26122 * @param {Array} pathOrCommands - another opentype.Path, an opentype.BoundingBox, or an array of commands. 26123 */ 26124 Path.prototype.extend = function(pathOrCommands) { 26125 if (pathOrCommands.commands) { 26126 pathOrCommands = pathOrCommands.commands; 26127 } else if (pathOrCommands instanceof BoundingBox) { 26128 var box = pathOrCommands; 26129 this.moveTo(box.x1, box.y1); 26130 this.lineTo(box.x2, box.y1); 26131 this.lineTo(box.x2, box.y2); 26132 this.lineTo(box.x1, box.y2); 26133 this.close(); 26134 return; 26135 } 26136 26137 Array.prototype.push.apply(this.commands, pathOrCommands); 26138 }; 26139 26140 /** 26141 * Calculate the bounding box of the path.
26142 * @returns {opentype.BoundingBox} 26143 */ 26144 Path.prototype.getBoundingBox = function() { 26145 var this$1 = this; 26146 26147 var box = new BoundingBox(); 26148 26149 var startX = 0; 26150 var startY = 0; 26151 var prevX = 0; 26152 var prevY = 0; 26153 for (var i = 0; i < this.commands.length; i++) { 26154 var cmd = this$1.commands[i]; 26155 switch (cmd.type) { 26156 case 'M': 26157 box.addPoint(cmd.x, cmd.y); 26158 startX = prevX = cmd.x; 26159 startY = prevY = cmd.y; 26160 break; 26161 case 'L': 26162 box.addPoint(cmd.x, cmd.y); 26163 prevX = cmd.x; 26164 prevY = cmd.y; 26165 break; 26166 case 'Q': 26167 box.addQuad(prevX, prevY, cmd.x1, cmd.y1, cmd.x, cmd.y); 26168 prevX = cmd.x; 26169 prevY = cmd.y; 26170 break; 26171 case 'C': 26172 box.addBezier( 26173 prevX, 26174 prevY, 26175 cmd.x1, 26176 cmd.y1, 26177 cmd.x2, 26178 cmd.y2, 26179 cmd.x, 26180 cmd.y 26181 ); 26182 prevX = cmd.x; 26183 prevY = cmd.y; 26184 break; 26185 case 'Z': 26186 prevX = startX; 26187 prevY = startY; 26188 break; 26189 default: 26190 throw new Error('Unexpected path command ' + cmd.type); 26191 } 26192 } 26193 if (box.isEmpty()) { 26194 box.addPoint(0, 0); 26195 } 26196 return box; 26197 }; 26198 26199 /** 26200 * Draw the path to a 2D context. 26201 * @param {CanvasRenderingContext2D} ctx - A 2D drawing context. 26202 */ 26203 Path.prototype.draw = function(ctx) { 26204 var this$1 = this; 26205 26206 ctx.beginPath(); 26207 for (var i = 0; i < this.commands.length; i += 1) { 26208 var cmd = this$1.commands[i]; 26209 if (cmd.type === 'M') { 26210 ctx.moveTo(cmd.x, cmd.y); 26211 } else if (cmd.type === 'L') { 26212 ctx.lineTo(cmd.x, cmd.y); 26213 } else if (cmd.type === 'C') { 26214 ctx.bezierCurveTo(cmd.x1, cmd.y1, cmd.x2, cmd.y2, cmd.x, cmd.y); 26215 } else if (cmd.type === 'Q') { 26216 ctx.quadraticCurveTo(cmd.x1, cmd.y1, cmd.x, cmd.y); 26217 } else if (cmd.type === 'Z') { 26218 ctx.closePath(); 26219 } 26220 } 26221 26222 if (this.fill) { 26223 ctx.fillStyle = this.fill; 26224 ctx.fill(); 26225 } 26226 26227 if (this.stroke) { 26228 ctx.strokeStyle = this.stroke; 26229 ctx.lineWidth = this.strokeWidth; 26230 ctx.stroke(); 26231 } 26232 }; 26233 26234 /** 26235 * Convert the Path to a string of path data instructions 26236 * See http://www.w3.org/TR/SVG/paths.html#PathData 26237 * @param {number} [decimalPlaces=2] - The amount of decimal places for floating-point values 26238 * @return {string} 26239 */ 26240 Path.prototype.toPathData = function(decimalPlaces) { 26241 var this$1 = this; 26242 26243 decimalPlaces = decimalPlaces !== undefined ? decimalPlaces : 2; 26244 26245 function floatToString(v) { 26246 if (Math.round(v) === v) { 26247 return '' + Math.round(v); 26248 } else { 26249 return v.toFixed(decimalPlaces); 26250 } 26251 } 26252 26253 function packValues() { 26254 var arguments$1 = arguments; 26255 26256 var s = ''; 26257 for (var i = 0; i < arguments.length; i += 1) { 26258 var v = arguments$1[i]; 26259 if (v >= 0 && i > 0) { 26260 s += ' '; 26261 } 26262 26263 s += floatToString(v); 26264 } 26265 26266 return s; 26267 } 26268 26269 var d = ''; 26270 for (var i = 0; i < this.commands.length; i += 1) { 26271 var cmd = this$1.commands[i]; 26272 if (cmd.type === 'M') { 26273 d += 'M' + packValues(cmd.x, cmd.y); 26274 } else if (cmd.type === 'L') { 26275 d += 'L' + packValues(cmd.x, cmd.y); 26276 } else if (cmd.type === 'C') { 26277 d += 'C' + packValues(cmd.x1, cmd.y1, cmd.x2, cmd.y2, cmd.x, cmd.y); 26278 } else if (cmd.type === 'Q') { 26279 d += 'Q' + packValues(cmd.x1, cmd.y1, cmd.x, cmd.y); 26280 } else if (cmd.type === 'Z') { 26281 d += 'Z'; 26282 } 26283 } 26284 26285 return d; 26286 }; 26287 26288 /** 26289 * Convert the path to an SVG <path> element, as a string. 26290 * @param {number} [decimalPlaces=2] - The amount of decimal places for floating-point values 26291 * @return {string} 26292 */ 26293 Path.prototype.toSVG = function(decimalPlaces) { 26294 var svg = '<path d="'; 26295 svg += this.toPathData(decimalPlaces); 26296 svg += '"'; 26297 if (this.fill && this.fill !== 'black') { 26298 if (this.fill === null) { 26299 svg += ' fill="none"'; 26300 } else { 26301 svg += ' fill="' + this.fill + '"'; 26302 } 26303 } 26304 26305 if (this.stroke) { 26306 svg += 26307 ' stroke="' + this.stroke + '" stroke-width="' + this.strokeWidth + '"'; 26308 } 26309 26310 svg += '/>'; 26311 return svg; 26312 }; 26313 26314 /** 26315 * Convert the path to a DOM element. 26316 * @param {number} [decimalPlaces=2] - The amount of decimal places for floating-point values 26317 * @return {SVGPathElement} 26318 */ 26319 Path.prototype.toDOMElement = function(decimalPlaces) { 26320 var temporaryPath = this.toPathData(decimalPlaces); 26321 var newPath = document.createElementNS( 26322 'http://www.w3.org/2000/svg', 26323 'path' 26324 ); 26325 26326 newPath.setAttribute('d', temporaryPath); 26327 26328 return newPath; 26329 }; 26330 26331 // Run-time checking of preconditions. 26332 26333 function fail(message) { 26334 throw new Error(message); 26335 } 26336 26337 // Precondition function that checks if the given predicate is true. 26338 // If not, it will throw an error. 26339 function argument(predicate, message) { 26340 if (!predicate) { 26341 fail(message); 26342 } 26343 } 26344 var check = { fail: fail, argument: argument, assert: argument }; 26345 26346 // Data types used in the OpenType font file. 26347 26348 var LIMIT16 = 32768; // The limit at which a 16-bit number switches signs == 2^15 26349 var LIMIT32 = 2147483648; // The limit at which a 32-bit number switches signs == 2 ^ 31 26350 26351 /** 26352 * @exports opentype.decode 26353 * @class 26354 */ 26355 var decode = {}; 26356 /** 26357 * @exports opentype.encode 26358 * @class 26359 */ 26360 var encode = {}; 26361 /** 26362 * @exports opentype.sizeOf 26363 * @class 26364 */ 26365 var sizeOf = {}; 26366 26367 // Return a function that always returns the same value. 26368 function constant(v) { 26369 return function() { 26370 return v; 26371 }; 26372 } 26373 26374 // OpenType data types ////////////////////////////////////////////////////// 26375 26376 /** 26377 * Convert an 8-bit unsigned integer to a list of 1 byte. 26378 * @param {number} 26379 * @returns {Array} 26380 */ 26381 encode.BYTE = function(v) { 26382 check.argument( 26383 v >= 0 && v <= 255, 26384 'Byte value should be between 0 and 255.' 26385 ); 26386 return [v]; 26387 }; 26388 /** 26389 * @constant 26390 * @type {number} 26391 */ 26392 sizeOf.BYTE = constant(1); 26393 26394 /** 26395 * Convert a 8-bit signed integer to a list of 1 byte. 26396 * @param {string} 26397 * @returns {Array} 26398 */ 26399 encode.CHAR = function(v) { 26400 return [v.charCodeAt(0)]; 26401 }; 26402 26403 /** 26404 * @constant 26405 * @type {number} 26406 */ 26407 sizeOf.CHAR = constant(1); 26408 26409 /**
26410 * Convert an ASCII string to a list of bytes. 26411 * @param {string} 26412 * @returns {Array} 26413 */ 26414 encode.CHARARRAY = function(v) { 26415 var b = []; 26416 for (var i = 0; i < v.length; i += 1) { 26417 b[i] = v.charCodeAt(i); 26418 } 26419 26420 return b; 26421 }; 26422 26423 /** 26424 * @param {Array} 26425 * @returns {number} 26426 */ 26427 sizeOf.CHARARRAY = function(v) { 26428 return v.length; 26429 }; 26430 26431 /** 26432 * Convert a 16-bit unsigned integer to a list of 2 bytes. 26433 * @param {number} 26434 * @returns {Array} 26435 */ 26436 encode.USHORT = function(v) { 26437 return [(v >> 8) & 0xff, v & 0xff]; 26438 }; 26439 26440 /** 26441 * @constant 26442 * @type {number} 26443 */ 26444 sizeOf.USHORT = constant(2); 26445 26446 /** 26447 * Convert a 16-bit signed integer to a list of 2 bytes. 26448 * @param {number} 26449 * @returns {Array} 26450 */ 26451 encode.SHORT = function(v) { 26452 // Two's complement 26453 if (v >= LIMIT16) { 26454 v = -(2 * LIMIT16 - v); 26455 } 26456 26457 return [(v >> 8) & 0xff, v & 0xff]; 26458 }; 26459 26460 /** 26461 * @constant 26462 * @type {number} 26463 */
26464 sizeOf.SHORT = constant(2); 26465 26466 /** 26467 * Convert a 24-bit unsigned integer to a list of 3 bytes. 26468 * @param {number} 26469 * @returns {Array} 26470 */ 26471 encode.UINT24 = function(v) { 26472 return [(v >> 16) & 0xff, (v >> 8) & 0xff, v & 0xff]; 26473 }; 26474 26475 /** 26476 * @constant 26477 * @type {number} 26478 */ 26479 sizeOf.UINT24 = constant(3); 26480 26481 /** 26482 * Convert a 32-bit unsigned integer to a list of 4 bytes. 26483 * @param {number} 26484 * @returns {Array} 26485 */ 26486 encode.ULONG = function(v) { 26487 return [(v >> 24) & 0xff, (v >> 16) & 0xff, (v >> 8) & 0xff, v & 0xff]; 26488 }; 26489 26490 /** 26491 * @constant 26492 * @type {number} 26493 */ 26494 sizeOf.ULONG = constant(4); 26495 26496 /** 26497 * Convert a 32-bit unsigned integer to a list of 4 bytes. 26498 * @param {number} 26499 * @returns {Array} 26500 */ 26501 encode.LONG = function(v) { 26502 // Two's complement 26503 if (v >= LIMIT32) { 26504 v = -(2 * LIMIT32 - v); 26505 } 26506 26507 return [(v >> 24) & 0xff, (v >> 16) & 0xff, (v >> 8) & 0xff, v & 0xff]; 26508 }; 26509 26510 /** 26511 * @constant 26512 * @type {number} 26513 */ 26514 sizeOf.LONG = constant(4); 26515 26516 encode.FIXED = encode.ULONG; 26517 sizeOf.FIXED = sizeOf.ULONG; 26518 26519 encode.FWORD = encode.SHORT; 26520 sizeOf.FWORD = sizeOf.SHORT; 26521 26522 encode.UFWORD = encode.USHORT; 26523 sizeOf.UFWORD = sizeOf.USHORT; 26524 26525 /** 26526 * Convert a 32-bit Apple Mac timestamp integer to a list of 8 bytes, 64-bit timestamp. 26527 * @param {number} 26528 * @returns {Array} 26529 */ 26530 encode.LONGDATETIME = function(v) { 26531 return [ 26532 0, 26533 0, 26534 0, 26535 0, 26536 (v >> 24) & 0xff, 26537 (v >> 16) & 0xff, 26538 (v >> 8) & 0xff, 26539 v & 0xff 26540 ]; 26541 }; 26542 26543 /** 26544 * @constant 26545 * @type {number} 26546 */ 26547 sizeOf.LONGDATETIME = constant(8); 26548 26549 /** 26550 * Convert a 4-char tag to a list of 4 bytes. 26551 * @param {string} 26552 * @returns {Array} 26553 */ 26554 encode.TAG = function(v) { 26555 check.argument(v.length === 4, 'Tag should be exactly 4 ASCII characters.'); 26556 return [v.charCodeAt(0), v.charCodeAt(1), v.charCodeAt(2), v.charCodeAt(3)]; 26557 }; 26558 26559 /** 26560 * @constant 26561 * @type {number} 26562 */ 26563 sizeOf.TAG = constant(4); 26564 26565 // CFF data types /////////////////////////////////////////////////////////// 26566 26567 encode.Card8 = encode.BYTE; 26568 sizeOf.Card8 = sizeOf.BYTE; 26569 26570 encode.Card16 = encode.USHORT; 26571 sizeOf.Card16 = sizeOf.USHORT; 26572 26573 encode.OffSize = encode.BYTE; 26574 sizeOf.OffSize = sizeOf.BYTE; 26575 26576 encode.SID = encode.USHORT;
26577 sizeOf.SID = sizeOf.USHORT; 26578 26579 // Convert a numeric operand or charstring number to a variable-size list of bytes. 26580 /** 26581 * Convert a numeric operand or charstring number to a variable-size list of bytes. 26582 * @param {number} 26583 * @returns {Array} 26584 */ 26585 encode.NUMBER = function(v) { 26586 if (v >= -107 && v <= 107) { 26587 return [v + 139]; 26588 } else if (v >= 108 && v <= 1131) { 26589 v = v - 108; 26590 return [(v >> 8) + 247, v & 0xff]; 26591 } else if (v >= -1131 && v <= -108) { 26592 v = -v - 108; 26593 return [(v >> 8) + 251, v & 0xff]; 26594 } else if (v >= -32768 && v <= 32767) { 26595 return encode.NUMBER16(v); 26596 } else { 26597 return encode.NUMBER32(v); 26598 } 26599 }; 26600 26601 /** 26602 * @param {number} 26603 * @returns {number} 26604 */ 26605 sizeOf.NUMBER = function(v) { 26606 return encode.NUMBER(v).length; 26607 }; 26608 26609 /** 26610 * Convert a signed number between -32768 and +32767 to a three-byte value. 26611 * This ensures we always use three bytes, but is not the most compact format. 26612 * @param {number} 26613 * @returns {Array} 26614 */ 26615 encode.NUMBER16 = function(v) { 26616 return [28, (v >> 8) & 0xff, v & 0xff]; 26617 }; 26618 26619 /** 26620 * @constant 26621 * @type {number} 26622 */ 26623 sizeOf.NUMBER16 = constant(3); 26624 26625 /** 26626 * Convert a signed number between -(2^31) and +(2^31-1) to a five-byte value. 26627 * This is useful if you want to be sure you always use four bytes, 26628 * at the expense of wasting a few bytes for smaller numbers. 26629 * @param {number} 26630 * @returns {Array} 26631 */ 26632 encode.NUMBER32 = function(v) { 26633 return [29, (v >> 24) & 0xff, (v >> 16) & 0xff, (v >> 8) & 0xff, v & 0xff]; 26634 }; 26635 26636 /** 26637 * @constant 26638 * @type {number} 26639 */ 26640 sizeOf.NUMBER32 = constant(5); 26641 26642 /** 26643 * @param {number} 26644 * @returns {Array} 26645 */ 26646 encode.REAL = function(v) { 26647 var value = v.toString(); 26648 26649 // Some numbers use an epsilon to encode the value. (e.g. JavaScript will store 0.0000001 as 1e-7) 26650 // This code converts it back to a number without the epsilon. 26651 var m = /\.(\d*?)(?:9{5,20}|0{5,20})\d{0,2}(?:e(.+)|$)/.exec(value); 26652 if (m) { 26653 var epsilon = parseFloat('1e' + ((m[2] ? +m[2] : 0) + m[1].length)); 26654 value = (Math.round(v * epsilon) / epsilon).toString(); 26655 } 26656 26657 var nibbles = ''; 26658 for (var i = 0, ii = value.length; i < ii; i += 1) { 26659 var c = value[i]; 26660 if (c === 'e') { 26661 nibbles += value[++i] === '-' ? 'c' : 'b'; 26662 } else if (c === '.') { 26663 nibbles += 'a'; 26664 } else if (c === '-') { 26665 nibbles += 'e'; 26666 } else { 26667 nibbles += c; 26668 } 26669 } 26670 26671 nibbles += nibbles.length & 1 ? 'f' : 'ff'; 26672 var out = [30]; 26673 for (var i$1 = 0, ii$1 = nibbles.length; i$1 < ii$1; i$1 += 2) { 26674 out.push(parseInt(nibbles.substr(i$1, 2), 16)); 26675 } 26676 26677 return out; 26678 }; 26679 26680 /** 26681 * @param {number} 26682 * @returns {number} 26683 */ 26684 sizeOf.REAL = function(v) { 26685 return encode.REAL(v).length; 26686 }; 26687 26688 encode.NAME = encode.CHARARRAY; 26689 sizeOf.NAME = sizeOf.CHARARRAY; 26690 26691 encode.STRING = encode.CHARARRAY;
26692 sizeOf.STRING = sizeOf.CHARARRAY; 26693 26694 /** 26695 * @param {DataView} data 26696 * @param {number} offset 26697 * @param {number} numBytes 26698 * @returns {string} 26699 */ 26700 decode.UTF8 = function(data, offset, numBytes) { 26701 var codePoints = []; 26702 var numChars = numBytes; 26703 for (var j = 0; j < numChars; j++, offset += 1) { 26704 codePoints[j] = data.getUint8(offset); 26705 } 26706 26707 return String.fromCharCode.apply(null, codePoints); 26708 }; 26709 26710 /** 26711 * @param {DataView} data 26712 * @param {number} offset 26713 * @param {number} numBytes 26714 * @returns {string} 26715 */ 26716 decode.UTF16 = function(data, offset, numBytes) { 26717 var codePoints = []; 26718 var numChars = numBytes / 2; 26719 for (var j = 0; j < numChars; j++, offset += 2) { 26720 codePoints[j] = data.getUint16(offset); 26721 } 26722 26723 return String.fromCharCode.apply(null, codePoints); 26724 }; 26725 26726 /** 26727 * Convert a JavaScript string to UTF16-BE. 26728 * @param {string} 26729 * @returns {Array} 26730 */ 26731 encode.UTF16 = function(v) { 26732 var b = []; 26733 for (var i = 0; i < v.length; i += 1) { 26734 var codepoint = v.charCodeAt(i); 26735 b[b.length] = (codepoint >> 8) & 0xff;
26736 b[b.length] = codepoint & 0xff; 26737 } 26738 26739 return b; 26740 }; 26741 26742 /** 26743 * @param {string} 26744 * @returns {number} 26745 */ 26746 sizeOf.UTF16 = function(v) { 26747 return v.length * 2; 26748 }; 26749 26750 // Data for converting old eight-bit Macintosh encodings to Unicode. 26751 // This representation is optimized for decoding; encoding is slower 26752 // and needs more memory. The assumption is that all opentype.js users 26753 // want to open fonts, but saving a font will be comparatively rare 26754 // so it can be more expensive. Keyed by IANA character set name. 26755 // 26756 // Python script for generating these strings: 26757 // 26758 // s = u''.join([chr(c).decode('mac_greek') for c in range(128, 256)]) 26759 // print(s.encode('utf-8')) 26760 /** 26761 * @private 26762 */ 26763 var eightBitMacEncodings = { 26764 // Python: 'mac_croatian' 26765 'x-mac-croatian': 26766 'Ãà ÃÃÃÃÃáà âäãåçéèêëÃìîïñóòôöõúùûüâ °¢£§â¢Â¶Ã®Šâ¢Â´Â¨â ŽÃâ±â¤â¥âµâââÅ¡â«ÂªÂºÎ©Å¾Ã¸' + 26767 '¿¡¬âÆâÄ«Äâ¦Â ÃÃÃÅÅÄâââââ÷â©ââ¬â¹âºÃ»â·âââ°ÃÄÃÄÃÃÃÃÃÃÃÄÃÃÃÃıË˯ÏÃË¸ÃæË', 26768 // Python: 'mac_cyrillic' 26769 'x-mac-cyrillic': 26770 'ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐРСТУФХЦЧШЩЪЫЬÐЮЯâ °Ò£§â¢Â¶Ð®©â¢ÐÑâ ÐÑâ±â¤â¥ÑµÒÐÐÑÐÑÐÑÐÑ' + 26771 'ÑР¬âÆââ«»â¦Â ÐÑÐÑÑââââââ÷âÐÑÐÑâÐÑÑабвгдежзийклмнопÑÑÑÑÑÑ ÑÑÑÑÑÑÑÑÑ', 26772 // http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/GAELIC.TXT 26773 'x-mac-gaelic': 26774 'Ãà ÃÃÃÃÃáà âäãåçéèêëÃìîïñóòôöõúùûüâ °¢£§â¢Â¶Ã®©â¢Â´Â¨â ÃÃá¸Â±â¤â¥á¸ÄÄá¸á¸á¸á¸Ä Ä¡á¹Ã¦Ã¸' + 26775 'á¹á¹á¹É¼ÆÅ¿á¹ «»â¦Â ÃÃÃÅÅââââââṡáºÃ¿Å¸á¹ªâ¬â¹âºÅ¶Å·á¹«Â·á»²á»³âÃÃÃÃÃÃÃÃÃÃÃâ£ÃÃÃÃıÃýŴŵáºáº áºáºáºáº', 26776 // Python: 'mac_greek' 26777 'x-mac-greek': 26778 'ù²Ã³ÃÃΠà âäΨçéèêë£â¢Ã®Ã¯â¢Â½â°Ã´Ã¶Â¦â¬Ã¹Ã»Ã¼â ÎÎÎÎÎΠî©ΣΪ§â °·Î±â¤â¥Â¥ÎÎÎÎÎÎÎΦΫΨΩ' + 26779 'άάÎΡâΤ«»â¦Â ΥΧÎÎÅââââââ÷ÎÎÎÎÎήίÏÎÏαβÏδεÏγηιξκλμνοÏÏÏÏÏθÏÏÏÏ Î¶ÏÏÎΰ\u00AD', 26780 // Python: 'mac_iceland' 26781 'x-mac-icelandic': 26782 'Ãà ÃÃÃÃÃáà âäãåçéèêëÃìîïñóòôöõúùûü𢣧â¢Â¶Ã®©â¢Â´Â¨â ÃÃâ±â¤â¥Â¥ÂµâââÏâ«ÂªÂºÎ©Ã¦Ã¸' + 26783 '¿¡¬âÆââ«»â¦Â ÃÃÃÅÅââââââ÷âÿŸââ¬ÃðÃþý·âââ°ÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃıË˯ËË˸ËËË', 26784 // http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/INUIT.TXT 26785 'x-mac-inuit': 26786 'ááá áááá±á²á³á´á¸á¹áááááááá¦áá®á¯á°á²á³ááááááá°á¡á¥á¦â¢Â¶á§Â®Â©â¢á¨áªá«á»áááá áááá¯á°á±á²á´áµá ááá' + 26787 'ááááªá¨á©áªá«áâ¦Â á®á¾áááââââââáááááááááááá¿áááááá áááááááá±á²á³á´áµá¶áá á¡á¢á£á¤á¥á¦á¼ÅÅ', 26788 // Python: 'mac_latin2' 26789 'x-mac-ce': 26790 'ÃÄÄÃÄÃÃÃ¡Ä ÄäÄÄÄ鏟ÄÃÄÄÄÄóÄôöõúÄÄüâ °Ä£§â¢Â¶Ã®©â¢Ä¨â ģĮįĪâ¤â¥Ä«Ä¶ââÅĻļĽľĹĺŠ' + 26791 'ÅŬâÅÅâ«»â¦Â ÅÅÃÅÅââââââ÷âÅÅÅÅâ¹âºÅÅÅÅ ââÅ¡ÅÅÃŤťÃŽžŪÃÃūŮÃůŰűŲųÃýķŻÅżĢË', 26792 // Python: 'mac_roman' 26793 macintosh: 26794 'Ãà ÃÃÃÃÃáà âäãåçéèêëÃìîïñóòôöõúùûüâ °¢£§â¢Â¶Ã®©â¢Â´Â¨â ÃÃâ±â¤â¥Â¥ÂµâââÏâ«ÂªÂºÎ©Ã¦Ã¸' + 26795 '¿¡¬âÆââ«»â¦Â ÃÃÃÅÅââââââ÷âÿŸââ¬â¹âºï¬ï¬â¡Â·âââ°ÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃıË˯ËË˸ËËË', 26796 // Python: 'mac_romanian' 26797 'x-mac-romanian': 26798 'Ãà ÃÃÃÃÃáà âäãåçéèêëÃìîïñóòôöõúùûüâ °¢£§â¢Â¶Ã®©â¢Â´Â¨â ÄÈâ±â¤â¥Â¥ÂµâââÏâ«ÂªÂºÎ©ÄÈ' + 26799 '¿¡¬âÆââ«»â¦Â ÃÃÃÅÅââââââ÷âÿŸââ¬â¹âºÈÈâ¡Â·âââ°ÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃıË˯ËË˸ËËË', 26800 // Python: 'mac_turkish' 26801 'x-mac-turkish': 26802 'Ãà ÃÃÃÃÃáà âäãåçéèêëÃìîïñóòôöõúùûüâ °¢£§â¢Â¶Ã®©â¢Â´Â¨â ÃÃâ±â¤â¥Â¥ÂµâââÏâ«ÂªÂºÎ©Ã¦Ã¸' + 26803 '¿¡¬âÆââ«»â¦Â ÃÃÃÅÅââââââ÷âÿŸÄÄİıÅÅâ¡Â·âââ°ÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃï¢ Ë˯ËË˸ËËË' 26804 }; 26805 26806 /** 26807 * Decodes an old-style Macintosh string. Returns either a Unicode JavaScript 26808 * string, or 'undefined' if the encoding is unsupported. For example, we do 26809 * not support Chinese, Japanese or Korean because these would need large 26810 * mapping tables. 26811 * @param {DataView} dataView 26812 * @param {number} offset 26813 * @param {number} dataLength 26814 * @param {string} encoding 26815 * @returns {string} 26816 */ 26817 decode.MACSTRING = function(dataView, offset, dataLength, encoding) { 26818 var table = eightBitMacEncodings[encoding]; 26819 if (table === undefined) { 26820 return undefined; 26821 } 26822 26823 var result = ''; 26824 for (var i = 0; i < dataLength; i++) { 26825 var c = dataView.getUint8(offset + i); 26826 // In all eight-bit Mac encodings, the characters 0x00..0x7F are 26827 // mapped to U+0000..U+007F; we only need to look up the others. 26828 if (c <= 0x7f) { 26829 result += String.fromCharCode(c); 26830 } else { 26831 result += table[c & 0x7f]; 26832 } 26833 } 26834 26835 return result; 26836 }; 26837 26838 // Helper function for encode.MACSTRING. Returns a dictionary for mapping 26839 // Unicode character codes to their 8-bit MacOS equivalent. This table 26840 // is not exactly a super cheap data structure, but we do not care because 26841 // encoding Macintosh strings is only rarely needed in typical applications. 26842 var macEncodingTableCache = typeof WeakMap === 'function' && new WeakMap(); 26843 var macEncodingCacheKeys; 26844 var getMacEncodingTable = function(encoding) { 26845 // Since we use encoding as a cache key for WeakMap, it has to be 26846 // a String object and not a literal. And at least on NodeJS 2.10.1, 26847 // WeakMap requires that the same String instance is passed for cache hits. 26848 if (!macEncodingCacheKeys) { 26849 macEncodingCacheKeys = {}; 26850 for (var e in eightBitMacEncodings) { 26851 /*jshint -W053 */ // Suppress "Do not use String as a constructor." 26852 macEncodingCacheKeys[e] = new String(e); 26853 } 26854 } 26855 26856 var cacheKey = macEncodingCacheKeys[encoding]; 26857 if (cacheKey === undefined) { 26858 return undefined; 26859 } 26860 26861 // We can't do "if (cache.has(key)) {return cache.get(key)}" here: 26862 // since garbage collection may run at any time, it could also kick in 26863 // between the calls to cache.has() and cache.get(). In that case, 26864 // we would return 'undefined' even though we do support the encoding. 26865 if (macEncodingTableCache) { 26866 var cachedTable = macEncodingTableCache.get(cacheKey); 26867 if (cachedTable !== undefined) { 26868 return cachedTable; 26869 } 26870 } 26871 26872 var decodingTable = eightBitMacEncodings[encoding]; 26873 if (decodingTable === undefined) { 26874 return undefined; 26875 } 26876 26877 var encodingTable = {}; 26878 for (var i = 0; i < decodingTable.length; i++) { 26879 encodingTable[decodingTable.charCodeAt(i)] = i + 0x80; 26880 } 26881 26882 if (macEncodingTableCache) { 26883 macEncodingTableCache.set(cacheKey, encodingTable); 26884 } 26885 26886 return encodingTable; 26887 }; 26888 26889 /** 26890 * Encodes an old-style Macintosh string. Returns a byte array upon success. 26891 * If the requested encoding is unsupported, or if the input string contains 26892 * a character that cannot be expressed in the encoding, the function returns 26893 * 'undefined'. 26894 * @param {string} str 26895 * @param {string} encoding 26896 * @returns {Array} 26897 */ 26898 encode.MACSTRING = function(str, encoding) { 26899 var table = getMacEncodingTable(encoding); 26900 if (table === undefined) { 26901 return undefined; 26902 } 26903 26904 var result = []; 26905 for (var i = 0; i < str.length; i++) { 26906 var c = str.charCodeAt(i); 26907 26908 // In all eight-bit Mac encodings, the characters 0x00..0x7F are 26909 // mapped to U+0000..U+007F; we only need to look up the others. 26910 if (c >= 0x80) { 26911 c = table[c]; 26912 if (c === undefined) { 26913 // str contains a Unicode character that cannot be encoded 26914 // in the requested encoding. 26915 return undefined; 26916 } 26917 } 26918 result[i] = c; 26919 // result.push(c); 26920 } 26921 26922 return result; 26923 }; 26924 26925 /** 26926 * @param {string} str 26927 * @param {string} encoding 26928 * @returns {number} 26929 */ 26930 sizeOf.MACSTRING = function(str, encoding) { 26931 var b = encode.MACSTRING(str, encoding); 26932 if (b !== undefined) { 26933 return b.length; 26934 } else { 26935 return 0; 26936 } 26937 }; 26938 26939 // Helper for encode.VARDELTAS 26940 function isByteEncodable(value) { 26941 return value >= -128 && value <= 127; 26942 } 26943 26944 // Helper for encode.VARDELTAS 26945 function encodeVarDeltaRunAsZeroes(deltas, pos, result) { 26946 var runLength = 0; 26947 var numDeltas = deltas.length; 26948 while (pos < numDeltas && runLength < 64 && deltas[pos] === 0) { 26949 ++pos; 26950 ++runLength; 26951 } 26952 result.push(0x80 | (runLength - 1)); 26953 return pos; 26954 } 26955 26956 // Helper for encode.VARDELTAS 26957 function encodeVarDeltaRunAsBytes(deltas, offset, result) { 26958 var runLength = 0; 26959 var numDeltas = deltas.length; 26960 var pos = offset; 26961 while (pos < numDeltas && runLength < 64) { 26962 var value = deltas[pos]; 26963 if (!isByteEncodable(value)) { 26964 break; 26965 } 26966
26967 // Within a byte-encoded run of deltas, a single zero is best 26968 // stored literally as 0x00 value. However, if we have two or 26969 // more zeroes in a sequence, it is better to start a new run. 26970 // Fore example, the sequence of deltas [15, 15, 0, 15, 15] 26971 // becomes 6 bytes (04 0F 0F 00 0F 0F) when storing the zero 26972 // within the current run, but 7 bytes (01 0F 0F 80 01 0F 0F) 26973 // when starting a new run. 26974 if (value === 0 && pos + 1 < numDeltas && deltas[pos + 1] === 0) { 26975 break; 26976 } 26977 26978 ++pos; 26979 ++runLength; 26980 } 26981 result.push(runLength - 1); 26982 for (var i = offset; i < pos; ++i) { 26983 result.push((deltas[i] + 256) & 0xff); 26984 } 26985 return pos; 26986 } 26987 26988 // Helper for encode.VARDELTAS 26989 function encodeVarDeltaRunAsWords(deltas, offset, result) { 26990 var runLength = 0; 26991 var numDeltas = deltas.length; 26992 var pos = offset; 26993 while (pos < numDeltas && runLength < 64) { 26994 var value = deltas[pos]; 26995
26996 // Within a word-encoded run of deltas, it is easiest to start 26997 // a new run (with a different encoding) whenever we encounter 26998 // a zero value. For example, the sequence [0x6666, 0, 0x7777] 26999 // needs 7 bytes when storing the zero inside the current run 27000 // (42 66 66 00 00 77 77), and equally 7 bytes when starting a 27001 // new run (40 66 66 80 40 77 77). 27002 if (value === 0) { 27003 break; 27004 } 27005 27006 // Within a word-encoded run of deltas, a single value in the 27007 // range (-128..127) should be encoded within the current run 27008 // because it is more compact. For example, the sequence 27009 // [0x6666, 2, 0x7777] becomes 7 bytes when storing the value 27010 // literally (42 66 66 00 02 77 77), but 8 bytes when starting 27011 // a new run (40 66 66 00 02 40 77 77). 27012 if ( 27013 isByteEncodable(value) && 27014 pos + 1 < numDeltas && 27015 isByteEncodable(deltas[pos + 1]) 27016 ) { 27017 break; 27018 } 27019 27020 ++pos; 27021 ++runLength; 27022 } 27023 result.push(0x40 | (runLength - 1)); 27024 for (var i = offset; i < pos; ++i) { 27025 var val = deltas[i]; 27026 result.push(((val + 0x10000) >> 8) & 0xff, (val + 0x100) & 0xff); 27027 } 27028 return pos; 27029 } 27030 27031 /** 27032 * Encode a list of variation adjustment deltas. 27033 * 27034 * Variation adjustment deltas are used in âgvarâ and âcvarâ tables. 27035 * They indicate how points (in âgvarâ) or values (in âcvarâ) get adjusted 27036 * when generating instances of variation fonts. 27037 * 27038 * @see https://www.microsoft.com/typography/otspec/gvar.htm 27039 * @see https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6gvar.html 27040 * @param {Array} 27041 * @return {Array} 27042 */ 27043 encode.VARDELTAS = function(deltas) { 27044 var pos = 0; 27045 var result = []; 27046 while (pos < deltas.length) { 27047 var value = deltas[pos]; 27048 if (value === 0) { 27049 pos = encodeVarDeltaRunAsZeroes(deltas, pos, result); 27050 } else if (value >= -128 && value <= 127) { 27051 pos = encodeVarDeltaRunAsBytes(deltas, pos, result); 27052 } else { 27053 pos = encodeVarDeltaRunAsWords(deltas, pos, result); 27054 } 27055 } 27056 return result; 27057 }; 27058 27059 // Convert a list of values to a CFF INDEX structure. 27060 // The values should be objects containing name / type / value. 27061 /** 27062 * @param {Array} l 27063 * @returns {Array} 27064 */ 27065 encode.INDEX = function(l) { 27066 //var offset, offsets, offsetEncoder, encodedOffsets, encodedOffset, data, 27067 // i, v; 27068 // Because we have to know which data type to use to encode the offsets, 27069 // we have to go through the values twice: once to encode the data and 27070 // calculate the offsets, then again to encode the offsets using the fitting data type. 27071 var offset = 1; // First offset is always 1. 27072 var offsets = [offset]; 27073 var data = []; 27074 for (var i = 0; i < l.length; i += 1) { 27075 var v = encode.OBJECT(l[i]); 27076 Array.prototype.push.apply(data, v); 27077 offset += v.length; 27078 offsets.push(offset); 27079 } 27080 27081 if (data.length === 0) { 27082 return [0, 0]; 27083 } 27084 27085 var encodedOffsets = []; 27086 var offSize = (1 + Math.floor(Math.log(offset) / Math.log(2)) / 8) | 0; 27087 var offsetEncoder = [ 27088 undefined, 27089 encode.BYTE, 27090 encode.USHORT, 27091 encode.UINT24, 27092 encode.ULONG 27093 ][offSize]; 27094 for (var i$1 = 0; i$1 < offsets.length; i$1 += 1) { 27095 var encodedOffset = offsetEncoder(offsets[i$1]); 27096 Array.prototype.push.apply(encodedOffsets, encodedOffset); 27097 } 27098 27099 return Array.prototype.concat( 27100 encode.Card16(l.length), 27101 encode.OffSize(offSize), 27102 encodedOffsets, 27103 data 27104 ); 27105 }; 27106 27107 /** 27108 * @param {Array} 27109 * @returns {number} 27110 */ 27111 sizeOf.INDEX = function(v) { 27112 return encode.INDEX(v).length; 27113 }; 27114 27115 /** 27116 * Convert an object to a CFF DICT structure. 27117 * The keys should be numeric. 27118 * The values should be objects containing name / type / value. 27119 * @param {Object} m 27120 * @returns {Array} 27121 */ 27122 encode.DICT = function(m) { 27123 var d = []; 27124 var keys = Object.keys(m); 27125 var length = keys.length; 27126 27127 for (var i = 0; i < length; i += 1) { 27128 // Object.keys() return string keys, but our keys are always numeric. 27129 var k = parseInt(keys[i], 0); 27130 var v = m[k]; 27131 // Value comes before the key. 27132 d = d.concat(encode.OPERAND(v.value, v.type)); 27133 d = d.concat(encode.OPERATOR(k)); 27134 } 27135 27136 return d; 27137 }; 27138 27139 /** 27140 * @param {Object} 27141 * @returns {number} 27142 */ 27143 sizeOf.DICT = function(m) { 27144 return encode.DICT(m).length; 27145 }; 27146 27147 /** 27148 * @param {number} 27149 * @returns {Array} 27150 */ 27151 encode.OPERATOR = function(v) { 27152 if (v < 1200) { 27153 return [v]; 27154 } else { 27155 return [12, v - 1200]; 27156 } 27157 }; 27158 27159 /** 27160 * @param {Array} v 27161 * @param {string} 27162 * @returns {Array} 27163 */ 27164 encode.OPERAND = function(v, type) { 27165 var d = []; 27166 if (Array.isArray(type)) { 27167 for (var i = 0; i < type.length; i += 1) { 27168 check.argument( 27169 v.length === type.length,
27170 'Not enough arguments given for type' + type 27171 ); 27172 d = d.concat(encode.OPERAND(v[i], type[i])); 27173 } 27174 } else { 27175 if (type === 'SID') { 27176 d = d.concat(encode.NUMBER(v)); 27177 } else if (type === 'offset') { 27178 // We make it easy for ourselves and always encode offsets as 27179 // 4 bytes. This makes offset calculation for the top dict easier. 27180 d = d.concat(encode.NUMBER32(v)); 27181 } else if (type === 'number') { 27182 d = d.concat(encode.NUMBER(v)); 27183 } else if (type === 'real') { 27184 d = d.concat(encode.REAL(v)); 27185 } else { 27186 throw new Error('Unknown operand type ' + type); 27187 // FIXME Add support for booleans 27188 } 27189 } 27190 27191 return d; 27192 }; 27193 27194 encode.OP = encode.BYTE; 27195 sizeOf.OP = sizeOf.BYTE; 27196 27197 // memoize charstring encoding using WeakMap if available 27198 var wmm = typeof WeakMap === 'function' && new WeakMap(); 27199 27200 /** 27201 * Convert a list of CharString operations to bytes. 27202 * @param {Array} 27203 * @returns {Array} 27204 */ 27205 encode.CHARSTRING = function(ops) { 27206 // See encode.MACSTRING for why we don't do "if (wmm && wmm.has(ops))". 27207 if (wmm) { 27208 var cachedValue = wmm.get(ops); 27209 if (cachedValue !== undefined) { 27210 return cachedValue; 27211 } 27212 } 27213 27214 var d = []; 27215 var length = ops.length; 27216 27217 for (var i = 0; i < length; i += 1) { 27218 var op = ops[i]; 27219 d = d.concat(encode[op.type](op.value)); 27220 } 27221 27222 if (wmm) { 27223 wmm.set(ops, d); 27224 } 27225 27226 return d; 27227 }; 27228 27229 /** 27230 * @param {Array} 27231 * @returns {number} 27232 */ 27233 sizeOf.CHARSTRING = function(ops) { 27234 return encode.CHARSTRING(ops).length; 27235 }; 27236 27237 // Utility functions //////////////////////////////////////////////////////// 27238 27239 /** 27240 * Convert an object containing name / type / value to bytes. 27241 * @param {Object} 27242 * @returns {Array} 27243 */ 27244 encode.OBJECT = function(v) { 27245 var encodingFunction = encode[v.type]; 27246 check.argument( 27247 encodingFunction !== undefined, 27248 'No encoding function for type ' + v.type 27249 ); 27250 return encodingFunction(v.value); 27251 }; 27252 27253 /** 27254 * @param {Object} 27255 * @returns {number} 27256 */ 27257 sizeOf.OBJECT = function(v) { 27258 var sizeOfFunction = sizeOf[v.type]; 27259 check.argument( 27260 sizeOfFunction !== undefined, 27261 'No sizeOf function for type ' + v.type 27262 ); 27263 return sizeOfFunction(v.value); 27264 }; 27265 27266 /** 27267 * Convert a table object to bytes. 27268 * A table contains a list of fields containing the metadata (name, type and default value). 27269 * The table itself has the field values set as attributes. 27270 * @param {opentype.Table} 27271 * @returns {Array} 27272 */ 27273 encode.TABLE = function(table) { 27274 var d = []; 27275 var length = table.fields.length; 27276 var subtables = []; 27277 var subtableOffsets = []; 27278 27279 for (var i = 0; i < length; i += 1) { 27280 var field = table.fields[i]; 27281 var encodingFunction = encode[field.type]; 27282 check.argument( 27283 encodingFunction !== undefined,
27284 'No encoding function for field type ' + 27285 field.type + 27286 ' (' + 27287 field.name + 27288 ')' 27289 ); 27290 var value = table[field.name]; 27291 if (value === undefined) { 27292 value = field.value; 27293 } 27294 27295 var bytes = encodingFunction(value); 27296 27297 if (field.type === 'TABLE') { 27298 subtableOffsets.push(d.length); 27299 d = d.concat([0, 0]); 27300 subtables.push(bytes); 27301 } else { 27302 d = d.concat(bytes); 27303 } 27304 } 27305 27306 for (var i$1 = 0; i$1 < subtables.length; i$1 += 1) { 27307 var o = subtableOffsets[i$1]; 27308 var offset = d.length; 27309 check.argument(offset < 65536, 'Table ' + table.tableName + ' too big.'); 27310 d[o] = offset >> 8; 27311 d[o + 1] = offset & 0xff; 27312 d = d.concat(subtables[i$1]); 27313 } 27314 27315 return d; 27316 }; 27317 27318 /** 27319 * @param {opentype.Table} 27320 * @returns {number} 27321 */ 27322 sizeOf.TABLE = function(table) { 27323 var numBytes = 0; 27324 var length = table.fields.length; 27325 27326 for (var i = 0; i < length; i += 1) { 27327 var field = table.fields[i]; 27328 var sizeOfFunction = sizeOf[field.type]; 27329 check.argument( 27330 sizeOfFunction !== undefined, 27331 'No sizeOf function for field type ' + 27332 field.type + 27333 ' (' + 27334 field.name + 27335 ')' 27336 ); 27337 var value = table[field.name]; 27338 if (value === undefined) { 27339 value = field.value; 27340 } 27341 27342 numBytes += sizeOfFunction(value); 27343 27344 // Subtables take 2 more bytes for offsets. 27345 if (field.type === 'TABLE') { 27346 numBytes += 2; 27347 } 27348 } 27349 27350 return numBytes; 27351 }; 27352 27353 encode.RECORD = encode.TABLE; 27354 sizeOf.RECORD = sizeOf.TABLE; 27355 27356 // Merge in a list of bytes. 27357 encode.LITERAL = function(v) { 27358 return v; 27359 }; 27360 27361 sizeOf.LITERAL = function(v) { 27362 return v.length; 27363 }; 27364 27365 // Table metadata 27366 27367 /** 27368 * @exports opentype.Table 27369 * @class 27370 * @param {string} tableName 27371 * @param {Array} fields 27372 * @param {Object} options 27373 * @constructor 27374 */ 27375 function Table(tableName, fields, options) { 27376 var this$1 = this; 27377 27378 for (var i = 0; i < fields.length; i += 1) { 27379 var field = fields[i]; 27380 this$1[field.name] = field.value; 27381 } 27382 27383 this.tableName = tableName; 27384 this.fields = fields; 27385 if (options) { 27386 var optionKeys = Object.keys(options); 27387 for (var i$1 = 0; i$1 < optionKeys.length; i$1 += 1) { 27388 var k = optionKeys[i$1]; 27389 var v = options[k]; 27390 if (this$1[k] !== undefined) { 27391 this$1[k] = v; 27392 } 27393 } 27394 } 27395 } 27396 27397 /** 27398 * Encodes the table and returns an array of bytes 27399 * @return {Array} 27400 */ 27401 Table.prototype.encode = function() { 27402 return encode.TABLE(this); 27403 }; 27404 27405 /** 27406 * Get the size of the table. 27407 * @return {number} 27408 */ 27409 Table.prototype.sizeOf = function() { 27410 return sizeOf.TABLE(this); 27411 }; 27412 27413 /** 27414 * @private 27415 */ 27416 function ushortList(itemName, list, count) { 27417 if (count === undefined) { 27418 count = list.length; 27419 } 27420 var fields = new Array(list.length + 1); 27421 fields[0] = { name: itemName + 'Count', type: 'USHORT', value: count }; 27422 for (var i = 0; i < list.length; i++) { 27423 fields[i + 1] = { name: itemName + i, type: 'USHORT', value: list[i] }; 27424 } 27425 return fields; 27426 } 27427 27428 /** 27429 * @private 27430 */ 27431 function tableList(itemName, records, itemCallback) { 27432 var count = records.length; 27433 var fields = new Array(count + 1); 27434 fields[0] = { name: itemName + 'Count', type: 'USHORT', value: count }; 27435 for (var i = 0; i < count; i++) { 27436 fields[i + 1] = { 27437 name: itemName + i, 27438 type: 'TABLE', 27439 value: itemCallback(records[i], i) 27440 }; 27441 } 27442 return fields; 27443 } 27444 27445 /** 27446 * @private 27447 */ 27448 function recordList(itemName, records, itemCallback) { 27449 var count = records.length; 27450 var fields = []; 27451 fields[0] = { name: itemName + 'Count', type: 'USHORT', value: count }; 27452 for (var i = 0; i < count; i++) { 27453 fields = fields.concat(itemCallback(records[i], i)); 27454 } 27455 return fields; 27456 } 27457 27458 // Common Layout Tables 27459 27460 /** 27461 * @exports opentype.Coverage 27462 * @class 27463 * @param {opentype.Table} 27464 * @constructor 27465 * @extends opentype.Table 27466 */ 27467 function Coverage(coverageTable) { 27468 if (coverageTable.format === 1) { 27469 Table.call( 27470 this, 27471 'coverageTable', 27472 [{ name: 'coverageFormat', type: 'USHORT', value: 1 }].concat( 27473 ushortList('glyph', coverageTable.glyphs) 27474 ) 27475 ); 27476 } else {
vendor: 4,697 bytes, lines 27477-27583
27477 check.assert(false, "Can't create coverage table format 2 yet."); 27478 } 27479 } 27480 Coverage.prototype = Object.create(Table.prototype); 27481 Coverage.prototype.constructor = Coverage; 27482 27483 function ScriptList(scriptListTable) { 27484 Table.call( 27485 this, 27486 'scriptListTable', 27487 recordList('scriptRecord', scriptListTable, function(scriptRecord, i) { 27488 var script = scriptRecord.script; 27489 var defaultLangSys = script.defaultLangSys; 27490 check.assert( 27491 !!defaultLangSys, 27492 'Unable to write GSUB: script ' + 27493 scriptRecord.tag + 27494 ' has no default language system.' 27495 ); 27496 return [ 27497 { name: 'scriptTag' + i, type: 'TAG', value: scriptRecord.tag }, 27498 { 27499 name: 'script' + i, 27500 type: 'TABLE', 27501 value: new Table( 27502 'scriptTable', 27503 [ 27504 { 27505 name: 'defaultLangSys', 27506 type: 'TABLE', 27507 value: new Table( 27508 'defaultLangSys', 27509 [ 27510 { name: 'lookupOrder', type: 'USHORT', value: 0 }, 27511 { 27512 name: 'reqFeatureIndex', 27513 type: 'USHORT', 27514 value: defaultLangSys.reqFeatureIndex 27515 } 27516 ].concat( 27517 ushortList('featureIndex', defaultLangSys.featureIndexes) 27518 ) 27519 ) 27520 } 27521 ].concat( 27522 recordList('langSys', script.langSysRecords, function( 27523 langSysRecord, 27524 i 27525 ) { 27526 var langSys = langSysRecord.langSys; 27527 return [ 27528 { 27529 name: 'langSysTag' + i, 27530 type: 'TAG', 27531 value: langSysRecord.tag 27532 }, 27533 { 27534 name: 'langSys' + i, 27535 type: 'TABLE', 27536 value: new Table( 27537 'langSys', 27538 [ 27539 { name: 'lookupOrder', type: 'USHORT', value: 0 }, 27540 { 27541 name: 'reqFeatureIndex', 27542 type: 'USHORT', 27543 value: langSys.reqFeatureIndex 27544 } 27545 ].concat( 27546 ushortList('featureIndex', langSys.featureIndexes) 27547 ) 27548 ) 27549 } 27550 ]; 27551 }) 27552 ) 27553 ) 27554 } 27555 ]; 27556 }) 27557 ); 27558 } 27559 ScriptList.prototype = Object.create(Table.prototype); 27560 ScriptList.prototype.constructor = ScriptList; 27561 27562 /** 27563 * @exports opentype.FeatureList 27564 * @class 27565 * @param {opentype.Table} 27566 * @constructor 27567 * @extends opentype.Table 27568 */ 27569 function FeatureList(featureListTable) { 27570 Table.call( 27571 this, 27572 'featureListTable', 27573 recordList('featureRecord', featureListTable, function(featureRecord, i) { 27574 var feature = featureRecord.feature; 27575 return [ 27576 { name: 'featureTag' + i, type: 'TAG', value: featureRecord.tag }, 27577 { 27578 name: 'feature' + i, 27579 type: 'TABLE', 27580 value: new Table( 27581 'featureTable', 27582 [ 27583 {
27584 name: 'featureParams', 27585 type: 'USHORT', 27586 value: feature.featureParams 27587 } 27588 ].concat(ushortList('lookupListIndex', feature.lookupListIndexes)) 27589 ) 27590 } 27591 ]; 27592 }) 27593 ); 27594 } 27595 FeatureList.prototype = Object.create(Table.prototype); 27596 FeatureList.prototype.constructor = FeatureList; 27597 27598 /** 27599 * @exports opentype.LookupList 27600 * @class 27601 * @param {opentype.Table} 27602 * @param {Object} 27603 * @constructor 27604 * @extends opentype.Table 27605 */ 27606 function LookupList(lookupListTable, subtableMakers) { 27607 Table.call( 27608 this, 27609 'lookupListTable', 27610 tableList('lookup', lookupListTable, function(lookupTable) { 27611 var subtableCallback = subtableMakers[lookupTable.lookupType]; 27612 check.assert( 27613 !!subtableCallback, 27614 'Unable to write GSUB lookup type ' + 27615 lookupTable.lookupType + 27616 ' tables.' 27617 ); 27618 return new Table( 27619 'lookupTable', 27620 [ 27621 { 27622 name: 'lookupType', 27623 type: 'USHORT', 27624 value: lookupTable.lookupType 27625 }, 27626 { 27627 name: 'lookupFlag', 27628 type: 'USHORT', 27629 value: lookupTable.lookupFlag 27630 } 27631 ].concat( 27632 tableList('subtable', lookupTable.subtables, subtableCallback) 27633 ) 27634 ); 27635 }) 27636 ); 27637 } 27638 LookupList.prototype = Object.create(Table.prototype); 27639 LookupList.prototype.constructor = LookupList; 27640 27641 // Record = same as Table, but inlined (a Table has an offset and its data is further in the stream) 27642 // Don't use offsets inside Records (probable bug), only in Tables. 27643 var table = { 27644 Table: Table, 27645 Record: Table, 27646 Coverage: Coverage, 27647 ScriptList: ScriptList, 27648 FeatureList: FeatureList, 27649 LookupList: LookupList, 27650 ushortList: ushortList, 27651 tableList: tableList, 27652 recordList: recordList 27653 }; 27654 27655 // Parsing utility functions 27656 27657 // Retrieve an unsigned byte from the DataView. 27658 function getByte(dataView, offset) { 27659 return dataView.getUint8(offset); 27660 } 27661 27662 // Retrieve an unsigned 16-bit short from the DataView. 27663 // The value is stored in big endian. 27664 function getUShort(dataView, offset) { 27665 return dataView.getUint16(offset, false); 27666 } 27667 27668 // Retrieve a signed 16-bit short from the DataView. 27669 // The value is stored in big endian. 27670 function getShort(dataView, offset) { 27671 return dataView.getInt16(offset, false); 27672 } 27673 27674 // Retrieve an unsigned 32-bit long from the DataView. 27675 // The value is stored in big endian. 27676 function getULong(dataView, offset) { 27677 return dataView.getUint32(offset, false); 27678 } 27679 27680 // Retrieve a 32-bit signed fixed-point number (16.16) from the DataView. 27681 // The value is stored in big endian. 27682 function getFixed(dataView, offset) { 27683 var decimal = dataView.getInt16(offset, false); 27684 var fraction = dataView.getUint16(offset + 2, false); 27685 return decimal + fraction / 65535; 27686 } 27687 27688 // Retrieve a 4-character tag from the DataView. 27689 // Tags are used to identify tables. 27690 function getTag(dataView, offset) { 27691 var tag = ''; 27692 for (var i = offset; i < offset + 4; i += 1) { 27693 tag += String.fromCharCode(dataView.getInt8(i)); 27694 } 27695 27696 return tag; 27697 } 27698 27699 // Retrieve an offset from the DataView. 27700 // Offsets are 1 to 4 bytes in length, depending on the offSize argument. 27701 function getOffset(dataView, offset, offSize) { 27702 var v = 0; 27703 for (var i = 0; i < offSize; i += 1) { 27704 v <<= 8; 27705 v += dataView.getUint8(offset + i); 27706 } 27707 27708 return v; 27709 } 27710 27711 // Retrieve a number of bytes from start offset to the end offset from the DataView. 27712 function getBytes(dataView, startOffset, endOffset) { 27713 var bytes = []; 27714 for (var i = startOffset; i < endOffset; i += 1) { 27715 bytes.push(dataView.getUint8(i)); 27716 } 27717 27718 return bytes; 27719 } 27720
vendor: 7,076 bytes, lines 27721-27902
27721 // Convert the list of bytes to a string. 27722 function bytesToString(bytes) { 27723 var s = ''; 27724 for (var i = 0; i < bytes.length; i += 1) { 27725 s += String.fromCharCode(bytes[i]); 27726 } 27727 27728 return s; 27729 } 27730 27731 var typeOffsets = { 27732 byte: 1, 27733 uShort: 2, 27734 short: 2, 27735 uLong: 4, 27736 fixed: 4, 27737 longDateTime: 8, 27738 tag: 4 27739 }; 27740 27741 // A stateful parser that changes the offset whenever a value is retrieved. 27742 // The data is a DataView. 27743 function Parser(data, offset) { 27744 this.data = data; 27745 this.offset = offset; 27746 this.relativeOffset = 0; 27747 } 27748 27749 Parser.prototype.parseByte = function() { 27750 var v = this.data.getUint8(this.offset + this.relativeOffset); 27751 this.relativeOffset += 1; 27752 return v; 27753 }; 27754 27755 Parser.prototype.parseChar = function() { 27756 var v = this.data.getInt8(this.offset + this.relativeOffset); 27757 this.relativeOffset += 1; 27758 return v; 27759 }; 27760 27761 Parser.prototype.parseCard8 = Parser.prototype.parseByte; 27762 27763 Parser.prototype.parseUShort = function() { 27764 var v = this.data.getUint16(this.offset + this.relativeOffset); 27765 this.relativeOffset += 2; 27766 return v; 27767 }; 27768 27769 Parser.prototype.parseCard16 = Parser.prototype.parseUShort; 27770 Parser.prototype.parseSID = Parser.prototype.parseUShort; 27771 Parser.prototype.parseOffset16 = Parser.prototype.parseUShort; 27772 27773 Parser.prototype.parseShort = function() { 27774 var v = this.data.getInt16(this.offset + this.relativeOffset); 27775 this.relativeOffset += 2; 27776 return v; 27777 }; 27778 27779 Parser.prototype.parseF2Dot14 = function() { 27780 var v = this.data.getInt16(this.offset + this.relativeOffset) / 16384; 27781 this.relativeOffset += 2; 27782 return v; 27783 }; 27784 27785 Parser.prototype.parseULong = function() { 27786 var v = getULong(this.data, this.offset + this.relativeOffset); 27787 this.relativeOffset += 4; 27788 return v; 27789 }; 27790 27791 Parser.prototype.parseOffset32 = Parser.prototype.parseULong; 27792 27793 Parser.prototype.parseFixed = function() { 27794 var v = getFixed(this.data, this.offset + this.relativeOffset); 27795 this.relativeOffset += 4; 27796 return v; 27797 }; 27798 27799 Parser.prototype.parseString = function(length) { 27800 var dataView = this.data; 27801 var offset = this.offset + this.relativeOffset; 27802 var string = ''; 27803 this.relativeOffset += length; 27804 for (var i = 0; i < length; i++) { 27805 string += String.fromCharCode(dataView.getUint8(offset + i)); 27806 } 27807 27808 return string; 27809 }; 27810 27811 Parser.prototype.parseTag = function() { 27812 return this.parseString(4); 27813 }; 27814 27815 // LONGDATETIME is a 64-bit integer. 27816 // JavaScript and unix timestamps traditionally use 32 bits, so we 27817 // only take the last 32 bits. 27818 // + Since until 2038 those bits will be filled by zeros we can ignore them. 27819 Parser.prototype.parseLongDateTime = function() { 27820 var v = getULong(this.data, this.offset + this.relativeOffset + 4); 27821 // Subtract seconds between 01/01/1904 and 01/01/1970 27822 // to convert Apple Mac timestamp to Standard Unix timestamp 27823 v -= 2082844800; 27824 this.relativeOffset += 8; 27825 return v; 27826 }; 27827 27828 Parser.prototype.parseVersion = function(minorBase) { 27829 var major = getUShort(this.data, this.offset + this.relativeOffset); 27830 27831 // How to interpret the minor version is very vague in the spec. 0x5000 is 5, 0x1000 is 1 27832 // Default returns the correct number if minor = 0xN000 where N is 0-9 27833 // Set minorBase to 1 for tables that use minor = N where N is 0-9 27834 var minor = getUShort(this.data, this.offset + this.relativeOffset + 2); 27835 this.relativeOffset += 4; 27836 if (minorBase === undefined) { 27837 minorBase = 0x1000; 27838 } 27839 return major + minor / minorBase / 10; 27840 }; 27841 27842 Parser.prototype.skip = function(type, amount) { 27843 if (amount === undefined) { 27844 amount = 1; 27845 } 27846 27847 this.relativeOffset += typeOffsets[type] * amount; 27848 }; 27849 27850 ///// Parsing lists and records /////////////////////////////// 27851 27852 // Parse a list of 32 bit unsigned integers. 27853 Parser.prototype.parseULongList = function(count) { 27854 if (count === undefined) { 27855 count = this.parseULong(); 27856 } 27857 var offsets = new Array(count); 27858 var dataView = this.data; 27859 var offset = this.offset + this.relativeOffset; 27860 for (var i = 0; i < count; i++) { 27861 offsets[i] = dataView.getUint32(offset); 27862 offset += 4; 27863 } 27864 27865 this.relativeOffset += count * 4; 27866 return offsets; 27867 }; 27868 27869 // Parse a list of 16 bit unsigned integers. The length of the list can be read on the stream 27870 // or provided as an argument. 27871 Parser.prototype.parseOffset16List = Parser.prototype.parseUShortList = function( 27872 count 27873 ) { 27874 if (count === undefined) { 27875 count = this.parseUShort(); 27876 } 27877 var offsets = new Array(count); 27878 var dataView = this.data; 27879 var offset = this.offset + this.relativeOffset; 27880 for (var i = 0; i < count; i++) { 27881 offsets[i] = dataView.getUint16(offset); 27882 offset += 2; 27883 } 27884 27885 this.relativeOffset += count * 2; 27886 return offsets; 27887 }; 27888 27889 // Parses a list of 16 bit signed integers. 27890 Parser.prototype.parseShortList = function(count) { 27891 var list = new Array(count); 27892 var dataView = this.data; 27893 var offset = this.offset + this.relativeOffset; 27894 for (var i = 0; i < count; i++) { 27895 list[i] = dataView.getInt16(offset); 27896 offset += 2; 27897 } 27898 27899 this.relativeOffset += count * 2; 27900 return list; 27901 }; 27902
27903 // Parses a list of bytes. 27904 Parser.prototype.parseByteList = function(count) { 27905 var list = new Array(count); 27906 var dataView = this.data; 27907 var offset = this.offset + this.relativeOffset; 27908 for (var i = 0; i < count; i++) { 27909 list[i] = dataView.getUint8(offset++); 27910 } 27911 27912 this.relativeOffset += count; 27913 return list; 27914 }; 27915 27916 /** 27917 * Parse a list of items. 27918 * Record count is optional, if omitted it is read from the stream. 27919 * itemCallback is one of the Parser methods. 27920 */ 27921 Parser.prototype.parseList = function(count, itemCallback) { 27922 var this$1 = this; 27923 27924 if (!itemCallback) { 27925 itemCallback = count; 27926 count = this.parseUShort(); 27927 } 27928 var list = new Array(count); 27929 for (var i = 0; i < count; i++) { 27930 list[i] = itemCallback.call(this$1); 27931 } 27932 return list; 27933 }; 27934 27935 Parser.prototype.parseList32 = function(count, itemCallback) { 27936 var this$1 = this; 27937 27938 if (!itemCallback) { 27939 itemCallback = count; 27940 count = this.parseULong(); 27941 } 27942 var list = new Array(count); 27943 for (var i = 0; i < count; i++) { 27944 list[i] = itemCallback.call(this$1); 27945 } 27946 return list; 27947 }; 27948 27949 /** 27950 * Parse a list of records. 27951 * Record count is optional, if omitted it is read from the stream. 27952 * Example of recordDescription: { sequenceIndex: Parser.uShort, lookupListIndex: Parser.uShort } 27953 */ 27954 Parser.prototype.parseRecordList = function(count, recordDescription) { 27955 var this$1 = this; 27956 27957 // If the count argument is absent, read it in the stream. 27958 if (!recordDescription) { 27959 recordDescription = count; 27960 count = this.parseUShort(); 27961 } 27962 var records = new Array(count); 27963 var fields = Object.keys(recordDescription); 27964 for (var i = 0; i < count; i++) { 27965 var rec = {}; 27966 for (var j = 0; j < fields.length; j++) { 27967 var fieldName = fields[j]; 27968 var fieldType = recordDescription[fieldName]; 27969 rec[fieldName] = fieldType.call(this$1); 27970 } 27971 records[i] = rec; 27972 } 27973 return records; 27974 }; 27975 27976 Parser.prototype.parseRecordList32 = function(count, recordDescription) { 27977 var this$1 = this; 27978 27979 // If the count argument is absent, read it in the stream. 27980 if (!recordDescription) { 27981 recordDescription = count; 27982 count = this.parseULong(); 27983 } 27984 var records = new Array(count); 27985 var fields = Object.keys(recordDescription); 27986 for (var i = 0; i < count; i++) { 27987 var rec = {}; 27988 for (var j = 0; j < fields.length; j++) { 27989 var fieldName = fields[j]; 27990 var fieldType = recordDescription[fieldName]; 27991 rec[fieldName] = fieldType.call(this$1); 27992 } 27993 records[i] = rec; 27994 } 27995 return records; 27996 }; 27997 27998 // Parse a data structure into an object 27999 // Example of description: { sequenceIndex: Parser.uShort, lookupListIndex: Parser.uShort } 28000 Parser.prototype.parseStruct = function(description) { 28001 var this$1 = this; 28002 28003 if (typeof description === 'function') { 28004 return description.call(this); 28005 } else { 28006 var fields = Object.keys(description); 28007 var struct = {}; 28008 for (var j = 0; j < fields.length; j++) { 28009 var fieldName = fields[j]; 28010 var fieldType = description[fieldName]; 28011 struct[fieldName] = fieldType.call(this$1); 28012 } 28013 return struct; 28014 } 28015 }; 28016 28017 /** 28018 * Parse a GPOS valueRecord
28019 * https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#value-record 28020 * valueFormat is optional, if omitted it is read from the stream. 28021 */ 28022 Parser.prototype.parseValueRecord = function(valueFormat) { 28023 if (valueFormat === undefined) { 28024 valueFormat = this.parseUShort(); 28025 } 28026 if (valueFormat === 0) { 28027 // valueFormat2 in kerning pairs is most often 0 28028 // in this case return undefined instead of an empty object, to save space 28029 return; 28030 } 28031 var valueRecord = {}; 28032 28033 if (valueFormat & 0x0001) { 28034 valueRecord.xPlacement = this.parseShort(); 28035 } 28036 if (valueFormat & 0x0002) { 28037 valueRecord.yPlacement = this.parseShort(); 28038 } 28039 if (valueFormat & 0x0004) { 28040 valueRecord.xAdvance = this.parseShort(); 28041 } 28042 if (valueFormat & 0x0008) { 28043 valueRecord.yAdvance = this.parseShort(); 28044 } 28045 28046 // Device table (non-variable font) / VariationIndex table (variable font) not supported 28047 // https://docs.microsoft.com/fr-fr/typography/opentype/spec/chapter2#devVarIdxTbls 28048 if (valueFormat & 0x0010) { 28049 valueRecord.xPlaDevice = undefined; 28050 this.parseShort(); 28051 } 28052 if (valueFormat & 0x0020) { 28053 valueRecord.yPlaDevice = undefined; 28054 this.parseShort(); 28055 } 28056 if (valueFormat & 0x0040) { 28057 valueRecord.xAdvDevice = undefined; 28058 this.parseShort(); 28059 } 28060 if (valueFormat & 0x0080) { 28061 valueRecord.yAdvDevice = undefined; 28062 this.parseShort(); 28063 } 28064 28065 return valueRecord; 28066 }; 28067 28068 /** 28069 * Parse a list of GPOS valueRecords 28070 * https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#value-record 28071 * valueFormat and valueCount are read from the stream. 28072 */ 28073 Parser.prototype.parseValueRecordList = function() { 28074 var this$1 = this; 28075 28076 var valueFormat = this.parseUShort(); 28077 var valueCount = this.parseUShort(); 28078 var values = new Array(valueCount); 28079 for (var i = 0; i < valueCount; i++) { 28080 values[i] = this$1.parseValueRecord(valueFormat); 28081 } 28082 return values; 28083 }; 28084 28085 Parser.prototype.parsePointer = function(description) { 28086 var structOffset = this.parseOffset16(); 28087 if (structOffset > 0) { 28088 // NULL offset => return undefined 28089 return new Parser(this.data, this.offset + structOffset).parseStruct( 28090 description 28091 ); 28092 } 28093 return undefined; 28094 }; 28095 28096 Parser.prototype.parsePointer32 = function(description) { 28097 var structOffset = this.parseOffset32(); 28098 if (structOffset > 0) { 28099 // NULL offset => return undefined 28100 return new Parser(this.data, this.offset + structOffset).parseStruct( 28101 description 28102 ); 28103 } 28104 return undefined; 28105 }; 28106 28107 /** 28108 * Parse a list of offsets to lists of 16-bit integers, 28109 * or a list of offsets to lists of offsets to any kind of items. 28110 * If itemCallback is not provided, a list of list of UShort is assumed. 28111 * If provided, itemCallback is called on each item and must parse the item. 28112 * See examples in tables/gsub.js 28113 */ 28114 Parser.prototype.parseListOfLists = function(itemCallback) { 28115 var this$1 = this; 28116 28117 var offsets = this.parseOffset16List(); 28118 var count = offsets.length; 28119 var relativeOffset = this.relativeOffset; 28120 var list = new Array(count); 28121 for (var i = 0; i < count; i++) { 28122 var start = offsets[i]; 28123 if (start === 0) { 28124 // NULL offset 28125 // Add i as owned property to list. Convenient with assert. 28126 list[i] = undefined; 28127 continue; 28128 } 28129 this$1.relativeOffset = start; 28130 if (itemCallback) { 28131 var subOffsets = this$1.parseOffset16List(); 28132 var subList = new Array(subOffsets.length); 28133 for (var j = 0; j < subOffsets.length; j++) { 28134 this$1.relativeOffset = start + subOffsets[j]; 28135 subList[j] = itemCallback.call(this$1); 28136 } 28137 list[i] = subList; 28138 } else { 28139 list[i] = this$1.parseUShortList(); 28140 } 28141 } 28142 this.relativeOffset = relativeOffset; 28143 return list; 28144 }; 28145
vendor: 5,706 bytes, lines 28146-28287
28146 ///// Complex tables parsing ////////////////////////////////// 28147 28148 // Parse a coverage table in a GSUB, GPOS or GDEF table. 28149 // https://www.microsoft.com/typography/OTSPEC/chapter2.htm 28150 // parser.offset must point to the start of the table containing the coverage. 28151 Parser.prototype.parseCoverage = function() { 28152 var this$1 = this; 28153 28154 var startOffset = this.offset + this.relativeOffset; 28155 var format = this.parseUShort(); 28156 var count = this.parseUShort(); 28157 if (format === 1) { 28158 return { 28159 format: 1, 28160 glyphs: this.parseUShortList(count) 28161 }; 28162 } else if (format === 2) { 28163 var ranges = new Array(count); 28164 for (var i = 0; i < count; i++) { 28165 ranges[i] = { 28166 start: this$1.parseUShort(), 28167 end: this$1.parseUShort(), 28168 index: this$1.parseUShort() 28169 }; 28170 } 28171 return { 28172 format: 2, 28173 ranges: ranges 28174 }; 28175 } 28176 throw new Error( 28177 '0x' + startOffset.toString(16) + ': Coverage format must be 1 or 2.' 28178 ); 28179 }; 28180 28181 // Parse a Class Definition Table in a GSUB, GPOS or GDEF table. 28182 // https://www.microsoft.com/typography/OTSPEC/chapter2.htm 28183 Parser.prototype.parseClassDef = function() { 28184 var startOffset = this.offset + this.relativeOffset; 28185 var format = this.parseUShort(); 28186 if (format === 1) { 28187 return { 28188 format: 1, 28189 startGlyph: this.parseUShort(), 28190 classes: this.parseUShortList() 28191 }; 28192 } else if (format === 2) { 28193 return { 28194 format: 2, 28195 ranges: this.parseRecordList({ 28196 start: Parser.uShort, 28197 end: Parser.uShort, 28198 classId: Parser.uShort 28199 }) 28200 }; 28201 } 28202 throw new Error( 28203 '0x' + startOffset.toString(16) + ': ClassDef format must be 1 or 2.' 28204 ); 28205 }; 28206 28207 ///// Static methods /////////////////////////////////// 28208 // These convenience methods can be used as callbacks and should be called with "this" context set to a Parser instance. 28209 28210 Parser.list = function(count, itemCallback) { 28211 return function() { 28212 return this.parseList(count, itemCallback); 28213 }; 28214 }; 28215 28216 Parser.list32 = function(count, itemCallback) { 28217 return function() { 28218 return this.parseList32(count, itemCallback); 28219 }; 28220 }; 28221 28222 Parser.recordList = function(count, recordDescription) { 28223 return function() { 28224 return this.parseRecordList(count, recordDescription); 28225 }; 28226 }; 28227 28228 Parser.recordList32 = function(count, recordDescription) { 28229 return function() { 28230 return this.parseRecordList32(count, recordDescription); 28231 }; 28232 }; 28233 28234 Parser.pointer = function(description) { 28235 return function() { 28236 return this.parsePointer(description); 28237 }; 28238 }; 28239 28240 Parser.pointer32 = function(description) { 28241 return function() { 28242 return this.parsePointer32(description); 28243 }; 28244 }; 28245 28246 Parser.tag = Parser.prototype.parseTag; 28247 Parser.byte = Parser.prototype.parseByte; 28248 Parser.uShort = Parser.offset16 = Parser.prototype.parseUShort; 28249 Parser.uShortList = Parser.prototype.parseUShortList; 28250 Parser.uLong = Parser.offset32 = Parser.prototype.parseULong; 28251 Parser.uLongList = Parser.prototype.parseULongList; 28252 Parser.struct = Parser.prototype.parseStruct; 28253 Parser.coverage = Parser.prototype.parseCoverage; 28254 Parser.classDef = Parser.prototype.parseClassDef; 28255 28256 ///// Script, Feature, Lookup lists /////////////////////////////////////////////// 28257 // https://www.microsoft.com/typography/OTSPEC/chapter2.htm 28258 28259 var langSysTable = { 28260 reserved: Parser.uShort, 28261 reqFeatureIndex: Parser.uShort, 28262 featureIndexes: Parser.uShortList 28263 }; 28264 28265 Parser.prototype.parseScriptList = function() { 28266 return ( 28267 this.parsePointer( 28268 Parser.recordList({ 28269 tag: Parser.tag, 28270 script: Parser.pointer({ 28271 defaultLangSys: Parser.pointer(langSysTable), 28272 langSysRecords: Parser.recordList({ 28273 tag: Parser.tag, 28274 langSys: Parser.pointer(langSysTable) 28275 }) 28276 }) 28277 }) 28278 ) || [] 28279 ); 28280 }; 28281 28282 Parser.prototype.parseFeatureList = function() { 28283 return ( 28284 this.parsePointer( 28285 Parser.recordList({ 28286 tag: Parser.tag, 28287 feature: Parser.pointer({
28288 featureParams: Parser.offset16, 28289 lookupListIndexes: Parser.uShortList 28290 }) 28291 }) 28292 ) || [] 28293 ); 28294 }; 28295 28296 Parser.prototype.parseLookupList = function(lookupTableParsers) { 28297 return ( 28298 this.parsePointer( 28299 Parser.list( 28300 Parser.pointer(function() { 28301 var lookupType = this.parseUShort(); 28302 check.argument( 28303 1 <= lookupType && lookupType <= 9, 28304 'GPOS/GSUB lookup type ' + lookupType + ' unknown.' 28305 ); 28306 var lookupFlag = this.parseUShort(); 28307 var useMarkFilteringSet = lookupFlag & 0x10; 28308 return { 28309 lookupType: lookupType, 28310 lookupFlag: lookupFlag, 28311 subtables: this.parseList( 28312 Parser.pointer(lookupTableParsers[lookupType]) 28313 ), 28314 markFilteringSet: useMarkFilteringSet 28315 ? this.parseUShort() 28316 : undefined 28317 }; 28318 }) 28319 ) 28320 ) || [] 28321 ); 28322 }; 28323 28324 Parser.prototype.parseFeatureVariationsList = function() { 28325 return ( 28326 this.parsePointer32(function() { 28327 var majorVersion = this.parseUShort(); 28328 var minorVersion = this.parseUShort(); 28329 check.argument( 28330 majorVersion === 1 && minorVersion < 1, 28331 'GPOS/GSUB feature variations table unknown.' 28332 ); 28333 var featureVariations = this.parseRecordList32({ 28334 conditionSetOffset: Parser.offset32, 28335 featureTableSubstitutionOffset: Parser.offset32 28336 }); 28337 return featureVariations; 28338 }) || [] 28339 ); 28340 }; 28341 28342 var parse = { 28343 getByte: getByte, 28344 getCard8: getByte, 28345 getUShort: getUShort, 28346 getCard16: getUShort, 28347 getShort: getShort, 28348 getULong: getULong, 28349 getFixed: getFixed, 28350 getTag: getTag, 28351 getOffset: getOffset, 28352 getBytes: getBytes, 28353 bytesToString: bytesToString, 28354 Parser: Parser 28355 }; 28356 28357 // The `cmap` table stores the mappings from characters to glyphs. 28358 28359 function parseCmapTableFormat12(cmap, p) { 28360 //Skip reserved. 28361 p.parseUShort(); 28362 28363 // Length in bytes of the sub-tables. 28364 cmap.length = p.parseULong(); 28365 cmap.language = p.parseULong(); 28366 28367 var groupCount; 28368 cmap.groupCount = groupCount = p.parseULong(); 28369 cmap.glyphIndexMap = {}; 28370 28371 for (var i = 0; i < groupCount; i += 1) { 28372 var startCharCode = p.parseULong(); 28373 var endCharCode = p.parseULong(); 28374 var startGlyphId = p.parseULong(); 28375 28376 for (var c = startCharCode; c <= endCharCode; c += 1) { 28377 cmap.glyphIndexMap[c] = startGlyphId; 28378 startGlyphId++; 28379 } 28380 } 28381 } 28382 28383 function parseCmapTableFormat4(cmap, p, data, start, offset) { 28384 // Length in bytes of the sub-tables. 28385 cmap.length = p.parseUShort(); 28386 cmap.language = p.parseUShort(); 28387 28388 // segCount is stored x 2. 28389 var segCount; 28390 cmap.segCount = segCount = p.parseUShort() >> 1; 28391 28392 // Skip searchRange, entrySelector, rangeShift. 28393 p.skip('uShort', 3); 28394 28395 // The "unrolled" mapping from character codes to glyph indices. 28396 cmap.glyphIndexMap = {}; 28397 var endCountParser = new parse.Parser(data, start + offset + 14); 28398 var startCountParser = new parse.Parser( 28399 data, 28400 start + offset + 16 + segCount * 2 28401 ); 28402 var idDeltaParser = new parse.Parser( 28403 data, 28404 start + offset + 16 + segCount * 4 28405 ); 28406 var idRangeOffsetParser = new parse.Parser( 28407 data, 28408 start + offset + 16 + segCount * 6 28409 ); 28410 var glyphIndexOffset = start + offset + 16 + segCount * 8; 28411 for (var i = 0; i < segCount - 1; i += 1) { 28412 var glyphIndex = void 0; 28413 var endCount = endCountParser.parseUShort(); 28414 var startCount = startCountParser.parseUShort(); 28415 var idDelta = idDeltaParser.parseShort(); 28416 var idRangeOffset = idRangeOffsetParser.parseUShort(); 28417 for (var c = startCount; c <= endCount; c += 1) {
28418 if (idRangeOffset !== 0) { 28419 // The idRangeOffset is relative to the current position in the idRangeOffset array. 28420 // Take the current offset in the idRangeOffset array. 28421 glyphIndexOffset = 28422 idRangeOffsetParser.offset + idRangeOffsetParser.relativeOffset - 2; 28423 28424 // Add the value of the idRangeOffset, which will move us into the glyphIndex array. 28425 glyphIndexOffset += idRangeOffset; 28426 28427 // Then add the character index of the current segment, multiplied by 2 for USHORTs. 28428 glyphIndexOffset += (c - startCount) * 2; 28429 glyphIndex = parse.getUShort(data, glyphIndexOffset); 28430 if (glyphIndex !== 0) { 28431 glyphIndex = (glyphIndex + idDelta) & 0xffff; 28432 } 28433 } else { 28434 glyphIndex = (c + idDelta) & 0xffff; 28435 } 28436 28437 cmap.glyphIndexMap[c] = glyphIndex; 28438 } 28439 } 28440 } 28441 28442 // Parse the `cmap` table. This table stores the mappings from characters to glyphs. 28443 // There are many available formats, but we only support the Windows format 4 and 12. 28444 // This function returns a `CmapEncoding` object or null if no supported format could be found. 28445 function parseCmapTable(data, start) { 28446 var cmap = {}; 28447 cmap.version = parse.getUShort(data, start); 28448 check.argument(cmap.version === 0, 'cmap table version should be 0.'); 28449 28450 // The cmap table can contain many sub-tables, each with their own format. 28451 // We're only interested in a "platform 0" (Unicode format) and "platform 3" (Windows format) table. 28452 cmap.numTables = parse.getUShort(data, start + 2); 28453 var offset = -1; 28454 for (var i = cmap.numTables - 1; i >= 0; i -= 1) { 28455 var platformId = parse.getUShort(data, start + 4 + i * 8); 28456 var encodingId = parse.getUShort(data, start + 4 + i * 8 + 2); 28457 if ( 28458 (platformId === 3 && 28459 (encodingId === 0 || encodingId === 1 || encodingId === 10)) || 28460 (platformId === 0 && 28461 (encodingId === 0 || 28462 encodingId === 1 || 28463 encodingId === 2 || 28464 encodingId === 3 || 28465 encodingId === 4)) 28466 ) { 28467 offset = parse.getULong(data, start + 4 + i * 8 + 4); 28468 break; 28469 } 28470 } 28471 28472 if (offset === -1) { 28473 // There is no cmap table in the font that we support. 28474 throw new Error('No valid cmap sub-tables found.'); 28475 } 28476 28477 var p = new parse.Parser(data, start + offset); 28478 cmap.format = p.parseUShort(); 28479 28480 if (cmap.format === 12) { 28481 parseCmapTableFormat12(cmap, p); 28482 } else if (cmap.format === 4) { 28483 parseCmapTableFormat4(cmap, p, data, start, offset); 28484 } else { 28485 throw new Error( 28486 'Only format 4 and 12 cmap tables are supported (found format ' + 28487 cmap.format + 28488 ').' 28489 ); 28490 } 28491 28492 return cmap; 28493 } 28494 28495 function addSegment(t, code, glyphIndex) { 28496 t.segments.push({ 28497 end: code, 28498 start: code, 28499 delta: -(code - glyphIndex), 28500 offset: 0, 28501 glyphIndex: glyphIndex 28502 }); 28503 } 28504 28505 function addTerminatorSegment(t) { 28506 t.segments.push({ 28507 end: 0xffff, 28508 start: 0xffff, 28509 delta: 1, 28510 offset: 0 28511 }); 28512 } 28513 28514 // Make cmap table, format 4 by default, 12 if needed only 28515 function makeCmapTable(glyphs) { 28516 // Plan 0 is the base Unicode Plan but emojis, for example are on another plan, and needs cmap 12 format (with 32bit) 28517 var isPlan0Only = true; 28518 var i; 28519 28520 // Check if we need to add cmap format 12 or if format 4 only is fine 28521 for (i = glyphs.length - 1; i > 0; i -= 1) { 28522 var g = glyphs.get(i); 28523 if (g.unicode > 65535) { 28524 console.log('Adding CMAP format 12 (needed!)'); 28525 isPlan0Only = false;
28526 break; 28527 } 28528 } 28529 28530 var cmapTable = [ 28531 { name: 'version', type: 'USHORT', value: 0 }, 28532 { name: 'numTables', type: 'USHORT', value: isPlan0Only ? 1 : 2 }, 28533 28534 // CMAP 4 header 28535 { name: 'platformID', type: 'USHORT', value: 3 }, 28536 { name: 'encodingID', type: 'USHORT', value: 1 }, 28537 { name: 'offset', type: 'ULONG', value: isPlan0Only ? 12 : 12 + 8 } 28538 ]; 28539 28540 if (!isPlan0Only) { 28541 cmapTable = cmapTable.concat([ 28542 // CMAP 12 header 28543 { name: 'cmap12PlatformID', type: 'USHORT', value: 3 }, // We encode only for PlatformID = 3 (Windows) because it is supported everywhere 28544 { name: 'cmap12EncodingID', type: 'USHORT', value: 10 }, 28545 { name: 'cmap12Offset', type: 'ULONG', value: 0 } 28546 ]); 28547 } 28548 28549 cmapTable = cmapTable.concat([ 28550 // CMAP 4 Subtable 28551 { name: 'format', type: 'USHORT', value: 4 }, 28552 { name: 'cmap4Length', type: 'USHORT', value: 0 }, 28553 { name: 'language', type: 'USHORT', value: 0 }, 28554 { name: 'segCountX2', type: 'USHORT', value: 0 }, 28555 { name: 'searchRange', type: 'USHORT', value: 0 }, 28556 { name: 'entrySelector', type: 'USHORT', value: 0 }, 28557 { name: 'rangeShift', type: 'USHORT', value: 0 } 28558 ]); 28559 28560 var t = new table.Table('cmap', cmapTable); 28561 28562 t.segments = []; 28563 for (i = 0; i < glyphs.length; i += 1) { 28564 var glyph = glyphs.get(i); 28565 for (var j = 0; j < glyph.unicodes.length; j += 1) { 28566 addSegment(t, glyph.unicodes[j], i); 28567 } 28568 28569 t.segments = t.segments.sort(function(a, b) { 28570 return a.start - b.start; 28571 }); 28572 } 28573 28574 addTerminatorSegment(t); 28575 28576 var segCount = t.segments.length; 28577 var segCountToRemove = 0; 28578 28579 // CMAP 4 28580 // Set up parallel segment arrays. 28581 var endCounts = []; 28582 var startCounts = []; 28583 var idDeltas = []; 28584 var idRangeOffsets = []; 28585 var glyphIds = []; 28586 28587 // CMAP 12 28588 var cmap12Groups = []; 28589 28590 // Reminder this loop is not following the specification at 100% 28591 // The specification -> find suites of characters and make a group 28592 // Here we're doing one group for each letter 28593 // Doing as the spec can save 8 times (or more) space 28594 for (i = 0; i < segCount; i += 1) { 28595 var segment = t.segments[i]; 28596 28597 // CMAP 4 28598 if (segment.end <= 65535 && segment.start <= 65535) { 28599 endCounts = endCounts.concat({ 28600 name: 'end_' + i, 28601 type: 'USHORT', 28602 value: segment.end 28603 }); 28604 startCounts = startCounts.concat({ 28605 name: 'start_' + i, 28606 type: 'USHORT', 28607 value: segment.start 28608 }); 28609 idDeltas = idDeltas.concat({ 28610 name: 'idDelta_' + i, 28611 type: 'SHORT', 28612 value: segment.delta 28613 }); 28614 idRangeOffsets = idRangeOffsets.concat({ 28615 name: 'idRangeOffset_' + i, 28616 type: 'USHORT', 28617 value: segment.offset 28618 }); 28619 if (segment.glyphId !== undefined) { 28620 glyphIds = glyphIds.concat({ 28621 name: 'glyph_' + i, 28622 type: 'USHORT', 28623 value: segment.glyphId 28624 }); 28625 } 28626 } else { 28627 // Skip Unicode > 65535 (16bit unsigned max) for CMAP 4, will be added in CMAP 12 28628 segCountToRemove += 1; 28629 } 28630 28631 // CMAP 12 28632 // Skip Terminator Segment 28633 if (!isPlan0Only && segment.glyphIndex !== undefined) { 28634 cmap12Groups = cmap12Groups.concat({ 28635 name: 'cmap12Start_' + i, 28636 type: 'ULONG', 28637 value: segment.start 28638 }); 28639 cmap12Groups = cmap12Groups.concat({ 28640 name: 'cmap12End_' + i, 28641 type: 'ULONG', 28642 value: segment.end 28643 }); 28644 cmap12Groups = cmap12Groups.concat({ 28645 name: 'cmap12Glyph_' + i, 28646 type: 'ULONG', 28647 value: segment.glyphIndex 28648 }); 28649 } 28650 } 28651 28652 // CMAP 4 Subtable 28653 t.segCountX2 = (segCount - segCountToRemove) * 2;
28654 t.searchRange = 28655 Math.pow( 28656 2, 28657 Math.floor(Math.log(segCount - segCountToRemove) / Math.log(2)) 28658 ) * 2; 28659 t.entrySelector = Math.log(t.searchRange / 2) / Math.log(2); 28660 t.rangeShift = t.segCountX2 - t.searchRange; 28661 28662 t.fields = t.fields.concat(endCounts); 28663 t.fields.push({ name: 'reservedPad', type: 'USHORT', value: 0 }); 28664 t.fields = t.fields.concat(startCounts); 28665 t.fields = t.fields.concat(idDeltas); 28666 t.fields = t.fields.concat(idRangeOffsets); 28667 t.fields = t.fields.concat(glyphIds); 28668 28669 t.cmap4Length = 28670 14 + // Subtable header 28671 endCounts.length * 2 + 28672 2 + // reservedPad 28673 startCounts.length * 2 + 28674 idDeltas.length * 2 + 28675 idRangeOffsets.length * 2 + 28676 glyphIds.length * 2; 28677 28678 if (!isPlan0Only) { 28679 // CMAP 12 Subtable 28680 var cmap12Length = 28681 16 + // Subtable header 28682 cmap12Groups.length * 4; 28683 28684 t.cmap12Offset = 12 + 2 * 2 + 4 + t.cmap4Length; 28685 t.fields = t.fields.concat([ 28686 { name: 'cmap12Format', type: 'USHORT', value: 12 }, 28687 { name: 'cmap12Reserved', type: 'USHORT', value: 0 }, 28688 { name: 'cmap12Length', type: 'ULONG', value: cmap12Length }, 28689 { name: 'cmap12Language', type: 'ULONG', value: 0 }, 28690 { name: 'cmap12nGroups', type: 'ULONG', value: cmap12Groups.length / 3 } 28691 ]); 28692 28693 t.fields = t.fields.concat(cmap12Groups); 28694 } 28695 28696 return t; 28697 } 28698 28699 var cmap = { parse: parseCmapTable, make: makeCmapTable }; 28700 28701 // Glyph encoding 28702 28703 var cffStandardStrings = [ 28704 '.notdef', 28705 'space', 28706 'exclam', 28707 'quotedbl', 28708 'numbersign', 28709 'dollar', 28710 'percent', 28711 'ampersand', 28712 'quoteright', 28713 'parenleft', 28714 'parenright', 28715 'asterisk', 28716 'plus', 28717 'comma', 28718 'hyphen', 28719 'period', 28720 'slash', 28721 'zero', 28722 'one', 28723 'two', 28724 'three', 28725 'four', 28726 'five', 28727 'six', 28728 'seven', 28729 'eight', 28730 'nine', 28731 'colon', 28732 'semicolon', 28733 'less', 28734 'equal', 28735 'greater', 28736 'question', 28737 'at', 28738 'A', 28739 'B', 28740 'C', 28741 'D', 28742 'E', 28743 'F', 28744 'G', 28745 'H', 28746 'I', 28747 'J', 28748 'K', 28749 'L', 28750 'M', 28751 'N', 28752 'O', 28753 'P', 28754 'Q', 28755 'R', 28756 'S', 28757 'T', 28758 'U', 28759 'V', 28760 'W', 28761 'X', 28762 'Y', 28763 'Z', 28764 'bracketleft', 28765 'backslash', 28766 'bracketright', 28767 'asciicircum', 28768 'underscore', 28769 'quoteleft', 28770 'a', 28771 'b', 28772 'c', 28773 'd', 28774 'e', 28775 'f', 28776 'g', 28777 'h', 28778 'i', 28779 'j', 28780 'k', 28781 'l', 28782 'm', 28783 'n', 28784 'o', 28785 'p', 28786 'q', 28787 'r', 28788 's', 28789 't', 28790 'u', 28791 'v', 28792 'w', 28793 'x', 28794 'y', 28795 'z', 28796 'braceleft', 28797 'bar', 28798 'braceright', 28799 'asciitilde', 28800 'exclamdown', 28801 'cent', 28802 'sterling', 28803 'fraction', 28804 'yen', 28805 'florin', 28806 'section', 28807 'currency', 28808 'quotesingle', 28809 'quotedblleft', 28810 'guillemotleft', 28811 'guilsinglleft', 28812 'guilsinglright', 28813 'fi', 28814 'fl', 28815 'endash', 28816 'dagger', 28817 'daggerdbl',
28818 'periodcentered', 28819 'paragraph', 28820 'bullet', 28821 'quotesinglbase', 28822 'quotedblbase', 28823 'quotedblright', 28824 'guillemotright', 28825 'ellipsis', 28826 'perthousand', 28827 'questiondown', 28828 'grave', 28829 'acute', 28830 'circumflex', 28831 'tilde', 28832 'macron', 28833 'breve', 28834 'dotaccent', 28835 'dieresis', 28836 'ring', 28837 'cedilla', 28838 'hungarumlaut', 28839 'ogonek', 28840 'caron', 28841 'emdash', 28842 'AE', 28843 'ordfeminine', 28844 'Lslash', 28845 'Oslash', 28846 'OE', 28847 'ordmasculine', 28848 'ae', 28849 'dotlessi', 28850 'lslash', 28851 'oslash', 28852 'oe', 28853 'germandbls', 28854 'onesuperior', 28855 'logicalnot', 28856 'mu', 28857 'trademark', 28858 'Eth', 28859 'onehalf', 28860 'plusminus', 28861 'Thorn', 28862 'onequarter', 28863 'divide', 28864 'brokenbar', 28865 'degree', 28866 'thorn', 28867 'threequarters', 28868 'twosuperior', 28869 'registered', 28870 'minus', 28871 'eth', 28872 'multiply', 28873 'threesuperior', 28874 'copyright', 28875 'Aacute', 28876 'Acircumflex', 28877 'Adieresis', 28878 'Agrave', 28879 'Aring', 28880 'Atilde', 28881 'Ccedilla', 28882 'Eacute', 28883 'Ecircumflex', 28884 'Edieresis', 28885 'Egrave', 28886 'Iacute', 28887 'Icircumflex', 28888 'Idieresis', 28889 'Igrave', 28890 'Ntilde', 28891 'Oacute', 28892 'Ocircumflex', 28893 'Odieresis', 28894 'Ograve', 28895 'Otilde', 28896 'Scaron', 28897 'Uacute', 28898 'Ucircumflex', 28899 'Udieresis', 28900 'Ugrave', 28901 'Yacute', 28902 'Ydieresis', 28903 'Zcaron', 28904 'aacute', 28905 'acircumflex', 28906 'adieresis', 28907 'agrave', 28908 'aring', 28909 'atilde', 28910 'ccedilla', 28911 'eacute', 28912 'ecircumflex', 28913 'edieresis', 28914 'egrave', 28915 'iacute', 28916 'icircumflex', 28917 'idieresis', 28918 'igrave', 28919 'ntilde', 28920 'oacute', 28921 'ocircumflex', 28922 'odieresis', 28923 'ograve', 28924 'otilde', 28925 'scaron', 28926 'uacute', 28927 'ucircumflex', 28928 'udieresis', 28929 'ugrave', 28930 'yacute', 28931 'ydieresis', 28932 'zcaron', 28933 'exclamsmall', 28934 'Hungarumlautsmall', 28935 'dollaroldstyle', 28936 'dollarsuperior', 28937 'ampersandsmall', 28938 'Acutesmall', 28939 'parenleftsuperior', 28940 'parenrightsuperior', 28941 '266 ff', 28942 'onedotenleader', 28943 'zerooldstyle', 28944 'oneoldstyle', 28945 'twooldstyle', 28946 'threeoldstyle', 28947 'fouroldstyle', 28948 'fiveoldstyle', 28949 'sixoldstyle', 28950 'sevenoldstyle', 28951 'eightoldstyle', 28952 'nineoldstyle', 28953 'commasuperior', 28954 'threequartersemdash', 28955 'periodsuperior', 28956 'questionsmall', 28957 'asuperior', 28958 'bsuperior', 28959 'centsuperior', 28960 'dsuperior', 28961 'esuperior', 28962 'isuperior', 28963 'lsuperior', 28964 'msuperior', 28965 'nsuperior', 28966 'osuperior', 28967 'rsuperior', 28968 'ssuperior', 28969 'tsuperior', 28970 'ff', 28971 'ffi', 28972 'ffl', 28973 'parenleftinferior', 28974 'parenrightinferior', 28975 'Circumflexsmall', 28976 'hyphensuperior', 28977 'Gravesmall', 28978 'Asmall', 28979 'Bsmall', 28980 'Csmall', 28981 'Dsmall', 28982 'Esmall', 28983 'Fsmall', 28984 'Gsmall', 28985 'Hsmall', 28986 'Ismall', 28987 'Jsmall', 28988 'Ksmall', 28989 'Lsmall', 28990 'Msmall',
28991 'Nsmall', 28992 'Osmall', 28993 'Psmall', 28994 'Qsmall', 28995 'Rsmall', 28996 'Ssmall', 28997 'Tsmall', 28998 'Usmall', 28999 'Vsmall', 29000 'Wsmall', 29001 'Xsmall', 29002 'Ysmall', 29003 'Zsmall', 29004 'colonmonetary', 29005 'onefitted', 29006 'rupiah', 29007 'Tildesmall', 29008 'exclamdownsmall', 29009 'centoldstyle', 29010 'Lslashsmall', 29011 'Scaronsmall', 29012 'Zcaronsmall', 29013 'Dieresissmall', 29014 'Brevesmall', 29015 'Caronsmall', 29016 'Dotaccentsmall', 29017 'Macronsmall', 29018 'figuredash', 29019 'hypheninferior', 29020 'Ogoneksmall', 29021 'Ringsmall', 29022 'Cedillasmall', 29023 'questiondownsmall', 29024 'oneeighth', 29025 'threeeighths', 29026 'fiveeighths', 29027 'seveneighths', 29028 'onethird', 29029 'twothirds', 29030 'zerosuperior', 29031 'foursuperior', 29032 'fivesuperior', 29033 'sixsuperior', 29034 'sevensuperior', 29035 'eightsuperior', 29036 'ninesuperior', 29037 'zeroinferior', 29038 'oneinferior', 29039 'twoinferior', 29040 'threeinferior', 29041 'fourinferior', 29042 'fiveinferior', 29043 'sixinferior', 29044 'seveninferior', 29045 'eightinferior', 29046 'nineinferior', 29047 'centinferior', 29048 'dollarinferior', 29049 'periodinferior', 29050 'commainferior', 29051 'Agravesmall', 29052 'Aacutesmall', 29053 'Acircumflexsmall', 29054 'Atildesmall', 29055 'Adieresissmall', 29056 'Aringsmall', 29057 'AEsmall', 29058 'Ccedillasmall', 29059 'Egravesmall', 29060 'Eacutesmall', 29061 'Ecircumflexsmall', 29062 'Edieresissmall', 29063 'Igravesmall', 29064 'Iacutesmall', 29065 'Icircumflexsmall', 29066 'Idieresissmall', 29067 'Ethsmall', 29068 'Ntildesmall', 29069 'Ogravesmall', 29070 'Oacutesmall', 29071 'Ocircumflexsmall', 29072 'Otildesmall', 29073 'Odieresissmall', 29074 'OEsmall', 29075 'Oslashsmall', 29076 'Ugravesmall', 29077 'Uacutesmall', 29078 'Ucircumflexsmall', 29079 'Udieresissmall', 29080 'Yacutesmall', 29081 'Thornsmall', 29082 'Ydieresissmall', 29083 '001.000', 29084 '001.001', 29085 '001.002', 29086 '001.003', 29087 'Black', 29088 'Bold', 29089 'Book', 29090 'Light', 29091 'Medium', 29092 'Regular', 29093 'Roman', 29094 'Semibold' 29095 ]; 29096 29097 var cffStandardEncoding = [ 29098 '', 29099 '', 29100 '', 29101 '', 29102 '', 29103 '', 29104 '', 29105 '', 29106 '', 29107 '', 29108 '', 29109 '', 29110 '', 29111 '', 29112 '', 29113 '', 29114 '', 29115 '', 29116 '', 29117 '', 29118 '', 29119 '', 29120 '', 29121 '', 29122 '', 29123 '', 29124 '', 29125 '', 29126 '', 29127 '', 29128 '', 29129 '', 29130 'space', 29131 'exclam', 29132 'quotedbl', 29133 'numbersign', 29134 'dollar', 29135 'percent', 29136 'ampersand', 29137 'quoteright', 29138 'parenleft', 29139 'parenright', 29140 'asterisk', 29141 'plus', 29142 'comma', 29143 'hyphen', 29144 'period', 29145 'slash', 29146 'zero', 29147 'one', 29148 'two', 29149 'three', 29150 'four', 29151 'five', 29152 'six', 29153 'seven', 29154 'eight', 29155 'nine', 29156 'colon', 29157 'semicolon', 29158 'less', 29159 'equal', 29160 'greater', 29161 'question', 29162 'at', 29163 'A', 29164 'B', 29165 'C', 29166 'D', 29167 'E', 29168 'F', 29169 'G', 29170 'H', 29171 'I', 29172 'J', 29173 'K', 29174 'L', 29175 'M',
29176 'N', 29177 'O', 29178 'P', 29179 'Q', 29180 'R', 29181 'S', 29182 'T', 29183 'U', 29184 'V', 29185 'W', 29186 'X', 29187 'Y', 29188 'Z', 29189 'bracketleft', 29190 'backslash', 29191 'bracketright', 29192 'asciicircum', 29193 'underscore', 29194 'quoteleft', 29195 'a', 29196 'b', 29197 'c', 29198 'd', 29199 'e', 29200 'f', 29201 'g', 29202 'h', 29203 'i', 29204 'j', 29205 'k', 29206 'l', 29207 'm', 29208 'n', 29209 'o', 29210 'p', 29211 'q', 29212 'r', 29213 's', 29214 't', 29215 'u', 29216 'v', 29217 'w', 29218 'x', 29219 'y', 29220 'z', 29221 'braceleft', 29222 'bar', 29223 'braceright', 29224 'asciitilde', 29225 '', 29226 '', 29227 '', 29228 '', 29229 '', 29230 '', 29231 '', 29232 '', 29233 '', 29234 '', 29235 '', 29236 '', 29237 '', 29238 '', 29239 '', 29240 '', 29241 '', 29242 '', 29243 '', 29244 '', 29245 '', 29246 '', 29247 '', 29248 '', 29249 '', 29250 '', 29251 '', 29252 '', 29253 '', 29254 '', 29255 '', 29256 '', 29257 '', 29258 '', 29259 'exclamdown', 29260 'cent', 29261 'sterling', 29262 'fraction', 29263 'yen', 29264 'florin', 29265 'section', 29266 'currency', 29267 'quotesingle', 29268 'quotedblleft', 29269 'guillemotleft', 29270 'guilsinglleft', 29271 'guilsinglright', 29272 'fi', 29273 'fl', 29274 '', 29275 'endash', 29276 'dagger', 29277 'daggerdbl',
29278 'periodcentered', 29279 '', 29280 'paragraph', 29281 'bullet', 29282 'quotesinglbase', 29283 'quotedblbase', 29284 'quotedblright', 29285 'guillemotright', 29286 'ellipsis', 29287 'perthousand', 29288 '', 29289 'questiondown', 29290 '', 29291 'grave', 29292 'acute', 29293 'circumflex', 29294 'tilde', 29295 'macron', 29296 'breve', 29297 'dotaccent', 29298 'dieresis', 29299 '', 29300 'ring', 29301 'cedilla', 29302 '', 29303 'hungarumlaut', 29304 'ogonek', 29305 'caron', 29306 'emdash', 29307 '', 29308 '', 29309 '', 29310 '', 29311 '', 29312 '', 29313 '', 29314 '', 29315 '', 29316 '', 29317 '', 29318 '', 29319 '', 29320 '', 29321 '', 29322 '', 29323 'AE', 29324 '', 29325 'ordfeminine', 29326 '', 29327 '', 29328 '', 29329 '', 29330 'Lslash', 29331 'Oslash', 29332 'OE', 29333 'ordmasculine', 29334 '', 29335 '', 29336 '', 29337 '', 29338 '', 29339 'ae', 29340 '', 29341 '', 29342 '', 29343 'dotlessi', 29344 '', 29345 '', 29346 'lslash', 29347 'oslash', 29348 'oe', 29349 'germandbls' 29350 ]; 29351 29352 var cffExpertEncoding = [ 29353 '', 29354 '', 29355 '', 29356 '', 29357 '', 29358 '', 29359 '', 29360 '', 29361 '', 29362 '', 29363 '', 29364 '', 29365 '', 29366 '', 29367 '', 29368 '', 29369 '', 29370 '', 29371 '', 29372 '', 29373 '', 29374 '', 29375 '', 29376 '', 29377 '', 29378 '', 29379 '', 29380 '', 29381 '', 29382 '', 29383 '', 29384 '', 29385 'space', 29386 'exclamsmall', 29387 'Hungarumlautsmall', 29388 '', 29389 'dollaroldstyle', 29390 'dollarsuperior', 29391 'ampersandsmall', 29392 'Acutesmall', 29393 'parenleftsuperior', 29394 'parenrightsuperior', 29395 'twodotenleader', 29396 'onedotenleader', 29397 'comma', 29398 'hyphen', 29399 'period', 29400 'fraction', 29401 'zerooldstyle', 29402 'oneoldstyle', 29403 'twooldstyle', 29404 'threeoldstyle', 29405 'fouroldstyle', 29406 'fiveoldstyle', 29407 'sixoldstyle', 29408 'sevenoldstyle', 29409 'eightoldstyle', 29410 'nineoldstyle', 29411 'colon', 29412 'semicolon', 29413 'commasuperior', 29414 'threequartersemdash', 29415 'periodsuperior', 29416 'questionsmall', 29417 '', 29418 'asuperior', 29419 'bsuperior', 29420 'centsuperior', 29421 'dsuperior', 29422 'esuperior', 29423 '', 29424 '', 29425 'isuperior', 29426 '', 29427 '', 29428 'lsuperior', 29429 'msuperior', 29430 'nsuperior', 29431 'osuperior', 29432 '', 29433 '', 29434 'rsuperior', 29435 'ssuperior', 29436 'tsuperior', 29437 '', 29438 'ff', 29439 'fi', 29440 'fl', 29441 'ffi', 29442 'ffl', 29443 'parenleftinferior', 29444 '', 29445 'parenrightinferior', 29446 'Circumflexsmall', 29447 'hyphensuperior', 29448 'Gravesmall', 29449 'Asmall', 29450 'Bsmall', 29451 'Csmall', 29452 'Dsmall', 29453 'Esmall', 29454 'Fsmall', 29455 'Gsmall', 29456 'Hsmall', 29457 'Ismall', 29458 'Jsmall', 29459 'Ksmall', 29460 'Lsmall', 29461 'Msmall',
29462 'Nsmall', 29463 'Osmall', 29464 'Psmall', 29465 'Qsmall', 29466 'Rsmall', 29467 'Ssmall', 29468 'Tsmall', 29469 'Usmall', 29470 'Vsmall', 29471 'Wsmall', 29472 'Xsmall', 29473 'Ysmall', 29474 'Zsmall', 29475 'colonmonetary', 29476 'onefitted', 29477 'rupiah', 29478 'Tildesmall', 29479 '', 29480 '', 29481 '', 29482 '', 29483 '', 29484 '', 29485 '', 29486 '', 29487 '', 29488 '', 29489 '', 29490 '', 29491 '', 29492 '', 29493 '', 29494 '', 29495 '', 29496 '', 29497 '', 29498 '', 29499 '', 29500 '', 29501 '', 29502 '', 29503 '', 29504 '', 29505 '', 29506 '', 29507 '', 29508 '', 29509 '', 29510 '', 29511 '', 29512 '', 29513 'exclamdownsmall', 29514 'centoldstyle', 29515 'Lslashsmall', 29516 '', 29517 '', 29518 'Scaronsmall', 29519 'Zcaronsmall', 29520 'Dieresissmall', 29521 'Brevesmall', 29522 'Caronsmall', 29523 '', 29524 'Dotaccentsmall', 29525 '', 29526 '', 29527 'Macronsmall', 29528 '', 29529 '', 29530 'figuredash', 29531 'hypheninferior', 29532 '', 29533 '', 29534 'Ogoneksmall', 29535 'Ringsmall', 29536 'Cedillasmall', 29537 '', 29538 '', 29539 '', 29540 'onequarter', 29541 'onehalf', 29542 'threequarters', 29543 'questiondownsmall', 29544 'oneeighth', 29545 'threeeighths', 29546 'fiveeighths', 29547 'seveneighths', 29548 'onethird', 29549 'twothirds', 29550 '', 29551 '', 29552 'zerosuperior', 29553 'onesuperior', 29554 'twosuperior', 29555 'threesuperior', 29556 'foursuperior', 29557 'fivesuperior', 29558 'sixsuperior', 29559 'sevensuperior', 29560 'eightsuperior', 29561 'ninesuperior', 29562 'zeroinferior', 29563 'oneinferior', 29564 'twoinferior', 29565 'threeinferior', 29566 'fourinferior', 29567 'fiveinferior', 29568 'sixinferior', 29569 'seveninferior', 29570 'eightinferior', 29571 'nineinferior', 29572 'centinferior', 29573 'dollarinferior', 29574 'periodinferior', 29575 'commainferior', 29576 'Agravesmall', 29577 'Aacutesmall', 29578 'Acircumflexsmall', 29579 'Atildesmall', 29580 'Adieresissmall', 29581 'Aringsmall', 29582 'AEsmall', 29583 'Ccedillasmall', 29584 'Egravesmall', 29585 'Eacutesmall', 29586 'Ecircumflexsmall', 29587 'Edieresissmall', 29588 'Igravesmall', 29589 'Iacutesmall', 29590 'Icircumflexsmall', 29591 'Idieresissmall', 29592 'Ethsmall', 29593 'Ntildesmall', 29594 'Ogravesmall', 29595 'Oacutesmall', 29596 'Ocircumflexsmall', 29597 'Otildesmall', 29598 'Odieresissmall', 29599 'OEsmall', 29600 'Oslashsmall', 29601 'Ugravesmall', 29602 'Uacutesmall', 29603 'Ucircumflexsmall', 29604 'Udieresissmall', 29605 'Yacutesmall', 29606 'Thornsmall', 29607 'Ydieresissmall' 29608 ]; 29609 29610 var standardNames = [ 29611 '.notdef', 29612 '.null', 29613 'nonmarkingreturn', 29614 'space', 29615 'exclam', 29616 'quotedbl', 29617 'numbersign', 29618 'dollar', 29619 'percent', 29620 'ampersand', 29621 'quotesingle', 29622 'parenleft', 29623 'parenright', 29624 'asterisk', 29625 'plus', 29626 'comma', 29627 'hyphen', 29628 'period', 29629 'slash', 29630 'zero', 29631 'one', 29632 'two', 29633 'three', 29634 'four', 29635 'five', 29636 'six', 29637 'seven', 29638 'eight', 29639 'nine', 29640 'colon', 29641 'semicolon', 29642 'less', 29643 'equal', 29644 'greater', 29645 'question', 29646 'at', 29647 'A', 29648 'B', 29649 'C', 29650 'D', 29651 'E', 29652 'F', 29653 'G', 29654 'H', 29655 'I', 29656 'J', 29657 'K', 29658 'L', 29659 'M',
29660 'N', 29661 'O', 29662 'P', 29663 'Q', 29664 'R', 29665 'S', 29666 'T', 29667 'U', 29668 'V', 29669 'W', 29670 'X', 29671 'Y', 29672 'Z', 29673 'bracketleft', 29674 'backslash', 29675 'bracketright', 29676 'asciicircum', 29677 'underscore', 29678 'grave', 29679 'a', 29680 'b', 29681 'c', 29682 'd', 29683 'e', 29684 'f', 29685 'g', 29686 'h', 29687 'i', 29688 'j', 29689 'k', 29690 'l', 29691 'm', 29692 'n', 29693 'o', 29694 'p', 29695 'q', 29696 'r', 29697 's', 29698 't', 29699 'u', 29700 'v', 29701 'w', 29702 'x', 29703 'y', 29704 'z', 29705 'braceleft', 29706 'bar', 29707 'braceright', 29708 'asciitilde', 29709 'Adieresis', 29710 'Aring', 29711 'Ccedilla', 29712 'Eacute', 29713 'Ntilde', 29714 'Odieresis', 29715 'Udieresis', 29716 'aacute', 29717 'agrave', 29718 'acircumflex', 29719 'adieresis', 29720 'atilde', 29721 'aring', 29722 'ccedilla', 29723 'eacute', 29724 'egrave', 29725 'ecircumflex', 29726 'edieresis', 29727 'iacute', 29728 'igrave', 29729 'icircumflex', 29730 'idieresis', 29731 'ntilde', 29732 'oacute', 29733 'ograve', 29734 'ocircumflex', 29735 'odieresis', 29736 'otilde', 29737 'uacute', 29738 'ugrave', 29739 'ucircumflex', 29740 'udieresis', 29741 'dagger', 29742 'degree', 29743 'cent', 29744 'sterling', 29745 'section', 29746 'bullet', 29747 'paragraph', 29748 'germandbls', 29749 'registered', 29750 'copyright', 29751 'trademark', 29752 'acute', 29753 'dieresis', 29754 'notequal', 29755 'AE', 29756 'Oslash', 29757 'infinity', 29758 'plusminus', 29759 'lessequal', 29760 'greaterequal', 29761 'yen', 29762 'mu', 29763 'partialdiff', 29764 'summation', 29765 'product', 29766 'pi', 29767 'integral', 29768 'ordfeminine', 29769 'ordmasculine', 29770 'Omega', 29771 'ae', 29772 'oslash', 29773 'questiondown', 29774 'exclamdown', 29775 'logicalnot', 29776 'radical', 29777 'florin', 29778 'approxequal', 29779 'Delta', 29780 'guillemotleft', 29781 'guillemotright', 29782 'ellipsis', 29783 'nonbreakingspace', 29784 'Agrave', 29785 'Atilde', 29786 'Otilde', 29787 'OE', 29788 'oe', 29789 'endash', 29790 'emdash', 29791 'quotedblleft', 29792 'quotedblright', 29793 'quoteleft', 29794 'quoteright', 29795 'divide', 29796 'lozenge', 29797 'ydieresis', 29798 'Ydieresis', 29799 'fraction', 29800 'currency', 29801 'guilsinglleft', 29802 'guilsinglright', 29803 'fi', 29804 'fl', 29805 'daggerdbl',
29806 'periodcentered', 29807 'quotesinglbase', 29808 'quotedblbase', 29809 'perthousand', 29810 'Acircumflex', 29811 'Ecircumflex', 29812 'Aacute', 29813 'Edieresis', 29814 'Egrave', 29815 'Iacute', 29816 'Icircumflex', 29817 'Idieresis', 29818 'Igrave', 29819 'Oacute', 29820 'Ocircumflex', 29821 'apple', 29822 'Ograve', 29823 'Uacute', 29824 'Ucircumflex', 29825 'Ugrave', 29826 'dotlessi', 29827 'circumflex', 29828 'tilde', 29829 'macron', 29830 'breve', 29831 'dotaccent', 29832 'ring', 29833 'cedilla', 29834 'hungarumlaut', 29835 'ogonek', 29836 'caron', 29837 'Lslash', 29838 'lslash', 29839 'Scaron', 29840 'scaron', 29841 'Zcaron', 29842 'zcaron', 29843 'brokenbar', 29844 'Eth', 29845 'eth', 29846 'Yacute', 29847 'yacute', 29848 'Thorn', 29849 'thorn', 29850 'minus', 29851 'multiply', 29852 'onesuperior', 29853 'twosuperior', 29854 'threesuperior', 29855 'onehalf', 29856 'onequarter', 29857 'threequarters', 29858 'franc', 29859 'Gbreve', 29860 'gbreve', 29861 'Idotaccent', 29862 'Scedilla', 29863 'scedilla', 29864 'Cacute', 29865 'cacute', 29866 'Ccaron', 29867 'ccaron', 29868 'dcroat' 29869 ]; 29870 29871 /** 29872 * This is the encoding used for fonts created from scratch. 29873 * It loops through all glyphs and finds the appropriate unicode value. 29874 * Since it's linear time, other encodings will be faster. 29875 * @exports opentype.DefaultEncoding 29876 * @class 29877 * @constructor 29878 * @param {opentype.Font} 29879 */ 29880 function DefaultEncoding(font) { 29881 this.font = font; 29882 } 29883 29884 DefaultEncoding.prototype.charToGlyphIndex = function(c) { 29885 var code = c.codePointAt(0); 29886 var glyphs = this.font.glyphs; 29887 if (glyphs) { 29888 for (var i = 0; i < glyphs.length; i += 1) { 29889 var glyph = glyphs.get(i); 29890 for (var j = 0; j < glyph.unicodes.length; j += 1) { 29891 if (glyph.unicodes[j] === code) { 29892 return i; 29893 } 29894 } 29895 } 29896 } 29897 return null; 29898 }; 29899 29900 /** 29901 * @exports opentype.CmapEncoding 29902 * @class 29903 * @constructor 29904 * @param {Object} cmap - a object with the cmap encoded data 29905 */ 29906 function CmapEncoding(cmap) { 29907 this.cmap = cmap; 29908 } 29909 29910 /** 29911 * @param {string} c - the character 29912 * @return {number} The glyph index. 29913 */ 29914 CmapEncoding.prototype.charToGlyphIndex = function(c) { 29915 return this.cmap.glyphIndexMap[c.codePointAt(0)] || 0; 29916 }; 29917 29918 /** 29919 * @exports opentype.CffEncoding 29920 * @class 29921 * @constructor 29922 * @param {string} encoding - The encoding 29923 * @param {Array} charset - The character set. 29924 */ 29925 function CffEncoding(encoding, charset) { 29926 this.encoding = encoding; 29927 this.charset = charset; 29928 } 29929 29930 /** 29931 * @param {string} s - The character 29932 * @return {number} The index. 29933 */ 29934 CffEncoding.prototype.charToGlyphIndex = function(s) { 29935 var code = s.codePointAt(0); 29936 var charName = this.encoding[code]; 29937 return this.charset.indexOf(charName); 29938 }; 29939 29940 /** 29941 * @exports opentype.GlyphNames 29942 * @class 29943 * @constructor 29944 * @param {Object} post 29945 */ 29946 function GlyphNames(post) { 29947 var this$1 = this; 29948 29949 switch (post.version) { 29950 case 1: 29951 this.names = standardNames.slice(); 29952 break; 29953 case 2: 29954 this.names = new Array(post.numberOfGlyphs); 29955 for (var i = 0; i < post.numberOfGlyphs; i++) { 29956 if (post.glyphNameIndex[i] < standardNames.length) { 29957 this$1.names[i] = standardNames[post.glyphNameIndex[i]]; 29958 } else { 29959 this$1.names[i] = 29960 post.names[post.glyphNameIndex[i] - standardNames.length]; 29961 } 29962 } 29963 29964 break; 29965 case 2.5: 29966 this.names = new Array(post.numberOfGlyphs); 29967 for (var i$1 = 0; i$1 < post.numberOfGlyphs; i$1++) { 29968 this$1.names[i$1] = standardNames[i$1 + post.glyphNameIndex[i$1]]; 29969 } 29970 29971 break; 29972 case 3: 29973 this.names = []; 29974 break; 29975 default: 29976 this.names = []; 29977 break; 29978 } 29979 } 29980 29981 /** 29982 * Gets the index of a glyph by name. 29983 * @param {string} name - The glyph name 29984 * @return {number} The index 29985 */ 29986 GlyphNames.prototype.nameToGlyphIndex = function(name) { 29987 return this.names.indexOf(name); 29988 }; 29989 29990 /** 29991 * @param {number} gid 29992 * @return {string} 29993 */ 29994 GlyphNames.prototype.glyphIndexToName = function(gid) { 29995 return this.names[gid]; 29996 }; 29997 29998 /** 29999 * @alias opentype.addGlyphNames 30000 * @param {opentype.Font} 30001 */ 30002 function addGlyphNames(font) { 30003 var glyph; 30004 var glyphIndexMap = font.tables.cmap.glyphIndexMap;
30005 var charCodes = Object.keys(glyphIndexMap); 30006 30007 for (var i = 0; i < charCodes.length; i += 1) { 30008 var c = charCodes[i]; 30009 var glyphIndex = glyphIndexMap[c]; 30010 glyph = font.glyphs.get(glyphIndex); 30011 glyph.addUnicode(parseInt(c)); 30012 } 30013 30014 for (var i$1 = 0; i$1 < font.glyphs.length; i$1 += 1) { 30015 glyph = font.glyphs.get(i$1); 30016 if (font.cffEncoding) { 30017 if (font.isCIDFont) { 30018 glyph.name = 'gid' + i$1; 30019 } else { 30020 glyph.name = font.cffEncoding.charset[i$1]; 30021 } 30022 } else if (font.glyphNames.names) { 30023 glyph.name = font.glyphNames.glyphIndexToName(i$1); 30024 } 30025 } 30026 } 30027 30028 // Drawing utility functions. 30029 30030 // Draw a line on the given context from point `x1,y1` to point `x2,y2`. 30031 function line(ctx, x1, y1, x2, y2) { 30032 ctx.beginPath(); 30033 ctx.moveTo(x1, y1); 30034 ctx.lineTo(x2, y2); 30035 ctx.stroke(); 30036 } 30037 30038 var draw = { line: line }; 30039 30040 // The Glyph object 30041 // import glyf from './tables/glyf' Can't be imported here, because it's a circular dependency 30042 30043 function getPathDefinition(glyph, path) { 30044 var _path = path || new Path(); 30045 return { 30046 configurable: true, 30047 30048 get: function() { 30049 if (typeof _path === 'function') { 30050 _path = _path(); 30051 } 30052 30053 return _path; 30054 }, 30055 30056 set: function(p) { 30057 _path = p; 30058 } 30059 }; 30060 } 30061 /** 30062 * @typedef GlyphOptions 30063 * @type Object 30064 * @property {string} [name] - The glyph name 30065 * @property {number} [unicode] 30066 * @property {Array} [unicodes] 30067 * @property {number} [xMin] 30068 * @property {number} [yMin] 30069 * @property {number} [xMax] 30070 * @property {number} [yMax] 30071 * @property {number} [advanceWidth] 30072 */ 30073 30074 // A Glyph is an individual mark that often corresponds to a character. 30075 // Some glyphs, such as ligatures, are a combination of many characters. 30076 // Glyphs are the basic building blocks of a font. 30077 // 30078 // The `Glyph` class contains utility methods for drawing the path and its points. 30079 /** 30080 * @exports opentype.Glyph 30081 * @class 30082 * @param {GlyphOptions} 30083 * @constructor 30084 */ 30085 function Glyph(options) { 30086 // By putting all the code on a prototype function (which is only declared once) 30087 // we reduce the memory requirements for larger fonts by some 2% 30088 this.bindConstructorValues(options); 30089 } 30090 30091 /** 30092 * @param {GlyphOptions} 30093 */ 30094 Glyph.prototype.bindConstructorValues = function(options) { 30095 this.index = options.index || 0; 30096 30097 // These three values cannot be deferred for memory optimization: 30098 this.name = options.name || null; 30099 this.unicode = options.unicode || undefined; 30100 this.unicodes = 30101 options.unicodes || options.unicode !== undefined 30102 ? [options.unicode] 30103 : []; 30104 30105 // But by binding these values only when necessary, we reduce can 30106 // the memory requirements by almost 3% for larger fonts. 30107 if (options.xMin) { 30108 this.xMin = options.xMin; 30109 } 30110 30111 if (options.yMin) { 30112 this.yMin = options.yMin; 30113 } 30114 30115 if (options.xMax) { 30116 this.xMax = options.xMax; 30117 } 30118 30119 if (options.yMax) { 30120 this.yMax = options.yMax; 30121 } 30122 30123 if (options.advanceWidth) { 30124 this.advanceWidth = options.advanceWidth; 30125 } 30126 30127 // The path for a glyph is the most memory intensive, and is bound as a value 30128 // with a getter/setter to ensure we actually do path parsing only once the 30129 // path is actually needed by anything.
30130 Object.defineProperty(this, 'path', getPathDefinition(this, options.path)); 30131 }; 30132 30133 /** 30134 * @param {number} 30135 */ 30136 Glyph.prototype.addUnicode = function(unicode) { 30137 if (this.unicodes.length === 0) { 30138 this.unicode = unicode; 30139 } 30140 30141 this.unicodes.push(unicode); 30142 }; 30143 30144 /** 30145 * Calculate the minimum bounding box for this glyph. 30146 * @return {opentype.BoundingBox} 30147 */ 30148 Glyph.prototype.getBoundingBox = function() { 30149 return this.path.getBoundingBox(); 30150 }; 30151 30152 /** 30153 * Convert the glyph to a Path we can draw on a drawing context. 30154 * @param {number} [x=0] - Horizontal position of the beginning of the text. 30155 * @param {number} [y=0] - Vertical position of the *baseline* of the text. 30156 * @param {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. 30157 * @param {Object=} options - xScale, yScale to stretch the glyph. 30158 * @param {opentype.Font} if hinting is to be used, the font 30159 * @return {opentype.Path} 30160 */ 30161 Glyph.prototype.getPath = function(x, y, fontSize, options, font) { 30162 x = x !== undefined ? x : 0; 30163 y = y !== undefined ? y : 0; 30164 fontSize = fontSize !== undefined ? fontSize : 72; 30165 var commands; 30166 var hPoints; 30167 if (!options) { 30168 options = {}; 30169 } 30170 var xScale = options.xScale; 30171 var yScale = options.yScale; 30172 30173 if (options.hinting && font && font.hinting) { 30174 // in case of hinting, the hinting engine takes care 30175 // of scaling the points (not the path) before hinting. 30176 hPoints = this.path && font.hinting.exec(this, fontSize); 30177 // in case the hinting engine failed hPoints is undefined 30178 // and thus reverts to plain rending 30179 } 30180 30181 if (hPoints) { 30182 // Call font.hinting.getCommands instead of `glyf.getPath(hPoints).commands` to avoid a circular dependency 30183 commands = font.hinting.getCommands(hPoints); 30184 x = Math.round(x); 30185 y = Math.round(y); 30186 // TODO in case of hinting xyScaling is not yet supported 30187 xScale = yScale = 1; 30188 } else { 30189 commands = this.path.commands; 30190 var scale = 1 / this.path.unitsPerEm * fontSize; 30191 if (xScale === undefined) { 30192 xScale = scale; 30193 } 30194 if (yScale === undefined) { 30195 yScale = scale; 30196 } 30197 } 30198 30199 var p = new Path(); 30200 for (var i = 0; i < commands.length; i += 1) { 30201 var cmd = commands[i]; 30202 if (cmd.type === 'M') { 30203 p.moveTo(x + cmd.x * xScale, y + -cmd.y * yScale); 30204 } else if (cmd.type === 'L') { 30205 p.lineTo(x + cmd.x * xScale, y + -cmd.y * yScale); 30206 } else if (cmd.type === 'Q') { 30207 p.quadraticCurveTo( 30208 x + cmd.x1 * xScale, 30209 y + -cmd.y1 * yScale, 30210 x + cmd.x * xScale, 30211 y + -cmd.y * yScale 30212 ); 30213 } else if (cmd.type === 'C') { 30214 p.curveTo( 30215 x + cmd.x1 * xScale, 30216 y + -cmd.y1 * yScale, 30217 x + cmd.x2 * xScale, 30218 y + -cmd.y2 * yScale, 30219 x + cmd.x * xScale, 30220 y + -cmd.y * yScale 30221 ); 30222 } else if (cmd.type === 'Z') { 30223 p.closePath(); 30224 } 30225 } 30226 30227 return p; 30228 }; 30229 30230 /** 30231 * Split the glyph into contours. 30232 * This function is here for backwards compatibility, and to 30233 * provide raw access to the TrueType glyph outlines. 30234 * @return {Array} 30235 */ 30236 Glyph.prototype.getContours = function() { 30237 var this$1 = this; 30238 30239 if (this.points === undefined) { 30240 return []; 30241 } 30242 30243 var contours = []; 30244 var currentContour = []; 30245 for (var i = 0; i < this.points.length; i += 1) { 30246 var pt = this$1.points[i]; 30247 currentContour.push(pt); 30248 if (pt.lastPointOfContour) { 30249 contours.push(currentContour); 30250 currentContour = []; 30251 } 30252 } 30253 30254 check.argument( 30255 currentContour.length === 0, 30256 'There are still points left in the current contour.' 30257 ); 30258 return contours; 30259 }; 30260 30261 /**
30262 * Calculate the xMin/yMin/xMax/yMax/lsb/rsb for a Glyph. 30263 * @return {Object} 30264 */ 30265 Glyph.prototype.getMetrics = function() { 30266 var commands = this.path.commands; 30267 var xCoords = []; 30268 var yCoords = []; 30269 for (var i = 0; i < commands.length; i += 1) { 30270 var cmd = commands[i]; 30271 if (cmd.type !== 'Z') { 30272 xCoords.push(cmd.x); 30273 yCoords.push(cmd.y); 30274 } 30275 30276 if (cmd.type === 'Q' || cmd.type === 'C') { 30277 xCoords.push(cmd.x1); 30278 yCoords.push(cmd.y1); 30279 } 30280 30281 if (cmd.type === 'C') { 30282 xCoords.push(cmd.x2); 30283 yCoords.push(cmd.y2); 30284 } 30285 } 30286 30287 var metrics = { 30288 xMin: Math.min.apply(null, xCoords), 30289 yMin: Math.min.apply(null, yCoords), 30290 xMax: Math.max.apply(null, xCoords), 30291 yMax: Math.max.apply(null, yCoords), 30292 leftSideBearing: this.leftSideBearing 30293 }; 30294 30295 if (!isFinite(metrics.xMin)) { 30296 metrics.xMin = 0; 30297 } 30298 30299 if (!isFinite(metrics.xMax)) { 30300 metrics.xMax = this.advanceWidth; 30301 } 30302 30303 if (!isFinite(metrics.yMin)) { 30304 metrics.yMin = 0; 30305 } 30306 30307 if (!isFinite(metrics.yMax)) { 30308 metrics.yMax = 0; 30309 } 30310 30311 metrics.rightSideBearing = 30312 this.advanceWidth - 30313 metrics.leftSideBearing - 30314 (metrics.xMax - metrics.xMin); 30315 return metrics; 30316 }; 30317 30318 /** 30319 * Draw the glyph on the given context. 30320 * @param {CanvasRenderingContext2D} ctx - A 2D drawing context, like Canvas. 30321 * @param {number} [x=0] - Horizontal position of the beginning of the text. 30322 * @param {number} [y=0] - Vertical position of the *baseline* of the text. 30323 * @param {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. 30324 * @param {Object=} options - xScale, yScale to stretch the glyph. 30325 */ 30326 Glyph.prototype.draw = function(ctx, x, y, fontSize, options) { 30327 this.getPath(x, y, fontSize, options).draw(ctx); 30328 }; 30329 30330 /** 30331 * Draw the points of the glyph. 30332 * On-curve points will be drawn in blue, off-curve points will be drawn in red. 30333 * @param {CanvasRenderingContext2D} ctx - A 2D drawing context, like Canvas. 30334 * @param {number} [x=0] - Horizontal position of the beginning of the text. 30335 * @param {number} [y=0] - Vertical position of the *baseline* of the text. 30336 * @param {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. 30337 */ 30338 Glyph.prototype.drawPoints = function(ctx, x, y, fontSize) { 30339 function drawCircles(l, x, y, scale) { 30340 var PI_SQ = Math.PI * 2; 30341 ctx.beginPath(); 30342 for (var j = 0; j < l.length; j += 1) { 30343 ctx.moveTo(x + l[j].x * scale, y + l[j].y * scale); 30344 ctx.arc(x + l[j].x * scale, y + l[j].y * scale, 2, 0, PI_SQ, false); 30345 } 30346 30347 ctx.closePath(); 30348 ctx.fill(); 30349 } 30350 30351 x = x !== undefined ? x : 0; 30352 y = y !== undefined ? y : 0; 30353 fontSize = fontSize !== undefined ? fontSize : 24; 30354 var scale = 1 / this.path.unitsPerEm * fontSize; 30355 30356 var blueCircles = []; 30357 var redCircles = []; 30358 var path = this.path; 30359 for (var i = 0; i < path.commands.length; i += 1) { 30360 var cmd = path.commands[i]; 30361 if (cmd.x !== undefined) { 30362 blueCircles.push({ x: cmd.x, y: -cmd.y }); 30363 } 30364 30365 if (cmd.x1 !== undefined) { 30366 redCircles.push({ x: cmd.x1, y: -cmd.y1 }); 30367 } 30368 30369 if (cmd.x2 !== undefined) { 30370 redCircles.push({ x: cmd.x2, y: -cmd.y2 }); 30371 } 30372 } 30373 30374 ctx.fillStyle = 'blue'; 30375 drawCircles(blueCircles, x, y, scale); 30376 ctx.fillStyle = 'red'; 30377 drawCircles(redCircles, x, y, scale); 30378 }; 30379 30380 /** 30381 * Draw lines indicating important font measurements. 30382 * Black lines indicate the origin of the coordinate system (point 0,0). 30383 * Blue lines indicate the glyph bounding box. 30384 * Green line indicates the advance width of the glyph.
30385 * @param {CanvasRenderingContext2D} ctx - A 2D drawing context, like Canvas. 30386 * @param {number} [x=0] - Horizontal position of the beginning of the text. 30387 * @param {number} [y=0] - Vertical position of the *baseline* of the text. 30388 * @param {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. 30389 */ 30390 Glyph.prototype.drawMetrics = function(ctx, x, y, fontSize) { 30391 var scale; 30392 x = x !== undefined ? x : 0; 30393 y = y !== undefined ? y : 0; 30394 fontSize = fontSize !== undefined ? fontSize : 24; 30395 scale = 1 / this.path.unitsPerEm * fontSize; 30396 ctx.lineWidth = 1; 30397 30398 // Draw the origin 30399 ctx.strokeStyle = 'black'; 30400 draw.line(ctx, x, -10000, x, 10000); 30401 draw.line(ctx, -10000, y, 10000, y); 30402 30403 // This code is here due to memory optimization: by not using 30404 // defaults in the constructor, we save a notable amount of memory. 30405 var xMin = this.xMin || 0; 30406 var yMin = this.yMin || 0; 30407 var xMax = this.xMax || 0; 30408 var yMax = this.yMax || 0; 30409 var advanceWidth = this.advanceWidth || 0; 30410 30411 // Draw the glyph box 30412 ctx.strokeStyle = 'blue'; 30413 draw.line(ctx, x + xMin * scale, -10000, x + xMin * scale, 10000); 30414 draw.line(ctx, x + xMax * scale, -10000, x + xMax * scale, 10000); 30415 draw.line(ctx, -10000, y + -yMin * scale, 10000, y + -yMin * scale); 30416 draw.line(ctx, -10000, y + -yMax * scale, 10000, y + -yMax * scale); 30417 30418 // Draw the advance width 30419 ctx.strokeStyle = 'green'; 30420 draw.line( 30421 ctx, 30422 x + advanceWidth * scale, 30423 -10000, 30424 x + advanceWidth * scale, 30425 10000 30426 ); 30427 }; 30428 30429 // The GlyphSet object 30430 30431 // Define a property on the glyph that depends on the path being loaded. 30432 function defineDependentProperty(glyph, externalName, internalName) { 30433 Object.defineProperty(glyph, externalName, { 30434 get: function() { 30435 // Request the path property to make sure the path is loaded. 30436 glyph.path; // jshint ignore:line 30437 return glyph[internalName]; 30438 }, 30439 set: function(newValue) { 30440 glyph[internalName] = newValue; 30441 }, 30442 enumerable: true, 30443 configurable: true 30444 }); 30445 } 30446 30447 /** 30448 * A GlyphSet represents all glyphs available in the font, but modelled using 30449 * a deferred glyph loader, for retrieving glyphs only once they are absolutely 30450 * necessary, to keep the memory footprint down. 30451 * @exports opentype.GlyphSet 30452 * @class 30453 * @param {opentype.Font} 30454 * @param {Array} 30455 */ 30456 function GlyphSet(font, glyphs) { 30457 var this$1 = this; 30458 30459 this.font = font; 30460 this.glyphs = {}; 30461 if (Array.isArray(glyphs)) { 30462 for (var i = 0; i < glyphs.length; i++) { 30463 this$1.glyphs[i] = glyphs[i]; 30464 } 30465 } 30466 30467 this.length = (glyphs && glyphs.length) || 0; 30468 } 30469 30470 /** 30471 * @param {number} index 30472 * @return {opentype.Glyph} 30473 */ 30474 GlyphSet.prototype.get = function(index) { 30475 if (typeof this.glyphs[index] === 'function') { 30476 this.glyphs[index] = this.glyphs[index](); 30477 } 30478 30479 return this.glyphs[index]; 30480 }; 30481 30482 /** 30483 * @param {number} index 30484 * @param {Object} 30485 */ 30486 GlyphSet.prototype.push = function(index, loader) { 30487 this.glyphs[index] = loader; 30488 this.length++; 30489 }; 30490 30491 /** 30492 * @alias opentype.glyphLoader 30493 * @param {opentype.Font} font 30494 * @param {number} index 30495 * @return {opentype.Glyph} 30496 */ 30497 function glyphLoader(font, index) { 30498 return new Glyph({ index: index, font: font }); 30499 } 30500 30501 /** 30502 * Generate a stub glyph that can be filled with all metadata *except* 30503 * the "points" and "path" properties, which must be loaded only once 30504 * the glyph's path is actually requested for text shaping. 30505 * @alias opentype.ttfGlyphLoader 30506 * @param {opentype.Font} font 30507 * @param {number} index 30508 * @param {Function} parseGlyph 30509 * @param {Object} data 30510 * @param {number} position 30511 * @param {Function} buildPath 30512 * @return {opentype.Glyph} 30513 */ 30514 function ttfGlyphLoader(font, index, parseGlyph, data, position, buildPath) { 30515 return function() { 30516 var glyph = new Glyph({ index: index, font: font }); 30517 30518 glyph.path = function() { 30519 parseGlyph(glyph, data, position); 30520 var path = buildPath(font.glyphs, glyph); 30521 path.unitsPerEm = font.unitsPerEm; 30522 return path; 30523 }; 30524
30525 defineDependentProperty(glyph, 'xMin', '_xMin'); 30526 defineDependentProperty(glyph, 'xMax', '_xMax'); 30527 defineDependentProperty(glyph, 'yMin', '_yMin'); 30528 defineDependentProperty(glyph, 'yMax', '_yMax'); 30529 30530 return glyph; 30531 }; 30532 } 30533 /** 30534 * @alias opentype.cffGlyphLoader 30535 * @param {opentype.Font} font 30536 * @param {number} index 30537 * @param {Function} parseCFFCharstring 30538 * @param {string} charstring 30539 * @return {opentype.Glyph} 30540 */ 30541 function cffGlyphLoader(font, index, parseCFFCharstring, charstring) { 30542 return function() { 30543 var glyph = new Glyph({ index: index, font: font }); 30544 30545 glyph.path = function() { 30546 var path = parseCFFCharstring(font, glyph, charstring); 30547 path.unitsPerEm = font.unitsPerEm; 30548 return path; 30549 }; 30550 30551 return glyph; 30552 }; 30553 } 30554 30555 var glyphset = { 30556 GlyphSet: GlyphSet, 30557 glyphLoader: glyphLoader, 30558 ttfGlyphLoader: ttfGlyphLoader, 30559 cffGlyphLoader: cffGlyphLoader 30560 }; 30561 30562 // The `CFF` table contains the glyph outlines in PostScript format. 30563 30564 // Custom equals function that can also check lists. 30565 function equals(a, b) { 30566 if (a === b) { 30567 return true; 30568 } else if (Array.isArray(a) && Array.isArray(b)) { 30569 if (a.length !== b.length) { 30570 return false; 30571 } 30572 30573 for (var i = 0; i < a.length; i += 1) { 30574 if (!equals(a[i], b[i])) { 30575 return false; 30576 } 30577 } 30578 30579 return true; 30580 } else { 30581 return false; 30582 } 30583 } 30584 30585 // Subroutines are encoded using the negative half of the number space. 30586 // See type 2 chapter 4.7 "Subroutine operators". 30587 function calcCFFSubroutineBias(subrs) { 30588 var bias; 30589 if (subrs.length < 1240) { 30590 bias = 107; 30591 } else if (subrs.length < 33900) { 30592 bias = 1131; 30593 } else { 30594 bias = 32768; 30595 } 30596 30597 return bias; 30598 } 30599 30600 // Parse a `CFF` INDEX array. 30601 // An index array consists of a list of offsets, then a list of objects at those offsets. 30602 function parseCFFIndex(data, start, conversionFn) { 30603 var offsets = []; 30604 var objects = []; 30605 var count = parse.getCard16(data, start); 30606 var objectOffset; 30607 var endOffset; 30608 if (count !== 0) { 30609 var offsetSize = parse.getByte(data, start + 2); 30610 objectOffset = start + (count + 1) * offsetSize + 2; 30611 var pos = start + 3; 30612 for (var i = 0; i < count + 1; i += 1) { 30613 offsets.push(parse.getOffset(data, pos, offsetSize)); 30614 pos += offsetSize; 30615 } 30616 30617 // The total size of the index array is 4 header bytes + the value of the last offset. 30618 endOffset = objectOffset + offsets[count]; 30619 } else { 30620 endOffset = start + 2; 30621 } 30622 30623 for (var i$1 = 0; i$1 < offsets.length - 1; i$1 += 1) { 30624 var value = parse.getBytes( 30625 data, 30626 objectOffset + offsets[i$1], 30627 objectOffset + offsets[i$1 + 1] 30628 ); 30629 if (conversionFn) { 30630 value = conversionFn(value); 30631 } 30632 30633 objects.push(value); 30634 } 30635 30636 return { objects: objects, startOffset: start, endOffset: endOffset }; 30637 } 30638 30639 // Parse a `CFF` DICT real value. 30640 function parseFloatOperand(parser) { 30641 var s = ''; 30642 var eof = 15; 30643 var lookup = [ 30644 '0', 30645 '1', 30646 '2', 30647 '3', 30648 '4', 30649 '5', 30650 '6', 30651 '7', 30652 '8', 30653 '9', 30654 '.', 30655 'E', 30656 'E-', 30657 null,
vendor: 4,555 bytes, lines 30658-30790
30658 '-' 30659 ]; 30660 while (true) { 30661 var b = parser.parseByte(); 30662 var n1 = b >> 4; 30663 var n2 = b & 15; 30664 30665 if (n1 === eof) { 30666 break; 30667 } 30668 30669 s += lookup[n1]; 30670 30671 if (n2 === eof) { 30672 break; 30673 } 30674 30675 s += lookup[n2]; 30676 } 30677 30678 return parseFloat(s); 30679 } 30680 30681 // Parse a `CFF` DICT operand. 30682 function parseOperand(parser, b0) { 30683 var b1; 30684 var b2; 30685 var b3; 30686 var b4; 30687 if (b0 === 28) { 30688 b1 = parser.parseByte(); 30689 b2 = parser.parseByte(); 30690 return (b1 << 8) | b2; 30691 } 30692 30693 if (b0 === 29) { 30694 b1 = parser.parseByte(); 30695 b2 = parser.parseByte(); 30696 b3 = parser.parseByte(); 30697 b4 = parser.parseByte(); 30698 return (b1 << 24) | (b2 << 16) | (b3 << 8) | b4; 30699 } 30700 30701 if (b0 === 30) { 30702 return parseFloatOperand(parser); 30703 } 30704 30705 if (b0 >= 32 && b0 <= 246) { 30706 return b0 - 139; 30707 } 30708 30709 if (b0 >= 247 && b0 <= 250) { 30710 b1 = parser.parseByte(); 30711 return (b0 - 247) * 256 + b1 + 108; 30712 } 30713 30714 if (b0 >= 251 && b0 <= 254) { 30715 b1 = parser.parseByte(); 30716 return -(b0 - 251) * 256 - b1 - 108; 30717 } 30718 30719 throw new Error('Invalid b0 ' + b0); 30720 } 30721 30722 // Convert the entries returned by `parseDict` to a proper dictionary. 30723 // If a value is a list of one, it is unpacked. 30724 function entriesToObject(entries) { 30725 var o = {}; 30726 for (var i = 0; i < entries.length; i += 1) { 30727 var key = entries[i][0]; 30728 var values = entries[i][1]; 30729 var value = void 0; 30730 if (values.length === 1) { 30731 value = values[0]; 30732 } else { 30733 value = values; 30734 } 30735 30736 if (o.hasOwnProperty(key) && !isNaN(o[key])) { 30737 throw new Error('Object ' + o + ' already has key ' + key); 30738 } 30739 30740 o[key] = value; 30741 } 30742 30743 return o; 30744 } 30745 30746 // Parse a `CFF` DICT object. 30747 // A dictionary contains key-value pairs in a compact tokenized format. 30748 function parseCFFDict(data, start, size) { 30749 start = start !== undefined ? start : 0; 30750 var parser = new parse.Parser(data, start); 30751 var entries = []; 30752 var operands = []; 30753 size = size !== undefined ? size : data.length; 30754 30755 while (parser.relativeOffset < size) { 30756 var op = parser.parseByte(); 30757 30758 // The first byte for each dict item distinguishes between operator (key) and operand (value). 30759 // Values <= 21 are operators. 30760 if (op <= 21) { 30761 // Two-byte operators have an initial escape byte of 12. 30762 if (op === 12) { 30763 op = 1200 + parser.parseByte(); 30764 } 30765 30766 entries.push([op, operands]); 30767 operands = []; 30768 } else { 30769 // Since the operands (values) come before the operators (keys), we store all operands in a list 30770 // until we encounter an operator. 30771 operands.push(parseOperand(parser, op)); 30772 } 30773 } 30774 30775 return entriesToObject(entries); 30776 } 30777 30778 // Given a String Index (SID), return the value of the string. 30779 // Strings below index 392 are standard CFF strings and are not encoded in the font. 30780 function getCFFString(strings, index) { 30781 if (index <= 390) { 30782 index = cffStandardStrings[index]; 30783 } else { 30784 index = strings[index - 391]; 30785 } 30786 30787 return index; 30788 } 30789 30790 // Interpret a dictionary and return a new dictionary with readable keys and values for missing entr
30790ies. 30791 // This function takes `meta` which is a list of objects containing `operand`, `name` and `default`. 30792 function interpretDict(dict, meta, strings) { 30793 var newDict = {}; 30794 var value; 30795 30796 // Because we also want to include missing values, we start out from the meta list 30797 // and lookup values in the dict. 30798 for (var i = 0; i < meta.length; i += 1) { 30799 var m = meta[i]; 30800 30801 if (Array.isArray(m.type)) { 30802 var values = []; 30803 values.length = m.type.length; 30804 for (var j = 0; j < m.type.length; j++) { 30805 value = dict[m.op] !== undefined ? dict[m.op][j] : undefined; 30806 if (value === undefined) { 30807 value = 30808 m.value !== undefined && m.value[j] !== undefined 30809 ? m.value[j] 30810 : null; 30811 } 30812 if (m.type[j] === 'SID') { 30813 value = getCFFString(strings, value); 30814 } 30815 values[j] = value; 30816 } 30817 newDict[m.name] = values; 30818 } else { 30819 value = dict[m.op]; 30820 if (value === undefined) { 30821 value = m.value !== undefined ? m.value : null; 30822 } 30823 30824 if (m.type === 'SID') { 30825 value = getCFFString(strings, value); 30826 } 30827 newDict[m.name] = value; 30828 } 30829 } 30830 30831 return newDict; 30832 } 30833 30834 // Parse the CFF header. 30835 function parseCFFHeader(data, start) { 30836 var header = {}; 30837 header.formatMajor = parse.getCard8(data, start); 30838 header.formatMinor = parse.getCard8(data, start + 1); 30839 header.size = parse.getCard8(data, start + 2); 30840 header.offsetSize = parse.getCard8(data, start + 3); 30841 header.startOffset = start; 30842 header.endOffset = start + 4; 30843 return header; 30844 } 30845 30846 var TOP_DICT_META = [ 30847 { name: 'version', op: 0, type: 'SID' }, 30848 { name: 'notice', op: 1, type: 'SID' }, 30849 { name: 'copyright', op: 1200, type: 'SID' }, 30850 { name: 'fullName', op: 2, type: 'SID' }, 30851 { name: 'familyName', op: 3, type: 'SID' }, 30852 { name: 'weight', op: 4, type: 'SID' }, 30853 { name: 'isFixedPitch', op: 1201, type: 'number', value: 0 }, 30854 { name: 'italicAngle', op: 1202, type: 'number', value: 0 }, 30855 { name: 'underlinePosition', op: 1203, type: 'number', value: -100 }, 30856 { name: 'underlineThickness', op: 1204, type: 'number', value: 50 }, 30857 { name: 'paintType', op: 1205, type: 'number', value: 0 }, 30858 { name: 'charstringType', op: 1206, type: 'number', value: 2 }, 30859 { 30860 name: 'fontMatrix', 30861 op: 1207, 30862 type: ['real', 'real', 'real', 'real', 'real', 'real'], 30863 value: [0.001, 0, 0, 0.001, 0, 0] 30864 }, 30865 { name: 'uniqueId', op: 13, type: 'number' }, 30866 { 30867 name: 'fontBBox', 30868 op: 5, 30869 type: ['number', 'number', 'number', 'number'], 30870 value: [0, 0, 0, 0] 30871 }, 30872 { name: 'strokeWidth', op: 1208, type: 'number', value: 0 }, 30873 { name: 'xuid', op: 14, type: [], value: null }, 30874 { name: 'charset', op: 15, type: 'offset', value: 0 }, 30875 { name: 'encoding', op: 16, type: 'offset', value: 0 }, 30876 { name: 'charStrings', op: 17, type: 'offset', value: 0 }, 30877 { name: 'private', op: 18, type: ['number', 'offset'], value: [0, 0] }, 30878 { name: 'ros', op: 1230, type: ['SID', 'SID', 'number'] }, 30879 { name: 'cidFontVersion', op: 1231, type: 'number', value: 0 }, 30880 { name: 'cidFontRevision', op: 1232, type: 'number', value: 0 }, 30881 { name: 'cidFontType', op: 1233, type: 'number', value: 0 }, 30882 { name: 'cidCount', op: 1234, type: 'number', value: 8720 }, 30883 { name: 'uidBase', op: 1235, type: 'number' }, 30884 { name: 'fdArray', op: 1236, type: 'offset' }, 30885 { name: 'fdSelect', op: 1237, type: 'offset' }, 30886 { name: 'fontName', op: 1238, type: 'SID' } 30887 ]; 30888 30889 var PRIVATE_DICT_META = [ 30890 { name: 'subrs', op: 19, type: 'offset', value: 0 }, 30891 { name: 'defaultWidthX', op: 20, type: 'number', value: 0 }, 30892 { name: 'nominalWidthX', op: 21, type: 'number', value: 0 } 30893 ]; 30894 30895 // Parse the CFF top dictionary. A CFF table can contain multiple fonts, each with their own top dictionary. 30896 // The top dictionary contains the essential metadata for the font, together with the private dictionary. 30897 function parseCFFTopDict(data, strings) { 30898 var dict = parseCFFDict(data, 0, data.byteLength); 30899 return interpretDict(dict, TOP_DICT_META, strings); 30900 } 30901 30902 // Parse the CFF private dictionary. We don't fully parse out all the values, only the ones we need. 30903 function parseCFFPrivateDict(data, start, size, strings) { 30904 var dict = parseCFFDict(data, start, size); 30905 return interpretDict(dict, PRIVATE_DICT_META, strings); 30906 } 30907 30908 // Returns a list of "Top DICT"s found using an INDEX list. 30909 // Used to read both the usual high-level Top DICTs and also the FDArray 30910 // discovered inside CID-keyed fonts. When a Top DICT has a reference to 30911 // a Private DICT that is read and saved into the Top DICT. 30912 // 30913 // In addition to the expected/optional values as outlined in TOP_DICT_META 30914 // the following values might be saved into the Top DICT. 30915 //
vendor: 26,738 bytes, lines 30916-31537
30916 // _subrs [] array of local CFF subroutines from Private DICT 30917 // _subrsBias bias value computed from number of subroutines 30918 // (see calcCFFSubroutineBias() and parseCFFCharstring()) 30919 // _defaultWidthX default widths for CFF characters 30920 // _nominalWidthX bias added to width embedded within glyph description 30921 // 30922 // _privateDict saved copy of parsed Private DICT from Top DICT 30923 function gatherCFFTopDicts(data, start, cffIndex, strings) { 30924 var topDictArray = []; 30925 for (var iTopDict = 0; iTopDict < cffIndex.length; iTopDict += 1) { 30926 var topDictData = new DataView(new Uint8Array(cffIndex[iTopDict]).buffer); 30927 var topDict = parseCFFTopDict(topDictData, strings); 30928 topDict._subrs = []; 30929 topDict._subrsBias = 0; 30930 var privateSize = topDict.private[0]; 30931 var privateOffset = topDict.private[1]; 30932 if (privateSize !== 0 && privateOffset !== 0) { 30933 var privateDict = parseCFFPrivateDict( 30934 data, 30935 privateOffset + start, 30936 privateSize, 30937 strings 30938 ); 30939 topDict._defaultWidthX = privateDict.defaultWidthX; 30940 topDict._nominalWidthX = privateDict.nominalWidthX; 30941 if (privateDict.subrs !== 0) { 30942 var subrOffset = privateOffset + privateDict.subrs; 30943 var subrIndex = parseCFFIndex(data, subrOffset + start); 30944 topDict._subrs = subrIndex.objects; 30945 topDict._subrsBias = calcCFFSubroutineBias(topDict._subrs); 30946 } 30947 topDict._privateDict = privateDict; 30948 } 30949 topDictArray.push(topDict); 30950 } 30951 return topDictArray; 30952 } 30953 30954 // Parse the CFF charset table, which contains internal names for all the glyphs. 30955 // This function will return a list of glyph names. 30956 // See Adobe TN #5176 chapter 13, "Charsets". 30957 function parseCFFCharset(data, start, nGlyphs, strings) { 30958 var sid; 30959 var count; 30960 var parser = new parse.Parser(data, start); 30961 30962 // The .notdef glyph is not included, so subtract 1. 30963 nGlyphs -= 1; 30964 var charset = ['.notdef']; 30965 30966 var format = parser.parseCard8(); 30967 if (format === 0) { 30968 for (var i = 0; i < nGlyphs; i += 1) { 30969 sid = parser.parseSID(); 30970 charset.push(getCFFString(strings, sid)); 30971 } 30972 } else if (format === 1) { 30973 while (charset.length <= nGlyphs) { 30974 sid = parser.parseSID(); 30975 count = parser.parseCard8(); 30976 for (var i$1 = 0; i$1 <= count; i$1 += 1) { 30977 charset.push(getCFFString(strings, sid)); 30978 sid += 1; 30979 } 30980 } 30981 } else if (format === 2) { 30982 while (charset.length <= nGlyphs) { 30983 sid = parser.parseSID(); 30984 count = parser.parseCard16(); 30985 for (var i$2 = 0; i$2 <= count; i$2 += 1) { 30986 charset.push(getCFFString(strings, sid)); 30987 sid += 1; 30988 } 30989 } 30990 } else { 30991 throw new Error('Unknown charset format ' + format); 30992 } 30993 30994 return charset; 30995 } 30996 30997 // Parse the CFF encoding data. Only one encoding can be specified per font. 30998 // See Adobe TN #5176 chapter 12, "Encodings". 30999 function parseCFFEncoding(data, start, charset) { 31000 var code; 31001 var enc = {}; 31002 var parser = new parse.Parser(data, start); 31003 var format = parser.parseCard8(); 31004 if (format === 0) { 31005 var nCodes = parser.parseCard8(); 31006 for (var i = 0; i < nCodes; i += 1) { 31007 code = parser.parseCard8(); 31008 enc[code] = i; 31009 } 31010 } else if (format === 1) { 31011 var nRanges = parser.parseCard8(); 31012 code = 1; 31013 for (var i$1 = 0; i$1 < nRanges; i$1 += 1) { 31014 var first = parser.parseCard8(); 31015 var nLeft = parser.parseCard8(); 31016 for (var j = first; j <= first + nLeft; j += 1) { 31017 enc[j] = code; 31018 code += 1; 31019 } 31020 } 31021 } else { 31022 throw new Error('Unknown encoding format ' + format); 31023 } 31024 31025 return new CffEncoding(enc, charset); 31026 } 31027 31028 // Take in charstring code and return a Glyph object. 31029 // The encoding is described in the Type 2 Charstring Format 31030 // https://www.microsoft.com/typography/OTSPEC/charstr2.htm 31031 function parseCFFCharstring(font, glyph, code) { 31032 var c1x; 31033 var c1y; 31034 var c2x; 31035 var c2y; 31036 var p = new Path(); 31037 var stack = []; 31038 var nStems = 0; 31039 var haveWidth = false; 31040 var open = false; 31041 var x = 0; 31042 var y = 0; 31043 var subrs; 31044 var subrsBias; 31045 var defaultWidthX; 31046 var nominalWidthX; 31047 if (font.isCIDFont) { 31048 var fdIndex = font.tables.cff.topDict._fdSelect[glyph.index]; 31049 var fdDict = font.tables.cff.topDict._fdArray[fdIndex]; 31050 subrs = fdDict._subrs; 31051 subrsBias = fdDict._subrsBias; 31052 defaultWidthX = fdDict._defaultWidthX; 31053 nominalWidthX = fdDict._nominalWidthX; 31054 } else { 31055 subrs = font.tables.cff.topDict._subrs; 31056 subrsBias = font.tables.cff.topDict._subrsBias; 31057 defaultWidthX = font.tables.cff.topDict._defaultWidthX; 31058 nominalWidthX = font.tables.cff.topDict._nominalWidthX; 31059 } 31060 var width = defaultWidthX; 31061 31062 function newContour(x, y) { 31063 if (open) { 31064 p.closePath(); 31065 } 31066 31067 p.moveTo(x, y); 31068 open = true; 31069 } 31070 31071 function parseStems() { 31072 var hasWidthArg; 31073 31074 // The number of stem operators on the stack is always even. 31075 // If the value is uneven, that means a width is specified. 31076 hasWidthArg = stack.length % 2 !== 0; 31077 if (hasWidthArg && !haveWidth) { 31078 width = stack.shift() + nominalWidthX; 31079 } 31080 31081 nStems += stack.length >> 1; 31082 stack.length = 0; 31083 haveWidth = true; 31084 } 31085 31086 function parse$$1(code) { 31087 var b1; 31088 var b2; 31089 var b3; 31090 var b4; 31091 var codeIndex; 31092 var subrCode; 31093 var jpx; 31094 var jpy; 31095 var c3x; 31096 var c3y; 31097 var c4x; 31098 var c4y; 31099 31100 var i = 0; 31101 while (i < code.length) { 31102 var v = code[i]; 31103 i += 1; 31104 switch (v) { 31105 case 1: // hstem 31106 parseStems(); 31107 break; 31108 case 3: // vstem 31109 parseStems(); 31110 break; 31111 case 4: // vmoveto 31112 if (stack.length > 1 && !haveWidth) { 31113 width = stack.shift() + nominalWidthX; 31114 haveWidth = true; 31115 } 31116 31117 y += stack.pop(); 31118 newContour(x, y); 31119 break; 31120 case 5: // rlineto 31121 while (stack.length > 0) { 31122 x += stack.shift(); 31123 y += stack.shift(); 31124 p.lineTo(x, y); 31125 } 31126 31127 break; 31128 case 6: // hlineto 31129 while (stack.length > 0) { 31130 x += stack.shift(); 31131 p.lineTo(x, y); 31132 if (stack.length === 0) { 31133 break; 31134 } 31135 31136 y += stack.shift(); 31137 p.lineTo(x, y); 31138 } 31139 31140 break; 31141 case 7: // vlineto 31142 while (stack.length > 0) { 31143 y += stack.shift(); 31144 p.lineTo(x, y); 31145 if (stack.length === 0) { 31146 break; 31147 } 31148 31149 x += stack.shift(); 31150 p.lineTo(x, y); 31151 } 31152 31153 break; 31154 case 8: // rrcurveto 31155 while (stack.length > 0) { 31156 c1x = x + stack.shift(); 31157 c1y = y + stack.shift(); 31158 c2x = c1x + stack.shift(); 31159 c2y = c1y + stack.shift(); 31160 x = c2x + stack.shift(); 31161 y = c2y + stack.shift(); 31162 p.curveTo(c1x, c1y, c2x, c2y, x, y); 31163 } 31164 31165 break; 31166 case 10: // callsubr 31167 codeIndex = stack.pop() + subrsBias; 31168 subrCode = subrs[codeIndex]; 31169 if (subrCode) { 31170 parse$$1(subrCode); 31171 } 31172 31173 break; 31174 case 11: // return 31175 return; 31176 case 12: // flex operators 31177 v = code[i]; 31178 i += 1; 31179 switch (v) { 31180 case 35: // flex 31181 // |- dx1 dy1 dx2 dy2 dx3 dy3 dx4 dy4 dx5 dy5 dx6 dy6 fd flex (12 35) |- 31182 c1x = x + stack.shift(); // dx1 31183 c1y = y + stack.shift(); // dy1 31184 c2x = c1x + stack.shift(); // dx2 31185 c2y = c1y + stack.shift(); // dy2 31186 jpx = c2x + stack.shift(); // dx3 31187 jpy = c2y + stack.shift(); // dy3 31188 c3x = jpx + stack.shift(); // dx4 31189 c3y = jpy + stack.shift(); // dy4 31190 c4x = c3x + stack.shift(); // dx5 31191 c4y = c3y + stack.shift(); // dy5 31192 x = c4x + stack.shift(); // dx6 31193 y = c4y + stack.shift(); // dy6 31194 stack.shift(); // flex depth 31195 p.curveTo(c1x, c1y, c2x, c2y, jpx, jpy); 31196 p.curveTo(c3x, c3y, c4x, c4y, x, y); 31197 break; 31198 case 34: // hflex 31199 // |- dx1 dx2 dy2 dx3 dx4 dx5 dx6 hflex (12 34) |- 31200 c1x = x + stack.shift(); // dx1 31201 c1y = y; // dy1 31202 c2x = c1x + stack.shift(); // dx2 31203 c2y = c1y + stack.shift(); // dy2 31204 jpx = c2x + stack.shift(); // dx3 31205 jpy = c2y; // dy3 31206 c3x = jpx + stack.shift(); // dx4 31207 c3y = c2y; // dy4 31208 c4x = c3x + stack.shift(); // dx5 31209 c4y = y; // dy5 31210 x = c4x + stack.shift(); // dx6 31211 p.curveTo(c1x, c1y, c2x, c2y, jpx, jpy); 31212 p.curveTo(c3x, c3y, c4x, c4y, x, y); 31213 break; 31214 case 36: // hflex1 31215 // |- dx1 dy1 dx2 dy2 dx3 dx4 dx5 dy5 dx6 hflex1 (12 36) |- 31216 c1x = x + stack.shift(); // dx1 31217 c1y = y + stack.shift(); // dy1 31218 c2x = c1x + stack.shift(); // dx2 31219 c2y = c1y + stack.shift(); // dy2 31220 jpx = c2x + stack.shift(); // dx3 31221 jpy = c2y; // dy3 31222 c3x = jpx + stack.shift(); // dx4 31223 c3y = c2y; // dy4 31224 c4x = c3x + stack.shift(); // dx5 31225 c4y = c3y + stack.shift(); // dy5 31226 x = c4x + stack.shift(); // dx6 31227 p.curveTo(c1x, c1y, c2x, c2y, jpx, jpy); 31228 p.curveTo(c3x, c3y, c4x, c4y, x, y); 31229 break; 31230 case 37: // flex1 31231 // |- dx1 dy1 dx2 dy2 dx3 dy3 dx4 dy4 dx5 dy5 d6 flex1 (12 37) |- 31232 c1x = x + stack.shift(); // dx1 31233 c1y = y + stack.shift(); // dy1 31234 c2x = c1x + stack.shift(); // dx2 31235 c2y = c1y + stack.shift(); // dy2 31236 jpx = c2x + stack.shift(); // dx3 31237 jpy = c2y + stack.shift(); // dy3 31238 c3x = jpx + stack.shift(); // dx4 31239 c3y = jpy + stack.shift(); // dy4 31240 c4x = c3x + stack.shift(); // dx5 31241 c4y = c3y + stack.shift(); // dy5 31242 if (Math.abs(c4x - x) > Math.abs(c4y - y)) { 31243 x = c4x + stack.shift(); 31244 } else { 31245 y = c4y + stack.shift(); 31246 } 31247 31248 p.curveTo(c1x, c1y, c2x, c2y, jpx, jpy); 31249 p.curveTo(c3x, c3y, c4x, c4y, x, y); 31250 break; 31251 default: 31252 console.log( 31253 'Glyph ' + glyph.index + ': unknown operator ' + 1200 + v 31254 ); 31255 stack.length = 0; 31256 } 31257 break; 31258 case 14: // endchar 31259 if (stack.length > 0 && !haveWidth) { 31260 width = stack.shift() + nominalWidthX; 31261 haveWidth = true; 31262 } 31263 31264 if (open) { 31265 p.closePath(); 31266 open = false; 31267 } 31268 31269 break; 31270 case 18: // hstemhm 31271 parseStems(); 31272 break; 31273 case 19: // hintmask 31274 case 20: // cntrmask 31275 parseStems(); 31276 i += (nStems + 7) >> 3; 31277 break; 31278 case 21: // rmoveto 31279 if (stack.length > 2 && !haveWidth) { 31280 width = stack.shift() + nominalWidthX; 31281 haveWidth = true; 31282 } 31283 31284 y += stack.pop(); 31285 x += stack.pop(); 31286 newContour(x, y); 31287 break; 31288 case 22: // hmoveto 31289 if (stack.length > 1 && !haveWidth) { 31290 width = stack.shift() + nominalWidthX; 31291 haveWidth = true; 31292 } 31293 31294 x += stack.pop(); 31295 newContour(x, y); 31296 break; 31297 case 23: // vstemhm 31298 parseStems(); 31299 break; 31300 case 24: // rcurveline 31301 while (stack.length > 2) { 31302 c1x = x + stack.shift(); 31303 c1y = y + stack.shift(); 31304 c2x = c1x + stack.shift(); 31305 c2y = c1y + stack.shift(); 31306 x = c2x + stack.shift(); 31307 y = c2y + stack.shift(); 31308 p.curveTo(c1x, c1y, c2x, c2y, x, y); 31309 } 31310 31311 x += stack.shift(); 31312 y += stack.shift(); 31313 p.lineTo(x, y); 31314 break; 31315 case 25: // rlinecurve 31316 while (stack.length > 6) { 31317 x += stack.shift(); 31318 y += stack.shift(); 31319 p.lineTo(x, y); 31320 } 31321 31322 c1x = x + stack.shift(); 31323 c1y = y + stack.shift(); 31324 c2x = c1x + stack.shift(); 31325 c2y = c1y + stack.shift(); 31326 x = c2x + stack.shift(); 31327 y = c2y + stack.shift(); 31328 p.curveTo(c1x, c1y, c2x, c2y, x, y); 31329 break; 31330 case 26: // vvcurveto 31331 if (stack.length % 2) { 31332 x += stack.shift(); 31333 } 31334 31335 while (stack.length > 0) { 31336 c1x = x; 31337 c1y = y + stack.shift(); 31338 c2x = c1x + stack.shift(); 31339 c2y = c1y + stack.shift(); 31340 x = c2x; 31341 y = c2y + stack.shift(); 31342 p.curveTo(c1x, c1y, c2x, c2y, x, y); 31343 } 31344 31345 break; 31346 case 27: // hhcurveto 31347 if (stack.length % 2) { 31348 y += stack.shift(); 31349 } 31350 31351 while (stack.length > 0) { 31352 c1x = x + stack.shift(); 31353 c1y = y; 31354 c2x = c1x + stack.shift(); 31355 c2y = c1y + stack.shift(); 31356 x = c2x + stack.shift(); 31357 y = c2y; 31358 p.curveTo(c1x, c1y, c2x, c2y, x, y); 31359 } 31360 31361 break; 31362 case 28: // shortint 31363 b1 = code[i]; 31364 b2 = code[i + 1]; 31365 stack.push(((b1 << 24) | (b2 << 16)) >> 16); 31366 i += 2; 31367 break; 31368 case 29: // callgsubr 31369 codeIndex = stack.pop() + font.gsubrsBias; 31370 subrCode = font.gsubrs[codeIndex]; 31371 if (subrCode) { 31372 parse$$1(subrCode); 31373 } 31374 31375 break; 31376 case 30: // vhcurveto 31377 while (stack.length > 0) { 31378 c1x = x; 31379 c1y = y + stack.shift(); 31380 c2x = c1x + stack.shift(); 31381 c2y = c1y + stack.shift(); 31382 x = c2x + stack.shift(); 31383 y = c2y + (stack.length === 1 ? stack.shift() : 0); 31384 p.curveTo(c1x, c1y, c2x, c2y, x, y); 31385 if (stack.length === 0) { 31386 break; 31387 } 31388 31389 c1x = x + stack.shift(); 31390 c1y = y; 31391 c2x = c1x + stack.shift(); 31392 c2y = c1y + stack.shift(); 31393 y = c2y + stack.shift(); 31394 x = c2x + (stack.length === 1 ? stack.shift() : 0); 31395 p.curveTo(c1x, c1y, c2x, c2y, x, y); 31396 } 31397 31398 break; 31399 case 31: // hvcurveto 31400 while (stack.length > 0) { 31401 c1x = x + stack.shift(); 31402 c1y = y; 31403 c2x = c1x + stack.shift(); 31404 c2y = c1y + stack.shift(); 31405 y = c2y + stack.shift(); 31406 x = c2x + (stack.length === 1 ? stack.shift() : 0); 31407 p.curveTo(c1x, c1y, c2x, c2y, x, y); 31408 if (stack.length === 0) { 31409 break; 31410 } 31411 31412 c1x = x; 31413 c1y = y + stack.shift(); 31414 c2x = c1x + stack.shift(); 31415 c2y = c1y + stack.shift(); 31416 x = c2x + stack.shift(); 31417 y = c2y + (stack.length === 1 ? stack.shift() : 0); 31418 p.curveTo(c1x, c1y, c2x, c2y, x, y); 31419 } 31420 31421 break; 31422 default: 31423 if (v < 32) { 31424 console.log('Glyph ' + glyph.index + ': unknown operator ' + v); 31425 } else if (v < 247) { 31426 stack.push(v - 139); 31427 } else if (v < 251) { 31428 b1 = code[i]; 31429 i += 1; 31430 stack.push((v - 247) * 256 + b1 + 108); 31431 } else if (v < 255) { 31432 b1 = code[i]; 31433 i += 1; 31434 stack.push(-(v - 251) * 256 - b1 - 108); 31435 } else { 31436 b1 = code[i]; 31437 b2 = code[i + 1]; 31438 b3 = code[i + 2]; 31439 b4 = code[i + 3]; 31440 i += 4; 31441 stack.push(((b1 << 24) | (b2 << 16) | (b3 << 8) | b4) / 65536); 31442 } 31443 } 31444 } 31445 } 31446 31447 parse$$1(code); 31448 31449 glyph.advanceWidth = width; 31450 return p; 31451 } 31452 31453 function parseCFFFDSelect(data, start, nGlyphs, fdArrayCount) { 31454 var fdSelect = []; 31455 var fdIndex; 31456 var parser = new parse.Parser(data, start); 31457 var format = parser.parseCard8(); 31458 if (format === 0) { 31459 // Simple list of nGlyphs elements 31460 for (var iGid = 0; iGid < nGlyphs; iGid++) { 31461 fdIndex = parser.parseCard8(); 31462 if (fdIndex >= fdArrayCount) { 31463 throw new Error( 31464 'CFF table CID Font FDSelect has bad FD index value ' + 31465 fdIndex + 31466 ' (FD count ' + 31467 fdArrayCount + 31468 ')' 31469 ); 31470 } 31471 fdSelect.push(fdIndex); 31472 } 31473 } else if (format === 3) { 31474 // Ranges 31475 var nRanges = parser.parseCard16(); 31476 var first = parser.parseCard16(); 31477 if (first !== 0) { 31478 throw new Error( 31479 'CFF Table CID Font FDSelect format 3 range has bad initial GID ' + 31480 first 31481 ); 31482 } 31483 var next; 31484 for (var iRange = 0; iRange < nRanges; iRange++) { 31485 fdIndex = parser.parseCard8(); 31486 next = parser.parseCard16(); 31487 if (fdIndex >= fdArrayCount) { 31488 throw new Error( 31489 'CFF table CID Font FDSelect has bad FD index value ' + 31490 fdIndex + 31491 ' (FD count ' + 31492 fdArrayCount + 31493 ')' 31494 ); 31495 } 31496 if (next > nGlyphs) { 31497 throw new Error( 31498 'CFF Table CID Font FDSelect format 3 range has bad GID ' + next 31499 ); 31500 } 31501 for (; first < next; first++) { 31502 fdSelect.push(fdIndex); 31503 } 31504 first = next; 31505 } 31506 if (next !== nGlyphs) { 31507 throw new Error( 31508 'CFF Table CID Font FDSelect format 3 range has bad final GID ' + next 31509 ); 31510 } 31511 } else { 31512 throw new Error( 31513 'CFF Table CID Font FDSelect table has unsupported format ' + format 31514 ); 31515 } 31516 return fdSelect; 31517 } 31518 31519 // Parse the `CFF` table, which contains the glyph outlines in PostScript format. 31520 function parseCFFTable(data, start, font) { 31521 font.tables.cff = {}; 31522 var header = parseCFFHeader(data, start); 31523 var nameIndex = parseCFFIndex(data, header.endOffset, parse.bytesToString); 31524 var topDictIndex = parseCFFIndex(data, nameIndex.endOffset); 31525 var stringIndex = parseCFFIndex( 31526 data, 31527 topDictIndex.endOffset, 31528 parse.bytesToString 31529 ); 31530 var globalSubrIndex = parseCFFIndex(data, stringIndex.endOffset); 31531 font.gsubrs = globalSubrIndex.objects; 31532 font.gsubrsBias = calcCFFSubroutineBias(font.gsubrs); 31533 31534 var topDictArray = gatherCFFTopDicts( 31535 data, 31536 start, 31537 topDictIndex.objects,
31538 stringIndex.objects 31539 ); 31540 if (topDictArray.length !== 1) { 31541 throw new Error( 31542 "CFF table has too many fonts in 'FontSet' - count of fonts NameIndex.length = " + 31543 topDictArray.length 31544 ); 31545 } 31546 31547 var topDict = topDictArray[0]; 31548 font.tables.cff.topDict = topDict; 31549 31550 if (topDict._privateDict) { 31551 font.defaultWidthX = topDict._privateDict.defaultWidthX; 31552 font.nominalWidthX = topDict._privateDict.nominalWidthX; 31553 } 31554 31555 if (topDict.ros[0] !== undefined && topDict.ros[1] !== undefined) { 31556 font.isCIDFont = true; 31557 } 31558 31559 if (font.isCIDFont) { 31560 var fdArrayOffset = topDict.fdArray; 31561 var fdSelectOffset = topDict.fdSelect; 31562 if (fdArrayOffset === 0 || fdSelectOffset === 0) { 31563 throw new Error( 31564 'Font is marked as a CID font, but FDArray and/or FDSelect information is missing' 31565 ); 31566 } 31567 fdArrayOffset += start; 31568 var fdArrayIndex = parseCFFIndex(data, fdArrayOffset); 31569 var fdArray = gatherCFFTopDicts( 31570 data, 31571 start, 31572 fdArrayIndex.objects, 31573 stringIndex.objects 31574 ); 31575 topDict._fdArray = fdArray; 31576 fdSelectOffset += start; 31577 topDict._fdSelect = parseCFFFDSelect( 31578 data, 31579 fdSelectOffset, 31580 font.numGlyphs, 31581 fdArray.length 31582 ); 31583 } 31584 31585 var privateDictOffset = start + topDict.private[1]; 31586 var privateDict = parseCFFPrivateDict( 31587 data, 31588 privateDictOffset, 31589 topDict.private[0], 31590 stringIndex.objects 31591 ); 31592 font.defaultWidthX = privateDict.defaultWidthX; 31593 font.nominalWidthX = privateDict.nominalWidthX; 31594 31595 if (privateDict.subrs !== 0) { 31596 var subrOffset = privateDictOffset + privateDict.subrs; 31597 var subrIndex = parseCFFIndex(data, subrOffset); 31598 font.subrs = subrIndex.objects; 31599 font.subrsBias = calcCFFSubroutineBias(font.subrs); 31600 } else { 31601 font.subrs = []; 31602 font.subrsBias = 0; 31603 } 31604 31605 // Offsets in the top dict are relative to the beginning of the CFF data, so add the CFF start offset. 31606 var charStringsIndex = parseCFFIndex(data, start + topDict.charStrings); 31607 font.nGlyphs = charStringsIndex.objects.length; 31608 31609 var charset = parseCFFCharset( 31610 data, 31611 start + topDict.charset, 31612 font.nGlyphs, 31613 stringIndex.objects 31614 ); 31615 if (topDict.encoding === 0) { 31616 // Standard encoding 31617 font.cffEncoding = new CffEncoding(cffStandardEncoding, charset); 31618 } else if (topDict.encoding === 1) { 31619 // Expert encoding 31620 font.cffEncoding = new CffEncoding(cffExpertEncoding, charset); 31621 } else { 31622 font.cffEncoding = parseCFFEncoding( 31623 data, 31624 start + topDict.encoding, 31625 charset 31626 ); 31627 } 31628 31629 // Prefer the CMAP encoding to the CFF encoding. 31630 font.encoding = font.encoding || font.cffEncoding; 31631 31632 font.glyphs = new glyphset.GlyphSet(font); 31633 for (var i = 0; i < font.nGlyphs; i += 1) { 31634 var charString = charStringsIndex.objects[i]; 31635 font.glyphs.push( 31636 i, 31637 glyphset.cffGlyphLoader(font, i, parseCFFCharstring, charString) 31638 ); 31639 } 31640 } 31641 31642 // Convert a string to a String ID (SID). 31643 // The list of strings is modified in place. 31644 function encodeString(s, strings) { 31645 var sid; 31646 31647 // Is the string in the CFF standard strings? 31648 var i = cffStandardStrings.indexOf(s); 31649 if (i >= 0) { 31650 sid = i; 31651 } 31652 31653 // Is the string already in the string index? 31654 i = strings.indexOf(s); 31655 if (i >= 0) { 31656 sid = i + cffStandardStrings.length; 31657 } else { 31658 sid = cffStandardStrings.length + strings.length;
31659 strings.push(s); 31660 } 31661 31662 return sid; 31663 } 31664 31665 function makeHeader() { 31666 return new table.Record('Header', [ 31667 { name: 'major', type: 'Card8', value: 1 }, 31668 { name: 'minor', type: 'Card8', value: 0 }, 31669 { name: 'hdrSize', type: 'Card8', value: 4 }, 31670 { name: 'major', type: 'Card8', value: 1 } 31671 ]); 31672 } 31673 31674 function makeNameIndex(fontNames) { 31675 var t = new table.Record('Name INDEX', [ 31676 { name: 'names', type: 'INDEX', value: [] } 31677 ]); 31678 t.names = []; 31679 for (var i = 0; i < fontNames.length; i += 1) { 31680 t.names.push({ name: 'name_' + i, type: 'NAME', value: fontNames[i] }); 31681 } 31682 31683 return t; 31684 } 31685 31686 // Given a dictionary's metadata, create a DICT structure. 31687 function makeDict(meta, attrs, strings) { 31688 var m = {}; 31689 for (var i = 0; i < meta.length; i += 1) { 31690 var entry = meta[i]; 31691 var value = attrs[entry.name]; 31692 if (value !== undefined && !equals(value, entry.value)) { 31693 if (entry.type === 'SID') { 31694 value = encodeString(value, strings); 31695 } 31696 31697 m[entry.op] = { name: entry.name, type: entry.type, value: value }; 31698 } 31699 } 31700 31701 return m; 31702 } 31703 31704 // The Top DICT houses the global font attributes. 31705 function makeTopDict(attrs, strings) { 31706 var t = new table.Record('Top DICT', [ 31707 { name: 'dict', type: 'DICT', value: {} } 31708 ]); 31709 t.dict = makeDict(TOP_DICT_META, attrs, strings); 31710 return t; 31711 } 31712 31713 function makeTopDictIndex(topDict) { 31714 var t = new table.Record('Top DICT INDEX', [ 31715 { name: 'topDicts', type: 'INDEX', value: [] } 31716 ]); 31717 t.topDicts = [{ name: 'topDict_0', type: 'TABLE', value: topDict }]; 31718 return t; 31719 } 31720 31721 function makeStringIndex(strings) { 31722 var t = new table.Record('String INDEX', [ 31723 { name: 'strings', type: 'INDEX', value: [] } 31724 ]); 31725 t.strings = []; 31726 for (var i = 0; i < strings.length; i += 1) { 31727 t.strings.push({ 31728 name: 'string_' + i, 31729 type: 'STRING', 31730 value: strings[i] 31731 }); 31732 } 31733 31734 return t; 31735 } 31736 31737 function makeGlobalSubrIndex() { 31738 // Currently we don't use subroutines. 31739 return new table.Record('Global Subr INDEX', [ 31740 { name: 'subrs', type: 'INDEX', value: [] } 31741 ]); 31742 } 31743 31744 function makeCharsets(glyphNames, strings) { 31745 var t = new table.Record('Charsets', [ 31746 { name: 'format', type: 'Card8', value: 0 } 31747 ]); 31748 for (var i = 0; i < glyphNames.length; i += 1) { 31749 var glyphName = glyphNames[i]; 31750 var glyphSID = encodeString(glyphName, strings); 31751 t.fields.push({ name: 'glyph_' + i, type: 'SID', value: glyphSID }); 31752 } 31753 31754 return t; 31755 } 31756 31757 function glyphToOps(glyph) { 31758 var ops = []; 31759 var path = glyph.path; 31760 ops.push({ name: 'width', type: 'NUMBER', value: glyph.advanceWidth }); 31761 var x = 0; 31762 var y = 0; 31763 for (var i = 0; i < path.commands.length; i += 1) { 31764 var dx = void 0; 31765 var dy = void 0; 31766 var cmd = path.commands[i]; 31767 if (cmd.type === 'Q') { 31768 // CFF only supports bézier curves, so convert the quad to a bézier. 31769 var _13 = 1 / 3; 31770 var _23 = 2 / 3; 31771 31772 // We're going to create a new command so we don't change the original path. 31773 cmd = { 31774 type: 'C', 31775 x: cmd.x, 31776 y: cmd.y, 31777 x1: _13 * x + _23 * cmd.x1, 31778 y1: _13 * y + _23 * cmd.y1, 31779 x2: _13 * cmd.x + _23 * cmd.x1, 31780 y2: _13 * cmd.y + _23 * cmd.y1 31781 }; 31782 } 31783 31784 if (cmd.type === 'M') { 31785 dx = Math.round(cmd.x - x); 31786 dy = Math.round(cmd.y - y); 31787 ops.push({ name: 'dx', type: 'NUMBER', value: dx }); 31788 ops.push({ name: 'dy', type: 'NUMBER', value: dy }); 31789 ops.push({ name: 'rmoveto', type: 'OP', value: 21 }); 31790 x = Math.round(cmd.x); 31791 y = Math.round(cmd.y); 31792 } else if (cmd.type === 'L') { 31793 dx = Math.round(cmd.x - x); 31794 dy = Math.round(cmd.y - y); 31795 ops.push({ name: 'dx', type: 'NUMBER', value: dx }); 31796 ops.push({ name: 'dy', type: 'NUMBER', value: dy }); 31797 ops.push({ name: 'rlineto', type: 'OP', value: 5 }); 31798 x = Math.round(cmd.x); 31799 y = Math.round(cmd.y); 31800 } else if (cmd.type === 'C') { 31801 var dx1 = Math.round(cmd.x1 - x); 31802 var dy1 = Math.round(cmd.y1 - y); 31803 var dx2 = Math.round(cmd.x2 - cmd.x1); 31804 var dy2 = Math.round(cmd.y2 - cmd.y1); 31805 dx = Math.round(cmd.x - cmd.x2); 31806 dy = Math.round(cmd.y - cmd.y2); 31807 ops.push({ name: 'dx1', type: 'NUMBER', value: dx1 }); 31808 ops.push({ name: 'dy1', type: 'NUMBER', value: dy1 }); 31809 ops.push({ name: 'dx2', type: 'NUMBER', value: dx2 }); 31810 ops.push({ name: 'dy2', type: 'NUMBER', value: dy2 }); 31811 ops.push({ name: 'dx', type: 'NUMBER', value: dx }); 31812 ops.push({ name: 'dy', type: 'NUMBER', value: dy }); 31813 ops.push({ name: 'rrcurveto', type: 'OP', value: 8 }); 31814 x = Math.round(cmd.x); 31815 y = Math.round(cmd.y); 31816 } 31817 31818 // Contours are closed automatically. 31819 } 31820
31821 ops.push({ name: 'endchar', type: 'OP', value: 14 }); 31822 return ops; 31823 } 31824 31825 function makeCharStringsIndex(glyphs) { 31826 var t = new table.Record('CharStrings INDEX', [ 31827 { name: 'charStrings', type: 'INDEX', value: [] } 31828 ]); 31829 31830 for (var i = 0; i < glyphs.length; i += 1) { 31831 var glyph = glyphs.get(i); 31832 var ops = glyphToOps(glyph); 31833 t.charStrings.push({ name: glyph.name, type: 'CHARSTRING', value: ops }); 31834 } 31835 31836 return t; 31837 } 31838 31839 function makePrivateDict(attrs, strings) { 31840 var t = new table.Record('Private DICT', [ 31841 { name: 'dict', type: 'DICT', value: {} } 31842 ]); 31843 t.dict = makeDict(PRIVATE_DICT_META, attrs, strings); 31844 return t; 31845 } 31846 31847 function makeCFFTable(glyphs, options) { 31848 var t = new table.Table('CFF ', [ 31849 { name: 'header', type: 'RECORD' }, 31850 { name: 'nameIndex', type: 'RECORD' }, 31851 { name: 'topDictIndex', type: 'RECORD' }, 31852 { name: 'stringIndex', type: 'RECORD' }, 31853 { name: 'globalSubrIndex', type: 'RECORD' }, 31854 { name: 'charsets', type: 'RECORD' }, 31855 { name: 'charStringsIndex', type: 'RECORD' }, 31856 { name: 'privateDict', type: 'RECORD' } 31857 ]); 31858 31859 var fontScale = 1 / options.unitsPerEm; 31860 // We use non-zero values for the offsets so that the DICT encodes them. 31861 // This is important because the size of the Top DICT plays a role in offset calculation, 31862 // and the size shouldn't change after we've written correct offsets. 31863 var attrs = { 31864 version: options.version, 31865 fullName: options.fullName, 31866 familyName: options.familyName, 31867 weight: options.weightName, 31868 fontBBox: options.fontBBox || [0, 0, 0, 0], 31869 fontMatrix: [fontScale, 0, 0, fontScale, 0, 0], 31870 charset: 999, 31871 encoding: 0, 31872 charStrings: 999, 31873 private: [0, 999] 31874 }; 31875 31876 var privateAttrs = {}; 31877 31878 var glyphNames = []; 31879 var glyph; 31880 31881 // Skip first glyph (.notdef) 31882 for (var i = 1; i < glyphs.length; i += 1) { 31883 glyph = glyphs.get(i); 31884 glyphNames.push(glyph.name); 31885 } 31886 31887 var strings = []; 31888 31889 t.header = makeHeader(); 31890 t.nameIndex = makeNameIndex([options.postScriptName]); 31891 var topDict = makeTopDict(attrs, strings); 31892 t.topDictIndex = makeTopDictIndex(topDict); 31893 t.globalSubrIndex = makeGlobalSubrIndex(); 31894 t.charsets = makeCharsets(glyphNames, strings); 31895 t.charStringsIndex = makeCharStringsIndex(glyphs); 31896 t.privateDict = makePrivateDict(privateAttrs, strings); 31897 31898 // Needs to come at the end, to encode all custom strings used in the font. 31899 t.stringIndex = makeStringIndex(strings); 31900 31901 var startOffset = 31902 t.header.sizeOf() + 31903 t.nameIndex.sizeOf() + 31904 t.topDictIndex.sizeOf() + 31905 t.stringIndex.sizeOf() + 31906 t.globalSubrIndex.sizeOf(); 31907 attrs.charset = startOffset; 31908 31909 // We use the CFF standard encoding; proper encoding will be handled in cmap. 31910 attrs.encoding = 0; 31911 attrs.charStrings = attrs.charset + t.charsets.sizeOf(); 31912 attrs.private[1] = attrs.charStrings + t.charStringsIndex.sizeOf(); 31913 31914 // Recreate the Top DICT INDEX with the correct offsets. 31915 topDict = makeTopDict(attrs, strings); 31916 t.topDictIndex = makeTopDictIndex(topDict); 31917 31918 return t; 31919 } 31920 31921 var cff = { parse: parseCFFTable, make: makeCFFTable }; 31922 31923 // The `head` table contains global information about the font. 31924 31925 // Parse the header `head` table 31926 function parseHeadTable(data, start) { 31927 var head = {}; 31928 var p = new parse.Parser(data, start); 31929 head.version = p.parseVersion(); 31930 head.fontRevision = Math.round(p.parseFixed() * 1000) / 1000; 31931 head.checkSumAdjustment = p.parseULong(); 31932 head.magicNumber = p.parseULong(); 31933 check.argument( 31934 head.magicNumber === 0x5f0f3cf5, 31935 'Font header has wrong magic number.' 31936 ); 31937 head.flags = p.parseUShort(); 31938 head.unitsPerEm = p.parseUShort(); 31939 head.created = p.parseLongDateTime(); 31940 head.modified = p.parseLongDateTime(); 31941 head.xMin = p.parseShort(); 31942 head.yMin = p.parseShort(); 31943 head.xMax = p.parseShort(); 31944 head.yMax = p.parseShort(); 31945 head.macStyle = p.parseUShort(); 31946 head.lowestRecPPEM = p.parseUShort(); 31947 head.fontDirectionHint = p.parseShort(); 31948 head.indexToLocFormat = p.parseShort(); 31949 head.glyphDataFormat = p.parseShort(); 31950 return head; 31951 } 31952 31953 function makeHeadTable(options) { 31954 // Apple Mac timestamp epoch is 01/01/1904 not 01/01/1970 31955 var timestamp = Math.round(new Date().getTime() / 1000) + 2082844800; 31956 var createdTimestamp = timestamp; 31957 31958 if (options.createdTimestamp) { 31959 createdTimestamp = options.createdTimestamp + 2082844800; 31960 } 31961 31962 return new table.Table( 31963 'head', 31964 [ 31965 { name: 'version', type: 'FIXED', value: 0x00010000 }, 31966 { name: 'fontRevision', type: 'FIXED', value: 0x00010000 }, 31967 { name: 'checkSumAdjustment', type: 'ULONG', value: 0 }, 31968 { name: 'magicNumber', type: 'ULONG', value: 0x5f0f3cf5 }, 31969 { name: 'flags', type: 'USHORT', value: 0 }, 31970 { name: 'unitsPerEm', type: 'USHORT', value: 1000 }, 31971 { name: 'created', type: 'LONGDATETIME', value: createdTimestamp }, 31972 { name: 'modified', type: 'LONGDATETIME', value: timestamp }, 31973 { name: 'xMin', type: 'SHORT', value: 0 }, 31974 { name: 'yMin', type: 'SHORT', value: 0 }, 31975 { name: 'xMax', type: 'SHORT', value: 0 }, 31976 { name: 'yMax', type: 'SHORT', value: 0 }, 31977 { name: 'macStyle', type: 'USHORT', value: 0 }, 31978 { name: 'lowestRecPPEM', type: 'USHORT', value: 0 },
31979 { name: 'fontDirectionHint', type: 'SHORT', value: 2 }, 31980 { name: 'indexToLocFormat', type: 'SHORT', value: 0 }, 31981 { name: 'glyphDataFormat', type: 'SHORT', value: 0 } 31982 ], 31983 options 31984 ); 31985 } 31986 31987 var head = { parse: parseHeadTable, make: makeHeadTable }; 31988 31989 // The `hhea` table contains information for horizontal layout. 31990 31991 // Parse the horizontal header `hhea` table 31992 function parseHheaTable(data, start) { 31993 var hhea = {}; 31994 var p = new parse.Parser(data, start); 31995 hhea.version = p.parseVersion(); 31996 hhea.ascender = p.parseShort(); 31997 hhea.descender = p.parseShort(); 31998 hhea.lineGap = p.parseShort(); 31999 hhea.advanceWidthMax = p.parseUShort(); 32000 hhea.minLeftSideBearing = p.parseShort(); 32001 hhea.minRightSideBearing = p.parseShort(); 32002 hhea.xMaxExtent = p.parseShort(); 32003 hhea.caretSlopeRise = p.parseShort(); 32004 hhea.caretSlopeRun = p.parseShort(); 32005 hhea.caretOffset = p.parseShort(); 32006 p.relativeOffset += 8; 32007 hhea.metricDataFormat = p.parseShort(); 32008 hhea.numberOfHMetrics = p.parseUShort(); 32009 return hhea; 32010 } 32011 32012 function makeHheaTable(options) { 32013 return new table.Table( 32014 'hhea', 32015 [ 32016 { name: 'version', type: 'FIXED', value: 0x00010000 }, 32017 { name: 'ascender', type: 'FWORD', value: 0 }, 32018 { name: 'descender', type: 'FWORD', value: 0 }, 32019 { name: 'lineGap', type: 'FWORD', value: 0 }, 32020 { name: 'advanceWidthMax', type: 'UFWORD', value: 0 }, 32021 { name: 'minLeftSideBearing', type: 'FWORD', value: 0 }, 32022 { name: 'minRightSideBearing', type: 'FWORD', value: 0 }, 32023 { name: 'xMaxExtent', type: 'FWORD', value: 0 }, 32024 { name: 'caretSlopeRise', type: 'SHORT', value: 1 }, 32025 { name: 'caretSlopeRun', type: 'SHORT', value: 0 }, 32026 { name: 'caretOffset', type: 'SHORT', value: 0 }, 32027 { name: 'reserved1', type: 'SHORT', value: 0 }, 32028 { name: 'reserved2', type: 'SHORT', value: 0 }, 32029 { name: 'reserved3', type: 'SHORT', value: 0 }, 32030 { name: 'reserved4', type: 'SHORT', value: 0 }, 32031 { name: 'metricDataFormat', type: 'SHORT', value: 0 }, 32032 { name: 'numberOfHMetrics', type: 'USHORT', value: 0 } 32033 ], 32034 options 32035 ); 32036 } 32037 32038 var hhea = { parse: parseHheaTable, make: makeHheaTable }; 32039 32040 // The `hmtx` table contains the horizontal metrics for all glyphs. 32041 32042 // Parse the `hmtx` table, which contains the horizontal metrics for all glyphs. 32043 // This function augments the glyph array, adding the advanceWidth and leftSideBearing to each glyph. 32044 function parseHmtxTable(data, start, numMetrics, numGlyphs, glyphs) { 32045 var advanceWidth; 32046 var leftSideBearing; 32047 var p = new parse.Parser(data, start); 32048 for (var i = 0; i < numGlyphs; i += 1) { 32049 // If the font is monospaced, only one entry is needed. This last entry applies to all subsequent glyphs. 32050 if (i < numMetrics) { 32051 advanceWidth = p.parseUShort(); 32052 leftSideBearing = p.parseShort(); 32053 } 32054 32055 var glyph = glyphs.get(i); 32056 glyph.advanceWidth = advanceWidth; 32057 glyph.leftSideBearing = leftSideBearing; 32058 } 32059 } 32060 32061 function makeHmtxTable(glyphs) { 32062 var t = new table.Table('hmtx', []); 32063 for (var i = 0; i < glyphs.length; i += 1) { 32064 var glyph = glyphs.get(i); 32065 var advanceWidth = glyph.advanceWidth || 0; 32066 var leftSideBearing = glyph.leftSideBearing || 0; 32067 t.fields.push({ 32068 name: 'advanceWidth_' + i, 32069 type: 'USHORT', 32070 value: advanceWidth 32071 }); 32072 t.fields.push({ 32073 name: 'leftSideBearing_' + i, 32074 type: 'SHORT', 32075 value: leftSideBearing 32076 }); 32077 } 32078 32079 return t; 32080 } 32081 32082 var hmtx = { parse: parseHmtxTable, make: makeHmtxTable }; 32083 32084 // The `ltag` table stores IETF BCP-47 language tags. It allows supporting 32085 32086 function makeLtagTable(tags) { 32087 var result = new table.Table('ltag', [ 32088 { name: 'version', type: 'ULONG', value: 1 }, 32089 { name: 'flags', type: 'ULONG', value: 0 }, 32090 { name: 'numTags', type: 'ULONG', value: tags.length } 32091 ]); 32092 32093 var stringPool = ''; 32094 var stringPoolOffset = 12 + tags.length * 4; 32095 for (var i = 0; i < tags.length; ++i) { 32096 var pos = stringPool.indexOf(tags[i]); 32097 if (pos < 0) { 32098 pos = stringPool.length;
vendor: 8,463 bytes, lines 32099-32349
32099 stringPool += tags[i]; 32100 } 32101 32102 result.fields.push({ 32103 name: 'offset ' + i, 32104 type: 'USHORT', 32105 value: stringPoolOffset + pos 32106 }); 32107 result.fields.push({ 32108 name: 'length ' + i, 32109 type: 'USHORT', 32110 value: tags[i].length 32111 }); 32112 } 32113 32114 result.fields.push({ 32115 name: 'stringPool', 32116 type: 'CHARARRAY', 32117 value: stringPool 32118 }); 32119 return result; 32120 } 32121 32122 function parseLtagTable(data, start) { 32123 var p = new parse.Parser(data, start); 32124 var tableVersion = p.parseULong(); 32125 check.argument(tableVersion === 1, 'Unsupported ltag table version.'); 32126 // The 'ltag' specification does not define any flags; skip the field. 32127 p.skip('uLong', 1); 32128 var numTags = p.parseULong(); 32129 32130 var tags = []; 32131 for (var i = 0; i < numTags; i++) { 32132 var tag = ''; 32133 var offset = start + p.parseUShort(); 32134 var length = p.parseUShort(); 32135 for (var j = offset; j < offset + length; ++j) { 32136 tag += String.fromCharCode(data.getInt8(j)); 32137 } 32138 32139 tags.push(tag); 32140 } 32141 32142 return tags; 32143 } 32144 32145 var ltag = { make: makeLtagTable, parse: parseLtagTable }; 32146 32147 // The `maxp` table establishes the memory requirements for the font. 32148 32149 // Parse the maximum profile `maxp` table. 32150 function parseMaxpTable(data, start) { 32151 var maxp = {}; 32152 var p = new parse.Parser(data, start); 32153 maxp.version = p.parseVersion(); 32154 maxp.numGlyphs = p.parseUShort(); 32155 if (maxp.version === 1.0) { 32156 maxp.maxPoints = p.parseUShort(); 32157 maxp.maxContours = p.parseUShort(); 32158 maxp.maxCompositePoints = p.parseUShort(); 32159 maxp.maxCompositeContours = p.parseUShort(); 32160 maxp.maxZones = p.parseUShort(); 32161 maxp.maxTwilightPoints = p.parseUShort(); 32162 maxp.maxStorage = p.parseUShort(); 32163 maxp.maxFunctionDefs = p.parseUShort(); 32164 maxp.maxInstructionDefs = p.parseUShort(); 32165 maxp.maxStackElements = p.parseUShort(); 32166 maxp.maxSizeOfInstructions = p.parseUShort(); 32167 maxp.maxComponentElements = p.parseUShort(); 32168 maxp.maxComponentDepth = p.parseUShort(); 32169 } 32170 32171 return maxp; 32172 } 32173 32174 function makeMaxpTable(numGlyphs) { 32175 return new table.Table('maxp', [ 32176 { name: 'version', type: 'FIXED', value: 0x00005000 }, 32177 { name: 'numGlyphs', type: 'USHORT', value: numGlyphs } 32178 ]); 32179 } 32180 32181 var maxp = { parse: parseMaxpTable, make: makeMaxpTable }; 32182 32183 // The `name` naming table. 32184 32185 // NameIDs for the name table. 32186 var nameTableNames = [ 32187 'copyright', // 0 32188 'fontFamily', // 1 32189 'fontSubfamily', // 2 32190 'uniqueID', // 3 32191 'fullName', // 4 32192 'version', // 5 32193 'postScriptName', // 6 32194 'trademark', // 7 32195 'manufacturer', // 8 32196 'designer', // 9 32197 'description', // 10 32198 'manufacturerURL', // 11 32199 'designerURL', // 12 32200 'license', // 13 32201 'licenseURL', // 14 32202 'reserved', // 15 32203 'preferredFamily', // 16 32204 'preferredSubfamily', // 17 32205 'compatibleFullName', // 18 32206 'sampleText', // 19 32207 'postScriptFindFontName', // 20 32208 'wwsFamily', // 21 32209 'wwsSubfamily' // 22 32210 ]; 32211 32212 var macLanguages = { 32213 0: 'en', 32214 1: 'fr', 32215 2: 'de', 32216 3: 'it', 32217 4: 'nl', 32218 5: 'sv', 32219 6: 'es', 32220 7: 'da', 32221 8: 'pt', 32222 9: 'no', 32223 10: 'he', 32224 11: 'ja', 32225 12: 'ar', 32226 13: 'fi', 32227 14: 'el', 32228 15: 'is', 32229 16: 'mt', 32230 17: 'tr', 32231 18: 'hr', 32232 19: 'zh-Hant', 32233 20: 'ur', 32234 21: 'hi', 32235 22: 'th', 32236 23: 'ko', 32237 24: 'lt', 32238 25: 'pl', 32239 26: 'hu', 32240 27: 'es', 32241 28: 'lv', 32242 29: 'se', 32243 30: 'fo', 32244 31: 'fa', 32245 32: 'ru', 32246 33: 'zh', 32247 34: 'nl-BE', 32248 35: 'ga', 32249 36: 'sq', 32250 37: 'ro', 32251 38: 'cz', 32252 39: 'sk', 32253 40: 'si', 32254 41: 'yi', 32255 42: 'sr', 32256 43: 'mk', 32257 44: 'bg', 32258 45: 'uk', 32259 46: 'be', 32260 47: 'uz', 32261 48: 'kk', 32262 49: 'az-Cyrl', 32263 50: 'az-Arab', 32264 51: 'hy', 32265 52: 'ka', 32266 53: 'mo', 32267 54: 'ky', 32268 55: 'tg', 32269 56: 'tk', 32270 57: 'mn-CN', 32271 58: 'mn', 32272 59: 'ps', 32273 60: 'ks', 32274 61: 'ku', 32275 62: 'sd', 32276 63: 'bo', 32277 64: 'ne', 32278 65: 'sa', 32279 66: 'mr', 32280 67: 'bn', 32281 68: 'as', 32282 69: 'gu', 32283 70: 'pa', 32284 71: 'or', 32285 72: 'ml', 32286 73: 'kn', 32287 74: 'ta', 32288 75: 'te', 32289 76: 'si', 32290 77: 'my', 32291 78: 'km', 32292 79: 'lo', 32293 80: 'vi', 32294 81: 'id', 32295 82: 'tl', 32296 83: 'ms', 32297 84: 'ms-Arab', 32298 85: 'am', 32299 86: 'ti', 32300 87: 'om', 32301 88: 'so', 32302 89: 'sw', 32303 90: 'rw', 32304 91: 'rn', 32305 92: 'ny', 32306 93: 'mg', 32307 94: 'eo', 32308 128: 'cy', 32309 129: 'eu', 32310 130: 'ca', 32311 131: 'la', 32312 132: 'qu', 32313 133: 'gn', 32314 134: 'ay', 32315 135: 'tt', 32316 136: 'ug', 32317 137: 'dz', 32318 138: 'jv', 32319 139: 'su', 32320 140: 'gl', 32321 141: 'af', 32322 142: 'br', 32323 143: 'iu', 32324 144: 'gd', 32325 145: 'gv', 32326 146: 'ga', 32327 147: 'to', 32328 148: 'el-polyton', 32329 149: 'kl', 32330 150: 'az', 32331 151: 'nn' 32332 }; 32333 32334 // MacOS language ID â MacOS script ID 32335 // 32336 // Note that the script ID is not sufficient to determine what encoding 32337 // to use in TrueType files. For some languages, MacOS used a modification 32338 // of a mainstream script. For example, an Icelandic name would be stored 32339 // with smRoman in the TrueType naming table, but the actual encoding 32340 // is a special Icelandic version of the normal Macintosh Roman encoding. 32341 // As another example, Inuktitut uses an 8-bit encoding for Canadian Aboriginal 32342 // Syllables but MacOS had run out of available script codes, so this was 32343 // done as a (pretty radical) "modification" of Ethiopic. 32344 // 32345 // http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/Readme.txt 32346 var macLanguageToScript = { 32347 0: 0, // langEnglish â smRoman 32348 1: 0, // langFrench â smRoman 32349 2: 0, // langGerman â smRoman
32350 3: 0, // langItalian â smRoman 32351 4: 0, // langDutch â smRoman 32352 5: 0, // langSwedish â smRoman 32353 6: 0, // langSpanish â smRoman 32354 7: 0, // langDanish â smRoman 32355 8: 0, // langPortuguese â smRoman 32356 9: 0, // langNorwegian â smRoman 32357 10: 5, // langHebrew â smHebrew 32358 11: 1, // langJapanese â smJapanese 32359 12: 4, // langArabic â smArabic 32360 13: 0, // langFinnish â smRoman 32361 14: 6, // langGreek â smGreek 32362 15: 0, // langIcelandic â smRoman (modified) 32363 16: 0, // langMaltese â smRoman 32364 17: 0, // langTurkish â smRoman (modified) 32365 18: 0, // langCroatian â smRoman (modified) 32366 19: 2, // langTradChinese â smTradChinese 32367 20: 4, // langUrdu â smArabic 32368 21: 9, // langHindi â smDevanagari 32369 22: 21, // langThai â smThai 32370 23: 3, // langKorean â smKorean 32371 24: 29, // langLithuanian â smCentralEuroRoman 32372 25: 29, // langPolish â smCentralEuroRoman 32373 26: 29, // langHungarian â smCentralEuroRoman 32374 27: 29, // langEstonian â smCentralEuroRoman 32375 28: 29, // langLatvian â smCentralEuroRoman 32376 29: 0, // langSami â smRoman 32377 30: 0, // langFaroese â smRoman (modified) 32378 31: 4, // langFarsi â smArabic (modified) 32379 32: 7, // langRussian â smCyrillic 32380 33: 25, // langSimpChinese â smSimpChinese 32381 34: 0, // langFlemish â smRoman 32382 35: 0, // langIrishGaelic â smRoman (modified) 32383 36: 0, // langAlbanian â smRoman 32384 37: 0, // langRomanian â smRoman (modified) 32385 38: 29, // langCzech â smCentralEuroRoman 32386 39: 29, // langSlovak â smCentralEuroRoman 32387 40: 0, // langSlovenian â smRoman (modified) 32388 41: 5, // langYiddish â smHebrew 32389 42: 7, // langSerbian â smCyrillic 32390 43: 7, // langMacedonian â smCyrillic 32391 44: 7, // langBulgarian â smCyrillic 32392 45: 7, // langUkrainian â smCyrillic (modified) 32393 46: 7, // langByelorussian â smCyrillic 32394 47: 7, // langUzbek â smCyrillic 32395 48: 7, // langKazakh â smCyrillic 32396 49: 7, // langAzerbaijani â smCyrillic 32397 50: 4, // langAzerbaijanAr â smArabic 32398 51: 24, // langArmenian â smArmenian 32399 52: 23, // langGeorgian â smGeorgian 32400 53: 7, // langMoldavian â smCyrillic 32401 54: 7, // langKirghiz â smCyrillic 32402 55: 7, // langTajiki â smCyrillic 32403 56: 7, // langTurkmen â smCyrillic 32404 57: 27, // langMongolian â smMongolian 32405 58: 7, // langMongolianCyr â smCyrillic 32406 59: 4, // langPashto â smArabic 32407 60: 4, // langKurdish â smArabic 32408 61: 4, // langKashmiri â smArabic 32409 62: 4, // langSindhi â smArabic 32410 63: 26, // langTibetan â smTibetan 32411 64: 9, // langNepali â smDevanagari 32412 65: 9, // langSanskrit â smDevanagari 32413 66: 9, // langMarathi â smDevanagari 32414 67: 13, // langBengali â smBengali 32415 68: 13, // langAssamese â smBengali 32416 69: 11, // langGujarati â smGujarati 32417 70: 10, // langPunjabi â smGurmukhi 32418 71: 12, // langOriya â smOriya 32419 72: 17, // langMalayalam â smMalayalam 32420 73: 16, // langKannada â smKannada 32421 74: 14, // langTamil â smTamil 32422 75: 15, // langTelugu â smTelugu 32423 76: 18, // langSinhalese â smSinhalese 32424 77: 19, // langBurmese â smBurmese 32425 78: 20, // langKhmer â smKhmer 32426 79: 22, // langLao â smLao 32427 80: 30, // langVietnamese â smVietnamese 32428 81: 0, // langIndonesian â smRoman 32429 82: 0, // langTagalog â smRoman 32430 83: 0, // langMalayRoman â smRoman 32431 84: 4, // langMalayArabic â smArabic 32432 85: 28, // langAmharic â smEthiopic 32433 86: 28, // langTigrinya â smEthiopic 32434 87: 28, // langOromo â smEthiopic 32435 88: 0, // langSomali â smRoman 32436 89: 0, // langSwahili â smRoman 32437 90: 0, // langKinyarwanda â smRoman 32438 91: 0, // langRundi â smRoman
32439 92: 0, // langNyanja â smRoman 32440 93: 0, // langMalagasy â smRoman 32441 94: 0, // langEsperanto â smRoman 32442 128: 0, // langWelsh â smRoman (modified) 32443 129: 0, // langBasque â smRoman 32444 130: 0, // langCatalan â smRoman 32445 131: 0, // langLatin â smRoman 32446 132: 0, // langQuechua â smRoman 32447 133: 0, // langGuarani â smRoman 32448 134: 0, // langAymara â smRoman 32449 135: 7, // langTatar â smCyrillic 32450 136: 4, // langUighur â smArabic 32451 137: 26, // langDzongkha â smTibetan 32452 138: 0, // langJavaneseRom â smRoman 32453 139: 0, // langSundaneseRom â smRoman 32454 140: 0, // langGalician â smRoman 32455 141: 0, // langAfrikaans â smRoman 32456 142: 0, // langBreton â smRoman (modified) 32457 143: 28, // langInuktitut â smEthiopic (modified) 32458 144: 0, // langScottishGaelic â smRoman (modified) 32459 145: 0, // langManxGaelic â smRoman (modified) 32460 146: 0, // langIrishGaelicScript â smRoman (modified) 32461 147: 0, // langTongan â smRoman 32462 148: 6, // langGreekAncient â smRoman 32463 149: 0, // langGreenlandic â smRoman 32464 150: 0, // langAzerbaijanRoman â smRoman 32465 151: 0 // langNynorsk â smRoman 32466 }; 32467 32468 // While Microsoft indicates a region/country for all its language 32469 // IDs, we omit the region code if it's equal to the "most likely 32470 // region subtag" according to Unicode CLDR. For scripts, we omit 32471 // the subtag if it is equal to the Suppress-Script entry in the 32472 // IANA language subtag registry for IETF BCP 47. 32473 // 32474 // For example, Microsoft states that its language code 0x041A is 32475 // Croatian in Croatia. We transform this to the BCP 47 language code 'hr' 32476 // and not 'hr-HR' because Croatia is the default country for Croatian, 32477 // according to Unicode CLDR. As another example, Microsoft states 32478 // that 0x101A is Croatian (Latin) in Bosnia-Herzegovina. We transform 32479 // this to 'hr-BA' and not 'hr-Latn-BA' because Latin is the default script 32480 // for the Croatian language, according to IANA. 32481 // 32482 // http://www.unicode.org/cldr/charts/latest/supplemental/likely_subtags.html 32483 // http://www.iana.org/assignments/language-subtag-registry/language-subtag-registry 32484 var windowsLanguages = { 32485 0x0436: 'af', 32486 0x041c: 'sq', 32487 0x0484: 'gsw', 32488 0x045e: 'am', 32489 0x1401: 'ar-DZ', 32490 0x3c01: 'ar-BH', 32491 0x0c01: 'ar', 32492 0x0801: 'ar-IQ', 32493 0x2c01: 'ar-JO', 32494 0x3401: 'ar-KW', 32495 0x3001: 'ar-LB', 32496 0x1001: 'ar-LY', 32497 0x1801: 'ary', 32498 0x2001: 'ar-OM', 32499 0x4001: 'ar-QA', 32500 0x0401: 'ar-SA', 32501 0x2801: 'ar-SY', 32502 0x1c01: 'aeb', 32503 0x3801: 'ar-AE', 32504 0x2401: 'ar-YE', 32505 0x042b: 'hy', 32506 0x044d: 'as', 32507 0x082c: 'az-Cyrl', 32508 0x042c: 'az', 32509 0x046d: 'ba', 32510 0x042d: 'eu', 32511 0x0423: 'be', 32512 0x0845: 'bn', 32513 0x0445: 'bn-IN', 32514 0x201a: 'bs-Cyrl', 32515 0x141a: 'bs', 32516 0x047e: 'br', 32517 0x0402: 'bg', 32518 0x0403: 'ca', 32519 0x0c04: 'zh-HK', 32520 0x1404: 'zh-MO', 32521 0x0804: 'zh', 32522 0x1004: 'zh-SG', 32523 0x0404: 'zh-TW', 32524 0x0483: 'co', 32525 0x041a: 'hr', 32526 0x101a: 'hr-BA', 32527 0x0405: 'cs', 32528 0x0406: 'da', 32529 0x048c: 'prs', 32530 0x0465: 'dv', 32531 0x0813: 'nl-BE', 32532 0x0413: 'nl', 32533 0x0c09: 'en-AU', 32534 0x2809: 'en-BZ', 32535 0x1009: 'en-CA', 32536 0x2409: 'en-029', 32537 0x4009: 'en-IN', 32538 0x1809: 'en-IE', 32539 0x2009: 'en-JM', 32540 0x4409: 'en-MY', 32541 0x1409: 'en-NZ', 32542 0x3409: 'en-PH', 32543 0x4809: 'en-SG', 32544 0x1c09: 'en-ZA', 32545 0x2c09: 'en-TT', 32546 0x0809: 'en-GB', 32547 0x0409: 'en', 32548 0x3009: 'en-ZW', 32549 0x0425: 'et', 32550 0x0438: 'fo', 32551 0x0464: 'fil', 32552 0x040b: 'fi', 32553 0x080c: 'fr-BE', 32554 0x0c0c: 'fr-CA', 32555 0x040c: 'fr', 32556 0x140c: 'fr-LU', 32557 0x180c: 'fr-MC', 32558 0x100c: 'fr-CH', 32559 0x0462: 'fy', 32560 0x0456: 'gl', 32561 0x0437: 'ka', 32562 0x0c07: 'de-AT', 32563 0x0407: 'de', 32564 0x1407: 'de-LI', 32565 0x1007: 'de-LU', 32566 0x0807: 'de-CH', 32567 0x0408: 'el', 32568 0x046f: 'kl', 32569 0x0447: 'gu', 32570 0x0468: 'ha', 32571 0x040d: 'he', 32572 0x0439: 'hi', 32573 0x040e: 'hu', 32574 0x040f: 'is', 32575 0x0470: 'ig', 32576 0x0421: 'id', 32577 0x045d: 'iu', 32578 0x085d: 'iu-Latn', 32579 0x083c: 'ga', 32580 0x0434: 'xh', 32581 0x0435: 'zu', 32582 0x0410: 'it', 32583 0x0810: 'it-CH', 32584 0x0411: 'ja', 32585 0x044b: 'kn', 32586 0x043f: 'kk',
32587 0x0453: 'km', 32588 0x0486: 'quc', 32589 0x0487: 'rw', 32590 0x0441: 'sw', 32591 0x0457: 'kok', 32592 0x0412: 'ko', 32593 0x0440: 'ky', 32594 0x0454: 'lo', 32595 0x0426: 'lv', 32596 0x0427: 'lt', 32597 0x082e: 'dsb', 32598 0x046e: 'lb', 32599 0x042f: 'mk', 32600 0x083e: 'ms-BN', 32601 0x043e: 'ms', 32602 0x044c: 'ml', 32603 0x043a: 'mt', 32604 0x0481: 'mi', 32605 0x047a: 'arn', 32606 0x044e: 'mr', 32607 0x047c: 'moh', 32608 0x0450: 'mn', 32609 0x0850: 'mn-CN', 32610 0x0461: 'ne', 32611 0x0414: 'nb', 32612 0x0814: 'nn', 32613 0x0482: 'oc', 32614 0x0448: 'or', 32615 0x0463: 'ps', 32616 0x0415: 'pl', 32617 0x0416: 'pt', 32618 0x0816: 'pt-PT', 32619 0x0446: 'pa', 32620 0x046b: 'qu-BO', 32621 0x086b: 'qu-EC', 32622 0x0c6b: 'qu', 32623 0x0418: 'ro', 32624 0x0417: 'rm', 32625 0x0419: 'ru', 32626 0x243b: 'smn', 32627 0x103b: 'smj-NO', 32628 0x143b: 'smj', 32629 0x0c3b: 'se-FI', 32630 0x043b: 'se', 32631 0x083b: 'se-SE', 32632 0x203b: 'sms', 32633 0x183b: 'sma-NO', 32634 0x1c3b: 'sms', 32635 0x044f: 'sa', 32636 0x1c1a: 'sr-Cyrl-BA', 32637 0x0c1a: 'sr', 32638 0x181a: 'sr-Latn-BA', 32639 0x081a: 'sr-Latn', 32640 0x046c: 'nso', 32641 0x0432: 'tn', 32642 0x045b: 'si', 32643 0x041b: 'sk', 32644 0x0424: 'sl', 32645 0x2c0a: 'es-AR', 32646 0x400a: 'es-BO', 32647 0x340a: 'es-CL', 32648 0x240a: 'es-CO', 32649 0x140a: 'es-CR', 32650 0x1c0a: 'es-DO', 32651 0x300a: 'es-EC', 32652 0x440a: 'es-SV', 32653 0x100a: 'es-GT', 32654 0x480a: 'es-HN', 32655 0x080a: 'es-MX', 32656 0x4c0a: 'es-NI', 32657 0x180a: 'es-PA', 32658 0x3c0a: 'es-PY', 32659 0x280a: 'es-PE', 32660 0x500a: 'es-PR', 32661 32662 // Microsoft has defined two different language codes for 32663 // âSpanish with modern sortingâ and âSpanish with traditional 32664 // sortingâ. This makes sense for collation APIs, and it would be 32665 // possible to express this in BCP 47 language tags via Unicode 32666 // extensions (eg., es-u-co-trad is Spanish with traditional 32667 // sorting). However, for storing names in fonts, the distinction 32668 // does not make sense, so we give âesâ in both cases. 32669 0x0c0a: 'es', 32670 0x040a: 'es', 32671 32672 0x540a: 'es-US', 32673 0x380a: 'es-UY', 32674 0x200a: 'es-VE', 32675 0x081d: 'sv-FI', 32676 0x041d: 'sv', 32677 0x045a: 'syr', 32678 0x0428: 'tg', 32679 0x085f: 'tzm', 32680 0x0449: 'ta', 32681 0x0444: 'tt', 32682 0x044a: 'te', 32683 0x041e: 'th', 32684 0x0451: 'bo', 32685 0x041f: 'tr', 32686 0x0442: 'tk', 32687 0x0480: 'ug', 32688 0x0422: 'uk', 32689 0x042e: 'hsb', 32690 0x0420: 'ur', 32691 0x0843: 'uz-Cyrl', 32692 0x0443: 'uz', 32693 0x042a: 'vi', 32694 0x0452: 'cy', 32695 0x0488: 'wo', 32696 0x0485: 'sah', 32697 0x0478: 'ii', 32698 0x046a: 'yo' 32699 }; 32700 32701 // Returns a IETF BCP 47 language code, for example 'zh-Hant' 32702 // for 'Chinese in the traditional script'. 32703 function getLanguageCode(platformID, languageID, ltag) { 32704 switch (platformID) { 32705 case 0: // Unicode 32706 if (languageID === 0xffff) { 32707 return 'und'; 32708 } else if (ltag) { 32709 return ltag[languageID]; 32710 } 32711 32712 break; 32713 32714 case 1: // Macintosh 32715 return macLanguages[languageID]; 32716 32717 case 3: // Windows 32718 return windowsLanguages[languageID]; 32719 } 32720 32721 return undefined; 32722 } 32723 32724 var utf16 = 'utf-16'; 32725 32726 // MacOS script ID â encoding. This table stores the default case, 32727 // which can be overridden by macLanguageEncodings. 32728 var macScriptEncodings = { 32729 0: 'macintosh', // smRoman 32730 1: 'x-mac-japanese', // smJapanese 32731 2: 'x-mac-chinesetrad', // smTradChinese 32732 3: 'x-mac-korean', // smKorean 32733 6: 'x-mac-greek', // smGreek 32734 7: 'x-mac-cyrillic', // smCyrillic 32735 9: 'x-mac-devanagai', // smDevanagari 32736 10: 'x-mac-gurmukhi', // smGurmukhi 32737 11: 'x-mac-gujarati', // smGujarati 32738 12: 'x-mac-oriya', // smOriya 32739 13: 'x-mac-bengali', // smBengali 32740 14: 'x-mac-tamil', // smTamil 32741 15: 'x-mac-telugu', // smTelugu 32742 16: 'x-mac-kannada', // smKannada 32743 17: 'x-mac-malayalam', // smMalayalam 32744 18: 'x-mac-sinhalese', // smSinhalese 32745 19: 'x-mac-burmese', // smBurmese 32746 20: 'x-mac-khmer', // smKhmer 32747 21: 'x-mac-thai', // smThai 32748 22: 'x-mac-lao', // smLao 32749 23: 'x-mac-georgian', // smGeorgian 32750 24: 'x-mac-armenian', // smArmenian 32751 25: 'x-mac-chinesesimp', // smSimpChinese 32752 26: 'x-mac-tibetan', // smTibetan 32753 27: 'x-mac-mongolian', // smMongolian 32754 28: 'x-mac-ethiopic', // smEthiopic 32755 29: 'x-mac-ce', // smCentralEuroRoman 32756 30: 'x-mac-vietnamese', // smVietnamese 32757 31: 'x-mac-extarabic' // smExtArabic 32758 }; 32759 32760 // MacOS language ID â encoding. This table stores the exceptional 32761 // cases, which override macScriptEncodings. For writing MacOS naming 32762 // tables, we need to emit a MacOS script ID. Therefore, we cannot 32763 // merge macScriptEncodings into macLanguageEncodings. 32764 // 32765 // http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/Readme.txt 32766 var macLanguageEncodings = { 32767 15: 'x-mac-icelandic', // langIcelandic 32768 17: 'x-mac-turkish', // langTurkish 32769 18: 'x-mac-croatian', // langCroatian 32770 24: 'x-mac-ce', // langLithuanian 32771 25: 'x-mac-ce', // langPolish 32772 26: 'x-mac-ce', // langHungarian 32773 27: 'x-mac-ce', // langEstonian 32774 28: 'x-mac-ce', // langLatvian 32775 30: 'x-mac-icelandic', // langFaroese 32776 37: 'x-mac-romanian', // langRomanian 32777 38: 'x-mac-ce', // langCzech 32778 39: 'x-mac-ce', // langSlovak 32779 40: 'x-mac-ce', // langSlovenian 32780 143: 'x-mac-inuit', // langInuktitut 32781 146: 'x-mac-gaelic' // langIrishGaelicScript 32782 }; 32783 32784 function getEncoding(platformID, encodingID, languageID) { 32785 switch (platformID) { 32786 case 0: // Unicode 32787 return utf16; 32788 32789 case 1: // Apple Macintosh 32790 return ( 32791 macLanguageEncodings[languageID] || macScriptEncodings[encodingID] 32792 ); 32793 32794 case 3: // Microsoft Windows 32795 if (encodingID === 1 || encodingID === 10) { 32796 return utf16; 32797 } 32798 32799 break; 32800 } 32801 32802 return undefined; 32803 } 32804 32805 // Parse the naming `name` table. 32806 // FIXME: Format 1 additional fields are not supported yet. 32807 // ltag is the content of the `ltag' table, such as ['en', 'zh-Hans', 'de-CH-1904']. 32808 function parseNameTable(data, start, ltag) { 32809 var name = {}; 32810 var p = new parse.Parser(data, start); 32811 var format = p.parseUShort(); 32812 var count = p.parseUShort(); 32813 var stringOffset = p.offset + p.parseUShort(); 32814 for (var i = 0; i < count; i++) { 32815 var platformID = p.parseUShort(); 32816 var encodingID = p.parseUShort(); 32817 var languageID = p.parseUShort(); 32818 var nameID = p.parseUShort(); 32819 var property = nameTableNames[nameID] || nameID; 32820 var byteLength = p.parseUShort(); 32821 var offset = p.parseUShort(); 32822 var language = getLanguageCode(platformID, languageID, ltag); 32823 var encoding = getEncoding(platformID, encodingID, languageID); 32824 if (encoding !== undefined && language !== undefined) { 32825 var text = void 0; 32826 if (encoding === utf16) { 32827 text = decode.UTF16(data, stringOffset + offset, byteLength); 32828 } else { 32829 text = decode.MACSTRING( 32830 data,
32831 stringOffset + offset, 32832 byteLength, 32833 encoding 32834 ); 32835 } 32836 32837 if (text) { 32838 var translations = name[property]; 32839 if (translations === undefined) { 32840 translations = name[property] = {}; 32841 } 32842 32843 translations[language] = text; 32844 } 32845 } 32846 } 32847 32848 var langTagCount = 0; 32849 if (format === 1) { 32850 // FIXME: Also handle Microsoft's 'name' table 1. 32851 langTagCount = p.parseUShort(); 32852 } 32853 32854 return name; 32855 } 32856 32857 // {23: 'foo'} â {'foo': 23} 32858 // ['bar', 'baz'] â {'bar': 0, 'baz': 1} 32859 function reverseDict(dict) { 32860 var result = {}; 32861 for (var key in dict) { 32862 result[dict[key]] = parseInt(key); 32863 } 32864 32865 return result; 32866 } 32867 32868 function makeNameRecord( 32869 platformID, 32870 encodingID, 32871 languageID, 32872 nameID, 32873 length, 32874 offset 32875 ) { 32876 return new table.Record('NameRecord', [ 32877 { name: 'platformID', type: 'USHORT', value: platformID }, 32878 { name: 'encodingID', type: 'USHORT', value: encodingID }, 32879 { name: 'languageID', type: 'USHORT', value: languageID }, 32880 { name: 'nameID', type: 'USHORT', value: nameID }, 32881 { name: 'length', type: 'USHORT', value: length }, 32882 { name: 'offset', type: 'USHORT', value: offset } 32883 ]); 32884 } 32885 32886 // Finds the position of needle in haystack, or -1 if not there. 32887 // Like String.indexOf(), but for arrays. 32888 function findSubArray(needle, haystack) { 32889 var needleLength = needle.length; 32890 var limit = haystack.length - needleLength + 1; 32891 32892 loop: for (var pos = 0; pos < limit; pos++) { 32893 for (; pos < limit; pos++) { 32894 for (var k = 0; k < needleLength; k++) { 32895 if (haystack[pos + k] !== needle[k]) { 32896 continue loop; 32897 } 32898 } 32899 32900 return pos; 32901 } 32902 } 32903 32904 return -1; 32905 } 32906 32907 function addStringToPool(s, pool) { 32908 var offset = findSubArray(s, pool); 32909 if (offset < 0) { 32910 offset = pool.length; 32911 var i = 0; 32912 var len = s.length; 32913 for (; i < len; ++i) { 32914 pool.push(s[i]); 32915 } 32916 } 32917 32918 return offset; 32919 } 32920 32921 function makeNameTable(names, ltag) { 32922 var nameID; 32923 var nameIDs = []; 32924 32925 var namesWithNumericKeys = {}; 32926 var nameTableIds = reverseDict(nameTableNames); 32927 for (var key in names) { 32928 var id = nameTableIds[key]; 32929 if (id === undefined) { 32930 id = key; 32931 } 32932 32933 nameID = parseInt(id); 32934 32935 if (isNaN(nameID)) { 32936 throw new Error( 32937 'Name table entry "' + 32938 key + 32939 '" does not exist, see nameTableNames for complete list.' 32940 ); 32941 } 32942 32943 namesWithNumericKeys[nameID] = names[key]; 32944 nameIDs.push(nameID); 32945 } 32946 32947 var macLanguageIds = reverseDict(macLanguages); 32948 var windowsLanguageIds = reverseDict(windowsLanguages); 32949 32950 var nameRecords = []; 32951 var stringPool = []; 32952 32953 for (var i = 0; i < nameIDs.length; i++) { 32954 nameID = nameIDs[i]; 32955 var translations = namesWithNumericKeys[nameID]; 32956 for (var lang in translations) { 32957 var text = translations[lang]; 32958 32959 // For MacOS, we try to emit the name in the form that was introduced 32960 // in the initial version of the TrueType spec (in the late 1980s). 32961 // However, this can fail for various reasons: the requested BCP 47 32962 // language code might not have an old-style Mac equivalent; 32963 // we might not have a codec for the needed character encoding; 32964 // or the name might contain characters that cannot be expressed 32965 // in the old-style Macintosh encoding. In case of failure, we emit 32966 // the name in a more modern fashion (Unicode encoding with BCP 47 32967 // language tags) that is recognized by MacOS 10.5, released in 2009. 32968 // If fonts were only read by operating systems, we could simply 32969 // emit all names in the modern form; this would be much easier. 32970 // However, there are many applications and libraries that read 32971 // 'name' tables directly, and these will usually only recognize 32972 // the ancient form (silently skipping the unrecognized names). 32973 var macPlatform = 1; // Macintosh 32974 var macLanguage = macLanguageIds[lang]; 32975 var macScript = macLanguageToScript[macLanguage]; 32976 var macEncoding = getEncoding(macPlatform, macScript, macLanguage); 32977 var macName = encode.MACSTRING(text, macEncoding); 32978 if (macName === undefined) { 32979 macPlatform = 0; // Unicode 32980 macLanguage = ltag.indexOf(lang); 32981 if (macLanguage < 0) { 32982 macLanguage = ltag.length; 32983 ltag.push(lang); 32984 } 32985 32986 macScript = 4; // Unicode 2.0 and later 32987 macName = encode.UTF16(text); 32988 } 32989
32990 var macNameOffset = addStringToPool(macName, stringPool); 32991 nameRecords.push( 32992 makeNameRecord( 32993 macPlatform, 32994 macScript, 32995 macLanguage, 32996 nameID, 32997 macName.length, 32998 macNameOffset 32999 ) 33000 ); 33001 33002 var winLanguage = windowsLanguageIds[lang]; 33003 if (winLanguage !== undefined) { 33004 var winName = encode.UTF16(text); 33005 var winNameOffset = addStringToPool(winName, stringPool); 33006 nameRecords.push( 33007 makeNameRecord( 33008 3, 33009 1, 33010 winLanguage, 33011 nameID, 33012 winName.length, 33013 winNameOffset 33014 ) 33015 ); 33016 } 33017 } 33018 } 33019 33020 nameRecords.sort(function(a, b) { 33021 return ( 33022 a.platformID - b.platformID || 33023 a.encodingID - b.encodingID || 33024 a.languageID - b.languageID || 33025 a.nameID - b.nameID 33026 ); 33027 }); 33028 33029 var t = new table.Table('name', [ 33030 { name: 'format', type: 'USHORT', value: 0 }, 33031 { name: 'count', type: 'USHORT', value: nameRecords.length }, 33032 { 33033 name: 'stringOffset', 33034 type: 'USHORT', 33035 value: 6 + nameRecords.length * 12 33036 } 33037 ]); 33038 33039 for (var r = 0; r < nameRecords.length; r++) { 33040 t.fields.push({ 33041 name: 'record_' + r, 33042 type: 'RECORD', 33043 value: nameRecords[r] 33044 }); 33045 } 33046 33047 t.fields.push({ name: 'strings', type: 'LITERAL', value: stringPool }); 33048 return t; 33049 } 33050 33051 var _name = { parse: parseNameTable, make: makeNameTable }; 33052 33053 // The `OS/2` table contains metrics required in OpenType fonts. 33054 33055 var unicodeRanges = [ 33056 { begin: 0x0000, end: 0x007f }, // Basic Latin 33057 { begin: 0x0080, end: 0x00ff }, // Latin-1 Supplement 33058 { begin: 0x0100, end: 0x017f }, // Latin Extended-A 33059 { begin: 0x0180, end: 0x024f }, // Latin Extended-B 33060 { begin: 0x0250, end: 0x02af }, // IPA Extensions 33061 { begin: 0x02b0, end: 0x02ff }, // Spacing Modifier Letters 33062 { begin: 0x0300, end: 0x036f }, // Combining Diacritical Marks 33063 { begin: 0x0370, end: 0x03ff }, // Greek and Coptic 33064 { begin: 0x2c80, end: 0x2cff }, // Coptic 33065 { begin: 0x0400, end: 0x04ff }, // Cyrillic 33066 { begin: 0x0530, end: 0x058f }, // Armenian 33067 { begin: 0x0590, end: 0x05ff }, // Hebrew 33068 { begin: 0xa500, end: 0xa63f }, // Vai 33069 { begin: 0x0600, end: 0x06ff }, // Arabic 33070 { begin: 0x07c0, end: 0x07ff }, // NKo 33071 { begin: 0x0900, end: 0x097f }, // Devanagari 33072 { begin: 0x0980, end: 0x09ff }, // Bengali 33073 { begin: 0x0a00, end: 0x0a7f }, // Gurmukhi 33074 { begin: 0x0a80, end: 0x0aff }, // Gujarati 33075 { begin: 0x0b00, end: 0x0b7f }, // Oriya 33076 { begin: 0x0b80, end: 0x0bff }, // Tamil 33077 { begin: 0x0c00, end: 0x0c7f }, // Telugu 33078 { begin: 0x0c80, end: 0x0cff }, // Kannada 33079 { begin: 0x0d00, end: 0x0d7f }, // Malayalam 33080 { begin: 0x0e00, end: 0x0e7f }, // Thai 33081 { begin: 0x0e80, end: 0x0eff }, // Lao 33082 { begin: 0x10a0, end: 0x10ff }, // Georgian 33083 { begin: 0x1b00, end: 0x1b7f }, // Balinese 33084 { begin: 0x1100, end: 0x11ff }, // Hangul Jamo 33085 { begin: 0x1e00, end: 0x1eff }, // Latin Extended Additional 33086 { begin: 0x1f00, end: 0x1fff }, // Greek Extended 33087 { begin: 0x2000, end: 0x206f }, // General Punctuation 33088 { begin: 0x2070, end: 0x209f }, // Superscripts And Subscripts 33089 { begin: 0x20a0, end: 0x20cf }, // Currency Symbol 33090 { begin: 0x20d0, end: 0x20ff }, // Combining Diacritical Marks For Symbols 33091 { begin: 0x2100, end: 0x214f }, // Letterlike Symbols 33092 { begin: 0x2150, end: 0x218f }, // Number Forms 33093 { begin: 0x2190, end: 0x21ff }, // Arrows 33094 { begin: 0x2200, end: 0x22ff }, // Mathematical Operators 33095 { begin: 0x2300, end: 0x23ff }, // Miscellaneous Technical 33096 { begin: 0x2400, end: 0x243f }, // Control Pictures 33097 { begin: 0x2440, end: 0x245f }, // Optical Character Recognition 33098 { begin: 0x2460, end: 0x24ff }, // Enclosed Alphanumerics 33099 { begin: 0x2500, end: 0x257f }, // Box Drawing 33100 { begin: 0x2580, end: 0x259f }, // Block Elements 33101 { begin: 0x25a0, end: 0x25ff }, // Geometric Shapes 33102 { begin: 0x2600, end: 0x26ff }, // Miscellaneous Symbols 33103 { begin: 0x2700, end: 0x27bf }, // Dingbats 33104 { begin: 0x3000, end: 0x303f }, // CJK Symbols And Punctuation 33105 { begin: 0x3040, end: 0x309f }, // Hiragana 33106 { begin: 0x30a0, end: 0x30ff }, // Katakana 33107 { begin: 0x3100, end: 0x312f }, // Bopomofo 33108 { begin: 0x3130, end: 0x318f }, // Hangul Compatibility Jamo 33109 { begin: 0xa840, end: 0xa87f }, // Phags-pa 33110 { begin: 0x3200, end: 0x32ff }, // Enclosed CJK Letters And Months 33111 { begin: 0x3300, end: 0x33ff }, // CJK Compatibility 33112 { begin: 0xac00, end: 0xd7af }, // Hangul Syllables 33113 { begin: 0xd800, end: 0xdfff }, // Non-Plane 0 * 33114 { begin: 0x10900, end: 0x1091f }, // Phoenicia 33115 { begin: 0x4e00, end: 0x9fff }, // CJK Unified Ideographs 33116 { begin: 0xe000, end: 0xf8ff }, // Private Use Area (plane 0) 33117 { begin: 0x31c0, end: 0x31ef }, // CJK Strokes 33118 { begin: 0xfb00, end: 0xfb4f }, // Alphabetic Presentation Forms 33119 { begin: 0xfb50, end: 0xfdff }, // Arabic Presentation Forms-A 33120 { begin: 0xfe20, end: 0xfe2f }, // Combining Half Marks 33121 { begin: 0xfe10, end: 0xfe1f }, // Vertical Forms 33122 { begin: 0xfe50, end: 0xfe6f }, // Small Form Variants 33123 { begin: 0xfe70, end: 0xfeff }, // Arabic Presentation Forms-B 33124 { begin: 0xff00, end: 0xffef }, // Halfwidth And Fullwidth Forms 33125 { begin: 0xfff0, end: 0xffff }, // Specials 33126 { begin: 0x0f00, end: 0x0fff }, // Tibetan 33127 { begin: 0x0700, end: 0x074f }, // Syriac 33128 { begin: 0x0780, end: 0x07bf }, // Thaana 33129 { begin: 0x0d80, end: 0x0dff }, // Sinhala 33130 { begin: 0x1000, end: 0x109f }, // Myanmar 33131 { begin: 0x1200, end: 0x137f }, // Ethiopic 33132 { begin: 0x13a0, end: 0x13ff }, // Cherokee 33133 { begin: 0x1400, end: 0x167f }, // Unified Canadian Aboriginal Syllabics 33134 { begin: 0x1680, end: 0x169f }, // Ogham 33135 { begin: 0x16a0, end: 0x16ff }, // Runic 33136 { begin: 0x1780, end: 0x17ff }, // Khmer 33137 { begin: 0x1800, end: 0x18af }, // Mongolian 33138 { begin: 0x2800, end: 0x28ff }, // Braille Patterns 33139 { begin: 0xa000, end: 0xa48f }, // Yi Syllables 33140 { begin: 0x1700, end: 0x171f }, // Tagalog 33141 { begin: 0x10300, end: 0x1032f }, // Old Italic 33142 { begin: 0x10330, end: 0x1034f }, // Gothic 33143 { begin: 0x10400, end: 0x1044f }, // Deseret 33144 { begin: 0x1d000, end: 0x1d0ff }, // Byzantine Musical Symbols 33145 { begin: 0x1d400, end: 0x1d7ff }, // Mathematical Alphanumeric Symbols 33146 { begin: 0xff000, end: 0xffffd }, // Private Use (plane 15) 33147 { begin: 0xfe00, end: 0xfe0f }, // Variation Selectors 33148 { begin: 0xe0000, end: 0xe007f }, // Tags 33149 { begin: 0x1900, end: 0x194f }, // Limbu 33150 { begin: 0x1950, end: 0x197f }, // Tai Le 33151 { begin: 0x1980, end: 0x19df }, // New Tai Lue 33152 { begin: 0x1a00, end: 0x1a1f }, // Buginese 33153 { begin: 0x2c00, end: 0x2c5f }, // Glagolitic 33154 { begin: 0x2d30, end: 0x2d7f }, // Tifinagh 33155 { begin: 0x4dc0, end: 0x4dff }, // Yijing Hexagram Symbols 33156 { begin: 0xa800, end: 0xa82f }, // Syloti Nagri 33157 { begin: 0x10000, end: 0x1007f }, // Linear B Syllabary 33158 { begin: 0x10140, end: 0x1018f }, // Ancient Greek Numbers 33159 { begin: 0x10380, end: 0x1039f }, // Ugaritic 33160 { begin: 0x103a0, end: 0x103df }, // Old Persian 33161 { begin: 0x10450, end: 0x1047f }, // Shavian 33162 { begin: 0x10480, end: 0x104af }, // Osmanya 33163 { begin: 0x10800, end: 0x1083f }, // Cypriot Syllabary 33164 { begin: 0x10a00, end: 0x10a5f }, // Kharoshthi 33165 { begin: 0x1d300, end: 0x1d35f }, // Tai Xuan Jing Symbols 33166 { begin: 0x12000, end: 0x123ff }, // Cuneiform 33167 { begin: 0x1d360, end: 0x1d37f }, // Counting Rod Numerals 33168 { begin: 0x1b80, end: 0x1bbf }, // Sundanese 33169 { begin: 0x1c00, end: 0x1c4f }, // Lepcha 33170 { begin: 0x1c50, end: 0x1c7f }, // Ol Chiki 33171 { begin: 0xa880, end: 0xa8df }, // Saurashtra 33172 { begin: 0xa900, end: 0xa92f }, // Kayah Li 33173 { begin: 0xa930, end: 0xa95f }, // Rejang 33174 { begin: 0xaa00, end: 0xaa5f }, // Cham 33175 { begin: 0x10190, end: 0x101cf }, // Ancient Symbols 33176 { begin: 0x101d0, end: 0x101ff }, // Phaistos Disc 33177 { begin: 0x102a0, end: 0x102df }, // Carian 33178 { begin: 0x1f030, end: 0x1f09f } // Domino Tiles 33179 ]; 33180 33181 function getUnicodeRange(unicode) { 33182 for (var i = 0; i < unicodeRanges.length; i += 1) { 33183 var range = unicodeRanges[i]; 33184 if (unicode >= range.begin && unicode < range.end) { 33185 return i; 33186 } 33187 } 33188 33189 return -1; 33190 } 33191 33192 // Parse the OS/2 and Windows metrics `OS/2` table 33193 function parseOS2Table(data, start) { 33194 var os2 = {}; 33195 var p = new parse.Parser(data, start); 33196 os2.version = p.parseUShort(); 33197 os2.xAvgCharWidth = p.parseShort(); 33198 os2.usWeightClass = p.parseUShort(); 33199 os2.usWidthClass = p.parseUShort(); 33200 os2.fsType = p.parseUShort(); 33201 os2.ySubscriptXSize = p.parseShort(); 33202 os2.ySubscriptYSize = p.parseShort(); 33203 os2.ySubscriptXOffset = p.parseShort(); 33204 os2.ySubscriptYOffset = p.parseShort(); 33205 os2.ySuperscriptXSize = p.parseShort(); 33206 os2.ySuperscriptYSize = p.parseShort(); 33207 os2.ySuperscriptXOffset = p.parseShort(); 33208 os2.ySuperscriptYOffset = p.parseShort(); 33209 os2.yStrikeoutSize = p.parseShort(); 33210 os2.yStrikeoutPosition = p.parseShort(); 33211 os2.sFamilyClass = p.parseShort(); 33212 os2.panose = []; 33213 for (var i = 0; i < 10; i++) { 33214 os2.panose[i] = p.parseByte(); 33215 } 33216 33217 os2.ulUnicodeRange1 = p.parseULong(); 33218 os2.ulUnicodeRange2 = p.parseULong(); 33219 os2.ulUnicodeRange3 = p.parseULong(); 33220 os2.ulUnicodeRange4 = p.parseULong(); 33221 os2.achVendID = String.fromCharCode( 33222 p.parseByte(), 33223 p.parseByte(), 33224 p.parseByte(), 33225 p.parseByte() 33226 ); 33227 os2.fsSelection = p.parseUShort(); 33228 os2.usFirstCharIndex = p.parseUShort(); 33229 os2.usLastCharIndex = p.parseUShort(); 33230 os2.sTypoAscender = p.parseShort(); 33231 os2.sTypoDescender = p.parseShort(); 33232 os2.sTypoLineGap = p.parseShort(); 33233 os2.usWinAscent = p.parseUShort(); 33234 os2.usWinDescent = p.parseUShort();
33235 if (os2.version >= 1) { 33236 os2.ulCodePageRange1 = p.parseULong(); 33237 os2.ulCodePageRange2 = p.parseULong(); 33238 } 33239 33240 if (os2.version >= 2) { 33241 os2.sxHeight = p.parseShort(); 33242 os2.sCapHeight = p.parseShort(); 33243 os2.usDefaultChar = p.parseUShort(); 33244 os2.usBreakChar = p.parseUShort(); 33245 os2.usMaxContent = p.parseUShort(); 33246 } 33247 33248 return os2; 33249 } 33250 33251 function makeOS2Table(options) { 33252 return new table.Table( 33253 'OS/2', 33254 [ 33255 { name: 'version', type: 'USHORT', value: 0x0003 }, 33256 { name: 'xAvgCharWidth', type: 'SHORT', value: 0 }, 33257 { name: 'usWeightClass', type: 'USHORT', value: 0 }, 33258 { name: 'usWidthClass', type: 'USHORT', value: 0 }, 33259 { name: 'fsType', type: 'USHORT', value: 0 }, 33260 { name: 'ySubscriptXSize', type: 'SHORT', value: 650 }, 33261 { name: 'ySubscriptYSize', type: 'SHORT', value: 699 }, 33262 { name: 'ySubscriptXOffset', type: 'SHORT', value: 0 }, 33263 { name: 'ySubscriptYOffset', type: 'SHORT', value: 140 }, 33264 { name: 'ySuperscriptXSize', type: 'SHORT', value: 650 }, 33265 { name: 'ySuperscriptYSize', type: 'SHORT', value: 699 }, 33266 { name: 'ySuperscriptXOffset', type: 'SHORT', value: 0 }, 33267 { name: 'ySuperscriptYOffset', type: 'SHORT', value: 479 }, 33268 { name: 'yStrikeoutSize', type: 'SHORT', value: 49 }, 33269 { name: 'yStrikeoutPosition', type: 'SHORT', value: 258 }, 33270 { name: 'sFamilyClass', type: 'SHORT', value: 0 }, 33271 { name: 'bFamilyType', type: 'BYTE', value: 0 }, 33272 { name: 'bSerifStyle', type: 'BYTE', value: 0 }, 33273 { name: 'bWeight', type: 'BYTE', value: 0 }, 33274 { name: 'bProportion', type: 'BYTE', value: 0 }, 33275 { name: 'bContrast', type: 'BYTE', value: 0 }, 33276 { name: 'bStrokeVariation', type: 'BYTE', value: 0 }, 33277 { name: 'bArmStyle', type: 'BYTE', value: 0 }, 33278 { name: 'bLetterform', type: 'BYTE', value: 0 }, 33279 { name: 'bMidline', type: 'BYTE', value: 0 }, 33280 { name: 'bXHeight', type: 'BYTE', value: 0 }, 33281 { name: 'ulUnicodeRange1', type: 'ULONG', value: 0 }, 33282 { name: 'ulUnicodeRange2', type: 'ULONG', value: 0 }, 33283 { name: 'ulUnicodeRange3', type: 'ULONG', value: 0 }, 33284 { name: 'ulUnicodeRange4', type: 'ULONG', value: 0 }, 33285 { name: 'achVendID', type: 'CHARARRAY', value: 'XXXX' }, 33286 { name: 'fsSelection', type: 'USHORT', value: 0 }, 33287 { name: 'usFirstCharIndex', type: 'USHORT', value: 0 }, 33288 { name: 'usLastCharIndex', type: 'USHORT', value: 0 }, 33289 { name: 'sTypoAscender', type: 'SHORT', value: 0 }, 33290 { name: 'sTypoDescender', type: 'SHORT', value: 0 }, 33291 { name: 'sTypoLineGap', type: 'SHORT', value: 0 }, 33292 { name: 'usWinAscent', type: 'USHORT', value: 0 }, 33293 { name: 'usWinDescent', type: 'USHORT', value: 0 }, 33294 { name: 'ulCodePageRange1', type: 'ULONG', value: 0 }, 33295 { name: 'ulCodePageRange2', type: 'ULONG', value: 0 }, 33296 { name: 'sxHeight', type: 'SHORT', value: 0 }, 33297 { name: 'sCapHeight', type: 'SHORT', value: 0 }, 33298 { name: 'usDefaultChar', type: 'USHORT', value: 0 },
vendor: 18,359 bytes, lines 33299-33724
33299 { name: 'usBreakChar', type: 'USHORT', value: 0 }, 33300 { name: 'usMaxContext', type: 'USHORT', value: 0 } 33301 ], 33302 options 33303 ); 33304 } 33305 33306 var os2 = { 33307 parse: parseOS2Table, 33308 make: makeOS2Table, 33309 unicodeRanges: unicodeRanges, 33310 getUnicodeRange: getUnicodeRange 33311 }; 33312 33313 // The `post` table stores additional PostScript information, such as glyph names. 33314 33315 // Parse the PostScript `post` table 33316 function parsePostTable(data, start) { 33317 var post = {}; 33318 var p = new parse.Parser(data, start); 33319 post.version = p.parseVersion(); 33320 post.italicAngle = p.parseFixed(); 33321 post.underlinePosition = p.parseShort(); 33322 post.underlineThickness = p.parseShort(); 33323 post.isFixedPitch = p.parseULong(); 33324 post.minMemType42 = p.parseULong(); 33325 post.maxMemType42 = p.parseULong(); 33326 post.minMemType1 = p.parseULong(); 33327 post.maxMemType1 = p.parseULong(); 33328 switch (post.version) { 33329 case 1: 33330 post.names = standardNames.slice(); 33331 break; 33332 case 2: 33333 post.numberOfGlyphs = p.parseUShort(); 33334 post.glyphNameIndex = new Array(post.numberOfGlyphs); 33335 for (var i = 0; i < post.numberOfGlyphs; i++) { 33336 post.glyphNameIndex[i] = p.parseUShort(); 33337 } 33338 33339 post.names = []; 33340 for (var i$1 = 0; i$1 < post.numberOfGlyphs; i$1++) { 33341 if (post.glyphNameIndex[i$1] >= standardNames.length) { 33342 var nameLength = p.parseChar(); 33343 post.names.push(p.parseString(nameLength)); 33344 } 33345 } 33346 33347 break; 33348 case 2.5: 33349 post.numberOfGlyphs = p.parseUShort(); 33350 post.offset = new Array(post.numberOfGlyphs); 33351 for (var i$2 = 0; i$2 < post.numberOfGlyphs; i$2++) { 33352 post.offset[i$2] = p.parseChar(); 33353 } 33354 33355 break; 33356 } 33357 return post; 33358 } 33359 33360 function makePostTable() { 33361 return new table.Table('post', [ 33362 { name: 'version', type: 'FIXED', value: 0x00030000 }, 33363 { name: 'italicAngle', type: 'FIXED', value: 0 }, 33364 { name: 'underlinePosition', type: 'FWORD', value: 0 }, 33365 { name: 'underlineThickness', type: 'FWORD', value: 0 }, 33366 { name: 'isFixedPitch', type: 'ULONG', value: 0 }, 33367 { name: 'minMemType42', type: 'ULONG', value: 0 }, 33368 { name: 'maxMemType42', type: 'ULONG', value: 0 }, 33369 { name: 'minMemType1', type: 'ULONG', value: 0 }, 33370 { name: 'maxMemType1', type: 'ULONG', value: 0 } 33371 ]); 33372 } 33373 33374 var post = { parse: parsePostTable, make: makePostTable }; 33375 33376 // The `GSUB` table contains ligatures, among other things. 33377 33378 var subtableParsers = new Array(9); // subtableParsers[0] is unused 33379 33380 // https://www.microsoft.com/typography/OTSPEC/GSUB.htm#SS 33381 subtableParsers[1] = function parseLookup1() { 33382 var start = this.offset + this.relativeOffset; 33383 var substFormat = this.parseUShort(); 33384 if (substFormat === 1) { 33385 return { 33386 substFormat: 1, 33387 coverage: this.parsePointer(Parser.coverage), 33388 deltaGlyphId: this.parseUShort() 33389 }; 33390 } else if (substFormat === 2) { 33391 return { 33392 substFormat: 2, 33393 coverage: this.parsePointer(Parser.coverage), 33394 substitute: this.parseOffset16List() 33395 }; 33396 } 33397 check.assert( 33398 false, 33399 '0x' + start.toString(16) + ': lookup type 1 format must be 1 or 2.' 33400 ); 33401 }; 33402 33403 // https://www.microsoft.com/typography/OTSPEC/GSUB.htm#MS 33404 subtableParsers[2] = function parseLookup2() { 33405 var substFormat = this.parseUShort(); 33406 check.argument( 33407 substFormat === 1, 33408 'GSUB Multiple Substitution Subtable identifier-format must be 1' 33409 ); 33410 return { 33411 substFormat: substFormat, 33412 coverage: this.parsePointer(Parser.coverage), 33413 sequences: this.parseListOfLists() 33414 }; 33415 }; 33416 33417 // https://www.microsoft.com/typography/OTSPEC/GSUB.htm#AS 33418 subtableParsers[3] = function parseLookup3() { 33419 var substFormat = this.parseUShort(); 33420 check.argument( 33421 substFormat === 1, 33422 'GSUB Alternate Substitution Subtable identifier-format must be 1' 33423 ); 33424 return { 33425 substFormat: substFormat, 33426 coverage: this.parsePointer(Parser.coverage), 33427 alternateSets: this.parseListOfLists() 33428 }; 33429 }; 33430 33431 // https://www.microsoft.com/typography/OTSPEC/GSUB.htm#LS 33432 subtableParsers[4] = function parseLookup4() { 33433 var substFormat = this.parseUShort(); 33434 check.argument( 33435 substFormat === 1, 33436 'GSUB ligature table identifier-format must be 1' 33437 ); 33438 return { 33439 substFormat: substFormat, 33440 coverage: this.parsePointer(Parser.coverage), 33441 ligatureSets: this.parseListOfLists(function() { 33442 return { 33443 ligGlyph: this.parseUShort(), 33444 components: this.parseUShortList(this.parseUShort() - 1) 33445 }; 33446 }) 33447 }; 33448 }; 33449 33450 var lookupRecordDesc = { 33451 sequenceIndex: Parser.uShort, 33452 lookupListIndex: Parser.uShort 33453 }; 33454 33455 // https://www.microsoft.com/typography/OTSPEC/GSUB.htm#CSF 33456 subtableParsers[5] = function parseLookup5() { 33457 var start = this.offset + this.relativeOffset; 33458 var substFormat = this.parseUShort(); 33459 33460 if (substFormat === 1) { 33461 return { 33462 substFormat: substFormat, 33463 coverage: this.parsePointer(Parser.coverage), 33464 ruleSets: this.parseListOfLists(function() { 33465 var glyphCount = this.parseUShort(); 33466 var substCount = this.parseUShort(); 33467 return { 33468 input: this.parseUShortList(glyphCount - 1), 33469 lookupRecords: this.parseRecordList(substCount, lookupRecordDesc) 33470 }; 33471 }) 33472 }; 33473 } else if (substFormat === 2) { 33474 return { 33475 substFormat: substFormat, 33476 coverage: this.parsePointer(Parser.coverage), 33477 classDef: this.parsePointer(Parser.classDef), 33478 classSets: this.parseListOfLists(function() { 33479 var glyphCount = this.parseUShort(); 33480 var substCount = this.parseUShort(); 33481 return { 33482 classes: this.parseUShortList(glyphCount - 1), 33483 lookupRecords: this.parseRecordList(substCount, lookupRecordDesc) 33484 }; 33485 }) 33486 }; 33487 } else if (substFormat === 3) { 33488 var glyphCount = this.parseUShort(); 33489 var substCount = this.parseUShort(); 33490 return { 33491 substFormat: substFormat, 33492 coverages: this.parseList(glyphCount, Parser.pointer(Parser.coverage)), 33493 lookupRecords: this.parseRecordList(substCount, lookupRecordDesc) 33494 }; 33495 } 33496 check.assert( 33497 false, 33498 '0x' + start.toString(16) + ': lookup type 5 format must be 1, 2 or 3.' 33499 ); 33500 }; 33501 33502 // https://www.microsoft.com/typography/OTSPEC/GSUB.htm#CC 33503 subtableParsers[6] = function parseLookup6() { 33504 var start = this.offset + this.relativeOffset; 33505 var substFormat = this.parseUShort(); 33506 if (substFormat === 1) { 33507 return { 33508 substFormat: 1, 33509 coverage: this.parsePointer(Parser.coverage), 33510 chainRuleSets: this.parseListOfLists(function() { 33511 return { 33512 backtrack: this.parseUShortList(), 33513 input: this.parseUShortList(this.parseShort() - 1), 33514 lookahead: this.parseUShortList(), 33515 lookupRecords: this.parseRecordList(lookupRecordDesc) 33516 }; 33517 }) 33518 }; 33519 } else if (substFormat === 2) { 33520 return { 33521 substFormat: 2, 33522 coverage: this.parsePointer(Parser.coverage), 33523 backtrackClassDef: this.parsePointer(Parser.classDef), 33524 inputClassDef: this.parsePointer(Parser.classDef), 33525 lookaheadClassDef: this.parsePointer(Parser.classDef), 33526 chainClassSet: this.parseListOfLists(function() { 33527 return { 33528 backtrack: this.parseUShortList(), 33529 input: this.parseUShortList(this.parseShort() - 1), 33530 lookahead: this.parseUShortList(), 33531 lookupRecords: this.parseRecordList(lookupRecordDesc) 33532 }; 33533 }) 33534 }; 33535 } else if (substFormat === 3) { 33536 return { 33537 substFormat: 3, 33538 backtrackCoverage: this.parseList(Parser.pointer(Parser.coverage)), 33539 inputCoverage: this.parseList(Parser.pointer(Parser.coverage)), 33540 lookaheadCoverage: this.parseList(Parser.pointer(Parser.coverage)), 33541 lookupRecords: this.parseRecordList(lookupRecordDesc) 33542 }; 33543 } 33544 check.assert( 33545 false, 33546 '0x' + start.toString(16) + ': lookup type 6 format must be 1, 2 or 3.' 33547 ); 33548 }; 33549 33550 // https://www.microsoft.com/typography/OTSPEC/GSUB.htm#ES 33551 subtableParsers[7] = function parseLookup7() { 33552 // Extension Substitution subtable 33553 var substFormat = this.parseUShort(); 33554 check.argument( 33555 substFormat === 1, 33556 'GSUB Extension Substitution subtable identifier-format must be 1' 33557 ); 33558 var extensionLookupType = this.parseUShort(); 33559 var extensionParser = new Parser( 33560 this.data, 33561 this.offset + this.parseULong() 33562 ); 33563 return { 33564 substFormat: 1, 33565 lookupType: extensionLookupType, 33566 extension: subtableParsers[extensionLookupType].call(extensionParser) 33567 }; 33568 }; 33569 33570 // https://www.microsoft.com/typography/OTSPEC/GSUB.htm#RCCS 33571 subtableParsers[8] = function parseLookup8() { 33572 var substFormat = this.parseUShort(); 33573 check.argument( 33574 substFormat === 1, 33575 'GSUB Reverse Chaining Contextual Single Substitution Subtable identifier-format must be 1' 33576 ); 33577 return { 33578 substFormat: substFormat, 33579 coverage: this.parsePointer(Parser.coverage), 33580 backtrackCoverage: this.parseList(Parser.pointer(Parser.coverage)), 33581 lookaheadCoverage: this.parseList(Parser.pointer(Parser.coverage)), 33582 substitutes: this.parseUShortList() 33583 }; 33584 }; 33585 33586 // https://www.microsoft.com/typography/OTSPEC/gsub.htm 33587 function parseGsubTable(data, start) { 33588 start = start || 0; 33589 var p = new Parser(data, start); 33590 var tableVersion = p.parseVersion(1); 33591 check.argument( 33592 tableVersion === 1 || tableVersion === 1.1, 33593 'Unsupported GSUB table version.' 33594 ); 33595 if (tableVersion === 1) { 33596 return { 33597 version: tableVersion, 33598 scripts: p.parseScriptList(), 33599 features: p.parseFeatureList(), 33600 lookups: p.parseLookupList(subtableParsers) 33601 }; 33602 } else { 33603 return { 33604 version: tableVersion, 33605 scripts: p.parseScriptList(), 33606 features: p.parseFeatureList(), 33607 lookups: p.parseLookupList(subtableParsers), 33608 variations: p.parseFeatureVariationsList() 33609 }; 33610 } 33611 } 33612 33613 // GSUB Writing ////////////////////////////////////////////// 33614 var subtableMakers = new Array(9); 33615 33616 subtableMakers[1] = function makeLookup1(subtable) { 33617 if (subtable.substFormat === 1) { 33618 return new table.Table('substitutionTable', [ 33619 { name: 'substFormat', type: 'USHORT', value: 1 }, 33620 { 33621 name: 'coverage', 33622 type: 'TABLE', 33623 value: new table.Coverage(subtable.coverage) 33624 }, 33625 { name: 'deltaGlyphID', type: 'USHORT', value: subtable.deltaGlyphId } 33626 ]); 33627 } else { 33628 return new table.Table( 33629 'substitutionTable', 33630 [ 33631 { name: 'substFormat', type: 'USHORT', value: 2 }, 33632 { 33633 name: 'coverage', 33634 type: 'TABLE', 33635 value: new table.Coverage(subtable.coverage) 33636 } 33637 ].concat(table.ushortList('substitute', subtable.substitute)) 33638 ); 33639 } 33640 check.fail('Lookup type 1 substFormat must be 1 or 2.'); 33641 }; 33642 33643 subtableMakers[3] = function makeLookup3(subtable) { 33644 check.assert( 33645 subtable.substFormat === 1, 33646 'Lookup type 3 substFormat must be 1.' 33647 ); 33648 return new table.Table( 33649 'substitutionTable', 33650 [ 33651 { name: 'substFormat', type: 'USHORT', value: 1 }, 33652 { 33653 name: 'coverage', 33654 type: 'TABLE', 33655 value: new table.Coverage(subtable.coverage) 33656 } 33657 ].concat( 33658 table.tableList('altSet', subtable.alternateSets, function( 33659 alternateSet 33660 ) { 33661 return new table.Table( 33662 'alternateSetTable', 33663 table.ushortList('alternate', alternateSet) 33664 ); 33665 }) 33666 ) 33667 ); 33668 }; 33669 33670 subtableMakers[4] = function makeLookup4(subtable) { 33671 check.assert( 33672 subtable.substFormat === 1, 33673 'Lookup type 4 substFormat must be 1.' 33674 ); 33675 return new table.Table( 33676 'substitutionTable', 33677 [ 33678 { name: 'substFormat', type: 'USHORT', value: 1 }, 33679 { 33680 name: 'coverage', 33681 type: 'TABLE', 33682 value: new table.Coverage(subtable.coverage) 33683 } 33684 ].concat( 33685 table.tableList('ligSet', subtable.ligatureSets, function(ligatureSet) { 33686 return new table.Table( 33687 'ligatureSetTable', 33688 table.tableList('ligature', ligatureSet, function(ligature) { 33689 return new table.Table( 33690 'ligatureTable', 33691 [ 33692 { name: 'ligGlyph', type: 'USHORT', value: ligature.ligGlyph } 33693 ].concat( 33694 table.ushortList( 33695 'component', 33696 ligature.components, 33697 ligature.components.length + 1 33698 ) 33699 ) 33700 ); 33701 }) 33702 ); 33703 }) 33704 ) 33705 ); 33706 }; 33707 33708 function makeGsubTable(gsub) { 33709 return new table.Table('GSUB', [ 33710 { name: 'version', type: 'ULONG', value: 0x10000 }, 33711 { 33712 name: 'scripts', 33713 type: 'TABLE', 33714 value: new table.ScriptList(gsub.scripts) 33715 }, 33716 { 33717 name: 'features', 33718 type: 'TABLE', 33719 value: new table.FeatureList(gsub.features) 33720 }, 33721 { 33722 name: 'lookups', 33723 type: 'TABLE', 33724 value: new table.LookupList(gsub.lookups, subtableMakers
33724) 33725 } 33726 ]); 33727 } 33728 33729 var gsub = { parse: parseGsubTable, make: makeGsubTable }; 33730 33731 // The `GPOS` table contains kerning pairs, among other things. 33732 33733 // Parse the metadata `meta` table. 33734 // https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6meta.html 33735 function parseMetaTable(data, start) { 33736 var p = new parse.Parser(data, start); 33737 var tableVersion = p.parseULong(); 33738 check.argument(tableVersion === 1, 'Unsupported META table version.'); 33739 p.parseULong(); // flags - currently unused and set to 0 33740 p.parseULong(); // tableOffset 33741 var numDataMaps = p.parseULong(); 33742 33743 var tags = {}; 33744 for (var i = 0; i < numDataMaps; i++) { 33745 var tag = p.parseTag(); 33746 var dataOffset = p.parseULong(); 33747 var dataLength = p.parseULong(); 33748 var text = decode.UTF8(data, start + dataOffset, dataLength); 33749 33750 tags[tag] = text; 33751 } 33752 return tags; 33753 } 33754 33755 function makeMetaTable(tags) { 33756 var numTags = Object.keys(tags).length; 33757 var stringPool = ''; 33758 var stringPoolOffset = 16 + numTags * 12; 33759 33760 var result = new table.Table('meta', [ 33761 { name: 'version', type: 'ULONG', value: 1 }, 33762 { name: 'flags', type: 'ULONG', value: 0 }, 33763 { name: 'offset', type: 'ULONG', value: stringPoolOffset }, 33764 { name: 'numTags', type: 'ULONG', value: numTags } 33765 ]); 33766 33767 for (var tag in tags) { 33768 var pos = stringPool.length; 33769 stringPool += tags[tag]; 33770 33771 result.fields.push({ name: 'tag ' + tag, type: 'TAG', value: tag }); 33772 result.fields.push({ 33773 name: 'offset ' + tag, 33774 type: 'ULONG', 33775 value: stringPoolOffset + pos 33776 }); 33777 result.fields.push({ 33778 name: 'length ' + tag, 33779 type: 'ULONG', 33780 value: tags[tag].length 33781 }); 33782 } 33783 33784 result.fields.push({ 33785 name: 'stringPool', 33786 type: 'CHARARRAY', 33787 value: stringPool 33788 }); 33789 33790 return result; 33791 } 33792 33793 var meta = { parse: parseMetaTable, make: makeMetaTable }; 33794 33795 // The `sfnt` wrapper provides organization for the tables in the font. 33796 33797 function log2(v) { 33798 return (Math.log(v) / Math.log(2)) | 0; 33799 } 33800 33801 function computeCheckSum(bytes) { 33802 while (bytes.length % 4 !== 0) { 33803 bytes.push(0); 33804 } 33805 33806 var sum = 0; 33807 for (var i = 0; i < bytes.length; i += 4) { 33808 sum += 33809 (bytes[i] << 24) + 33810 (bytes[i + 1] << 16) + 33811 (bytes[i + 2] << 8) + 33812 bytes[i + 3]; 33813 } 33814 33815 sum %= Math.pow(2, 32); 33816 return sum; 33817 } 33818 33819 function makeTableRecord(tag, checkSum, offset, length) { 33820 return new table.Record('Table Record', [ 33821 { name: 'tag', type: 'TAG', value: tag !== undefined ? tag : '' }, 33822 { 33823 name: 'checkSum', 33824 type: 'ULONG', 33825 value: checkSum !== undefined ? checkSum : 0 33826 }, 33827 { 33828 name: 'offset', 33829 type: 'ULONG', 33830 value: offset !== undefined ? offset : 0 33831 }, 33832 { 33833 name: 'length', 33834 type: 'ULONG', 33835 value: length !== undefined ? length : 0 33836 } 33837 ]); 33838 } 33839 33840 function makeSfntTable(tables) { 33841 var sfnt = new table.Table('sfnt', [ 33842 { name: 'version', type: 'TAG', value: 'OTTO' }, 33843 { name: 'numTables', type: 'USHORT', value: 0 },
33844 { name: 'searchRange', type: 'USHORT', value: 0 }, 33845 { name: 'entrySelector', type: 'USHORT', value: 0 }, 33846 { name: 'rangeShift', type: 'USHORT', value: 0 } 33847 ]); 33848 sfnt.tables = tables; 33849 sfnt.numTables = tables.length; 33850 var highestPowerOf2 = Math.pow(2, log2(sfnt.numTables)); 33851 sfnt.searchRange = 16 * highestPowerOf2; 33852 sfnt.entrySelector = log2(highestPowerOf2); 33853 sfnt.rangeShift = sfnt.numTables * 16 - sfnt.searchRange; 33854 33855 var recordFields = []; 33856 var tableFields = []; 33857 33858 var offset = sfnt.sizeOf() + makeTableRecord().sizeOf() * sfnt.numTables; 33859 while (offset % 4 !== 0) { 33860 offset += 1; 33861 tableFields.push({ name: 'padding', type: 'BYTE', value: 0 }); 33862 } 33863 33864 for (var i = 0; i < tables.length; i += 1) { 33865 var t = tables[i]; 33866 check.argument( 33867 t.tableName.length === 4, 33868 'Table name' + t.tableName + ' is invalid.' 33869 ); 33870 var tableLength = t.sizeOf(); 33871 var tableRecord = makeTableRecord( 33872 t.tableName, 33873 computeCheckSum(t.encode()), 33874 offset, 33875 tableLength 33876 ); 33877 recordFields.push({ 33878 name: tableRecord.tag + ' Table Record', 33879 type: 'RECORD', 33880 value: tableRecord 33881 }); 33882 tableFields.push({ 33883 name: t.tableName + ' table', 33884 type: 'RECORD', 33885 value: t 33886 }); 33887 offset += tableLength; 33888 check.argument( 33889 !isNaN(offset), 33890 'Something went wrong calculating the offset.' 33891 ); 33892 while (offset % 4 !== 0) { 33893 offset += 1; 33894 tableFields.push({ name: 'padding', type: 'BYTE', value: 0 }); 33895 } 33896 } 33897 33898 // Table records need to be sorted alphabetically. 33899 recordFields.sort(function(r1, r2) { 33900 if (r1.value.tag > r2.value.tag) { 33901 return 1; 33902 } else { 33903 return -1; 33904 } 33905 }); 33906 33907 sfnt.fields = sfnt.fields.concat(recordFields); 33908 sfnt.fields = sfnt.fields.concat(tableFields); 33909 return sfnt; 33910 } 33911 33912 // Get the metrics for a character. If the string has more than one character 33913 // this function returns metrics for the first available character. 33914 // You can provide optional fallback metrics if no characters are available. 33915 function metricsForChar(font, chars, notFoundMetrics) { 33916 for (var i = 0; i < chars.length; i += 1) { 33917 var glyphIndex = font.charToGlyphIndex(chars[i]); 33918 if (glyphIndex > 0) { 33919 var glyph = font.glyphs.get(glyphIndex); 33920 return glyph.getMetrics(); 33921 } 33922 } 33923 33924 return notFoundMetrics; 33925 } 33926 33927 function average(vs) { 33928 var sum = 0; 33929 for (var i = 0; i < vs.length; i += 1) { 33930 sum += vs[i]; 33931 } 33932 33933 return sum / vs.length; 33934 } 33935 33936 // Convert the font object to a SFNT data structure. 33937 // This structure contains all the necessary tables and metadata to create a binary OTF file. 33938 function fontToSfntTable(font) { 33939 var xMins = []; 33940 var yMins = []; 33941 var xMaxs = []; 33942 var yMaxs = []; 33943 var advanceWidths = []; 33944 var leftSideBearings = []; 33945 var rightSideBearings = []; 33946 var firstCharIndex; 33947 var lastCharIndex = 0; 33948 var ulUnicodeRange1 = 0; 33949 var ulUnicodeRange2 = 0; 33950 var ulUnicodeRange3 = 0; 33951 var ulUnicodeRange4 = 0; 33952 33953 for (var i = 0; i < font.glyphs.length; i += 1) { 33954 var glyph = font.glyphs.get(i); 33955 var unicode = glyph.unicode | 0; 33956 33957 if (isNaN(glyph.advanceWidth)) { 33958 throw new Error( 33959 'Glyph ' + glyph.name + ' (' + i + '): advanceWidth is not a number.' 33960 ); 33961 } 33962 33963 if (firstCharIndex > unicode || firstCharIndex === undefined) { 33964 // ignore .notdef char 33965 if (unicode > 0) { 33966 firstCharIndex = unicode; 33967 } 33968 } 33969 33970 if (lastCharIndex < unicode) { 33971 lastCharIndex = unicode; 33972 } 33973 33974 var position = os2.getUnicodeRange(unicode); 33975 if (position < 32) { 33976 ulUnicodeRange1 |= 1 << position; 33977 } else if (position < 64) { 33978 ulUnicodeRange2 |= 1 << (position - 32); 33979 } else if (position < 96) { 33980 ulUnicodeRange3 |= 1 << (position - 64); 33981 } else if (position < 123) { 33982 ulUnicodeRange4 |= 1 << (position - 96); 33983 } else { 33984 throw new Error( 33985 'Unicode ranges bits > 123 are reserved for internal usage' 33986 ); 33987 } 33988 // Skip non-important characters. 33989 if (glyph.name === '.notdef') { 33990 continue; 33991 } 33992 var metrics = glyph.getMetrics(); 33993 xMins.push(metrics.xMin); 33994 yMins.push(metrics.yMin); 33995 xMaxs.push(metrics.xMax);
33996 yMaxs.push(metrics.yMax); 33997 leftSideBearings.push(metrics.leftSideBearing); 33998 rightSideBearings.push(metrics.rightSideBearing); 33999 advanceWidths.push(glyph.advanceWidth); 34000 } 34001 34002 var globals = { 34003 xMin: Math.min.apply(null, xMins), 34004 yMin: Math.min.apply(null, yMins), 34005 xMax: Math.max.apply(null, xMaxs), 34006 yMax: Math.max.apply(null, yMaxs), 34007 advanceWidthMax: Math.max.apply(null, advanceWidths), 34008 advanceWidthAvg: average(advanceWidths), 34009 minLeftSideBearing: Math.min.apply(null, leftSideBearings), 34010 maxLeftSideBearing: Math.max.apply(null, leftSideBearings), 34011 minRightSideBearing: Math.min.apply(null, rightSideBearings) 34012 }; 34013 globals.ascender = font.ascender; 34014 globals.descender = font.descender; 34015 34016 var headTable = head.make({ 34017 flags: 3, // 00000011 (baseline for font at y=0; left sidebearing point at x=0) 34018 unitsPerEm: font.unitsPerEm, 34019 xMin: globals.xMin, 34020 yMin: globals.yMin, 34021 xMax: globals.xMax, 34022 yMax: globals.yMax, 34023 lowestRecPPEM: 3, 34024 createdTimestamp: font.createdTimestamp 34025 }); 34026 34027 var hheaTable = hhea.make({ 34028 ascender: globals.ascender, 34029 descender: globals.descender, 34030 advanceWidthMax: globals.advanceWidthMax, 34031 minLeftSideBearing: globals.minLeftSideBearing, 34032 minRightSideBearing: globals.minRightSideBearing, 34033 xMaxExtent: globals.maxLeftSideBearing + (globals.xMax - globals.xMin), 34034 numberOfHMetrics: font.glyphs.length 34035 }); 34036 34037 var maxpTable = maxp.make(font.glyphs.length); 34038 34039 var os2Table = os2.make({ 34040 xAvgCharWidth: Math.round(globals.advanceWidthAvg), 34041 usWeightClass: font.tables.os2.usWeightClass, 34042 usWidthClass: font.tables.os2.usWidthClass, 34043 usFirstCharIndex: firstCharIndex, 34044 usLastCharIndex: lastCharIndex, 34045 ulUnicodeRange1: ulUnicodeRange1, 34046 ulUnicodeRange2: ulUnicodeRange2, 34047 ulUnicodeRange3: ulUnicodeRange3, 34048 ulUnicodeRange4: ulUnicodeRange4, 34049 fsSelection: font.tables.os2.fsSelection, // REGULAR 34050 // See http://typophile.com/node/13081 for more info on vertical metrics. 34051 // We get metrics for typical characters (such as "x" for xHeight). 34052 // We provide some fallback characters if characters are unavailable: their 34053 // ordering was chosen experimentally. 34054 sTypoAscender: globals.ascender, 34055 sTypoDescender: globals.descender, 34056 sTypoLineGap: 0, 34057 usWinAscent: globals.yMax, 34058 usWinDescent: Math.abs(globals.yMin), 34059 ulCodePageRange1: 1, // FIXME: hard-code Latin 1 support for now 34060 sxHeight: metricsForChar(font, 'xyvw', { 34061 yMax: Math.round(globals.ascender / 2) 34062 }).yMax, 34063 sCapHeight: metricsForChar(font, 'HIKLEFJMNTZBDPRAGOQSUVWXY', globals) 34064 .yMax, 34065 usDefaultChar: font.hasChar(' ') ? 32 : 0, // Use space as the default character, if available. 34066 usBreakChar: font.hasChar(' ') ? 32 : 0 // Use space as the break character, if available. 34067 }); 34068 34069 var hmtxTable = hmtx.make(font.glyphs); 34070 var cmapTable = cmap.make(font.glyphs); 34071 34072 var englishFamilyName = font.getEnglishName('fontFamily'); 34073 var englishStyleName = font.getEnglishName('fontSubfamily'); 34074 var englishFullName = englishFamilyName + ' ' + englishStyleName; 34075 var postScriptName = font.getEnglishName('postScriptName'); 34076 if (!postScriptName) { 34077 postScriptName = 34078 englishFamilyName.replace(/\s/g, '') + '-' + englishStyleName; 34079 } 34080 34081 var names = {}; 34082 for (var n in font.names) { 34083 names[n] = font.names[n]; 34084 } 34085 34086 if (!names.uniqueID) { 34087 names.uniqueID = { 34088 en: font.getEnglishName('manufacturer') + ':' + englishFullName 34089 }; 34090 } 34091 34092 if (!names.postScriptName) { 34093 names.postScriptName = { en: postScriptName }; 34094 } 34095 34096 if (!names.preferredFamily) { 34097 names.preferredFamily = font.names.fontFamily; 34098 } 34099 34100 if (!names.preferredSubfamily) { 34101 names.preferredSubfamily = font.names.fontSubfam
34101ily; 34102 } 34103 34104 var languageTags = []; 34105 var nameTable = _name.make(names, languageTags); 34106 var ltagTable = 34107 languageTags.length > 0 ? ltag.make(languageTags) : undefined; 34108 34109 var postTable = post.make(); 34110 var cffTable = cff.make(font.glyphs, { 34111 version: font.getEnglishName('version'), 34112 fullName: englishFullName, 34113 familyName: englishFamilyName, 34114 weightName: englishStyleName, 34115 postScriptName: postScriptName, 34116 unitsPerEm: font.unitsPerEm, 34117 fontBBox: [0, globals.yMin, globals.ascender, globals.advanceWidthMax] 34118 }); 34119 34120 var metaTable = 34121 font.metas && Object.keys(font.metas).length > 0 34122 ? meta.make(font.metas) 34123 : undefined; 34124 34125 // The order does not matter because makeSfntTable() will sort them. 34126 var tables = [ 34127 headTable, 34128 hheaTable, 34129 maxpTable, 34130 os2Table, 34131 nameTable, 34132 cmapTable, 34133 postTable, 34134 cffTable, 34135 hmtxTable 34136 ]; 34137 if (ltagTable) { 34138 tables.push(ltagTable); 34139 } 34140 // Optional tables 34141 if (font.tables.gsub) { 34142 tables.push(gsub.make(font.tables.gsub)); 34143 } 34144 if (metaTable) { 34145 tables.push(metaTable); 34146 } 34147 34148 var sfntTable = makeSfntTable(tables); 34149 34150 // Compute the font's checkSum and store it in head.checkSumAdjustment. 34151 var bytes = sfntTable.encode(); 34152 var checkSum = computeCheckSum(bytes); 34153 var tableFields = sfntTable.fields; 34154 var checkSumAdjusted = false; 34155 for (var i$1 = 0; i$1 < tableFields.length; i$1 += 1) { 34156 if (tableFields[i$1].name === 'head table') { 34157 tableFields[i$1].value.checkSumAdjustment = 0xb1b0afba - checkSum; 34158 checkSumAdjusted = true; 34159 break; 34160 } 34161 } 34162 34163 if (!checkSumAdjusted) { 34164 throw new Error('Could not find head table with checkSum to adjust.'); 34165 } 34166 34167 return sfntTable; 34168 } 34169 34170 var sfnt = { 34171 make: makeSfntTable, 34172 fontToTable: fontToSfntTable, 34173 computeCheckSum: computeCheckSum 34174 }; 34175 34176 // The Layout object is the prototype of Substitution objects, and provides 34177 34178 function searchTag(arr, tag) { 34179 /* jshint bitwise: false */ 34180 var imin = 0; 34181 var imax = arr.length - 1; 34182 while (imin <= imax) { 34183 var imid = (imin + imax) >>> 1; 34184 var val = arr[imid].tag; 34185 if (val === tag) { 34186 return imid; 34187 } else if (val < tag) { 34188 imin = imid + 1; 34189 } else { 34190 imax = imid - 1; 34191 } 34192 } 34193 // Not found: return -1-insertion point 34194 return -imin - 1; 34195 } 34196 34197 function binSearch(arr, value) { 34198 /* jshint bitwise: false */ 34199 var imin = 0; 34200 var imax = arr.length - 1; 34201 while (imin <= imax) { 34202 var imid = (imin + imax) >>> 1; 34203 var val = arr[imid]; 34204 if (val === value) { 34205 return imid; 34206 } else if (val < value) { 34207 imin = imid + 1; 34208 } else { 34209 imax = imid - 1; 34210 } 34211 } 34212 // Not found: return -1-insertion point 34213 return -imin - 1; 34214 } 34215 34216 // binary search in a list of ranges (coverage, class definition)
vendor: 10,989 bytes, lines 34217-34481
34217 function searchRange(ranges, value) { 34218 // jshint bitwise: false 34219 var range; 34220 var imin = 0; 34221 var imax = ranges.length - 1; 34222 while (imin <= imax) { 34223 var imid = (imin + imax) >>> 1; 34224 range = ranges[imid]; 34225 var start = range.start; 34226 if (start === value) { 34227 return range; 34228 } else if (start < value) { 34229 imin = imid + 1; 34230 } else { 34231 imax = imid - 1; 34232 } 34233 } 34234 if (imin > 0) { 34235 range = ranges[imin - 1]; 34236 if (value > range.end) { 34237 return 0; 34238 } 34239 return range; 34240 } 34241 } 34242 34243 /** 34244 * @exports opentype.Layout 34245 * @class 34246 */ 34247 function Layout(font, tableName) { 34248 this.font = font; 34249 this.tableName = tableName; 34250 } 34251 34252 Layout.prototype = { 34253 /** 34254 * Binary search an object by "tag" property 34255 * @instance 34256 * @function searchTag 34257 * @memberof opentype.Layout 34258 * @param {Array} arr 34259 * @param {string} tag 34260 * @return {number} 34261 */ 34262 searchTag: searchTag, 34263 34264 /** 34265 * Binary search in a list of numbers 34266 * @instance 34267 * @function binSearch 34268 * @memberof opentype.Layout 34269 * @param {Array} arr 34270 * @param {number} value 34271 * @return {number} 34272 */ 34273 binSearch: binSearch, 34274 34275 /** 34276 * Get or create the Layout table (GSUB, GPOS etc). 34277 * @param {boolean} create - Whether to create a new one. 34278 * @return {Object} The GSUB or GPOS table. 34279 */ 34280 getTable: function(create) { 34281 var layout = this.font.tables[this.tableName]; 34282 if (!layout && create) { 34283 layout = this.font.tables[this.tableName] = this.createDefaultTable(); 34284 } 34285 return layout; 34286 }, 34287 34288 /** 34289 * Returns all scripts in the substitution table. 34290 * @instance 34291 * @return {Array} 34292 */ 34293 getScriptNames: function() { 34294 var layout = this.getTable(); 34295 if (!layout) { 34296 return []; 34297 } 34298 return layout.scripts.map(function(script) { 34299 return script.tag; 34300 }); 34301 }, 34302 34303 /** 34304 * Returns the best bet for a script name. 34305 * Returns 'DFLT' if it exists. 34306 * If not, returns 'latn' if it exists. 34307 * If neither exist, returns undefined. 34308 */ 34309 getDefaultScriptName: function() { 34310 var layout = this.getTable(); 34311 if (!layout) { 34312 return; 34313 } 34314 var hasLatn = false; 34315 for (var i = 0; i < layout.scripts.length; i++) { 34316 var name = layout.scripts[i].tag; 34317 if (name === 'DFLT') { 34318 return name; 34319 } 34320 if (name === 'latn') { 34321 hasLatn = true; 34322 } 34323 } 34324 if (hasLatn) { 34325 return 'latn'; 34326 } 34327 }, 34328 34329 /** 34330 * Returns all LangSysRecords in the given script. 34331 * @instance 34332 * @param {string} [script='DFLT'] 34333 * @param {boolean} create - forces the creation of this script table if it doesn't exist. 34334 * @return {Object} An object with tag and script properties. 34335 */ 34336 getScriptTable: function(script, create) { 34337 var layout = this.getTable(create); 34338 if (layout) { 34339 script = script || 'DFLT'; 34340 var scripts = layout.scripts; 34341 var pos = searchTag(layout.scripts, script); 34342 if (pos >= 0) { 34343 return scripts[pos].script; 34344 } else if (create) { 34345 var scr = { 34346 tag: script, 34347 script: { 34348 defaultLangSys: { 34349 reserved: 0, 34350 reqFeatureIndex: 0xffff, 34351 featureIndexes: [] 34352 }, 34353 langSysRecords: [] 34354 } 34355 }; 34356 scripts.splice(-1 - pos, 0, scr); 34357 return scr.script; 34358 } 34359 } 34360 }, 34361 34362 /** 34363 * Returns a language system table 34364 * @instance 34365 * @param {string} [script='DFLT'] 34366 * @param {string} [language='dlft'] 34367 * @param {boolean} create - forces the creation of this langSysTable if it doesn't exist. 34368 * @return {Object} 34369 */ 34370 getLangSysTable: function(script, language, create) { 34371 var scriptTable = this.getScriptTable(script, create); 34372 if (scriptTable) { 34373 if (!language || language === 'dflt' || language === 'DFLT') { 34374 return scriptTable.defaultLangSys; 34375 } 34376 var pos = searchTag(scriptTable.langSysRecords, language); 34377 if (pos >= 0) { 34378 return scriptTable.langSysRecords[pos].langSys; 34379 } else if (create) { 34380 var langSysRecord = { 34381 tag: language, 34382 langSys: { 34383 reserved: 0, 34384 reqFeatureIndex: 0xffff, 34385 featureIndexes: [] 34386 } 34387 }; 34388 scriptTable.langSysRecords.splice(-1 - pos, 0, langSysRecord); 34389 return langSysRecord.langSys; 34390 } 34391 } 34392 }, 34393 34394 /** 34395 * Get a specific feature table. 34396 * @instance 34397 * @param {string} [script='DFLT'] 34398 * @param {string} [language='dlft'] 34399 * @param {string} feature - One of the codes listed at https://www.microsoft.com/typography/OTSPEC/featurelist.htm 34400 * @param {boolean} create - forces the creation of the feature table if it doesn't exist. 34401 * @return {Object} 34402 */ 34403 getFeatureTable: function(script, language, feature, create) { 34404 var langSysTable = this.getLangSysTable(script, language, create); 34405 if (langSysTable) { 34406 var featureRecord; 34407 var featIndexes = langSysTable.featureIndexes; 34408 var allFeatures = this.font.tables[this.tableName].features; 34409 // The FeatureIndex array of indices is in arbitrary order, 34410 // even if allFeatures is sorted alphabetically by feature tag. 34411 for (var i = 0; i < featIndexes.length; i++) { 34412 featureRecord = allFeatures[featIndexes[i]]; 34413 if (featureRecord.tag === feature) { 34414 return featureRecord.feature; 34415 } 34416 } 34417 if (create) { 34418 var index = allFeatures.length; 34419 // Automatic ordering of features would require to shift feature indexes in the script list. 34420 check.assert( 34421 index === 0 || feature >= allFeatures[index - 1].tag, 34422 'Features must be added in alphabetical order.' 34423 ); 34424 featureRecord = { 34425 tag: feature, 34426 feature: { params: 0, lookupListIndexes: [] } 34427 }; 34428 allFeatures.push(featureRecord); 34429 featIndexes.push(index); 34430 return featureRecord.feature; 34431 } 34432 } 34433 }, 34434 34435 /** 34436 * Get the lookup tables of a given type for a script/language/feature. 34437 * @instance 34438 * @param {string} [script='DFLT'] 34439 * @param {string} [language='dlft'] 34440 * @param {string} feature - 4-letter feature code 34441 * @param {number} lookupType - 1 to 9 34442 * @param {boolean} create - forces the creation of the lookup table if it doesn't exist, with no subtables. 34443 * @return {Object[]} 34444 */ 34445 getLookupTables: function(script, language, feature, lookupType, create) { 34446 var featureTable = this.getFeatureTable( 34447 script, 34448 language, 34449 feature, 34450 create 34451 ); 34452 var tables = []; 34453 if (featureTable) { 34454 var lookupTable; 34455 var lookupListIndexes = featureTable.lookupListIndexes; 34456 var allLookups = this.font.tables[this.tableName].lookups; 34457 // lookupListIndexes are in no particular order, so use naive search. 34458 for (var i = 0; i < lookupListIndexes.length; i++) { 34459 lookupTable = allLookups[lookupListIndexes[i]]; 34460 if (lookupTable.lookupType === lookupType) { 34461 tables.push(lookupTable); 34462 } 34463 } 34464 if (tables.length === 0 && create) { 34465 lookupTable = { 34466 lookupType: lookupType, 34467 lookupFlag: 0, 34468 subtables: [], 34469 markFilteringSet: undefined 34470 }; 34471 var index = allLookups.length; 34472 allLookups.push(lookupTable); 34473 lookupListIndexes.push(index); 34474 return [lookupTable]; 34475 } 34476 } 34477 return tables; 34478 }, 34479 34480 /** 34481 * Find a glyph in a class definition table
34482 * https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#class-definition-table 34483 * @param {object} classDefTable - an OpenType Layout class definition table 34484 * @param {number} glyphIndex - the index of the glyph to find 34485 * @returns {number} -1 if not found 34486 */ 34487 getGlyphClass: function(classDefTable, glyphIndex) { 34488 switch (classDefTable.format) { 34489 case 1: 34490 if ( 34491 classDefTable.startGlyph <= glyphIndex && 34492 glyphIndex < classDefTable.startGlyph + classDefTable.classes.length 34493 ) { 34494 return classDefTable.classes[glyphIndex - classDefTable.startGlyph]; 34495 } 34496 return 0; 34497 case 2: 34498 var range = searchRange(classDefTable.ranges, glyphIndex); 34499 return range ? range.classId : 0; 34500 } 34501 }, 34502 34503 /** 34504 * Find a glyph in a coverage table 34505 * https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#coverage-table 34506 * @param {object} coverageTable - an OpenType Layout coverage table 34507 * @param {number} glyphIndex - the index of the glyph to find 34508 * @returns {number} -1 if not found 34509 */ 34510 getCoverageIndex: function(coverageTable, glyphIndex) { 34511 switch (coverageTable.format) { 34512 case 1: 34513 var index = binSearch(coverageTable.glyphs, glyphIndex); 34514 return index >= 0 ? index : -1; 34515 case 2: 34516 var range = searchRange(coverageTable.ranges, glyphIndex); 34517 return range ? range.index + glyphIndex - range.start : -1; 34518 } 34519 }, 34520 34521 /** 34522 * Returns the list of glyph indexes of a coverage table. 34523 * Format 1: the list is stored raw 34524 * Format 2: compact list as range records. 34525 * @instance 34526 * @param {Object} coverageTable 34527 * @return {Array} 34528 */ 34529 expandCoverage: function(coverageTable) { 34530 if (coverageTable.format === 1) { 34531 return coverageTable.glyphs; 34532 } else { 34533 var glyphs = []; 34534 var ranges = coverageTable.ranges; 34535 for (var i = 0; i < ranges.length; i++) { 34536 var range = ranges[i]; 34537 var start = range.start; 34538 var end = range.end; 34539 for (var j = start; j <= end; j++) { 34540 glyphs.push(j); 34541 } 34542 } 34543 return glyphs; 34544 } 34545 } 34546 }; 34547 34548 // The Position object provides utility methods to manipulate 34549 34550 /** 34551 * @exports opentype.Position 34552 * @class 34553 * @extends opentype.Layout 34554 * @param {opentype.Font} 34555 * @constructor 34556 */ 34557 function Position(font) { 34558 Layout.call(this, font, 'gpos'); 34559 } 34560 34561 Position.prototype = Layout.prototype; 34562 34563 /** 34564 * Init some data for faster and easier access later. 34565 */ 34566 Position.prototype.init = function() { 34567 var script = this.getDefaultScriptName(); 34568 this.defaultKerningTables = this.getKerningTables(script); 34569 }; 34570 34571 /** 34572 * Find a glyph pair in a list of lookup tables of type 2 and retrieve the xAdvance kerning value. 34573 * 34574 * @param {integer} leftIndex - left glyph index 34575 * @param {integer} rightIndex - right glyph index 34576 * @returns {integer} 34577 */ 34578 Position.prototype.getKerningValue = function( 34579 kerningLookups, 34580 leftIndex, 34581 rightIndex 34582 ) { 34583 var this$1 = this; 34584 34585 for (var i = 0; i < kerningLookups.length; i++) { 34586 var subtables = kerningLookups[i].subtables; 34587 for (var j = 0; j < subtables.length; j++) { 34588 var subtable = subtables[j]; 34589 var covIndex = this$1.getCoverageIndex(subtable.coverage, leftIndex); 34590 if (covIndex < 0) { 34591 continue; 34592 } 34593 switch (subtable.posFormat) { 34594 case 1: 34595 // Search Pair Adjustment Positioning Format 1 34596 var pairSet = subtable.pairSets[covIndex]; 34597 for (var k = 0; k < pairSet.length; k++) { 34598 var pair = pairSet[k]; 34599 if (pair.secondGlyph === rightIndex) { 34600 return (pair.value1 && pair.value1.xAdvance) || 0; 34601 } 34602 } 34603 break; // left glyph found, not right glyph - try next subtable 34604 case 2: 34605 // Search Pair Adjustment Positioning Format 2 34606 var class1 = this$1.getGlyphClass(subtable.classDef1, leftIndex); 34607 var class2 = this$1.getGlyphClass(subtable.classDef2, rightIndex); 34608 var pair$1 = subtable.classRecords[class1][class2]; 34609 return (pair$1.value1 && pair$1.value1.xAdvance) || 0; 34610 } 34611 } 34612 } 34613 return 0; 34614 }; 34615 34616 /** 34617 * List all kerning lookup tables. 34618 * 34619 * @param {string} [script='DFLT'] - use font.position.getDefaultScriptName() for a better default value 34620 * @param {string} [language='dflt'] 34621 * @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) 34622 */ 34623 Position.prototype.getKerningTables = function(script, language) { 34624 if (this.font.tables.gpos) { 34625 return this.getLookupTables(script, language, 'kern', 2); 34626 } 34627 }; 34628 34629 // The Substitution object provides utility methods to manipulate 34630 34631 /** 34632 * @exports opentype.Substitution 34633 * @class
vendor: 117,208 bytes, lines 34634-38203
34634 * @extends opentype.Layout 34635 * @param {opentype.Font} 34636 * @constructor 34637 */ 34638 function Substitution(font) { 34639 Layout.call(this, font, 'gsub'); 34640 } 34641 34642 // Check if 2 arrays of primitives are equal. 34643 function arraysEqual(ar1, ar2) { 34644 var n = ar1.length; 34645 if (n !== ar2.length) { 34646 return false; 34647 } 34648 for (var i = 0; i < n; i++) { 34649 if (ar1[i] !== ar2[i]) { 34650 return false; 34651 } 34652 } 34653 return true; 34654 } 34655 34656 // Find the first subtable of a lookup table in a particular format. 34657 function getSubstFormat(lookupTable, format, defaultSubtable) { 34658 var subtables = lookupTable.subtables; 34659 for (var i = 0; i < subtables.length; i++) { 34660 var subtable = subtables[i]; 34661 if (subtable.substFormat === format) { 34662 return subtable; 34663 } 34664 } 34665 if (defaultSubtable) { 34666 subtables.push(defaultSubtable); 34667 return defaultSubtable; 34668 } 34669 return undefined; 34670 } 34671 34672 Substitution.prototype = Layout.prototype; 34673 34674 /** 34675 * Create a default GSUB table. 34676 * @return {Object} gsub - The GSUB table. 34677 */ 34678 Substitution.prototype.createDefaultTable = function() { 34679 // Generate a default empty GSUB table with just a DFLT script and dflt lang sys. 34680 return { 34681 version: 1, 34682 scripts: [ 34683 { 34684 tag: 'DFLT', 34685 script: { 34686 defaultLangSys: { 34687 reserved: 0, 34688 reqFeatureIndex: 0xffff, 34689 featureIndexes: [] 34690 }, 34691 langSysRecords: [] 34692 } 34693 } 34694 ], 34695 features: [], 34696 lookups: [] 34697 }; 34698 }; 34699 34700 /** 34701 * List all single substitutions (lookup type 1) for a given script, language, and feature. 34702 * @param {string} [script='DFLT'] 34703 * @param {string} [language='dflt'] 34704 * @param {string} feature - 4-character feature name ('aalt', 'salt', 'ss01'...) 34705 * @return {Array} substitutions - The list of substitutions. 34706 */ 34707 Substitution.prototype.getSingle = function(feature, script, language) { 34708 var this$1 = this; 34709 34710 var substitutions = []; 34711 var lookupTables = this.getLookupTables(script, language, feature, 1); 34712 for (var idx = 0; idx < lookupTables.length; idx++) { 34713 var subtables = lookupTables[idx].subtables; 34714 for (var i = 0; i < subtables.length; i++) { 34715 var subtable = subtables[i]; 34716 var glyphs = this$1.expandCoverage(subtable.coverage); 34717 var j = void 0; 34718 if (subtable.substFormat === 1) { 34719 var delta = subtable.deltaGlyphId; 34720 for (j = 0; j < glyphs.length; j++) { 34721 var glyph = glyphs[j]; 34722 substitutions.push({ sub: glyph, by: glyph + delta }); 34723 } 34724 } else { 34725 var substitute = subtable.substitute; 34726 for (j = 0; j < glyphs.length; j++) { 34727 substitutions.push({ sub: glyphs[j], by: substitute[j] }); 34728 } 34729 } 34730 } 34731 } 34732 return substitutions; 34733 }; 34734 34735 /** 34736 * List all alternates (lookup type 3) for a given script, language, and feature. 34737 * @param {string} [script='DFLT'] 34738 * @param {string} [language='dflt'] 34739 * @param {string} feature - 4-character feature name ('aalt', 'salt'...) 34740 * @return {Array} alternates - The list of alternates 34741 */ 34742 Substitution.prototype.getAlternates = function(feature, script, language) { 34743 var this$1 = this; 34744 34745 var alternates = []; 34746 var lookupTables = this.getLookupTables(script, language, feature, 3); 34747 for (var idx = 0; idx < lookupTables.length; idx++) { 34748 var subtables = lookupTables[idx].subtables; 34749 for (var i = 0; i < subtables.length; i++) { 34750 var subtable = subtables[i]; 34751 var glyphs = this$1.expandCoverage(subtable.coverage); 34752 var alternateSets = subtable.alternateSets; 34753 for (var j = 0; j < glyphs.length; j++) { 34754 alternates.push({ sub: glyphs[j], by: alternateSets[j] }); 34755 } 34756 } 34757 } 34758 return alternates; 34759 }; 34760 34761 /** 34762 * List all ligatures (lookup type 4) for a given script, language, and feature. 34763 * The result is an array of ligature objects like { sub: [ids], by: id } 34764 * @param {string} feature - 4-letter feature name ('liga', 'rlig', 'dlig'...) 34765 * @param {string} [script='DFLT'] 34766 * @param {string} [language='dflt'] 34767 * @return {Array} ligatures - The list of ligatures. 34768 */ 34769 Substitution.prototype.getLigatures = function(feature, script, language) { 34770 var this$1 = this; 34771 34772 var ligatures = []; 34773 var lookupTables = this.getLookupTables(script, language, feature, 4); 34774 for (var idx = 0; idx < lookupTables.length; idx++) { 34775 var subtables = lookupTables[idx].subtables; 34776 for (var i = 0; i < subtables.length; i++) { 34777 var subtable = subtables[i]; 34778 var glyphs = this$1.expandCoverage(subtable.coverage); 34779 var ligatureSets = subtable.ligatureSets; 34780 for (var j = 0; j < glyphs.length; j++) { 34781 var startGlyph = glyphs[j]; 34782 var ligSet = ligatureSets[j]; 34783 for (var k = 0; k < ligSet.length; k++) { 34784 var lig = ligSet[k]; 34785 ligatures.push({ 34786 sub: [startGlyph].concat(lig.components), 34787 by: lig.ligGlyph 34788 }); 34789 } 34790 } 34791 } 34792 } 34793 return ligatures; 34794 }; 34795 34796 /** 34797 * Add or modify a single substitution (lookup type 1) 34798 * Format 2, more flexible, is always used. 34799 * @param {string} feature - 4-letter feature name ('liga', 'rlig', 'dlig'...) 34800 * @param {Object} substitution - { sub: id, delta: number } for format 1 or { sub: id, by: id } for format 2. 34801 * @param {string} [script='DFLT'] 34802 * @param {string} [language='dflt'] 34803 */ 34804 Substitution.prototype.addSingle = function( 34805 feature, 34806 substitution, 34807 script, 34808 language 34809 ) { 34810 var lookupTable = this.getLookupTables( 34811 script, 34812 language, 34813 feature, 34814 1, 34815 true 34816 )[0]; 34817 var subtable = getSubstFormat(lookupTable, 2, { 34818 // lookup type 1 subtable, format 2, coverage format 1 34819 substFormat: 2, 34820 coverage: { format: 1, glyphs: [] }, 34821 substitute: [] 34822 }); 34823 check.assert( 34824 subtable.coverage.format === 1, 34825 'Ligature: unable to modify coverage table format ' + 34826 subtable.coverage.format 34827 ); 34828 var coverageGlyph = substitution.sub; 34829 var pos = this.binSearch(subtable.coverage.glyphs, coverageGlyph); 34830 if (pos < 0) { 34831 pos = -1 - pos; 34832 subtable.coverage.glyphs.splice(pos, 0, coverageGlyph); 34833 subtable.substitute.splice(pos, 0, 0); 34834 } 34835 subtable.substitute[pos] = substitution.by; 34836 }; 34837 34838 /** 34839 * Add or modify an alternate substitution (lookup type 1) 34840 * @param {string} feature - 4-letter feature name ('liga', 'rlig', 'dlig'...) 34841 * @param {Object} substitution - { sub: id, by: [ids] } 34842 * @param {string} [script='DFLT'] 34843 * @param {string} [language='dflt'] 34844 */ 34845 Substitution.prototype.addAlternate = function( 34846 feature, 34847 substitution, 34848 script, 34849 language 34850 ) { 34851 var lookupTable = this.getLookupTables( 34852 script, 34853 language, 34854 feature, 34855 3, 34856 true 34857 )[0]; 34858 var subtable = getSubstFormat(lookupTable, 1, { 34859 // lookup type 3 subtable, format 1, coverage format 1 34860 substFormat: 1, 34861 coverage: { format: 1, glyphs: [] }, 34862 alternateSets: [] 34863 }); 34864 check.assert( 34865 subtable.coverage.format === 1, 34866 'Ligature: unable to modify coverage table format ' + 34867 subtable.coverage.format 34868 ); 34869 var coverageGlyph = substitution.sub; 34870 var pos = this.binSearch(subtable.coverage.glyphs, coverageGlyph); 34871 if (pos < 0) { 34872 pos = -1 - pos; 34873 subtable.coverage.glyphs.splice(pos, 0, coverageGlyph); 34874 subtable.alternateSets.splice(pos, 0, 0); 34875 } 34876 subtable.alternateSets[pos] = substitution.by; 34877 }; 34878 34879 /** 34880 * Add a ligature (lookup type 4) 34881 * Ligatures with more components must be stored ahead of those with fewer components in order to be found 34882 * @param {string} feature - 4-letter feature name ('liga', 'rlig', 'dlig'...) 34883 * @param {Object} ligature - { sub: [ids], by: id } 34884 * @param {string} [script='DFLT'] 34885 * @param {string} [language='dflt'] 34886 */ 34887 Substitution.prototype.addLigature = function( 34888 feature, 34889 ligature, 34890 script, 34891 language 34892 ) { 34893 var lookupTable = this.getLookupTables( 34894 script, 34895 language, 34896 feature, 34897 4, 34898 true 34899 )[0]; 34900 var subtable = lookupTable.subtables[0]; 34901 if (!subtable) { 34902 subtable = { 34903 // lookup type 4 subtable, format 1, coverage format 1 34904 substFormat: 1, 34905 coverage: { format: 1, glyphs: [] }, 34906 ligatureSets: [] 34907 }; 34908 lookupTable.subtables[0] = subtable; 34909 } 34910 check.assert( 34911 subtable.coverage.format === 1, 34912 'Ligature: unable to modify coverage table format ' + 34913 subtable.coverage.format 34914 ); 34915 var coverageGlyph = ligature.sub[0]; 34916 var ligComponents = ligature.sub.slice(1); 34917 var ligatureTable = { 34918 ligGlyph: ligature.by, 34919 components: ligComponents 34920 }; 34921 var pos = this.binSearch(subtable.coverage.glyphs, coverageGlyph); 34922 if (pos >= 0) { 34923 // ligatureSet already exists 34924 var ligatureSet = subtable.ligatureSets[pos]; 34925 for (var i = 0; i < ligatureSet.length; i++) { 34926 // If ligature already exists, return. 34927 if (arraysEqual(ligatureSet[i].components, ligComponents)) { 34928 return; 34929 } 34930 } 34931 // ligature does not exist: add it. 34932 ligatureSet.push(ligatureTable); 34933 } else { 34934 // Create a new ligatureSet and add coverage for the first glyph. 34935 pos = -1 - pos; 34936 subtable.coverage.glyphs.splice(pos, 0, coverageGlyph); 34937 subtable.ligatureSets.splice(pos, 0, [ligatureTable]); 34938 } 34939 }; 34940 34941 /** 34942 * List all feature data for a given script and language. 34943 * @param {string} feature - 4-letter feature name 34944 * @param {string} [script='DFLT'] 34945 * @param {string} [language='dflt'] 34946 * @return {Array} substitutions - The list of substitutions. 34947 */ 34948 Substitution.prototype.getFeature = function(feature, script, language) { 34949 if (/ss\d\d/.test(feature)) { 34950 // ss01 - ss20 34951 return this.getSingle(feature, script, language); 34952 } 34953 switch (feature) { 34954 case 'aalt': 34955 case 'salt': 34956 return this.getSingle(feature, script, language).concat( 34957 this.getAlternates(feature, script, language) 34958 ); 34959 case 'dlig': 34960 case 'liga': 34961 case 'rlig': 34962 return this.getLigatures(feature, script, language); 34963 } 34964 return undefined; 34965 }; 34966 34967 /** 34968 * Add a substitution to a feature for a given script and language. 34969 * @param {string} feature - 4-letter feature name 34970 * @param {Object} sub - the substitution to add (an object like { sub: id or [ids], by: id or [ids] }) 34971 * @param {string} [script='DFLT'] 34972 * @param {string} [language='dflt'] 34973 */ 34974 Substitution.prototype.add = function(feature, sub, script, language) { 34975 if (/ss\d\d/.test(feature)) { 34976 // ss01 - ss20 34977 return this.addSingle(feature, sub, script, language); 34978 } 34979 switch (feature) { 34980 case 'aalt': 34981 case 'salt': 34982 if (typeof sub.by === 'number') { 34983 return this.addSingle(feature, sub, script, language); 34984 } 34985 return this.addAlternate(feature, sub, script, language); 34986 case 'dlig': 34987 case 'liga': 34988 case 'rlig': 34989 return this.addLigature(feature, sub, script, language); 34990 } 34991 return undefined; 34992 }; 34993 34994 function isBrowser() { 34995 return typeof window !== 'undefined'; 34996 } 34997 34998 function nodeBufferToArrayBuffer(buffer) { 34999 var ab = new ArrayBuffer(buffer.length); 35000 var view = new Uint8Array(ab); 35001 for (var i = 0; i < buffer.length; ++i) { 35002 view[i] = buffer[i]; 35003 } 35004 35005 return ab; 35006 } 35007 35008 function arrayBufferToNodeBuffer(ab) { 35009 var buffer = new Buffer(ab.byteLength); 35010 var view = new Uint8Array(ab); 35011 for (var i = 0; i < buffer.length; ++i) { 35012 buffer[i] = view[i]; 35013 } 35014 35015 return buffer; 35016 } 35017 35018 function checkArgument(expression, message) { 35019 if (!expression) { 35020 throw message; 35021 } 35022 } 35023 35024 // The `glyf` table describes the glyphs in TrueType outline format. 35025 35026 // Parse the coordinate data for a glyph. 35027 function parseGlyphCoordinate( 35028 p, 35029 flag, 35030 previousValue, 35031 shortVectorBitMask, 35032 sameBitMask 35033 ) { 35034 var v; 35035 if ((flag & shortVectorBitMask) > 0) { 35036 // The coordinate is 1 byte long. 35037 v = p.parseByte(); 35038 // The `same` bit is re-used for short values to signify the sign of the value. 35039 if ((flag & sameBitMask) === 0) { 35040 v = -v; 35041 } 35042 35043 v = previousValue + v; 35044 } else { 35045 // The coordinate is 2 bytes long. 35046 // If the `same` bit is set, the coordinate is the same as the previous coordinate. 35047 if ((flag & sameBitMask) > 0) { 35048 v = previousValue; 35049 } else { 35050 // Parse the coordinate as a signed 16-bit delta value. 35051 v = previousValue + p.parseShort(); 35052 } 35053 } 35054 35055 return v; 35056 } 35057 35058 // Parse a TrueType glyph. 35059 function parseGlyph(glyph, data, start) { 35060 var p = new parse.Parser(data, start); 35061 glyph.numberOfContours = p.parseShort(); 35062 glyph._xMin = p.parseShort(); 35063 glyph._yMin = p.parseShort(); 35064 glyph._xMax = p.parseShort(); 35065 glyph._yMax = p.parseShort(); 35066 var flags; 35067 var flag; 35068 35069 if (glyph.numberOfContours > 0) { 35070 // This glyph is not a composite. 35071 var endPointIndices = (glyph.endPointIndices = []); 35072 for (var i = 0; i < glyph.numberOfContours; i += 1) { 35073 endPointIndices.push(p.parseUShort()); 35074 } 35075 35076 glyph.instructionLength = p.parseUShort(); 35077 glyph.instructions = []; 35078 for (var i$1 = 0; i$1 < glyph.instructionLength; i$1 += 1) { 35079 glyph.instructions.push(p.parseByte()); 35080 } 35081 35082 var numberOfCoordinates = endPointIndices[endPointIndices.length - 1] + 1; 35083 flags = []; 35084 for (var i$2 = 0; i$2 < numberOfCoordinates; i$2 += 1) { 35085 flag = p.parseByte(); 35086 flags.push(flag); 35087 // If bit 3 is set, we repeat this flag n times, where n is the next byte. 35088 if ((flag & 8) > 0) { 35089 var repeatCount = p.parseByte(); 35090 for (var j = 0; j < repeatCount; j += 1) { 35091 flags.push(flag); 35092 i$2 += 1; 35093 } 35094 } 35095 } 35096 35097 check.argument(flags.length === numberOfCoordinates, 'Bad flags.'); 35098 35099 if (endPointIndices.length > 0) { 35100 var points = []; 35101 var point; 35102 // X/Y coordinates are relative to the previous point, except for the first point which is relative to 0,0. 35103 if (numberOfCoordinates > 0) { 35104 for (var i$3 = 0; i$3 < numberOfCoordinates; i$3 += 1) { 35105 flag = flags[i$3]; 35106 point = {}; 35107 point.onCurve = !!(flag & 1); 35108 point.lastPointOfContour = endPointIndices.indexOf(i$3) >= 0; 35109 points.push(point); 35110 } 35111 35112 var px = 0; 35113 for (var i$4 = 0; i$4 < numberOfCoordinates; i$4 += 1) { 35114 flag = flags[i$4]; 35115 point = points[i$4]; 35116 point.x = parseGlyphCoordinate(p, flag, px, 2, 16); 35117 px = point.x; 35118 } 35119 35120 var py = 0; 35121 for (var i$5 = 0; i$5 < numberOfCoordinates; i$5 += 1) { 35122 flag = flags[i$5]; 35123 point = points[i$5]; 35124 point.y = parseGlyphCoordinate(p, flag, py, 4, 32); 35125 py = point.y; 35126 } 35127 } 35128 35129 glyph.points = points; 35130 } else { 35131 glyph.points = []; 35132 } 35133 } else if (glyph.numberOfContours === 0) { 35134 glyph.points = []; 35135 } else { 35136 glyph.isComposite = true; 35137 glyph.points = []; 35138 glyph.components = []; 35139 var moreComponents = true; 35140 while (moreComponents) { 35141 flags = p.parseUShort(); 35142 var component = { 35143 glyphIndex: p.parseUShort(), 35144 xScale: 1, 35145 scale01: 0, 35146 scale10: 0, 35147 yScale: 1, 35148 dx: 0, 35149 dy: 0 35150 }; 35151 if ((flags & 1) > 0) { 35152 // The arguments are words 35153 if ((flags & 2) > 0) { 35154 // values are offset 35155 component.dx = p.parseShort(); 35156 component.dy = p.parseShort(); 35157 } else { 35158 // values are matched points 35159 component.matchedPoints = [p.parseUShort(), p.parseUShort()]; 35160 } 35161 } else { 35162 // The arguments are bytes 35163 if ((flags & 2) > 0) { 35164 // values are offset 35165 component.dx = p.parseChar(); 35166 component.dy = p.parseChar(); 35167 } else { 35168 // values are matched points 35169 component.matchedPoints = [p.parseByte(), p.parseByte()]; 35170 } 35171 } 35172 35173 if ((flags & 8) > 0) { 35174 // We have a scale 35175 component.xScale = component.yScale = p.parseF2Dot14(); 35176 } else if ((flags & 64) > 0) { 35177 // We have an X / Y scale 35178 component.xScale = p.parseF2Dot14(); 35179 component.yScale = p.parseF2Dot14(); 35180 } else if ((flags & 128) > 0) { 35181 // We have a 2x2 transformation 35182 component.xScale = p.parseF2Dot14(); 35183 component.scale01 = p.parseF2Dot14(); 35184 component.scale10 = p.parseF2Dot14(); 35185 component.yScale = p.parseF2Dot14(); 35186 } 35187 35188 glyph.components.push(component); 35189 moreComponents = !!(flags & 32); 35190 } 35191 if (flags & 0x100) { 35192 // We have instructions 35193 glyph.instructionLength = p.parseUShort(); 35194 glyph.instructions = []; 35195 for (var i$6 = 0; i$6 < glyph.instructionLength; i$6 += 1) { 35196 glyph.instructions.push(p.parseByte()); 35197 } 35198 } 35199 } 35200 } 35201 35202 // Transform an array of points and return a new array. 35203 function transformPoints(points, transform) { 35204 var newPoints = []; 35205 for (var i = 0; i < points.length; i += 1) { 35206 var pt = points[i]; 35207 var newPt = { 35208 x: transform.xScale * pt.x + transform.scale01 * pt.y + transform.dx, 35209 y: transform.scale10 * pt.x + transform.yScale * pt.y + transform.dy, 35210 onCurve: pt.onCurve, 35211 lastPointOfContour: pt.lastPointOfContour 35212 }; 35213 newPoints.push(newPt); 35214 } 35215 35216 return newPoints; 35217 } 35218 35219 function getContours(points) { 35220 var contours = []; 35221 var currentContour = []; 35222 for (var i = 0; i < points.length; i += 1) { 35223 var pt = points[i]; 35224 currentContour.push(pt); 35225 if (pt.lastPointOfContour) { 35226 contours.push(currentContour); 35227 currentContour = []; 35228 } 35229 } 35230 35231 check.argument( 35232 currentContour.length === 0, 35233 'There are still points left in the current contour.' 35234 ); 35235 return contours; 35236 } 35237 35238 // Convert the TrueType glyph outline to a Path. 35239 function getPath(points) { 35240 var p = new Path(); 35241 if (!points) { 35242 return p; 35243 } 35244 35245 var contours = getContours(points); 35246 35247 for (var contourIndex = 0; contourIndex < contours.length; ++contourIndex) { 35248 var contour = contours[contourIndex]; 35249 35250 var prev = null; 35251 var curr = contour[contour.length - 1]; 35252 var next = contour[0]; 35253 35254 if (curr.onCurve) { 35255 p.moveTo(curr.x, curr.y); 35256 } else { 35257 if (next.onCurve) { 35258 p.moveTo(next.x, next.y); 35259 } else { 35260 // If both first and last points are off-curve, start at their middle. 35261 var start = { 35262 x: (curr.x + next.x) * 0.5, 35263 y: (curr.y + next.y) * 0.5 35264 }; 35265 p.moveTo(start.x, start.y); 35266 } 35267 } 35268 35269 for (var i = 0; i < contour.length; ++i) { 35270 prev = curr; 35271 curr = next; 35272 next = contour[(i + 1) % contour.length]; 35273 35274 if (curr.onCurve) { 35275 // This is a straight line. 35276 p.lineTo(curr.x, curr.y); 35277 } else { 35278 var prev2 = prev; 35279 var next2 = next; 35280 35281 if (!prev.onCurve) { 35282 prev2 = { x: (curr.x + prev.x) * 0.5, y: (curr.y + prev.y) * 0.5 }; 35283 } 35284 35285 if (!next.onCurve) { 35286 next2 = { x: (curr.x + next.x) * 0.5, y: (curr.y + next.y) * 0.5 }; 35287 } 35288 35289 p.quadraticCurveTo(curr.x, curr.y, next2.x, next2.y); 35290 } 35291 } 35292 35293 p.closePath(); 35294 } 35295 return p; 35296 } 35297 35298 function buildPath(glyphs, glyph) { 35299 if (glyph.isComposite) { 35300 for (var j = 0; j < glyph.components.length; j += 1) { 35301 var component = glyph.components[j]; 35302 var componentGlyph = glyphs.get(component.glyphIndex); 35303 // Force the ttfGlyphLoader to parse the glyph. 35304 componentGlyph.getPath(); 35305 if (componentGlyph.points) { 35306 var transformedPoints = void 0; 35307 if (component.matchedPoints === undefined) { 35308 // component positioned by offset 35309 transformedPoints = transformPoints( 35310 componentGlyph.points, 35311 component 35312 ); 35313 } else { 35314 // component positioned by matched points 35315 if ( 35316 component.matchedPoints[0] > glyph.points.length - 1 || 35317 component.matchedPoints[1] > componentGlyph.points.length - 1 35318 ) { 35319 throw Error('Matched points out of range in ' + glyph.name); 35320 } 35321 var firstPt = glyph.points[component.matchedPoints[0]]; 35322 var secondPt = componentGlyph.points[component.matchedPoints[1]]; 35323 var transform = { 35324 xScale: component.xScale, 35325 scale01: component.scale01, 35326 scale10: component.scale10, 35327 yScale: component.yScale, 35328 dx: 0, 35329 dy: 0 35330 }; 35331 secondPt = transformPoints([secondPt], transform)[0]; 35332 transform.dx = firstPt.x - secondPt.x; 35333 transform.dy = firstPt.y - secondPt.y; 35334 transformedPoints = transformPoints( 35335 componentGlyph.points, 35336 transform 35337 ); 35338 } 35339 glyph.points = glyph.points.concat(transformedPoints); 35340 } 35341 } 35342 } 35343 35344 return getPath(glyph.points); 35345 } 35346 35347 // Parse all the glyphs according to the offsets from the `loca` table. 35348 function parseGlyfTable(data, start, loca, font) { 35349 var glyphs = new glyphset.GlyphSet(font); 35350 35351 // The last element of the loca table is invalid. 35352 for (var i = 0; i < loca.length - 1; i += 1) { 35353 var offset = loca[i]; 35354 var nextOffset = loca[i + 1]; 35355 if (offset !== nextOffset) { 35356 glyphs.push( 35357 i, 35358 glyphset.ttfGlyphLoader( 35359 font, 35360 i, 35361 parseGlyph, 35362 data, 35363 start + offset, 35364 buildPath 35365 ) 35366 ); 35367 } else { 35368 glyphs.push(i, glyphset.glyphLoader(font, i)); 35369 } 35370 } 35371 35372 return glyphs; 35373 } 35374 35375 var glyf = { getPath: getPath, parse: parseGlyfTable }; 35376 35377 /* A TrueType font hinting interpreter. 35378 * 35379 * (c) 2017 Axel Kittenberger 35380 * 35381 * This interpreter has been implemented according to this documentation: 35382 * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM05/Chap5.html 35383 * 35384 * According to the documentation F24DOT6 values are used for pixels. 35385 * That means calculation is 1/64 pixel accurate and uses integer operations. 35386 * However, Javascript has floating point operations by default and only 35387 * those are available. One could make a case to simulate the 1/64 accuracy 35388 * exactly by truncating after every division operation 35389 * (for example with << 0) to get pixel exactly results as other TrueType 35390 * implementations. It may make sense since some fonts are pixel optimized 35391 * by hand using DELTAP instructions. The current implementation doesn't 35392 * and rather uses full floating point precision. 35393 * 35394 * xScale, yScale and rotation is currently ignored. 35395 * 35396 * A few non-trivial instructions are missing as I didn't encounter yet 35397 * a font that used them to test a possible implementation. 35398 * 35399 * Some fonts seem to use undocumented features regarding the twilight zone. 35400 * Only some of them are implemented as they were encountered. 35401 * 35402 * The exports.DEBUG statements are removed on the minified distribution file. 35403 */ 35404 35405 var instructionTable; 35406 var exec; 35407 var execGlyph; 35408 var execComponent; 35409 35410 /* 35411 * Creates a hinting object. 35412 * 35413 * There ought to be exactly one 35414 * for each truetype font that is used for hinting. 35415 */ 35416 function Hinting(font) { 35417 // the font this hinting object is for 35418 this.font = font; 35419 35420 this.getCommands = function(hPoints) { 35421 return glyf.getPath(hPoints).commands; 35422 }; 35423 35424 // cached states 35425 this._fpgmState = this._prepState = undefined; 35426 35427 // errorState 35428 // 0 ... all okay 35429 // 1 ... had an error in a glyf, 35430 // continue working but stop spamming 35431 // the console 35432 // 2 ... error at prep, stop hinting at this ppem 35433 // 3 ... error at fpeg, stop hinting for this font at all 35434 this._errorState = 0; 35435 } 35436 35437 /* 35438 * Not rounding. 35439 */ 35440 function roundOff(v) { 35441 return v; 35442 } 35443 35444 /* 35445 * Rounding to grid. 35446 */ 35447 function roundToGrid(v) { 35448 //Rounding in TT is supposed to "symmetrical around zero" 35449 return Math.sign(v) * Math.round(Math.abs(v)); 35450 } 35451 35452 /* 35453 * Rounding to double grid. 35454 */ 35455 function roundToDoubleGrid(v) { 35456 return Math.sign(v) * Math.round(Math.abs(v * 2)) / 2; 35457 } 35458 35459 /* 35460 * Rounding to half grid. 35461 */ 35462 function roundToHalfGrid(v) { 35463 return Math.sign(v) * (Math.round(Math.abs(v) + 0.5) - 0.5); 35464 } 35465 35466 /* 35467 * Rounding to up to grid. 35468 */ 35469 function roundUpToGrid(v) { 35470 return Math.sign(v) * Math.ceil(Math.abs(v)); 35471 } 35472 35473 /* 35474 * Rounding to down to grid. 35475 */ 35476 function roundDownToGrid(v) { 35477 return Math.sign(v) * Math.floor(Math.abs(v)); 35478 } 35479 35480 /* 35481 * Super rounding. 35482 */ 35483 var roundSuper = function(v) { 35484 var period = this.srPeriod; 35485 var phase = this.srPhase; 35486 var threshold = this.srThreshold; 35487 var sign = 1; 35488 35489 if (v < 0) { 35490 v = -v; 35491 sign = -1; 35492 } 35493 35494 v += threshold - phase; 35495 35496 v = Math.trunc(v / period) * period; 35497 35498 v += phase; 35499 35500 // according to http://xgridfit.sourceforge.net/round.html 35501 if (v < 0) { 35502 return phase * sign; 35503 } 35504 35505 return v * sign; 35506 }; 35507 35508 /* 35509 * Unit vector of x-axis. 35510 */ 35511 var xUnitVector = { 35512 x: 1, 35513 35514 y: 0, 35515 35516 axis: 'x', 35517 35518 // Gets the projected distance between two points. 35519 // o1/o2 ... if true, respective original position is used. 35520 distance: function(p1, p2, o1, o2) { 35521 return (o1 ? p1.xo : p1.x) - (o2 ? p2.xo : p2.x); 35522 }, 35523 35524 // Moves point p so the moved position has the same relative 35525 // position to the moved positions of rp1 and rp2 than the 35526 // original positions had. 35527 // 35528 // See APPENDIX on INTERPOLATE at the bottom of this file. 35529 interpolate: function(p, rp1, rp2, pv) { 35530 var do1; 35531 var do2; 35532 var doa1; 35533 var doa2; 35534 var dm1; 35535 var dm2; 35536 var dt; 35537 35538 if (!pv || pv === this) { 35539 do1 = p.xo - rp1.xo; 35540 do2 = p.xo - rp2.xo; 35541 dm1 = rp1.x - rp1.xo; 35542 dm2 = rp2.x - rp2.xo; 35543 doa1 = Math.abs(do1); 35544 doa2 = Math.abs(do2); 35545 dt = doa1 + doa2; 35546 35547 if (dt === 0) { 35548 p.x = p.xo + (dm1 + dm2) / 2; 35549 return; 35550 } 35551 35552 p.x = p.xo + (dm1 * doa2 + dm2 * doa1) / dt; 35553 return; 35554 } 35555 35556 do1 = pv.distance(p, rp1, true, true); 35557 do2 = pv.distance(p, rp2, true, true); 35558 dm1 = pv.distance(rp1, rp1, false, true); 35559 dm2 = pv.distance(rp2, rp2, false, true); 35560 doa1 = Math.abs(do1); 35561 doa2 = Math.abs(do2); 35562 dt = doa1 + doa2; 35563 35564 if (dt === 0) { 35565 xUnitVector.setRelative(p, p, (dm1 + dm2) / 2, pv, true); 35566 return; 35567 } 35568 35569 xUnitVector.setRelative(p, p, (dm1 * doa2 + dm2 * doa1) / dt, pv, true); 35570 }, 35571 35572 // Slope of line normal to this 35573 normalSlope: Number.NEGATIVE_INFINITY, 35574 35575 // Sets the point 'p' relative to point 'rp' 35576 // by the distance 'd'. 35577 // 35578 // See APPENDIX on SETRELATIVE at the bottom of this file. 35579 // 35580 // p ... point to set 35581 // rp ... reference point 35582 // d ... distance on projection vector 35583 // pv ... projection vector (undefined = this) 35584 // org ... if true, uses the original position of rp as reference. 35585 setRelative: function(p, rp, d, pv, org) { 35586 if (!pv || pv === this) { 35587 p.x = (org ? rp.xo : rp.x) + d; 35588 return; 35589 } 35590 35591 var rpx = org ? rp.xo : rp.x; 35592 var rpy = org ? rp.yo : rp.y; 35593 var rpdx = rpx + d * pv.x; 35594 var rpdy = rpy + d * pv.y; 35595 35596 p.x = rpdx + (p.y - rpdy) / pv.normalSlope; 35597 }, 35598 35599 // Slope of vector line. 35600 slope: 0, 35601 35602 // Touches the point p. 35603 touch: function(p) { 35604 p.xTouched = true; 35605 }, 35606 35607 // Tests if a point p is touched. 35608 touched: function(p) { 35609 return p.xTouched; 35610 }, 35611 35612 // Untouches the point p. 35613 untouch: function(p) { 35614 p.xTouched = false; 35615 } 35616 }; 35617 35618 /* 35619 * Unit vector of y-axis. 35620 */ 35621 var yUnitVector = { 35622 x: 0, 35623 35624 y: 1, 35625 35626 axis: 'y', 35627 35628 // Gets the projected distance between two points. 35629 // o1/o2 ... if true, respective original position is used. 35630 distance: function(p1, p2, o1, o2) { 35631 return (o1 ? p1.yo : p1.y) - (o2 ? p2.yo : p2.y); 35632 }, 35633 35634 // Moves point p so the moved position has the same relative 35635 // position to the moved positions of rp1 and rp2 than the 35636 // original positions had. 35637 // 35638 // See APPENDIX on INTERPOLATE at the bottom of this file. 35639 interpolate: function(p, rp1, rp2, pv) { 35640 var do1; 35641 var do2; 35642 var doa1; 35643 var doa2; 35644 var dm1; 35645 var dm2; 35646 var dt; 35647 35648 if (!pv || pv === this) { 35649 do1 = p.yo - rp1.yo; 35650 do2 = p.yo - rp2.yo; 35651 dm1 = rp1.y - rp1.yo; 35652 dm2 = rp2.y - rp2.yo; 35653 doa1 = Math.abs(do1); 35654 doa2 = Math.abs(do2); 35655 dt = doa1 + doa2; 35656 35657 if (dt === 0) { 35658 p.y = p.yo + (dm1 + dm2) / 2; 35659 return; 35660 } 35661 35662 p.y = p.yo + (dm1 * doa2 + dm2 * doa1) / dt; 35663 return; 35664 } 35665 35666 do1 = pv.distance(p, rp1, true, true); 35667 do2 = pv.distance(p, rp2, true, true); 35668 dm1 = pv.distance(rp1, rp1, false, true); 35669 dm2 = pv.distance(rp2, rp2, false, true); 35670 doa1 = Math.abs(do1); 35671 doa2 = Math.abs(do2); 35672 dt = doa1 + doa2; 35673 35674 if (dt === 0) { 35675 yUnitVector.setRelative(p, p, (dm1 + dm2) / 2, pv, true); 35676 return; 35677 } 35678 35679 yUnitVector.setRelative(p, p, (dm1 * doa2 + dm2 * doa1) / dt, pv, true); 35680 }, 35681 35682 // Slope of line normal to this. 35683 normalSlope: 0, 35684 35685 // Sets the point 'p' relative to point 'rp' 35686 // by the distance 'd' 35687 // 35688 // See APPENDIX on SETRELATIVE at the bottom of this file. 35689 // 35690 // p ... point to set 35691 // rp ... reference point 35692 // d ... distance on projection vector 35693 // pv ... projection vector (undefined = this) 35694 // org ... if true, uses the original position of rp as reference. 35695 setRelative: function(p, rp, d, pv, org) { 35696 if (!pv || pv === this) { 35697 p.y = (org ? rp.yo : rp.y) + d; 35698 return; 35699 } 35700 35701 var rpx = org ? rp.xo : rp.x; 35702 var rpy = org ? rp.yo : rp.y; 35703 var rpdx = rpx + d * pv.x; 35704 var rpdy = rpy + d * pv.y; 35705 35706 p.y = rpdy + pv.normalSlope * (p.x - rpdx); 35707 }, 35708 35709 // Slope of vector line. 35710 slope: Number.POSITIVE_INFINITY, 35711 35712 // Touches the point p. 35713 touch: function(p) { 35714 p.yTouched = true; 35715 }, 35716 35717 // Tests if a point p is touched. 35718 touched: function(p) { 35719 return p.yTouched; 35720 }, 35721 35722 // Untouches the point p. 35723 untouch: function(p) { 35724 p.yTouched = false; 35725 } 35726 }; 35727 35728 Object.freeze(xUnitVector); 35729 Object.freeze(yUnitVector); 35730 35731 /* 35732 * Creates a unit vector that is not x- or y-axis. 35733 */ 35734 function UnitVector(x, y) { 35735 this.x = x; 35736 this.y = y; 35737 this.axis = undefined; 35738 this.slope = y / x; 35739 this.normalSlope = -x / y; 35740 Object.freeze(this); 35741 } 35742 35743 /* 35744 * Gets the projected distance between two points. 35745 * o1/o2 ... if true, respective original position is used. 35746 */ 35747 UnitVector.prototype.distance = function(p1, p2, o1, o2) { 35748 return ( 35749 this.x * xUnitVector.distance(p1, p2, o1, o2) + 35750 this.y * yUnitVector.distance(p1, p2, o1, o2) 35751 ); 35752 }; 35753 35754 /* 35755 * Moves point p so the moved position has the same relative 35756 * position to the moved positions of rp1 and rp2 than the 35757 * original positions had. 35758 * 35759 * See APPENDIX on INTERPOLATE at the bottom of this file. 35760 */ 35761 UnitVector.prototype.interpolate = function(p, rp1, rp2, pv) { 35762 var dm1; 35763 var dm2; 35764 var do1; 35765 var do2; 35766 var doa1; 35767 var doa2; 35768 var dt; 35769 35770 do1 = pv.distance(p, rp1, true, true); 35771 do2 = pv.distance(p, rp2, true, true); 35772 dm1 = pv.distance(rp1, rp1, false, true); 35773 dm2 = pv.distance(rp2, rp2, false, true); 35774 doa1 = Math.abs(do1); 35775 doa2 = Math.abs(do2); 35776 dt = doa1 + doa2; 35777 35778 if (dt === 0) { 35779 this.setRelative(p, p, (dm1 + dm2) / 2, pv, true); 35780 return; 35781 } 35782 35783 this.setRelative(p, p, (dm1 * doa2 + dm2 * doa1) / dt, pv, true); 35784 }; 35785 35786 /* 35787 * Sets the point 'p' relative to point 'rp' 35788 * by the distance 'd' 35789 * 35790 * See APPENDIX on SETRELATIVE at the bottom of this file. 35791 * 35792 * p ... point to set 35793 * rp ... reference point 35794 * d ... distance on projection vector 35795 * pv ... projection vector (undefined = this) 35796 * org ... if true, uses the original position of rp as reference. 35797 */ 35798 UnitVector.prototype.setRelative = function(p, rp, d, pv, org) { 35799 pv = pv || this; 35800 35801 var rpx = org ? rp.xo : rp.x; 35802 var rpy = org ? rp.yo : rp.y; 35803 var rpdx = rpx + d * pv.x; 35804 var rpdy = rpy + d * pv.y; 35805 35806 var pvns = pv.normalSlope; 35807 var fvs = this.slope; 35808 35809 var px = p.x; 35810 var py = p.y; 35811 35812 p.x = (fvs * px - pvns * rpdx + rpdy - py) / (fvs - pvns); 35813 p.y = fvs * (p.x - px) + py; 35814 }; 35815 35816 /* 35817 * Touches the point p. 35818 */ 35819 UnitVector.prototype.touch = function(p) { 35820 p.xTouched = true; 35821 p.yTouched = true; 35822 }; 35823 35824 /* 35825 * Returns a unit vector with x/y coordinates. 35826 */ 35827 function getUnitVector(x, y) { 35828 var d = Math.sqrt(x * x + y * y); 35829 35830 x /= d; 35831 y /= d; 35832 35833 if (x === 1 && y === 0) { 35834 return xUnitVector; 35835 } else if (x === 0 && y === 1) { 35836 return yUnitVector; 35837 } else { 35838 return new UnitVector(x, y); 35839 } 35840 } 35841 35842 /* 35843 * Creates a point in the hinting engine. 35844 */ 35845 function HPoint(x, y, lastPointOfContour, onCurve) { 35846 this.x = this.xo = Math.round(x * 64) / 64; // hinted x value and original x-value 35847 this.y = this.yo = Math.round(y * 64) / 64; // hinted y value and original y-value 35848 35849 this.lastPointOfContour = lastPointOfContour; 35850 this.onCurve = onCurve; 35851 this.prevPointOnContour = undefined; 35852 this.nextPointOnContour = undefined; 35853 this.xTouched = false; 35854 this.yTouched = false; 35855 35856 Object.preventExtensions(this); 35857 } 35858 35859 /* 35860 * Returns the next touched point on the contour. 35861 * 35862 * v ... unit vector to test touch axis. 35863 */ 35864 HPoint.prototype.nextTouched = function(v) { 35865 var p = this.nextPointOnContour; 35866 35867 while (!v.touched(p) && p !== this) { 35868 p = p.nextPointOnContour; 35869 } 35870 35871 return p; 35872 }; 35873 35874 /* 35875 * Returns the previous touched point on the contour 35876 * 35877 * v ... unit vector to test touch axis. 35878 */ 35879 HPoint.prototype.prevTouched = function(v) { 35880 var p = this.prevPointOnContour; 35881 35882 while (!v.touched(p) && p !== this) { 35883 p = p.prevPointOnContour; 35884 } 35885 35886 return p; 35887 }; 35888 35889 /* 35890 * The zero point. 35891 */ 35892 var HPZero = Object.freeze(new HPoint(0, 0)); 35893 35894 /* 35895 * The default state of the interpreter. 35896 * 35897 * Note: Freezing the defaultState and then deriving from it 35898 * makes the V8 Javascript engine going awkward, 35899 * so this is avoided, albeit the defaultState shouldn't 35900 * ever change. 35901 */ 35902 var defaultState = { 35903 cvCutIn: 17 / 16, // control value cut in 35904 deltaBase: 9, 35905 deltaShift: 0.125, 35906 loop: 1, // loops some instructions 35907 minDis: 1, // minimum distance 35908 autoFlip: true 35909 }; 35910 35911 /* 35912 * The current state of the interpreter. 35913 * 35914 * env ... 'fpgm' or 'prep' or 'glyf' 35915 * prog ... the program 35916 */ 35917 function State(env, prog) { 35918 this.env = env; 35919 this.stack = []; 35920 this.prog = prog; 35921 35922 switch (env) { 35923 case 'glyf': 35924 this.zp0 = this.zp1 = this.zp2 = 1; 35925 this.rp0 = this.rp1 = this.rp2 = 0; 35926 /* fall through */ 35927 case 'prep': 35928 this.fv = this.pv = this.dpv = xUnitVector; 35929 this.round = roundToGrid; 35930 } 35931 } 35932 35933 /* 35934 * Executes a glyph program. 35935 * 35936 * This does the hinting for each glyph. 35937 * 35938 * Returns an array of moved points. 35939 * 35940 * glyph: the glyph to hint 35941 * ppem: the size the glyph is rendered for 35942 */ 35943 Hinting.prototype.exec = function(glyph, ppem) { 35944 if (typeof ppem !== 'number') { 35945 throw new Error('Point size is not a number!'); 35946 } 35947 35948 // Received a fatal error, don't do any hinting anymore. 35949 if (this._errorState > 2) { 35950 return; 35951 } 35952 35953 var font = this.font; 35954 var prepState = this._prepState; 35955 35956 if (!prepState || prepState.ppem !== ppem) { 35957 var fpgmState = this._fpgmState; 35958 35959 if (!fpgmState) { 35960 // Executes the fpgm state. 35961 // This is used by fonts to define functions. 35962 State.prototype = defaultState; 35963 35964 fpgmState = this._fpgmState = new State('fpgm', font.tables.fpgm); 35965 35966 fpgmState.funcs = []; 35967 fpgmState.font = font; 35968 35969 if (exports.DEBUG) { 35970 console.log('---EXEC FPGM---'); 35971 fpgmState.step = -1; 35972 } 35973 35974 try { 35975 exec(fpgmState); 35976 } catch (e) { 35977 console.log('Hinting error in FPGM:' + e); 35978 this._errorState = 3; 35979 return; 35980 } 35981 } 35982 35983 // Executes the prep program for this ppem setting. 35984 // This is used by fonts to set cvt values 35985 // depending on to be rendered font size. 35986 35987 State.prototype = fpgmState; 35988 prepState = this._prepState = new State('prep', font.tables.prep); 35989 35990 prepState.ppem = ppem; 35991 35992 // Creates a copy of the cvt table 35993 // and scales it to the current ppem setting. 35994 var oCvt = font.tables.cvt; 35995 if (oCvt) { 35996 var cvt = (prepState.cvt = new Array(oCvt.length)); 35997 var scale = ppem / font.unitsPerEm; 35998 for (var c = 0; c < oCvt.length; c++) { 35999 cvt[c] = oCvt[c] * scale; 36000 } 36001 } else { 36002 prepState.cvt = []; 36003 } 36004 36005 if (exports.DEBUG) { 36006 console.log('---EXEC PREP---'); 36007 prepState.step = -1; 36008 } 36009 36010 try { 36011 exec(prepState); 36012 } catch (e) { 36013 if (this._errorState < 2) { 36014 console.log('Hinting error in PREP:' + e); 36015 } 36016 this._errorState = 2; 36017 } 36018 } 36019 36020 if (this._errorState > 1) { 36021 return; 36022 } 36023 36024 try { 36025 return execGlyph(glyph, prepState); 36026 } catch (e) { 36027 if (this._errorState < 1) { 36028 console.log('Hinting error:' + e); 36029 console.log('Note: further hinting errors are silenced'); 36030 } 36031 this._errorState = 1; 36032 return undefined; 36033 } 36034 }; 36035 36036 /* 36037 * Executes the hinting program for a glyph. 36038 */ 36039 execGlyph = function(glyph, prepState) { 36040 // original point positions 36041 var xScale = prepState.ppem / prepState.font.unitsPerEm; 36042 var yScale = xScale; 36043 var components = glyph.components; 36044 var contours; 36045 var gZone; 36046 var state; 36047 36048 State.prototype = prepState; 36049 if (!components) { 36050 state = new State('glyf', glyph.instructions); 36051 if (exports.DEBUG) { 36052 console.log('---EXEC GLYPH---'); 36053 state.step = -1; 36054 } 36055 execComponent(glyph, state, xScale, yScale); 36056 gZone = state.gZone; 36057 } else { 36058 var font = prepState.font; 36059 gZone = []; 36060 contours = []; 36061 for (var i = 0; i < components.length; i++) { 36062 var c = components[i]; 36063 var cg = font.glyphs.get(c.glyphIndex); 36064 36065 state = new State('glyf', cg.instructions); 36066 36067 if (exports.DEBUG) { 36068 console.log('---EXEC COMP ' + i + '---'); 36069 state.step = -1; 36070 } 36071 36072 execComponent(cg, state, xScale, yScale); 36073 // appends the computed points to the result array 36074 // post processes the component points 36075 var dx = Math.round(c.dx * xScale); 36076 var dy = Math.round(c.dy * yScale); 36077 var gz = state.gZone; 36078 var cc = state.contours; 36079 for (var pi = 0; pi < gz.length; pi++) { 36080 var p = gz[pi]; 36081 p.xTouched = p.yTouched = false; 36082 p.xo = p.x = p.x + dx; 36083 p.yo = p.y = p.y + dy; 36084 } 36085 36086 var gLen = gZone.length; 36087 gZone.push.apply(gZone, gz); 36088 for (var j = 0; j < cc.length; j++) { 36089 contours.push(cc[j] + gLen); 36090 } 36091 } 36092 36093 if (glyph.instructions && !state.inhibitGridFit) { 36094 // the composite has instructions on its own 36095 state = new State('glyf', glyph.instructions); 36096 36097 state.gZone = state.z0 = state.z1 = state.z2 = gZone; 36098 36099 state.contours = contours; 36100 36101 // note: HPZero cannot be used here, since 36102 // the point might be modified 36103 gZone.push( 36104 new HPoint(0, 0), 36105 new HPoint(Math.round(glyph.advanceWidth * xScale), 0) 36106 ); 36107 36108 if (exports.DEBUG) { 36109 console.log('---EXEC COMPOSITE---'); 36110 state.step = -1; 36111 } 36112 36113 exec(state); 36114 36115 gZone.length -= 2; 36116 } 36117 } 36118 36119 return gZone; 36120 }; 36121 36122 /* 36123 * Executes the hinting program for a component of a multi-component glyph 36124 * or of the glyph itself for a non-component glyph. 36125 */ 36126 execComponent = function(glyph, state, xScale, yScale) { 36127 var points = glyph.points || []; 36128 var pLen = points.length; 36129 var gZone = (state.gZone = state.z0 = state.z1 = state.z2 = []); 36130 var contours = (state.contours = []); 36131 36132 // Scales the original points and 36133 // makes copies for the hinted points. 36134 var cp; // current point 36135 for (var i = 0; i < pLen; i++) { 36136 cp = points[i]; 36137 36138 gZone[i] = new HPoint( 36139 cp.x * xScale, 36140 cp.y * yScale, 36141 cp.lastPointOfContour, 36142 cp.onCurve 36143 ); 36144 } 36145 36146 // Chain links the contours. 36147 var sp; // start point 36148 var np; // next point 36149 36150 for (var i$1 = 0; i$1 < pLen; i$1++) { 36151 cp = gZone[i$1]; 36152 36153 if (!sp) { 36154 sp = cp; 36155 contours.push(i$1); 36156 } 36157 36158 if (cp.lastPointOfContour) { 36159 cp.nextPointOnContour = sp; 36160 sp.prevPointOnContour = cp; 36161 sp = undefined; 36162 } else { 36163 np = gZone[i$1 + 1]; 36164 cp.nextPointOnContour = np; 36165 np.prevPointOnContour = cp; 36166 } 36167 } 36168 36169 if (state.inhibitGridFit) { 36170 return; 36171 } 36172 36173 if (exports.DEBUG) { 36174 console.log('PROCESSING GLYPH', state.stack); 36175 for (var i$2 = 0; i$2 < pLen; i$2++) { 36176 console.log(i$2, gZone[i$2].x, gZone[i$2].y); 36177 } 36178 } 36179 36180 gZone.push( 36181 new HPoint(0, 0), 36182 new HPoint(Math.round(glyph.advanceWidth * xScale), 0) 36183 ); 36184 36185 exec(state); 36186 36187 // Removes the extra points. 36188 gZone.length -= 2; 36189 36190 if (exports.DEBUG) { 36191 console.log('FINISHED GLYPH', state.stack); 36192 for (var i$3 = 0; i$3 < pLen; i$3++) { 36193 console.log(i$3, gZone[i$3].x, gZone[i$3].y); 36194 } 36195 } 36196 }; 36197 36198 /* 36199 * Executes the program loaded in state. 36200 */ 36201 exec = function(state) { 36202 var prog = state.prog; 36203 36204 if (!prog) { 36205 return; 36206 } 36207 36208 var pLen = prog.length; 36209 var ins; 36210 36211 for (state.ip = 0; state.ip < pLen; state.ip++) { 36212 if (exports.DEBUG) { 36213 state.step++; 36214 } 36215 ins = instructionTable[prog[state.ip]]; 36216 36217 if (!ins) { 36218 throw new Error( 36219 'unknown instruction: 0x' + Number(prog[state.ip]).toString(16) 36220 ); 36221 } 36222 36223 ins(state); 36224 36225 // very extensive debugging for each step 36226 /* 36227 if (exports.DEBUG) { 36228 var da; 36229 if (state.gZone) { 36230 da = []; 36231 for (let i = 0; i < state.gZone.length; i++) 36232 { 36233 da.push(i + ' ' + 36234 state.gZone[i].x * 64 + ' ' + 36235 state.gZone[i].y * 64 + ' ' + 36236 (state.gZone[i].xTouched ? 'x' : '') + 36237 (state.gZone[i].yTouched ? 'y' : '') 36238 ); 36239 } 36240 console.log('GZ', da); 36241 } 36242 36243 if (state.tZone) { 36244 da = []; 36245 for (let i = 0; i < state.tZone.length; i++) { 36246 da.push(i + ' ' + 36247 state.tZone[i].x * 64 + ' ' + 36248 state.tZone[i].y * 64 + ' ' + 36249 (state.tZone[i].xTouched ? 'x' : '') + 36250 (state.tZone[i].yTouched ? 'y' : '') 36251 ); 36252 } 36253 console.log('TZ', da); 36254 } 36255 36256 if (state.stack.length > 10) { 36257 console.log( 36258 state.stack.length, 36259 '...', state.stack.slice(state.stack.length - 10) 36260 ); 36261 } else { 36262 console.log(state.stack.length, state.stack); 36263 } 36264 } 36265 */ 36266 } 36267 }; 36268 36269 /* 36270 * Initializes the twilight zone. 36271 * 36272 * This is only done if a SZPx instruction 36273 * refers to the twilight zone. 36274 */ 36275 function initTZone(state) { 36276 var tZone = (state.tZone = new Array(state.gZone.length)); 36277 36278 // no idea if this is actually correct... 36279 for (var i = 0; i < tZone.length; i++) { 36280 tZone[i] = new HPoint(0, 0); 36281 } 36282 } 36283 36284 /* 36285 * Skips the instruction pointer ahead over an IF/ELSE block. 36286 * handleElse .. if true breaks on matching ELSE 36287 */ 36288 function skip(state, handleElse) { 36289 var prog = state.prog; 36290 var ip = state.ip; 36291 var nesting = 1; 36292 var ins; 36293 36294 do { 36295 ins = prog[++ip]; 36296 if (ins === 0x58) { 36297 // IF 36298 nesting++; 36299 } else if (ins === 0x59) { 36300 // EIF 36301 nesting--; 36302 } else if (ins === 0x40) { 36303 // NPUSHB 36304 ip += prog[ip + 1] + 1; 36305 } else if (ins === 0x41) { 36306 // NPUSHW 36307 ip += 2 * prog[ip + 1] + 1; 36308 } else if (ins >= 0xb0 && ins <= 0xb7) { 36309 // PUSHB 36310 ip += ins - 0xb0 + 1; 36311 } else if (ins >= 0xb8 && ins <= 0xbf) { 36312 // PUSHW 36313 ip += (ins - 0xb8 + 1) * 2; 36314 } else if (handleElse && nesting === 1 && ins === 0x1b) { 36315 // ELSE 36316 break; 36317 } 36318 } while (nesting > 0); 36319 36320 state.ip = ip; 36321 } 36322 36323 /*----------------------------------------------------------* 36324 * And then a lot of instructions... * 36325 *----------------------------------------------------------*/ 36326 36327 // SVTCA[a] Set freedom and projection Vectors To Coordinate Axis 36328 // 0x00-0x01 36329 function SVTCA(v, state) { 36330 if (exports.DEBUG) { 36331 console.log(state.step, 'SVTCA[' + v.axis + ']'); 36332 } 36333 36334 state.fv = state.pv = state.dpv = v; 36335 } 36336 36337 // SPVTCA[a] Set Projection Vector to Coordinate Axis 36338 // 0x02-0x03 36339 function SPVTCA(v, state) { 36340 if (exports.DEBUG) { 36341 console.log(state.step, 'SPVTCA[' + v.axis + ']'); 36342 } 36343 36344 state.pv = state.dpv = v; 36345 } 36346 36347 // SFVTCA[a] Set Freedom Vector to Coordinate Axis 36348 // 0x04-0x05 36349 function SFVTCA(v, state) { 36350 if (exports.DEBUG) { 36351 console.log(state.step, 'SFVTCA[' + v.axis + ']'); 36352 } 36353 36354 state.fv = v; 36355 } 36356 36357 // SPVTL[a] Set Projection Vector To Line 36358 // 0x06-0x07 36359 function SPVTL(a, state) { 36360 var stack = state.stack; 36361 var p2i = stack.pop(); 36362 var p1i = stack.pop(); 36363 var p2 = state.z2[p2i]; 36364 var p1 = state.z1[p1i]; 36365 36366 if (exports.DEBUG) { 36367 console.log('SPVTL[' + a + ']', p2i, p1i); 36368 } 36369 36370 var dx; 36371 var dy; 36372 36373 if (!a) { 36374 dx = p1.x - p2.x; 36375 dy = p1.y - p2.y; 36376 } else { 36377 dx = p2.y - p1.y; 36378 dy = p1.x - p2.x; 36379 } 36380 36381 state.pv = state.dpv = getUnitVector(dx, dy); 36382 } 36383 36384 // SFVTL[a] Set Freedom Vector To Line 36385 // 0x08-0x09 36386 function SFVTL(a, state) { 36387 var stack = state.stack; 36388 var p2i = stack.pop(); 36389 var p1i = stack.pop(); 36390 var p2 = state.z2[p2i]; 36391 var p1 = state.z1[p1i]; 36392 36393 if (exports.DEBUG) { 36394 console.log('SFVTL[' + a + ']', p2i, p1i); 36395 } 36396 36397 var dx; 36398 var dy; 36399 36400 if (!a) { 36401 dx = p1.x - p2.x; 36402 dy = p1.y - p2.y; 36403 } else { 36404 dx = p2.y - p1.y; 36405 dy = p1.x - p2.x; 36406 } 36407 36408 state.fv = getUnitVector(dx, dy); 36409 } 36410 36411 // SPVFS[] Set Projection Vector From Stack 36412 // 0x0A 36413 function SPVFS(state) { 36414 var stack = state.stack; 36415 var y = stack.pop(); 36416 var x = stack.pop(); 36417 36418 if (exports.DEBUG) { 36419 console.log(state.step, 'SPVFS[]', y, x); 36420 } 36421 36422 state.pv = state.dpv = getUnitVector(x, y); 36423 } 36424 36425 // SFVFS[] Set Freedom Vector From Stack 36426 // 0x0B 36427 function SFVFS(state) { 36428 var stack = state.stack; 36429 var y = stack.pop(); 36430 var x = stack.pop(); 36431 36432 if (exports.DEBUG) { 36433 console.log(state.step, 'SPVFS[]', y, x); 36434 } 36435 36436 state.fv = getUnitVector(x, y); 36437 } 36438 36439 // GPV[] Get Projection Vector 36440 // 0x0C 36441 function GPV(state) { 36442 var stack = state.stack; 36443 var pv = state.pv; 36444 36445 if (exports.DEBUG) { 36446 console.log(state.step, 'GPV[]'); 36447 } 36448 36449 stack.push(pv.x * 0x4000); 36450 stack.push(pv.y * 0x4000); 36451 } 36452 36453 // GFV[] Get Freedom Vector 36454 // 0x0C 36455 function GFV(state) { 36456 var stack = state.stack; 36457 var fv = state.fv; 36458 36459 if (exports.DEBUG) { 36460 console.log(state.step, 'GFV[]'); 36461 } 36462 36463 stack.push(fv.x * 0x4000); 36464 stack.push(fv.y * 0x4000); 36465 } 36466 36467 // SFVTPV[] Set Freedom Vector To Projection Vector 36468 // 0x0E 36469 function SFVTPV(state) { 36470 state.fv = state.pv; 36471 36472 if (exports.DEBUG) { 36473 console.log(state.step, 'SFVTPV[]'); 36474 } 36475 } 36476 36477 // ISECT[] moves point p to the InterSECTion of two lines 36478 // 0x0F 36479 function ISECT(state) { 36480 var stack = state.stack; 36481 var pa0i = stack.pop(); 36482 var pa1i = stack.pop(); 36483 var pb0i = stack.pop(); 36484 var pb1i = stack.pop(); 36485 var pi = stack.pop(); 36486 var z0 = state.z0; 36487 var z1 = state.z1; 36488 var pa0 = z0[pa0i]; 36489 var pa1 = z0[pa1i]; 36490 var pb0 = z1[pb0i]; 36491 var pb1 = z1[pb1i]; 36492 var p = state.z2[pi]; 36493 36494 if (exports.DEBUG) { 36495 console.log('ISECT[], ', pa0i, pa1i, pb0i, pb1i, pi); 36496 } 36497 36498 // math from 36499 // en.wikipedia.org/wiki/Line%E2%80%93line_intersection#Given_two_points_on_each_line 36500 36501 var x1 = pa0.x; 36502 var y1 = pa0.y; 36503 var x2 = pa1.x; 36504 var y2 = pa1.y; 36505 var x3 = pb0.x; 36506 var y3 = pb0.y; 36507 var x4 = pb1.x; 36508 var y4 = pb1.y; 36509 36510 var div = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4); 36511 var f1 = x1 * y2 - y1 * x2; 36512 var f2 = x3 * y4 - y3 * x4; 36513 36514 p.x = (f1 * (x3 - x4) - f2 * (x1 - x2)) / div; 36515 p.y = (f1 * (y3 - y4) - f2 * (y1 - y2)) / div; 36516 } 36517 36518 // SRP0[] Set Reference Point 0 36519 // 0x10 36520 function SRP0(state) { 36521 state.rp0 = state.stack.pop(); 36522 36523 if (exports.DEBUG) { 36524 console.log(state.step, 'SRP0[]', state.rp0); 36525 } 36526 } 36527 36528 // SRP1[] Set Reference Point 1 36529 // 0x11 36530 function SRP1(state) { 36531 state.rp1 = state.stack.pop(); 36532 36533 if (exports.DEBUG) { 36534 console.log(state.step, 'SRP1[]', state.rp1); 36535 } 36536 } 36537 36538 // SRP1[] Set Reference Point 2 36539 // 0x12 36540 function SRP2(state) { 36541 state.rp2 = state.stack.pop(); 36542 36543 if (exports.DEBUG) { 36544 console.log(state.step, 'SRP2[]', state.rp2); 36545 } 36546 } 36547 36548 // SZP0[] Set Zone Pointer 0 36549 // 0x13 36550 function SZP0(state) { 36551 var n = state.stack.pop(); 36552 36553 if (exports.DEBUG) { 36554 console.log(state.step, 'SZP0[]', n); 36555 } 36556 36557 state.zp0 = n; 36558 36559 switch (n) { 36560 case 0: 36561 if (!state.tZone) { 36562 initTZone(state); 36563 } 36564 state.z0 = state.tZone; 36565 break; 36566 case 1: 36567 state.z0 = state.gZone; 36568 break; 36569 default: 36570 throw new Error('Invalid zone pointer'); 36571 } 36572 } 36573 36574 // SZP1[] Set Zone Pointer 1 36575 // 0x14 36576 function SZP1(state) { 36577 var n = state.stack.pop(); 36578 36579 if (exports.DEBUG) { 36580 console.log(state.step, 'SZP1[]', n); 36581 } 36582 36583 state.zp1 = n; 36584 36585 switch (n) { 36586 case 0: 36587 if (!state.tZone) { 36588 initTZone(state); 36589 } 36590 state.z1 = state.tZone; 36591 break; 36592 case 1: 36593 state.z1 = state.gZone; 36594 break; 36595 default: 36596 throw new Error('Invalid zone pointer'); 36597 } 36598 } 36599 36600 // SZP2[] Set Zone Pointer 2 36601 // 0x15 36602 function SZP2(state) { 36603 var n = state.stack.pop(); 36604 36605 if (exports.DEBUG) { 36606 console.log(state.step, 'SZP2[]', n); 36607 } 36608 36609 state.zp2 = n; 36610 36611 switch (n) { 36612 case 0: 36613 if (!state.tZone) { 36614 initTZone(state); 36615 } 36616 state.z2 = state.tZone; 36617 break; 36618 case 1: 36619 state.z2 = state.gZone; 36620 break; 36621 default: 36622 throw new Error('Invalid zone pointer'); 36623 } 36624 } 36625 36626 // SZPS[] Set Zone PointerS 36627 // 0x16 36628 function SZPS(state) { 36629 var n = state.stack.pop(); 36630 36631 if (exports.DEBUG) { 36632 console.log(state.step, 'SZPS[]', n); 36633 } 36634 36635 state.zp0 = state.zp1 = state.zp2 = n; 36636 36637 switch (n) { 36638 case 0: 36639 if (!state.tZone) { 36640 initTZone(state); 36641 } 36642 state.z0 = state.z1 = state.z2 = state.tZone; 36643 break; 36644 case 1: 36645 state.z0 = state.z1 = state.z2 = state.gZone; 36646 break; 36647 default: 36648 throw new Error('Invalid zone pointer'); 36649 } 36650 } 36651 36652 // SLOOP[] Set LOOP variable 36653 // 0x17 36654 function SLOOP(state) { 36655 state.loop = state.stack.pop(); 36656 36657 if (exports.DEBUG) { 36658 console.log(state.step, 'SLOOP[]', state.loop); 36659 } 36660 } 36661 36662 // RTG[] Round To Grid 36663 // 0x18 36664 function RTG(state) { 36665 if (exports.DEBUG) { 36666 console.log(state.step, 'RTG[]'); 36667 } 36668 36669 state.round = roundToGrid; 36670 } 36671 36672 // RTHG[] Round To Half Grid 36673 // 0x19 36674 function RTHG(state) { 36675 if (exports.DEBUG) { 36676 console.log(state.step, 'RTHG[]'); 36677 } 36678 36679 state.round = roundToHalfGrid; 36680 } 36681 36682 // SMD[] Set Minimum Distance 36683 // 0x1A 36684 function SMD(state) { 36685 var d = state.stack.pop(); 36686 36687 if (exports.DEBUG) { 36688 console.log(state.step, 'SMD[]', d); 36689 } 36690 36691 state.minDis = d / 0x40; 36692 } 36693 36694 // ELSE[] ELSE clause 36695 // 0x1B 36696 function ELSE(state) { 36697 // This instruction has been reached by executing a then branch 36698 // so it just skips ahead until matching EIF. 36699 // 36700 // In case the IF was negative the IF[] instruction already 36701 // skipped forward over the ELSE[] 36702 36703 if (exports.DEBUG) { 36704 console.log(state.step, 'ELSE[]'); 36705 } 36706 36707 skip(state, false); 36708 } 36709 36710 // JMPR[] JuMP Relative 36711 // 0x1C 36712 function JMPR(state) { 36713 var o = state.stack.pop(); 36714 36715 if (exports.DEBUG) { 36716 console.log(state.step, 'JMPR[]', o); 36717 } 36718 36719 // A jump by 1 would do nothing. 36720 state.ip += o - 1; 36721 } 36722 36723 // SCVTCI[] Set Control Value Table Cut-In 36724 // 0x1D 36725 function SCVTCI(state) { 36726 var n = state.stack.pop(); 36727 36728 if (exports.DEBUG) { 36729 console.log(state.step, 'SCVTCI[]', n); 36730 } 36731 36732 state.cvCutIn = n / 0x40; 36733 } 36734 36735 // DUP[] DUPlicate top stack element 36736 // 0x20 36737 function DUP(state) { 36738 var stack = state.stack; 36739 36740 if (exports.DEBUG) { 36741 console.log(state.step, 'DUP[]'); 36742 } 36743 36744 stack.push(stack[stack.length - 1]); 36745 } 36746 36747 // POP[] POP top stack element 36748 // 0x21 36749 function POP(state) { 36750 if (exports.DEBUG) { 36751 console.log(state.step, 'POP[]'); 36752 } 36753 36754 state.stack.pop(); 36755 } 36756 36757 // CLEAR[] CLEAR the stack 36758 // 0x22 36759 function CLEAR(state) { 36760 if (exports.DEBUG) { 36761 console.log(state.step, 'CLEAR[]'); 36762 } 36763 36764 state.stack.length = 0; 36765 } 36766 36767 // SWAP[] SWAP the top two elements on the stack 36768 // 0x23 36769 function SWAP(state) { 36770 var stack = state.stack; 36771 36772 var a = stack.pop(); 36773 var b = stack.pop(); 36774 36775 if (exports.DEBUG) { 36776 console.log(state.step, 'SWAP[]'); 36777 } 36778 36779 stack.push(a); 36780 stack.push(b); 36781 } 36782 36783 // DEPTH[] DEPTH of the stack 36784 // 0x24 36785 function DEPTH(state) { 36786 var stack = state.stack; 36787 36788 if (exports.DEBUG) { 36789 console.log(state.step, 'DEPTH[]'); 36790 } 36791 36792 stack.push(stack.length); 36793 } 36794 36795 // LOOPCALL[] LOOPCALL function 36796 // 0x2A 36797 function LOOPCALL(state) { 36798 var stack = state.stack; 36799 var fn = stack.pop(); 36800 var c = stack.pop(); 36801 36802 if (exports.DEBUG) { 36803 console.log(state.step, 'LOOPCALL[]', fn, c); 36804 } 36805 36806 // saves callers program 36807 var cip = state.ip; 36808 var cprog = state.prog; 36809 36810 state.prog = state.funcs[fn]; 36811 36812 // executes the function 36813 for (var i = 0; i < c; i++) { 36814 exec(state); 36815 36816 if (exports.DEBUG) { 36817 console.log( 36818 ++state.step, 36819 i + 1 < c ? 'next loopcall' : 'done loopcall', 36820 i 36821 ); 36822 } 36823 } 36824 36825 // restores the callers program 36826 state.ip = cip; 36827 state.prog = cprog; 36828 } 36829 36830 // CALL[] CALL function 36831 // 0x2B 36832 function CALL(state) { 36833 var fn = state.stack.pop(); 36834 36835 if (exports.DEBUG) { 36836 console.log(state.step, 'CALL[]', fn); 36837 } 36838 36839 // saves callers program 36840 var cip = state.ip; 36841 var cprog = state.prog; 36842 36843 state.prog = state.funcs[fn]; 36844 36845 // executes the function 36846 exec(state); 36847 36848 // restores the callers program 36849 state.ip = cip; 36850 state.prog = cprog; 36851 36852 if (exports.DEBUG) { 36853 console.log(++state.step, 'returning from', fn); 36854 } 36855 } 36856 36857 // CINDEX[] Copy the INDEXed element to the top of the stack 36858 // 0x25 36859 function CINDEX(state) { 36860 var stack = state.stack; 36861 var k = stack.pop(); 36862 36863 if (exports.DEBUG) { 36864 console.log(state.step, 'CINDEX[]', k); 36865 } 36866 36867 // In case of k == 1, it copies the last element after popping 36868 // thus stack.length - k. 36869 stack.push(stack[stack.length - k]); 36870 } 36871 36872 // MINDEX[] Move the INDEXed element to the top of the stack 36873 // 0x26 36874 function MINDEX(state) { 36875 var stack = state.stack; 36876 var k = stack.pop(); 36877 36878 if (exports.DEBUG) { 36879 console.log(state.step, 'MINDEX[]', k); 36880 } 36881 36882 stack.push(stack.splice(stack.length - k, 1)[0]); 36883 } 36884 36885 // FDEF[] Function DEFinition 36886 // 0x2C 36887 function FDEF(state) { 36888 if (state.env !== 'fpgm') { 36889 throw new Error('FDEF not allowed here'); 36890 } 36891 var stack = state.stack; 36892 var prog = state.prog; 36893 var ip = state.ip; 36894 36895 var fn = stack.pop(); 36896 var ipBegin = ip; 36897 36898 if (exports.DEBUG) { 36899 console.log(state.step, 'FDEF[]', fn); 36900 } 36901 36902 while (prog[++ip] !== 0x2d) {} 36903 36904 state.ip = ip; 36905 state.funcs[fn] = prog.slice(ipBegin + 1, ip); 36906 } 36907 36908 // MDAP[a] Move Direct Absolute Point 36909 // 0x2E-0x2F 36910 function MDAP(round, state) { 36911 var pi = state.stack.pop(); 36912 var p = state.z0[pi]; 36913 var fv = state.fv; 36914 var pv = state.pv; 36915 36916 if (exports.DEBUG) { 36917 console.log(state.step, 'MDAP[' + round + ']', pi); 36918 } 36919 36920 var d = pv.distance(p, HPZero); 36921 36922 if (round) { 36923 d = state.round(d); 36924 } 36925 36926 fv.setRelative(p, HPZero, d, pv); 36927 fv.touch(p); 36928 36929 state.rp0 = state.rp1 = pi; 36930 } 36931 36932 // IUP[a] Interpolate Untouched Points through the outline 36933 // 0x30 36934 function IUP(v, state) { 36935 var z2 = state.z2; 36936 var pLen = z2.length - 2; 36937 var cp; 36938 var pp; 36939 var np; 36940 36941 if (exports.DEBUG) { 36942 console.log(state.step, 'IUP[' + v.axis + ']'); 36943 } 36944 36945 for (var i = 0; i < pLen; i++) { 36946 cp = z2[i]; // current point 36947 36948 // if this point has been touched go on 36949 if (v.touched(cp)) { 36950 continue; 36951 } 36952 36953 pp = cp.prevTouched(v); 36954 36955 // no point on the contour has been touched? 36956 if (pp === cp) { 36957 continue; 36958 } 36959 36960 np = cp.nextTouched(v); 36961 36962 if (pp === np) { 36963 // only one point on the contour has been touched 36964 // so simply moves the point like that 36965 36966 v.setRelative(cp, cp, v.distance(pp, pp, false, true), v, true); 36967 } 36968 36969 v.interpolate(cp, pp, np, v); 36970 } 36971 } 36972 36973 // SHP[] SHift Point using reference point 36974 // 0x32-0x33 36975 function SHP(a, state) { 36976 var stack = state.stack; 36977 var rpi = a ? state.rp1 : state.rp2; 36978 var rp = (a ? state.z0 : state.z1)[rpi]; 36979 var fv = state.fv; 36980 var pv = state.pv; 36981 var loop = state.loop; 36982 var z2 = state.z2; 36983 36984 while (loop--) { 36985 var pi = stack.pop(); 36986 var p = z2[pi]; 36987 36988 var d = pv.distance(rp, rp, false, true); 36989 fv.setRelative(p, p, d, pv); 36990 fv.touch(p); 36991 36992 if (exports.DEBUG) { 36993 console.log( 36994 state.step, 36995 (state.loop > 1 ? 'loop ' + (state.loop - loop) + ': ' : '') + 36996 'SHP[' + 36997 (a ? 'rp1' : 'rp2') + 36998 ']', 36999 pi 37000 ); 37001 } 37002 } 37003 37004 state.loop = 1; 37005 } 37006 37007 // SHC[] SHift Contour using reference point 37008 // 0x36-0x37 37009 function SHC(a, state) { 37010 var stack = state.stack; 37011 var rpi = a ? state.rp1 : state.rp2; 37012 var rp = (a ? state.z0 : state.z1)[rpi]; 37013 var fv = state.fv; 37014 var pv = state.pv; 37015 var ci = stack.pop(); 37016 var sp = state.z2[state.contours[ci]]; 37017 var p = sp; 37018 37019 if (exports.DEBUG) { 37020 console.log(state.step, 'SHC[' + a + ']', ci); 37021 } 37022 37023 var d = pv.distance(rp, rp, false, true); 37024 37025 do { 37026 if (p !== rp) { 37027 fv.setRelative(p, p, d, pv); 37028 } 37029 p = p.nextPointOnContour; 37030 } while (p !== sp); 37031 } 37032 37033 // SHZ[] SHift Zone using reference point 37034 // 0x36-0x37 37035 function SHZ(a, state) { 37036 var stack = state.stack; 37037 var rpi = a ? state.rp1 : state.rp2; 37038 var rp = (a ? state.z0 : state.z1)[rpi]; 37039 var fv = state.fv; 37040 var pv = state.pv; 37041 37042 var e = stack.pop(); 37043 37044 if (exports.DEBUG) { 37045 console.log(state.step, 'SHZ[' + a + ']', e); 37046 } 37047 37048 var z; 37049 switch (e) { 37050 case 0: 37051 z = state.tZone; 37052 break; 37053 case 1: 37054 z = state.gZone; 37055 break; 37056 default: 37057 throw new Error('Invalid zone'); 37058 } 37059 37060 var p; 37061 var d = pv.distance(rp, rp, false, true); 37062 var pLen = z.length - 2; 37063 for (var i = 0; i < pLen; i++) { 37064 p = z[i]; 37065 fv.setRelative(p, p, d, pv); 37066 //if (p !== rp) fv.setRelative(p, p, d, pv); 37067 } 37068 } 37069 37070 // SHPIX[] SHift point by a PIXel amount 37071 // 0x38 37072 function SHPIX(state) { 37073 var stack = state.stack; 37074 var loop = state.loop; 37075 var fv = state.fv; 37076 var d = stack.pop() / 0x40; 37077 var z2 = state.z2; 37078 37079 while (loop--) { 37080 var pi = stack.pop(); 37081 var p = z2[pi]; 37082 37083 if (exports.DEBUG) { 37084 console.log( 37085 state.step, 37086 (state.loop > 1 ? 'loop ' + (state.loop - loop) + ': ' : '') + 37087 'SHPIX[]', 37088 pi, 37089 d 37090 ); 37091 } 37092 37093 fv.setRelative(p, p, d); 37094 fv.touch(p); 37095 } 37096 37097 state.loop = 1; 37098 } 37099 37100 // IP[] Interpolate Point 37101 // 0x39 37102 function IP(state) { 37103 var stack = state.stack; 37104 var rp1i = state.rp1; 37105 var rp2i = state.rp2; 37106 var loop = state.loop; 37107 var rp1 = state.z0[rp1i]; 37108 var rp2 = state.z1[rp2i]; 37109 var fv = state.fv; 37110 var pv = state.dpv; 37111 var z2 = state.z2; 37112 37113 while (loop--) { 37114 var pi = stack.pop(); 37115 var p = z2[pi]; 37116 37117 if (exports.DEBUG) { 37118 console.log( 37119 state.step, 37120 (state.loop > 1 ? 'loop ' + (state.loop - loop) + ': ' : '') + 'IP[]', 37121 pi, 37122 rp1i, 37123 '<->', 37124 rp2i 37125 ); 37126 } 37127 37128 fv.interpolate(p, rp1, rp2, pv); 37129 37130 fv.touch(p); 37131 } 37132 37133 state.loop = 1; 37134 } 37135 37136 // MSIRP[a] Move Stack Indirect Relative Point 37137 // 0x3A-0x3B 37138 function MSIRP(a, state) { 37139 var stack = state.stack; 37140 var d = stack.pop() / 64; 37141 var pi = stack.pop(); 37142 var p = state.z1[pi]; 37143 var rp0 = state.z0[state.rp0]; 37144 var fv = state.fv; 37145 var pv = state.pv; 37146 37147 fv.setRelative(p, rp0, d, pv); 37148 fv.touch(p); 37149 37150 if (exports.DEBUG) { 37151 console.log(state.step, 'MSIRP[' + a + ']', d, pi); 37152 } 37153 37154 state.rp1 = state.rp0; 37155 state.rp2 = pi; 37156 if (a) { 37157 state.rp0 = pi; 37158 } 37159 } 37160 37161 // ALIGNRP[] Align to reference point. 37162 // 0x3C 37163 function ALIGNRP(state) { 37164 var stack = state.stack; 37165 var rp0i = state.rp0; 37166 var rp0 = state.z0[rp0i]; 37167 var loop = state.loop; 37168 var fv = state.fv; 37169 var pv = state.pv; 37170 var z1 = state.z1; 37171 37172 while (loop--) { 37173 var pi = stack.pop(); 37174 var p = z1[pi]; 37175 37176 if (exports.DEBUG) { 37177 console.log( 37178 state.step, 37179 (state.loop > 1 ? 'loop ' + (state.loop - loop) + ': ' : '') + 37180 'ALIGNRP[]', 37181 pi 37182 ); 37183 } 37184 37185 fv.setRelative(p, rp0, 0, pv); 37186 fv.touch(p); 37187 } 37188 37189 state.loop = 1; 37190 } 37191 37192 // RTG[] Round To Double Grid 37193 // 0x3D 37194 function RTDG(state) { 37195 if (exports.DEBUG) { 37196 console.log(state.step, 'RTDG[]'); 37197 } 37198 37199 state.round = roundToDoubleGrid; 37200 } 37201 37202 // MIAP[a] Move Indirect Absolute Point 37203 // 0x3E-0x3F 37204 function MIAP(round, state) { 37205 var stack = state.stack; 37206 var n = stack.pop(); 37207 var pi = stack.pop(); 37208 var p = state.z0[pi]; 37209 var fv = state.fv; 37210 var pv = state.pv; 37211 var cv = state.cvt[n]; 37212 37213 if (exports.DEBUG) { 37214 console.log(state.step, 'MIAP[' + round + ']', n, '(', cv, ')', pi); 37215 } 37216 37217 var d = pv.distance(p, HPZero); 37218 37219 if (round) { 37220 if (Math.abs(d - cv) < state.cvCutIn) { 37221 d = cv; 37222 } 37223 37224 d = state.round(d); 37225 } 37226 37227 fv.setRelative(p, HPZero, d, pv); 37228 37229 if (state.zp0 === 0) { 37230 p.xo = p.x; 37231 p.yo = p.y; 37232 } 37233 37234 fv.touch(p); 37235 37236 state.rp0 = state.rp1 = pi; 37237 } 37238 37239 // NPUSB[] PUSH N Bytes 37240 // 0x40 37241 function NPUSHB(state) { 37242 var prog = state.prog; 37243 var ip = state.ip; 37244 var stack = state.stack; 37245 37246 var n = prog[++ip]; 37247 37248 if (exports.DEBUG) { 37249 console.log(state.step, 'NPUSHB[]', n); 37250 } 37251 37252 for (var i = 0; i < n; i++) { 37253 stack.push(prog[++ip]); 37254 } 37255 37256 state.ip = ip; 37257 } 37258 37259 // NPUSHW[] PUSH N Words 37260 // 0x41 37261 function NPUSHW(state) { 37262 var ip = state.ip; 37263 var prog = state.prog; 37264 var stack = state.stack; 37265 var n = prog[++ip]; 37266 37267 if (exports.DEBUG) { 37268 console.log(state.step, 'NPUSHW[]', n); 37269 } 37270 37271 for (var i = 0; i < n; i++) { 37272 var w = (prog[++ip] << 8) | prog[++ip]; 37273 if (w & 0x8000) { 37274 w = -((w ^ 0xffff) + 1); 37275 } 37276 stack.push(w); 37277 } 37278 37279 state.ip = ip; 37280 } 37281 37282 // WS[] Write Store 37283 // 0x42 37284 function WS(state) { 37285 var stack = state.stack; 37286 var store = state.store; 37287 37288 if (!store) { 37289 store = state.store = []; 37290 } 37291 37292 var v = stack.pop(); 37293 var l = stack.pop(); 37294 37295 if (exports.DEBUG) { 37296 console.log(state.step, 'WS', v, l); 37297 } 37298 37299 store[l] = v; 37300 } 37301 37302 // RS[] Read Store 37303 // 0x43 37304 function RS(state) { 37305 var stack = state.stack; 37306 var store = state.store; 37307 37308 var l = stack.pop(); 37309 37310 if (exports.DEBUG) { 37311 console.log(state.step, 'RS', l); 37312 } 37313 37314 var v = (store && store[l]) || 0; 37315 37316 stack.push(v); 37317 } 37318 37319 // WCVTP[] Write Control Value Table in Pixel units 37320 // 0x44 37321 function WCVTP(state) { 37322 var stack = state.stack; 37323 37324 var v = stack.pop(); 37325 var l = stack.pop(); 37326 37327 if (exports.DEBUG) { 37328 console.log(state.step, 'WCVTP', v, l); 37329 } 37330 37331 state.cvt[l] = v / 0x40; 37332 } 37333 37334 // RCVT[] Read Control Value Table entry 37335 // 0x45 37336 function RCVT(state) { 37337 var stack = state.stack; 37338 var cvte = stack.pop(); 37339 37340 if (exports.DEBUG) { 37341 console.log(state.step, 'RCVT', cvte); 37342 } 37343 37344 stack.push(state.cvt[cvte] * 0x40); 37345 } 37346 37347 // GC[] Get Coordinate projected onto the projection vector 37348 // 0x46-0x47 37349 function GC(a, state) { 37350 var stack = state.stack; 37351 var pi = stack.pop(); 37352 var p = state.z2[pi]; 37353 37354 if (exports.DEBUG) { 37355 console.log(state.step, 'GC[' + a + ']', pi); 37356 } 37357 37358 stack.push(state.dpv.distance(p, HPZero, a, false) * 0x40); 37359 } 37360 37361 // MD[a] Measure Distance 37362 // 0x49-0x4A 37363 function MD(a, state) { 37364 var stack = state.stack; 37365 var pi2 = stack.pop(); 37366 var pi1 = stack.pop(); 37367 var p2 = state.z1[pi2]; 37368 var p1 = state.z0[pi1]; 37369 var d = state.dpv.distance(p1, p2, a, a); 37370 37371 if (exports.DEBUG) { 37372 console.log(state.step, 'MD[' + a + ']', pi2, pi1, '->', d); 37373 } 37374 37375 state.stack.push(Math.round(d * 64)); 37376 } 37377 37378 // MPPEM[] Measure Pixels Per EM 37379 // 0x4B 37380 function MPPEM(state) { 37381 if (exports.DEBUG) { 37382 console.log(state.step, 'MPPEM[]'); 37383 } 37384 state.stack.push(state.ppem); 37385 } 37386 37387 // FLIPON[] set the auto FLIP Boolean to ON 37388 // 0x4D 37389 function FLIPON(state) { 37390 if (exports.DEBUG) { 37391 console.log(state.step, 'FLIPON[]'); 37392 } 37393 state.autoFlip = true; 37394 } 37395 37396 // LT[] Less Than 37397 // 0x50 37398 function LT(state) { 37399 var stack = state.stack; 37400 var e2 = stack.pop(); 37401 var e1 = stack.pop(); 37402 37403 if (exports.DEBUG) { 37404 console.log(state.step, 'LT[]', e2, e1); 37405 } 37406 37407 stack.push(e1 < e2 ? 1 : 0); 37408 } 37409 37410 // LTEQ[] Less Than or EQual 37411 // 0x53 37412 function LTEQ(state) { 37413 var stack = state.stack; 37414 var e2 = stack.pop(); 37415 var e1 = stack.pop(); 37416 37417 if (exports.DEBUG) { 37418 console.log(state.step, 'LTEQ[]', e2, e1); 37419 } 37420 37421 stack.push(e1 <= e2 ? 1 : 0); 37422 } 37423 37424 // GTEQ[] Greater Than 37425 // 0x52 37426 function GT(state) { 37427 var stack = state.stack; 37428 var e2 = stack.pop(); 37429 var e1 = stack.pop(); 37430 37431 if (exports.DEBUG) { 37432 console.log(state.step, 'GT[]', e2, e1); 37433 } 37434 37435 stack.push(e1 > e2 ? 1 : 0); 37436 } 37437 37438 // GTEQ[] Greater Than or EQual 37439 // 0x53 37440 function GTEQ(state) { 37441 var stack = state.stack; 37442 var e2 = stack.pop(); 37443 var e1 = stack.pop(); 37444 37445 if (exports.DEBUG) { 37446 console.log(state.step, 'GTEQ[]', e2, e1); 37447 } 37448 37449 stack.push(e1 >= e2 ? 1 : 0); 37450 } 37451 37452 // EQ[] EQual 37453 // 0x54 37454 function EQ(state) { 37455 var stack = state.stack; 37456 var e2 = stack.pop(); 37457 var e1 = stack.pop(); 37458 37459 if (exports.DEBUG) { 37460 console.log(state.step, 'EQ[]', e2, e1); 37461 } 37462 37463 stack.push(e2 === e1 ? 1 : 0); 37464 } 37465 37466 // NEQ[] Not EQual 37467 // 0x55 37468 function NEQ(state) { 37469 var stack = state.stack; 37470 var e2 = stack.pop(); 37471 var e1 = stack.pop(); 37472 37473 if (exports.DEBUG) { 37474 console.log(state.step, 'NEQ[]', e2, e1); 37475 } 37476 37477 stack.push(e2 !== e1 ? 1 : 0); 37478 } 37479 37480 // ODD[] ODD 37481 // 0x56 37482 function ODD(state) { 37483 var stack = state.stack; 37484 var n = stack.pop(); 37485 37486 if (exports.DEBUG) { 37487 console.log(state.step, 'ODD[]', n); 37488 } 37489 37490 stack.push(Math.trunc(n) % 2 ? 1 : 0); 37491 } 37492 37493 // EVEN[] EVEN 37494 // 0x57 37495 function EVEN(state) { 37496 var stack = state.stack; 37497 var n = stack.pop(); 37498 37499 if (exports.DEBUG) { 37500 console.log(state.step, 'EVEN[]', n); 37501 } 37502 37503 stack.push(Math.trunc(n) % 2 ? 0 : 1); 37504 } 37505 37506 // IF[] IF test 37507 // 0x58 37508 function IF(state) { 37509 var test = state.stack.pop(); 37510 37511 if (exports.DEBUG) { 37512 console.log(state.step, 'IF[]', test); 37513 } 37514 37515 // if test is true it just continues 37516 // if not the ip is skipped until matching ELSE or EIF 37517 if (!test) { 37518 skip(state, true); 37519 37520 if (exports.DEBUG) { 37521 console.log(state.step, 'EIF[]'); 37522 } 37523 } 37524 } 37525 37526 // EIF[] End IF 37527 // 0x59 37528 function EIF(state) { 37529 // this can be reached normally when 37530 // executing an else branch. 37531 // -> just ignore it 37532 37533 if (exports.DEBUG) { 37534 console.log(state.step, 'EIF[]'); 37535 } 37536 } 37537 37538 // AND[] logical AND 37539 // 0x5A 37540 function AND(state) { 37541 var stack = state.stack; 37542 var e2 = stack.pop(); 37543 var e1 = stack.pop(); 37544 37545 if (exports.DEBUG) { 37546 console.log(state.step, 'AND[]', e2, e1); 37547 } 37548 37549 stack.push(e2 && e1 ? 1 : 0); 37550 } 37551 37552 // OR[] logical OR 37553 // 0x5B 37554 function OR(state) { 37555 var stack = state.stack; 37556 var e2 = stack.pop(); 37557 var e1 = stack.pop(); 37558 37559 if (exports.DEBUG) { 37560 console.log(state.step, 'OR[]', e2, e1); 37561 } 37562 37563 stack.push(e2 || e1 ? 1 : 0); 37564 } 37565 37566 // NOT[] logical NOT 37567 // 0x5C 37568 function NOT(state) { 37569 var stack = state.stack; 37570 var e = stack.pop(); 37571 37572 if (exports.DEBUG) { 37573 console.log(state.step, 'NOT[]', e); 37574 } 37575 37576 stack.push(e ? 0 : 1); 37577 } 37578 37579 // DELTAP1[] DELTA exception P1 37580 // DELTAP2[] DELTA exception P2 37581 // DELTAP3[] DELTA exception P3 37582 // 0x5D, 0x71, 0x72 37583 function DELTAP123(b, state) { 37584 var stack = state.stack; 37585 var n = stack.pop(); 37586 var fv = state.fv; 37587 var pv = state.pv; 37588 var ppem = state.ppem; 37589 var base = state.deltaBase + (b - 1) * 16; 37590 var ds = state.deltaShift; 37591 var z0 = state.z0; 37592 37593 if (exports.DEBUG) { 37594 console.log(state.step, 'DELTAP[' + b + ']', n, stack); 37595 } 37596 37597 for (var i = 0; i < n; i++) { 37598 var pi = stack.pop(); 37599 var arg = stack.pop(); 37600 var appem = base + ((arg & 0xf0) >> 4); 37601 if (appem !== ppem) { 37602 continue; 37603 } 37604 37605 var mag = (arg & 0x0f) - 8; 37606 if (mag >= 0) { 37607 mag++; 37608 } 37609 if (exports.DEBUG) { 37610 console.log(state.step, 'DELTAPFIX', pi, 'by', mag * ds); 37611 } 37612 37613 var p = z0[pi]; 37614 fv.setRelative(p, p, mag * ds, pv); 37615 } 37616 } 37617 37618 // SDB[] Set Delta Base in the graphics state 37619 // 0x5E 37620 function SDB(state) { 37621 var stack = state.stack; 37622 var n = stack.pop(); 37623 37624 if (exports.DEBUG) { 37625 console.log(state.step, 'SDB[]', n); 37626 } 37627 37628 state.deltaBase = n; 37629 } 37630 37631 // SDS[] Set Delta Shift in the graphics state 37632 // 0x5F 37633 function SDS(state) { 37634 var stack = state.stack; 37635 var n = stack.pop(); 37636 37637 if (exports.DEBUG) { 37638 console.log(state.step, 'SDS[]', n); 37639 } 37640 37641 state.deltaShift = Math.pow(0.5, n); 37642 } 37643 37644 // ADD[] ADD 37645 // 0x60 37646 function ADD(state) { 37647 var stack = state.stack; 37648 var n2 = stack.pop(); 37649 var n1 = stack.pop(); 37650 37651 if (exports.DEBUG) { 37652 console.log(state.step, 'ADD[]', n2, n1); 37653 } 37654 37655 stack.push(n1 + n2); 37656 } 37657 37658 // SUB[] SUB 37659 // 0x61 37660 function SUB(state) { 37661 var stack = state.stack; 37662 var n2 = stack.pop(); 37663 var n1 = stack.pop(); 37664 37665 if (exports.DEBUG) { 37666 console.log(state.step, 'SUB[]', n2, n1); 37667 } 37668 37669 stack.push(n1 - n2); 37670 } 37671 37672 // DIV[] DIV 37673 // 0x62 37674 function DIV(state) { 37675 var stack = state.stack; 37676 var n2 = stack.pop(); 37677 var n1 = stack.pop(); 37678 37679 if (exports.DEBUG) { 37680 console.log(state.step, 'DIV[]', n2, n1); 37681 } 37682 37683 stack.push(n1 * 64 / n2); 37684 } 37685 37686 // MUL[] MUL 37687 // 0x63 37688 function MUL(state) { 37689 var stack = state.stack; 37690 var n2 = stack.pop(); 37691 var n1 = stack.pop(); 37692 37693 if (exports.DEBUG) { 37694 console.log(state.step, 'MUL[]', n2, n1); 37695 } 37696 37697 stack.push(n1 * n2 / 64); 37698 } 37699 37700 // ABS[] ABSolute value 37701 // 0x64 37702 function ABS(state) { 37703 var stack = state.stack; 37704 var n = stack.pop(); 37705 37706 if (exports.DEBUG) { 37707 console.log(state.step, 'ABS[]', n); 37708 } 37709 37710 stack.push(Math.abs(n)); 37711 } 37712 37713 // NEG[] NEGate 37714 // 0x65 37715 function NEG(state) { 37716 var stack = state.stack; 37717 var n = stack.pop(); 37718 37719 if (exports.DEBUG) { 37720 console.log(state.step, 'NEG[]', n); 37721 } 37722 37723 stack.push(-n); 37724 } 37725 37726 // FLOOR[] FLOOR 37727 // 0x66 37728 function FLOOR(state) { 37729 var stack = state.stack; 37730 var n = stack.pop(); 37731 37732 if (exports.DEBUG) { 37733 console.log(state.step, 'FLOOR[]', n); 37734 } 37735 37736 stack.push(Math.floor(n / 0x40) * 0x40); 37737 } 37738 37739 // CEILING[] CEILING 37740 // 0x67 37741 function CEILING(state) { 37742 var stack = state.stack; 37743 var n = stack.pop(); 37744 37745 if (exports.DEBUG) { 37746 console.log(state.step, 'CEILING[]', n); 37747 } 37748 37749 stack.push(Math.ceil(n / 0x40) * 0x40); 37750 } 37751 37752 // ROUND[ab] ROUND value 37753 // 0x68-0x6B 37754 function ROUND(dt, state) { 37755 var stack = state.stack; 37756 var n = stack.pop(); 37757 37758 if (exports.DEBUG) { 37759 console.log(state.step, 'ROUND[]'); 37760 } 37761 37762 stack.push(state.round(n / 0x40) * 0x40); 37763 } 37764 37765 // WCVTF[] Write Control Value Table in Funits 37766 // 0x70 37767 function WCVTF(state) { 37768 var stack = state.stack; 37769 var v = stack.pop(); 37770 var l = stack.pop(); 37771 37772 if (exports.DEBUG) { 37773 console.log(state.step, 'WCVTF[]', v, l); 37774 } 37775 37776 state.cvt[l] = v * state.ppem / state.font.unitsPerEm; 37777 } 37778 37779 // DELTAC1[] DELTA exception C1 37780 // DELTAC2[] DELTA exception C2 37781 // DELTAC3[] DELTA exception C3 37782 // 0x73, 0x74, 0x75 37783 function DELTAC123(b, state) { 37784 var stack = state.stack; 37785 var n = stack.pop(); 37786 var ppem = state.ppem; 37787 var base = state.deltaBase + (b - 1) * 16; 37788 var ds = state.deltaShift; 37789 37790 if (exports.DEBUG) { 37791 console.log(state.step, 'DELTAC[' + b + ']', n, stack); 37792 } 37793 37794 for (var i = 0; i < n; i++) { 37795 var c = stack.pop(); 37796 var arg = stack.pop(); 37797 var appem = base + ((arg & 0xf0) >> 4); 37798 if (appem !== ppem) { 37799 continue; 37800 } 37801 37802 var mag = (arg & 0x0f) - 8; 37803 if (mag >= 0) { 37804 mag++; 37805 } 37806 37807 var delta = mag * ds; 37808 37809 if (exports.DEBUG) { 37810 console.log(state.step, 'DELTACFIX', c, 'by', delta); 37811 } 37812 37813 state.cvt[c] += delta; 37814 } 37815 } 37816 37817 // SROUND[] Super ROUND 37818 // 0x76 37819 function SROUND(state) { 37820 var n = state.stack.pop(); 37821 37822 if (exports.DEBUG) { 37823 console.log(state.step, 'SROUND[]', n); 37824 } 37825 37826 state.round = roundSuper; 37827 37828 var period; 37829 37830 switch (n & 0xc0) { 37831 case 0x00: 37832 period = 0.5; 37833 break; 37834 case 0x40: 37835 period = 1; 37836 break; 37837 case 0x80: 37838 period = 2; 37839 break; 37840 default: 37841 throw new Error('invalid SROUND value'); 37842 } 37843 37844 state.srPeriod = period; 37845 37846 switch (n & 0x30) { 37847 case 0x00: 37848 state.srPhase = 0; 37849 break; 37850 case 0x10: 37851 state.srPhase = 0.25 * period; 37852 break; 37853 case 0x20: 37854 state.srPhase = 0.5 * period; 37855 break; 37856 case 0x30: 37857 state.srPhase = 0.75 * period; 37858 break; 37859 default: 37860 throw new Error('invalid SROUND value'); 37861 } 37862 37863 n &= 0x0f; 37864 37865 if (n === 0) { 37866 state.srThreshold = 0; 37867 } else { 37868 state.srThreshold = (n / 8 - 0.5) * period; 37869 } 37870 } 37871 37872 // S45ROUND[] Super ROUND 45 degrees 37873 // 0x77 37874 function S45ROUND(state) { 37875 var n = state.stack.pop(); 37876 37877 if (exports.DEBUG) { 37878 console.log(state.step, 'S45ROUND[]', n); 37879 } 37880 37881 state.round = roundSuper; 37882 37883 var period; 37884 37885 switch (n & 0xc0) { 37886 case 0x00: 37887 period = Math.sqrt(2) / 2; 37888 break; 37889 case 0x40: 37890 period = Math.sqrt(2); 37891 break; 37892 case 0x80: 37893 period = 2 * Math.sqrt(2); 37894 break; 37895 default: 37896 throw new Error('invalid S45ROUND value'); 37897 } 37898 37899 state.srPeriod = period; 37900 37901 switch (n & 0x30) { 37902 case 0x00: 37903 state.srPhase = 0; 37904 break; 37905 case 0x10: 37906 state.srPhase = 0.25 * period; 37907 break; 37908 case 0x20: 37909 state.srPhase = 0.5 * period; 37910 break; 37911 case 0x30: 37912 state.srPhase = 0.75 * period; 37913 break; 37914 default: 37915 throw new Error('invalid S45ROUND value'); 37916 } 37917 37918 n &= 0x0f; 37919 37920 if (n === 0) { 37921 state.srThreshold = 0; 37922 } else { 37923 state.srThreshold = (n / 8 - 0.5) * period; 37924 } 37925 } 37926 37927 // ROFF[] Round Off 37928 // 0x7A 37929 function ROFF(state) { 37930 if (exports.DEBUG) { 37931 console.log(state.step, 'ROFF[]'); 37932 } 37933 37934 state.round = roundOff; 37935 } 37936 37937 // RUTG[] Round Up To Grid 37938 // 0x7C 37939 function RUTG(state) { 37940 if (exports.DEBUG) { 37941 console.log(state.step, 'RUTG[]'); 37942 } 37943 37944 state.round = roundUpToGrid; 37945 } 37946 37947 // RDTG[] Round Down To Grid 37948 // 0x7D 37949 function RDTG(state) { 37950 if (exports.DEBUG) { 37951 console.log(state.step, 'RDTG[]'); 37952 } 37953 37954 state.round = roundDownToGrid; 37955 } 37956 37957 // SCANCTRL[] SCAN conversion ConTRoL 37958 // 0x85 37959 function SCANCTRL(state) { 37960 var n = state.stack.pop(); 37961 37962 // ignored by opentype.js 37963 37964 if (exports.DEBUG) { 37965 console.log(state.step, 'SCANCTRL[]', n); 37966 } 37967 } 37968 37969 // SDPVTL[a] Set Dual Projection Vector To Line 37970 // 0x86-0x87 37971 function SDPVTL(a, state) { 37972 var stack = state.stack; 37973 var p2i = stack.pop(); 37974 var p1i = stack.pop(); 37975 var p2 = state.z2[p2i]; 37976 var p1 = state.z1[p1i]; 37977 37978 if (exports.DEBUG) { 37979 console.log(state.step, 'SDPVTL[' + a + ']', p2i, p1i); 37980 } 37981 37982 var dx; 37983 var dy; 37984 37985 if (!a) { 37986 dx = p1.x - p2.x; 37987 dy = p1.y - p2.y; 37988 } else { 37989 dx = p2.y - p1.y; 37990 dy = p1.x - p2.x; 37991 } 37992 37993 state.dpv = getUnitVector(dx, dy); 37994 } 37995 37996 // GETINFO[] GET INFOrmation 37997 // 0x88 37998 function GETINFO(state) { 37999 var stack = state.stack; 38000 var sel = stack.pop(); 38001 var r = 0; 38002 38003 if (exports.DEBUG) { 38004 console.log(state.step, 'GETINFO[]', sel); 38005 } 38006 38007 // v35 as in no subpixel hinting 38008 if (sel & 0x01) { 38009 r = 35; 38010 } 38011 38012 // TODO rotation and stretch currently not supported 38013 // and thus those GETINFO are always 0. 38014 38015 // opentype.js is always gray scaling 38016 if (sel & 0x20) { 38017 r |= 0x1000; 38018 } 38019 38020 stack.push(r); 38021 } 38022 38023 // ROLL[] ROLL the top three stack elements 38024 // 0x8A 38025 function ROLL(state) { 38026 var stack = state.stack; 38027 var a = stack.pop(); 38028 var b = stack.pop(); 38029 var c = stack.pop(); 38030 38031 if (exports.DEBUG) { 38032 console.log(state.step, 'ROLL[]'); 38033 } 38034 38035 stack.push(b); 38036 stack.push(a); 38037 stack.push(c); 38038 } 38039 38040 // MAX[] MAXimum of top two stack elements 38041 // 0x8B 38042 function MAX(state) { 38043 var stack = state.stack; 38044 var e2 = stack.pop(); 38045 var e1 = stack.pop(); 38046 38047 if (exports.DEBUG) { 38048 console.log(state.step, 'MAX[]', e2, e1); 38049 } 38050 38051 stack.push(Math.max(e1, e2)); 38052 } 38053 38054 // MIN[] MINimum of top two stack elements 38055 // 0x8C 38056 function MIN(state) { 38057 var stack = state.stack; 38058 var e2 = stack.pop(); 38059 var e1 = stack.pop(); 38060 38061 if (exports.DEBUG) { 38062 console.log(state.step, 'MIN[]', e2, e1); 38063 } 38064 38065 stack.push(Math.min(e1, e2)); 38066 } 38067 38068 // SCANTYPE[] SCANTYPE 38069 // 0x8D 38070 function SCANTYPE(state) { 38071 var n = state.stack.pop(); 38072 // ignored by opentype.js 38073 if (exports.DEBUG) { 38074 console.log(state.step, 'SCANTYPE[]', n); 38075 } 38076 } 38077 38078 // INSTCTRL[] INSTCTRL 38079 // 0x8D 38080 function INSTCTRL(state) { 38081 var s = state.stack.pop(); 38082 var v = state.stack.pop(); 38083 38084 if (exports.DEBUG) { 38085 console.log(state.step, 'INSTCTRL[]', s, v); 38086 } 38087 38088 switch (s) { 38089 case 1: 38090 state.inhibitGridFit = !!v; 38091 return; 38092 case 2: 38093 state.ignoreCvt = !!v; 38094 return; 38095 default: 38096 throw new Error('invalid INSTCTRL[] selector'); 38097 } 38098 } 38099 38100 // PUSHB[abc] PUSH Bytes 38101 // 0xB0-0xB7 38102 function PUSHB(n, state) { 38103 var stack = state.stack; 38104 var prog = state.prog; 38105 var ip = state.ip; 38106 38107 if (exports.DEBUG) { 38108 console.log(state.step, 'PUSHB[' + n + ']'); 38109 } 38110 38111 for (var i = 0; i < n; i++) { 38112 stack.push(prog[++ip]); 38113 } 38114 38115 state.ip = ip; 38116 } 38117 38118 // PUSHW[abc] PUSH Words 38119 // 0xB8-0xBF 38120 function PUSHW(n, state) { 38121 var ip = state.ip; 38122 var prog = state.prog; 38123 var stack = state.stack; 38124 38125 if (exports.DEBUG) { 38126 console.log(state.ip, 'PUSHW[' + n + ']'); 38127 } 38128 38129 for (var i = 0; i < n; i++) { 38130 var w = (prog[++ip] << 8) | prog[++ip]; 38131 if (w & 0x8000) { 38132 w = -((w ^ 0xffff) + 1); 38133 } 38134 stack.push(w); 38135 } 38136 38137 state.ip = ip; 38138 } 38139 38140 // MDRP[abcde] Move Direct Relative Point 38141 // 0xD0-0xEF 38142 // (if indirect is 0) 38143 // 38144 // and 38145 // 38146 // MIRP[abcde] Move Indirect Relative Point 38147 // 0xE0-0xFF 38148 // (if indirect is 1) 38149 38150 function MDRP_MIRP(indirect, setRp0, keepD, ro, dt, state) { 38151 var stack = state.stack; 38152 var cvte = indirect && stack.pop(); 38153 var pi = stack.pop(); 38154 var rp0i = state.rp0; 38155 var rp = state.z0[rp0i]; 38156 var p = state.z1[pi]; 38157 38158 var md = state.minDis; 38159 var fv = state.fv; 38160 var pv = state.dpv; 38161 var od; // original distance 38162 var d; // moving distance 38163 var sign; // sign of distance 38164 var cv; 38165 38166 d = od = pv.distance(p, rp, true, true); 38167 sign = d >= 0 ? 1 : -1; // Math.sign would be 0 in case of 0 38168 38169 // TODO consider autoFlip 38170 d = Math.abs(d); 38171 38172 if (indirect) { 38173 cv = state.cvt[cvte]; 38174 38175 if (ro && Math.abs(d - cv) < state.cvCutIn) { 38176 d = cv; 38177 } 38178 } 38179 38180 if (keepD && d < md) { 38181 d = md; 38182 } 38183 38184 if (ro) { 38185 d = state.round(d); 38186 } 38187 38188 fv.setRelative(p, rp, sign * d, pv); 38189 fv.touch(p); 38190 38191 if (exports.DEBUG) { 38192 console.log( 38193 state.step, 38194 (indirect ? 'MIRP[' : 'MDRP[') + 38195 (setRp0 ? 'M' : 'm') + 38196 (keepD ? '>' : '_') + 38197 (ro ? 'R' : '_') + 38198 (dt === 0 ? 'Gr' : dt === 1 ? 'Bl' : dt === 2 ? 'Wh' : '') + 38199 ']', 38200 indirect ? cvte + '(' + state.cvt[cvte] + ',' + cv + ')' : '', 38201 pi, 38202 '(d =', 38203 od,
38204 '->', 38205 sign * d, 38206 ')' 38207 ); 38208 } 38209 38210 state.rp1 = state.rp0; 38211 state.rp2 = pi; 38212 if (setRp0) { 38213 state.rp0 = pi; 38214 } 38215 } 38216 38217 /* 38218 * The instruction table. 38219 */ 38220 instructionTable = [ 38221 /* 0x00 */ SVTCA.bind(undefined, yUnitVector), 38222 /* 0x01 */ SVTCA.bind(undefined, xUnitVector), 38223 /* 0x02 */ SPVTCA.bind(undefined, yUnitVector), 38224 /* 0x03 */ SPVTCA.bind(undefined, xUnitVector), 38225 /* 0x04 */ SFVTCA.bind(undefined, yUnitVector), 38226 /* 0x05 */ SFVTCA.bind(undefined, xUnitVector), 38227 /* 0x06 */ SPVTL.bind(undefined, 0), 38228 /* 0x07 */ SPVTL.bind(undefined, 1), 38229 /* 0x08 */ SFVTL.bind(undefined, 0), 38230 /* 0x09 */ SFVTL.bind(undefined, 1), 38231 /* 0x0A */ SPVFS, 38232 /* 0x0B */ SFVFS, 38233 /* 0x0C */ GPV, 38234 /* 0x0D */ GFV, 38235 /* 0x0E */ SFVTPV, 38236 /* 0x0F */ ISECT, 38237 /* 0x10 */ SRP0, 38238 /* 0x11 */ SRP1, 38239 /* 0x12 */ SRP2, 38240 /* 0x13 */ SZP0, 38241 /* 0x14 */ SZP1, 38242 /* 0x15 */ SZP2, 38243 /* 0x16 */ SZPS, 38244 /* 0x17 */ SLOOP, 38245 /* 0x18 */ RTG, 38246 /* 0x19 */ RTHG, 38247 /* 0x1A */ SMD, 38248 /* 0x1B */ ELSE, 38249 /* 0x1C */ JMPR, 38250 /* 0x1D */ SCVTCI, 38251 /* 0x1E */ undefined, // TODO SSWCI 38252 /* 0x1F */ undefined, // TODO SSW 38253 /* 0x20 */ DUP, 38254 /* 0x21 */ POP, 38255 /* 0x22 */ CLEAR, 38256 /* 0x23 */ SWAP, 38257 /* 0x24 */ DEPTH, 38258 /* 0x25 */ CINDEX, 38259 /* 0x26 */ MINDEX, 38260 /* 0x27 */ undefined, // TODO ALIGNPTS 38261 /* 0x28 */ undefined, 38262 /* 0x29 */ undefined, // TODO UTP 38263 /* 0x2A */ LOOPCALL, 38264 /* 0x2B */ CALL, 38265 /* 0x2C */ FDEF, 38266 /* 0x2D */ undefined, // ENDF (eaten by FDEF) 38267 /* 0x2E */ MDAP.bind(undefined, 0), 38268 /* 0x2F */ MDAP.bind(undefined, 1), 38269 /* 0x30 */ IUP.bind(undefined, yUnitVector), 38270 /* 0x31 */ IUP.bind(undefined, xUnitVector), 38271 /* 0x32 */ SHP.bind(undefined, 0), 38272 /* 0x33 */ SHP.bind(undefined, 1), 38273 /* 0x34 */ SHC.bind(undefined, 0), 38274 /* 0x35 */ SHC.bind(undefined, 1), 38275 /* 0x36 */ SHZ.bind(undefined, 0), 38276 /* 0x37 */ SHZ.bind(undefined, 1), 38277 /* 0x38 */ SHPIX, 38278 /* 0x39 */ IP, 38279 /* 0x3A */ MSIRP.bind(undefined, 0), 38280 /* 0x3B */ MSIRP.bind(undefined, 1), 38281 /* 0x3C */ ALIGNRP, 38282 /* 0x3D */ RTDG, 38283 /* 0x3E */ MIAP.bind(undefined, 0), 38284 /* 0x3F */ MIAP.bind(undefined, 1), 38285 /* 0x40 */ NPUSHB, 38286 /* 0x41 */ NPUSHW, 38287 /* 0x42 */ WS, 38288 /* 0x43 */ RS, 38289 /* 0x44 */ WCVTP, 38290 /* 0x45 */ RCVT, 38291 /* 0x46 */ GC.bind(undefined, 0), 38292 /* 0x47 */ GC.bind(undefined, 1), 38293 /* 0x48 */ undefined, // TODO SCFS 38294 /* 0x49 */ MD.bind(undefined, 0), 38295 /* 0x4A */ MD.bind(undefined, 1), 38296 /* 0x4B */ MPPEM, 38297 /* 0x4C */ undefined, // TODO MPS 38298 /* 0x4D */ FLIPON, 38299 /* 0x4E */ undefined, // TODO FLIPOFF 38300 /* 0x4F */ undefined, // TODO DEBUG 38301 /* 0x50 */ LT, 38302 /* 0x51 */ LTEQ, 38303 /* 0x52 */ GT, 38304 /* 0x53 */ GTEQ, 38305 /* 0x54 */ EQ, 38306 /* 0x55 */ NEQ, 38307 /* 0x56 */ ODD, 38308 /* 0x57 */ EVEN, 38309 /* 0x58 */ IF, 38310 /* 0x59 */ EIF, 38311 /* 0x5A */ AND, 38312 /* 0x5B */ OR, 38313 /* 0x5C */ NOT, 38314 /* 0x5D */ DELTAP123.bind(undefined, 1), 38315 /* 0x5E */ SDB, 38316 /* 0x5F */ SDS, 38317 /* 0x60 */ ADD, 38318 /* 0x61 */ SUB, 38319 /* 0x62 */ DIV, 38320 /* 0x63 */ MUL, 38321 /* 0x64 */ ABS, 38322 /* 0x65 */ NEG, 38323 /* 0x66 */ FLOOR, 38324 /* 0x67 */ CEILING, 38325 /* 0x68 */ ROUND.bind(undefined, 0), 38326 /* 0x69 */ ROUND.bind(undefined, 1), 38327 /* 0x6A */ ROUND.bind(undefined, 2), 38328 /* 0x6B */ ROUND.bind(undefined, 3), 38329 /* 0x6C */ undefined, // TODO NROUND[ab] 38330 /* 0x6D */ undefined, // TODO NROUND[ab] 38331 /* 0x6E */ undefined, // TODO NROUND[ab] 38332 /* 0x6F */ undefined, // TODO NROUND[ab] 38333 /* 0x70 */ WCVTF, 38334 /* 0x71 */ DELTAP123.bind(undefined, 2), 38335 /* 0x72 */ DELTAP123.bind(undefined, 3), 38336 /* 0x73 */ DELTAC123.bind(undefined, 1), 38337 /* 0x74 */ DELTAC123.bind(undefined, 2), 38338 /* 0x75 */ DELTAC123.bind(undefined, 3), 38339 /* 0x76 */ SROUND, 38340 /* 0x77 */ S45ROUND, 38341 /* 0x78 */ undefined, // TODO JROT[] 38342 /* 0x79 */ undefined, // TODO JROF[] 38343 /* 0x7A */ ROFF, 38344 /* 0x7B */ undefined, 38345 /* 0x7C */ RUTG, 38346 /* 0x7D */ RDTG, 38347 /* 0x7E */ POP, // actually SANGW, supposed to do only a pop though 38348 /* 0x7F */ POP, // actually AA, supposed to do only a pop though 38349 /* 0x80 */ undefined, // TODO FLIPPT 38350 /* 0x81 */ undefined, // TODO FLIPRGON 38351 /* 0x82 */ undefined, // TODO FLIPRGOFF 38352 /* 0x83 */ undefined, 38353 /* 0x84 */ undefined, 38354 /* 0x85 */ SCANCTRL, 38355 /* 0x86 */ SDPVTL.bind(undefined, 0), 38356 /* 0x87 */ SDPVTL.bind(undefined, 1), 38357 /* 0x88 */ GETINFO, 38358 /* 0x89 */ undefined, // TODO IDEF 38359 /* 0x8A */ ROLL, 38360 /* 0x8B */ MAX, 38361 /* 0x8C */ MIN, 38362 /* 0x8D */ SCANTYPE, 38363 /* 0x8E */ INSTCTRL, 38364 /* 0x8F */ undefined, 38365 /* 0x90 */ undefined, 38366 /* 0x91 */ undefined, 38367 /* 0x92 */ undefined, 38368 /* 0x93 */ undefined, 38369 /* 0x94 */ undefined, 38370 /* 0x95 */ undefined, 38371 /* 0x96 */ undefined, 38372 /* 0x97 */ undefined, 38373 /* 0x98 */ undefined, 38374 /* 0x99 */ undefined, 38375 /* 0x9A */ undefined, 38376 /* 0x9B */ undefined, 38377 /* 0x9C */ undefined, 38378 /* 0x9D */ undefined, 38379 /* 0x9E */ undefined, 38380 /* 0x9F */ undefined, 38381 /* 0xA0 */ undefined, 38382 /* 0xA1 */ undefined, 38383 /* 0xA2 */ undefined, 38384 /* 0xA3 */ undefined, 38385 /* 0xA4 */ undefined, 38386 /* 0xA5 */ undefined, 38387 /* 0xA6 */ undefined, 38388 /* 0xA7 */ undefined, 38389 /* 0xA8 */ undefined, 38390 /* 0xA9 */ undefined, 38391 /* 0xAA */ undefined, 38392 /* 0xAB */ undefined, 38393 /* 0xAC */ undefined, 38394 /* 0xAD */ undefined, 38395 /* 0xAE */ undefined, 38396 /* 0xAF */ undefined, 38397 /* 0xB0 */ PUSHB.bind(undefined, 1), 38398 /* 0xB1 */ PUSHB.bind(undefined, 2), 38399 /* 0xB2 */ PUSHB.bind(undefined, 3), 38400 /* 0xB3 */ PUSHB.bind(undefined, 4), 38401 /* 0xB4 */ PUSHB.bind(undefined, 5), 38402 /* 0xB5 */ PUSHB.bind(undefined, 6), 38403 /* 0xB6 */ PUSHB.bind(undefined, 7), 38404 /* 0xB7 */ PUSHB.bind(undefined, 8), 38405 /* 0xB8 */ PUSHW.bind(undefined, 1), 38406 /* 0xB9 */ PUSHW.bind(undefined, 2), 38407 /* 0xBA */ PUSHW.bind(undefined, 3), 38408 /* 0xBB */ PUSHW.bind(undefined, 4), 38409 /* 0xBC */ PUSHW.bind(undefined, 5), 38410 /* 0xBD */ PUSHW.bind(undefined, 6), 38411 /* 0xBE */ PUSHW.bind(undefined, 7), 38412 /* 0xBF */ PUSHW.bind(undefined, 8), 38413 /* 0xC0 */ MDRP_MIRP.bind(undefined, 0, 0, 0, 0, 0), 38414 /* 0xC1 */ MDRP_MIRP.bind(undefined, 0, 0, 0, 0, 1), 38415 /* 0xC2 */ MDRP_MIRP.bind(undefined, 0, 0, 0, 0, 2), 38416 /* 0xC3 */ MDRP_MIRP.bind(undefined, 0, 0, 0, 0, 3), 38417 /* 0xC4 */ MDRP_MIRP.bind(undefined, 0, 0, 0, 1, 0), 38418 /* 0xC5 */ MDRP_MIRP.bind(undefined, 0, 0, 0, 1, 1), 38419 /* 0xC6 */ MDRP_MIRP.bind(undefined, 0, 0, 0, 1, 2), 38420 /* 0xC7 */ MDRP_MIRP.bind(undefined, 0, 0, 0, 1, 3), 38421 /* 0xC8 */ MDRP_MIRP.bind(undefined, 0, 0, 1, 0, 0), 38422 /* 0xC9 */ MDRP_MIRP.bind(undefined, 0, 0, 1, 0, 1), 38423 /* 0xCA */ MDRP_MIRP.bind(undefined, 0, 0, 1, 0, 2), 38424 /* 0xCB */ MDRP_MIRP.bind(undefined, 0, 0, 1, 0, 3), 38425 /* 0xCC */ MDRP_MIRP.bind(undefined, 0, 0, 1, 1, 0), 38426 /* 0xCD */ MDRP_MIRP.bind(undefined, 0, 0, 1, 1, 1), 38427 /* 0xCE */ MDRP_MIRP.bind(undefined, 0, 0, 1, 1, 2), 38428 /* 0xCF */ MDRP_MIRP.bind(undefined, 0, 0, 1, 1, 3), 38429 /* 0xD0 */ MDRP_MIRP.bind(undefined, 0, 1, 0, 0, 0), 38430 /* 0xD1 */ MDRP_MIRP.bind(undefined, 0, 1, 0, 0, 1), 38431 /* 0xD2 */ MDRP_MIRP.bind(undefined, 0, 1, 0, 0, 2), 38432 /* 0xD3 */ MDRP_MIRP.bind(undefined, 0, 1, 0, 0, 3), 38433 /* 0xD4 */ MDRP_MIRP.bind(undefined, 0, 1, 0, 1, 0), 38434 /* 0xD5 */ MDRP_MIRP.bind(undefined, 0, 1, 0, 1, 1), 38435 /* 0xD6 */ MDRP_MIRP.bind(undefined, 0, 1, 0, 1, 2), 38436 /* 0xD7 */ MDRP_MIRP.bind(undefined, 0, 1, 0, 1, 3), 38437 /* 0xD8 */ MDRP_MIRP.bind(undefined, 0, 1, 1, 0, 0), 38438 /* 0xD9 */ MDRP_MIRP.bind(undefined, 0, 1, 1, 0, 1), 38439 /* 0xDA */ MDRP_MIRP.bind(undefined, 0, 1, 1, 0, 2), 38440 /* 0xDB */ MDRP_MIRP.bind(undefined, 0, 1, 1, 0, 3), 38441 /* 0xDC */ MDRP_MIRP.bind(undefined, 0, 1, 1, 1, 0), 38442 /* 0xDD */ MDRP_MIRP.bind(undefined, 0, 1, 1, 1, 1), 38443 /* 0xDE */ MDRP_MIRP.bind(undefined, 0, 1, 1, 1, 2), 38444 /* 0xDF */ MDRP_MIRP.bind(undefined, 0, 1, 1, 1, 3), 38445 /* 0xE0 */ MDRP_MIRP.bind(undefined, 1, 0, 0, 0, 0), 38446 /* 0xE1 */ MDRP_MIRP.bind(undefined, 1, 0, 0, 0, 1), 38447 /* 0xE2 */ MDRP_MIRP.bind(undefined, 1, 0, 0, 0, 2), 38448 /* 0xE3 */ MDRP_MIRP.bind(undefined, 1, 0, 0, 0, 3), 38449 /* 0xE4 */ MDRP_MIRP.bind(undefined, 1, 0, 0, 1, 0), 38450 /* 0xE5 */ MDRP_MIRP.bind(undefined, 1, 0, 0, 1, 1), 38451 /* 0xE6 */ MDRP_MIRP.bind(undefined, 1, 0, 0, 1, 2), 38452 /* 0xE7 */ MDRP_MIRP.bind(undefined, 1, 0, 0, 1, 3), 38453 /* 0xE8 */ MDRP_MIRP.bind(undefined, 1, 0, 1, 0, 0), 38454 /* 0xE9 */ MDRP_MIRP.bind(undefined, 1, 0, 1, 0, 1), 38455 /* 0xEA */ MDRP_MIRP.bind(undefined, 1, 0, 1, 0, 2), 38456 /* 0xEB */ MDRP_MIRP.bind(undefined, 1, 0, 1, 0, 3), 38457 /* 0xEC */ MDRP_MIRP.bind(undefined, 1, 0, 1, 1, 0), 38458 /* 0xED */ MDRP_MIRP.bind(undefined, 1, 0, 1, 1, 1), 38459 /* 0xEE */ MDRP_MIRP.bind(undefined, 1, 0, 1, 1, 2), 38460 /* 0xEF */ MDRP_MIRP.bind(undefined, 1, 0, 1, 1, 3), 38461 /* 0xF0 */ MDRP_MIRP.bind(undefined, 1, 1, 0, 0, 0), 38462 /* 0xF1 */ MDRP_MIRP.bind(undefined, 1, 1, 0, 0, 1), 38463 /* 0xF2 */ MDRP_MIRP.bind(undefined, 1, 1, 0, 0, 2), 38464 /* 0xF3 */ MDRP_MIRP.bind(undefined, 1, 1, 0, 0, 3), 38465 /* 0xF4 */ MDRP_MIRP.bind(undefined, 1, 1, 0, 1, 0), 38466 /* 0xF5 */ MDRP_MIRP.bind(undefined, 1, 1, 0, 1, 1), 38467 /* 0xF6 */ MDRP_MIRP.bind(undefined, 1, 1, 0, 1, 2), 38468 /* 0xF7 */ MDRP_MIRP.bind(undefined, 1, 1, 0, 1, 3), 38469 /* 0xF8 */ MDRP_MIRP.bind(undefined, 1, 1, 1, 0, 0), 38470 /* 0xF9 */ MDRP_MIRP.bind(undefined, 1, 1, 1, 0, 1), 38471 /* 0xFA */ MDRP_MIRP.bind(undefined, 1, 1, 1, 0, 2), 38472 /* 0xFB */ MDRP_MIRP.bind(undefined, 1, 1, 1, 0, 3), 38473 /* 0xFC */ MDRP_MIRP.bind(undefined, 1, 1, 1, 1, 0), 38474 /* 0xFD */ MDRP_MIRP.bind(undefined, 1, 1, 1, 1, 1), 38475 /* 0xFE */ MDRP_MIRP.bind(undefined, 1, 1, 1, 1, 2), 38476 /* 0xFF */ MDRP_MIRP.bind(undefined, 1, 1, 1, 1, 3) 38477 ]; 38478 38479 /***************************** 38480 Mathematical Considerations 38481 ****************************** 38482 38483 fv ... refers to freedom vector 38484 pv ... refers to projection vector 38485 rp ... refers to reference point 38486 p ... refers to to point being operated on 38487 d ... refers to distance 38488 38489 SETRELATIVE: 38490 ============ 38491 38492 case freedom vector == x-axis: 38493 ------------------------------ 38494 38495 (pv) 38496 .-' 38497 rpd .-' 38498 .-* 38499 d .-'90°' 38500 .-' ' 38501 .-' ' 38502 *-' ' b 38503 rp ' 38504 ' 38505 ' 38506 p *----------*-------------- (fv) 38507 pm 38508 38509 rpdx = rpx + d * pv.x 38510 rpdy = rpy + d * pv.y 38511 38512 equation of line b 38513 38514 y - rpdy = pvns * (x- rpdx) 38515 38516 y = p.y 38517 38518 x = rpdx + ( p.y - rpdy ) / pvns 38519 38520 38521 case freedom vector == y-axis: 38522 ------------------------------ 38523 38524 * pm 38525 |\ 38526 | \ 38527 | \ 38528 | \ 38529 | \ 38530 | \ 38531 | \ 38532 | \ 38533 | \ 38534 | \ b 38535 | \ 38536 | \ 38537 | \ .-' (pv) 38538 | 90° \.-' 38539 | .-'* rpd 38540 | .-' 38541 * *-' d 38542 p rp 38543 38544 rpdx = rpx + d * pv.x 38545 rpdy = rpy + d * pv.y 38546 38547 equation of line b: 38548 pvns ... normal slope to pv 38549 38550 y - rpdy = pvns * (x - rpdx) 38551 38552 x = p.x 38553 38554 y = rpdy + pvns * (p.x - rpdx) 38555 38556 38557 38558 generic case: 38559 ------------- 38560 38561 38562 .'(fv) 38563 .' 38564 .* pm 38565 .' ! 38566 .' . 38567 .' ! 38568 .' . b 38569 .' ! 38570 * . 38571 p ! 38572 90° . ... (pv) 38573 ...-*-''' 38574 ...---''' rpd 38575 ...---''' d 38576 *--''' 38577 rp 38578 38579 rpdx = rpx + d * pv.x 38580 rpdy = rpy + d * pv.y 38581 38582 equation of line b: 38583 pvns... normal slope to pv 38584 38585 y - rpdy = pvns * (x - rpdx) 38586 38587 equation of freedom vector line: 38588 fvs ... slope of freedom vector (=fy/fx) 38589
38590 y - py = fvs * (x - px) 38591 38592 38593 on pm both equations are true for same x/y 38594 38595 y - rpdy = pvns * (x - rpdx) 38596 38597 y - py = fvs * (x - px) 38598 38599 form to y and set equal: 38600 38601 pvns * (x - rpdx) + rpdy = fvs * (x - px) + py 38602 38603 expand: 38604 38605 pvns * x - pvns * rpdx + rpdy = fvs * x - fvs * px + py 38606 38607 switch: 38608 38609 fvs * x - fvs * px + py = pvns * x - pvns * rpdx + rpdy 38610 38611 solve for x: 38612 38613 fvs * x - pvns * x = fvs * px - pvns * rpdx - py + rpdy 38614 38615 38616 38617 fvs * px - pvns * rpdx + rpdy - py 38618 x = ----------------------------------- 38619 fvs - pvns 38620 38621 and: 38622 38623 y = fvs * (x - px) + py 38624 38625 38626 38627 INTERPOLATE: 38628 ============ 38629 38630 Examples of point interpolation. 38631 38632 The weight of the movement of the reference point gets bigger 38633 the further the other reference point is away, thus the safest 38634 option (that is avoiding 0/0 divisions) is to weight the 38635 original distance of the other point by the sum of both distances. 38636 38637 If the sum of both distances is 0, then move the point by the 38638 arithmetic average of the movement of both reference points. 38639 38640 38641 38642 38643 (+6) 38644 rp1o *---->*rp1 38645 . . (+12) 38646 . . rp2o *---------->* rp2 38647 . . . . 38648 . . . . 38649 . 10 20 . . 38650 |.........|...................| . 38651 . . . 38652 . . (+8) . 38653 po *------>*p . 38654 . . . 38655 . 12 . 24 . 38656 |...........|.......................| 38657 36 38658 38659 38660 ------- 38661 38662 38663 38664 (+10) 38665 rp1o *-------->*rp1 38666 . . (-10) 38667 . . rp2 *<---------* rpo2 38668 . . . . 38669 . . . . 38670 . 10 . 30 . . 38671 |.........|.............................| 38672 . . 38673 . (+5) . 38674 po *--->* p . 38675 . . . 38676 . . 20 . 38677 |....|..............| 38678 5 15 38679 38680 38681 ------- 38682 38683 38684 (+10) 38685 rp1o *-------->*rp1 38686 . . 38687 . . 38688 rp2o *-------->*rp2 38689 38690 38691 (+10) 38692 po *-------->* p 38693 38694 ------- 38695 38696 38697 (+10) 38698 rp1o *-------->*rp1 38699 . . 38700 . .(+30) 38701 rp2o *---------------------------->*rp2 38702 38703 38704 (+25) 38705 po *----------------------->* p 38706 38707 38708 38709 vim: set ts=4 sw=4 expandtab: 38710 *****/ 38711 38712 // The Font object 38713 38714 // This code is based on Array.from implementation for strings in https://github.com/mathiasbynens/Array.from 38715 var arrayFromString = 38716 Array.from || 38717 function(s) { 38718 return ( 38719 s.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]?|[^\uD800-\uDFFF]|./g) || [] 38720 ); 38721 }; 38722 38723 /** 38724 * @typedef FontOptions 38725 * @type Object 38726 * @property {Boolean} empty - whether to create a new empty font 38727 * @property {string} familyName 38728 * @property {string} styleName 38729 * @property {string=} fullName 38730 * @property {string=} postScriptName 38731 * @property {string=} designer 38732 * @property {string=} designerURL 38733 * @property {string=} manufacturer 38734 * @property {string=} manufacturerURL 38735 * @property {string=} license 38736 * @property {string=} licenseURL 38737 * @property {string=} version 38738 * @property {string=} description 38739 * @property {string=} copyright 38740 * @property {string=} trademark 38741 * @property {Number} unitsPerEm 38742 * @property {Number} ascender 38743 * @property {Number} descender 38744 * @property {Number} createdTimestamp 38745 * @property {string=} weightClass 38746 * @property {string=} widthClass 38747 * @property {string=} fsSelection 38748 */ 38749 38750 /** 38751 * A Font represents a loaded OpenType font file. 38752 * It contains a set of glyphs and methods to draw text on a drawing context, 38753 * or to get a path representing the text. 38754 * @exports opentype.Font 38755 * @class 38756 * @param {FontOptions} 38757 * @constructor 38758 */ 38759 function Font(options) { 38760 options = options || {}; 38761 38762 if (!options.empty) { 38763 // Check that we've provided the minimum set of names. 38764 checkArgument( 38765 options.familyName, 38766 'When creating a new Font object, familyName is required.' 38767 ); 38768 checkArgument( 38769 options.styleName, 38770 'When creating a new Font object, styleName is required.' 38771 ); 38772 checkArgument( 38773 options.unitsPerEm, 38774 'When creating a new Font object, unitsPerEm is required.' 38775 ); 38776 checkArgument( 38777 options.ascender, 38778 'When creating a new Font object, ascender is required.' 38779 ); 38780 checkArgument( 38781 options.descender, 38782 'When creating a new Font object, descender is required.' 38783 ); 38784 checkArgument( 38785 options.descender < 0, 38786 'Descender should be negative (e.g. -512).' 38787 ); 38788
38789 // OS X will complain if the names are empty, so we put a single space everywhere by default. 38790 this.names = { 38791 fontFamily: { en: options.familyName || ' ' }, 38792 fontSubfamily: { en: options.styleName || ' ' }, 38793 fullName: { 38794 en: options.fullName || options.familyName + ' ' + options.styleName 38795 }, 38796 // postScriptName may not contain any whitespace 38797 postScriptName: { 38798 en: 38799 options.postScriptName || 38800 (options.familyName + options.styleName).replace(/\s/g, '') 38801 }, 38802 designer: { en: options.designer || ' ' }, 38803 designerURL: { en: options.designerURL || ' ' }, 38804 manufacturer: { en: options.manufacturer || ' ' }, 38805 manufacturerURL: { en: options.manufacturerURL || ' ' }, 38806 license: { en: o
38806ptions.license || ' ' }, 38807 licenseURL: { en: options.licenseURL || ' ' }, 38808 version: { en: options.version || 'Version 0.1' }, 38809 description: { en: options.description || ' ' }, 38810 copyright: { en: options.copyright || ' ' }, 38811 trademark: { en: options.trademark || ' ' } 38812 }; 38813 this.unitsPerEm = options.unitsPerEm || 1000; 38814 this.ascender = options.ascender; 38815 this.descender = options.descender; 38816 this.createdTimestamp = options.createdTimestamp; 38817 this.tables = { 38818 os2: { 38819 usWeightClass: options.weightClass || this.usWeightClasses.MEDIUM, 38820 usWidthClass: options.widthClass || this.usWidthClasses.MEDIUM, 38821 fsSelection: options.fsSelection || this.fsSelectionValues.REGULAR 38822 } 38823 }; 38824 } 38825 38826 this.supported = true; // Deprecated: parseBuffer will throw an error if font is not supported. 38827 this.glyphs = new glyphset.GlyphSet(this, options.glyphs || []); 38828 this.encoding = new DefaultEncoding(this); 38829 this.position = new Position(this); 38830 this.substitution = new Substitution(this); 38831 this.tables = this.tables || {}; 38832 38833 Object.defineProperty(this, 'hinting', { 38834 get: function() { 38835 if (this._hinting) { 38836 return this._hinting; 38837 } 38838 if (this.outlinesFormat === 'truetype') { 38839 return (this._hinting = new Hinting(this)); 38840 } 38841 } 38842 }); 38843 } 38844 38845 /** 38846 * Check if the font has a glyph for the given character. 38847 * @param {string} 38848 * @return {Boolean} 38849 */ 38850 Font.prototype.hasChar = function(c) { 38851 return this.encoding.charToGlyphIndex(c) !== null; 38852 }; 38853 38854 /** 38855 * Convert the given character to a single glyph index. 38856 * Note that this function assumes that there is a one-to-one mapping between 38857 * the given character and a glyph; for complex scripts this might not be the case. 38858 * @param {string} 38859 * @return {Number} 38860 */ 38861 Font.prototype.charToGlyphIndex = function(s) { 38862 return this.encoding.charToGlyphIndex(s); 38863 }; 38864 38865 /** 38866 * Convert the given character to a single Glyph object. 38867 * Note that this function assumes that there is a one-to-one mapping between 38868 * the given character and a glyph; for complex scripts this might not be the case. 38869 * @param {string} 38870 * @return {opentype.Glyph} 38871 */ 38872 Font.prototype.charToGlyph = function(c) { 38873 var glyphIndex = this.charToGlyphIndex(c); 38874 var glyph = this.glyphs.get(glyphIndex); 38875 if (!glyph) { 38876 // .notdef 38877 glyph = this.glyphs.get(0); 38878 } 38879 38880 return glyph; 38881 }; 38882 38883 /** 38884 * Convert the given text to a list of Glyph objects. 38885 * Note that there is no strict one-to-one mapping between characters and 38886 * glyphs, so the list of returned glyphs can be larger or smaller than the 38887 * length of the given string. 38888 * @param {string} 38889 * @param {GlyphRenderOptions} [options] 38890 * @return {opentype.Glyph[]} 38891 */ 38892 Font.prototype.stringToGlyphs = function(s, options) { 38893 var this$1 = this; 38894 38895 options = options || this.defaultRenderOptions; 38896 // Get glyph indexes 38897 var chars = arrayFromString(s); 38898 var indexes = []; 38899 for (var i = 0; i < chars.length; i += 1) { 38900 var c = chars[i]; 38901 indexes.push(this$1.charToGlyphIndex(c)); 38902 } 38903 var length = indexes.length; 38904 38905 // Apply substitutions on glyph indexes 38906 if (options.features) { 38907 var script = options.script || this.substitution.getDefaultScriptName(); 38908 var manyToOne = []; 38909 if (options.features.liga) { 38910 manyToOne = manyToOne.concat( 38911 this.substitution.getFeature('liga', script, options.language) 38912 ); 38913 } 38914 if (options.features.rlig) { 38915 manyToOne = manyToOne.concat( 38916 this.substitution.getFeature('rlig', script, options.language) 38917 ); 38918 } 38919 for (var i$1 = 0; i$1 < length; i$1 += 1) { 38920 for (var j = 0; j < manyToOne.length; j++) { 38921 var ligature = manyToOne[j]; 38922 var components = ligature.sub; 38923 var compCount = components.length; 38924 var k = 0; 38925 while (k < compCount && components[k] === indexes[i$1 + k]) { 38926 k++; 38927 } 38928 if (k === compCount) { 38929 indexes.splice(i$1, compCount, ligature.by); 38930 length = length - compCount + 1; 38931 } 38932 } 38933 } 38934 } 38935 38936 // convert glyph indexes to glyph objects 38937 var glyphs = new Array(length); 38938 var notdef = this.glyphs.get(0); 38939 for (var i$2 = 0; i$2 < length; i$2 += 1) { 38940 glyphs[i$2] = this$1.glyphs.get(indexes[i$2]) || notdef; 38941 } 38942 return glyphs; 38943 }; 38944 38945 /** 38946 * @param {string} 38947 * @return {Number} 38948 */ 38949 Font.prototype.nameToGlyphIndex = function(name) { 38950 return this.glyphNames.nameToGlyphIndex(name); 38951 }; 38952 38953 /** 38954 * @param {string} 38955 * @return {opentype.Glyph} 38956 */ 38957 Font.prototype.nameToGlyph = function(name) { 38958 var glyphIndex = this.nameToGlyphIndex(name); 38959 var glyph = this.glyphs.get(glyphIndex); 38960 if (!glyph) { 38961 // .notdef 38962 glyph = this.glyphs.get(0); 38963 } 38964 38965 return glyph; 38966 }; 38967 38968 /** 38969 * @param {Number} 38970 * @return {String} 38971 */ 38972 Font.prototype.glyphIndexToName = function(gid) { 38973 if (!this.glyphNames.glyphIndexToName) { 38974 return ''; 38975 } 38976 38977 return this.glyphNames.glyphIndexToName(gid); 38978 }; 38979 38980 /** 38981 * Retrieve the value of the kerning pair between the left glyph (or its index) 38982 * and the right glyph (or its index). If no kerning pair is found, return 0. 38983 * The kerning value gets added to the advance width when calculating the spacing 38984 * between glyphs. 38985 * For GPOS kerning, this method uses the default script and language, which covers 38986 * most use cases. To have greater control, use font.position.getKerningValue . 38987 * @param {opentype.Glyph} leftGlyph 38988 * @param {opentype.Glyph} rightGlyph 38989 * @return {Number} 38990 */ 38991 Font.prototype.getKerningValue = function(leftGlyph, rightGlyph) { 38992 leftGlyph = leftGlyph.index || leftGlyph; 38993 rightGlyph = rightGlyph.index || rightGlyph; 38994 var gposKerning = this.position.defaultKerningTables; 38995 if (gposKerning) { 38996 return this.position.getKerningValue(gposKerning, leftGlyph, rightGlyph); 38997 } 38998 // "kern" table 38999 return this.kerningPairs[leftGlyph + ',' + rightGlyph] || 0; 39000 }; 39001 39002 /** 39003 * @typedef GlyphRenderOptions 39004 * @type Object 39005 * @property {string} [script] - script used to determine which features to apply. By default, 'DFLT' or 'latn' is used. 39006 * See https://www.microsoft.com/typography/otspec/scripttags.htm 39007 * @property {string} [language='dflt'] - language system used to determine which features to apply. 39008 * See https://www.microsoft.com/typography/developers/opentype/languagetags.aspx 39009 * @property {boolean} [kerning=true] - whether to include kerning values 39010 * @property {object} [features] - OpenType Layout feature tags. Used to enable or disable the features of the given script/language system. 39011 * See https://www.microsoft.com/typography/otspec/featuretags.htm 39012 */ 39013 Font.prototype.defaultRenderOptions = { 39014 kerning: true, 39015 features: { 39016 liga: true, 39017 rlig: true 39018 } 39019 }; 39020 39021 /** 39022 * Helper function that invokes the given callback for each glyph in the given text. 39023 * The callback gets `(glyph, x, y, fontSize, options)`.* @param {string} text 39024 * @param {string} text - The text to apply. 39025 * @param {number} [x=0] - Horizontal position of the beginning of the text. 39026 * @param {number} [y=0] - Vertical position of the *baseline* of the text. 39027 * @param {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. 39028 * @param {GlyphRenderOptions=} options 39029 * @param {Function} callback 39030 */ 39031 Font.prototype.forEachGlyph = function( 39032 text, 39033 x, 39034 y, 39035 fontSize, 39036 options, 39037 callback 39038 ) { 39039 var this$1 = this; 39040 39041 x = x !== undefined ? x : 0; 39042 y = y !== undefined ? y : 0; 39043 fontSize = fontSize !== undefined ? fontSize : 72; 39044 options = options || this.defaultRenderOptions; 39045 var fontScale = 1 / this.unitsPerEm * fontSize; 39046 var glyphs = this.stringToGlyphs(text, options); 39047 var kerningLookups; 39048 if (options.kerning) { 39049 var script = options.script || this.position.getDefaultScriptName(); 39050 kerningLookups = this.position.getKerningTables(script, options.language); 39051 } 39052 for (var i = 0; i < glyphs.length; i += 1) { 39053 var glyph = glyphs[i]; 39054 callback.call(this$1, glyph, x, y, fontSize, options); 39055 if (glyph.advanceWidth) { 39056 x += glyph.advanceWidth * fontScale; 39057 } 39058 39059 if (options.kerning && i < glyphs.length - 1) { 39060 // We should apply position adjustment lookups in a more generic way. 39061 // Here we only use the xAdvance value. 39062 var kerningValue = kerningLookups 39063 ? this$1.position.getKerningValue( 39064 kerningLookups, 39065 glyph.index, 39066 glyphs[i + 1].index 39067 ) 39068 : this$1.getKerningValue(glyph, glyphs[i + 1]); 39069 x += kerningValue * fontScale; 39070 } 39071 39072 if (options.letterSpacing) { 39073 x += options.letterSpacing * fontSize; 39074 } else if (options.tracking) { 39075 x += options.tracking / 1000 * fontSize; 39076 } 39077 } 39078 return x; 39079 }; 39080 39081 /** 39082 * Create a Path object that represents the given text. 39083 * @param {string} text - The text to create. 39084 * @param {number} [x=0] - Horizontal position of the beginning of the text. 39085 * @param {number} [y=0] - Vertical position of the *baseline* of the text. 39086 * @param {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. 39087 * @param {GlyphRenderOptions=} options 39088 * @return {opentype.Path} 39089 */ 39090 Font.prototype.getPath = function(text, x, y, fontSize, options) { 39091 var fullPath = new Path(); 39092 this.forEachGlyph(text, x, y, fontSize, options, function( 39093 glyph, 39094 gX, 39095 gY, 39096 gFontSize 39097 ) { 39098 var glyphPath = glyph.getPath(gX, gY, gFontSize, options, this); 39099 fullPath.extend(glyphPath); 39100 }); 39101 return fullPath; 39102 }; 39103 39104 /** 39105 * Create an array of Path objects that represent the glyphs of a given text. 39106 * @param {string} text - The text to create. 39107 * @param {number} [x=0] - Horizontal position of the beginning of the text. 39108 * @param {number} [y=0] - Vertical position of the *baseline* of the text. 39109 * @param {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. 39110 * @param {GlyphRenderOptions=} options 39111 * @return {opentype.Path[]} 39112 */ 39113 Font.prototype.getPaths = function(text, x, y, fontSize, options) { 39114 var glyphPaths = []; 39115 this.forEachGlyph(text, x, y, fontSize, options, function( 39116 glyph, 39117 gX, 39118 gY, 39119 gFontSize 39120 ) { 39121 var glyphPath = glyph.getPath(gX, gY, gFontSize, options, this); 39122 glyphPaths.push(glyphPath); 39123 }); 39124 39125 return glyphPaths; 39126 }; 39127 39128 /** 39129 * Returns the advance width of a text. 39130 * 39131 * This is something different than Path.getBoundingBox() as for example a 39132 * suffixed whitespace increases the advanceWidth but not the bounding box 39133 * or an overhanging letter like a calligraphic 'f' might have a quite larger 39134 * bounding box than its advance width. 39135 * 39136 * This corresponds to canvas2dContext.measureText(text).width 39137 * 39138 * @param {string} text - The text to create. 39139 * @param {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. 39140 * @param {GlyphRenderOptions=} options 39141 * @return advance width 39142 */ 39143 Font.prototype.getAdvanceWidth = function(text, fontSize, options) { 39144 return this.forEachGlyph(text, 0, 0, fontSize, options, function() {}); 39145 }; 39146 39147 /** 39148 * Draw the text on the given drawing context.
39149 * @param {CanvasRenderingContext2D} ctx - A 2D drawing context, like Canvas. 39150 * @param {string} text - The text to create. 39151 * @param {number} [x=0] - Horizontal position of the beginning of the text. 39152 * @param {number} [y=0] - Vertical position of the *baseline* of the text. 39153 * @param {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. 39154 * @param {GlyphRenderOptions=} options 39155 */ 39156 Font.prototype.draw = function(ctx, text, x, y, fontSize, options) { 39157 this.getPath(text, x, y, fontSize, options).draw(ctx); 39158 }; 39159 39160 /** 39161 * Draw the points of all glyphs in the text. 39162 * On-curve points will be drawn in blue, off-curve points will be drawn in red. 39163 * @param {CanvasRenderingContext2D} ctx - A 2D drawing context, like Canvas. 39164 * @param {string} text - The text to create. 39165 * @param {number} [x=0] - Horizontal position of the beginning of the text. 39166 * @param {number} [y=0] - Vertical position of the *baseline* of the text. 39167 * @param {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. 39168 * @param {GlyphRenderOptions=} options 39169 */ 39170 Font.prototype.drawPoints = function(ctx, text, x, y, fontSize, options) { 39171 this.forEachGlyph(text, x, y, fontSize, options, function( 39172 glyph, 39173 gX, 39174 gY, 39175 gFontSize 39176 ) { 39177 glyph.drawPoints(ctx, gX, gY, gFontSize); 39178 }); 39179 }; 39180 39181 /** 39182 * Draw lines indicating important font measurements for all glyphs in the text. 39183 * Black lines indicate the origin of the coordinate system (point 0,0). 39184 * Blue lines indicate the glyph bounding box. 39185 * Green line indicates the advance width of the glyph. 39186 * @param {CanvasRenderingContext2D} ctx - A 2D drawing context, like Canvas. 39187 * @param {string} text - The text to create. 39188 * @param {number} [x=0] - Horizontal position of the beginning of the text. 39189 * @param {number} [y=0] - Vertical position of the *baseline* of the text. 39190 * @param {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. 39191 * @param {GlyphRenderOptions=} options 39192 */ 39193 Font.prototype.drawMetrics = function(ctx, text, x, y, fontSize, options) { 39194 this.forEachGlyph(text, x, y, fontSize, options, function( 39195 glyph, 39196 gX, 39197 gY, 39198 gFontSize 39199 ) { 39200 glyph.drawMetrics(ctx, gX, gY, gFontSize); 39201 }); 39202 }; 39203 39204 /** 39205 * @param {string} 39206 * @return {string} 39207 */ 39208 Font.prototype.getEnglishName = function(name) { 39209 var translations = this.names[name]; 39210 if (translations) { 39211 return translations.en; 39212 } 39213 }; 39214 39215 /** 39216 * Validate 39217 */ 39218 Font.prototype.validate = function() { 39219 var _this = this; 39220 39221 function assert(predicate, message) {} 39222 39223 function assertNamePresent(name) { 39224 var englishName = _this.getEnglishName(name); 39225 assert( 39226 englishName && englishName.trim().length > 0, 39227 'No English ' + name + ' specified.' 39228 ); 39229 } 39230 39231 // Identification information 39232 assertNamePresent('fontFamily'); 39233 assertNamePresent('weightName'); 39234 assertNamePresent('manufacturer'); 39235 assertNamePresent('copyright'); 39236 assertNamePresent('version'); 39237 39238 // Dimension information 39239 assert(this.unitsPerEm > 0, 'No unitsPerEm specified.'); 39240 }; 39241 39242 /** 39243 * Convert the font object to a SFNT data structure. 39244 * This structure contains all the necessary tables and metadata to create a binary OTF file. 39245 * @return {opentype.Table} 39246 */ 39247 Font.prototype.toTables = function() { 39248 return sfnt.fontToTable(this); 39249 }; 39250 /** 39251 * @deprecated Font.toBuffer is deprecated. Use Font.toArrayBuffer instead. 39252 */ 39253 Font.prototype.toBuffer = function() { 39254 console.warn( 39255 'Font.toBuffer is deprecated. Use Font.toArrayBuffer instead.' 39256 ); 39257 return this.toArrayBuffer(); 39258 }; 39259 /** 39260 * Converts a `opentype.Font` into an `ArrayBuffer` 39261 * @return {ArrayBuffer} 39262 */ 39263 Font.prototype.toArrayBuffer = function() { 39264 var sfntTable = this.toTables(); 39265 var bytes = sfntTable.encode(); 39266 var buffer = new ArrayBuffer(bytes.length); 39267 var intArray = new Uint8Array(buffer); 39268 for (var i = 0; i < bytes.length; i++) { 39269 intArray[i] = bytes[i]; 39270 } 39271 39272 return buffer; 39273 }; 39274 39275 /** 39276 * Initiate a download of the OpenType font. 39277 */ 39278 Font.prototype.download = function(fileName) { 39279 var familyName = this.getEnglishName('fontFamily');
39280 var styleName = this.getEnglishName('fontSubfamily'); 39281 fileName = 39282 fileName || familyName.replace(/\s/g, '') + '-' + styleName + '.otf'; 39283 var arrayBuffer = this.toArrayBuffer(); 39284 39285 if (isBrowser()) { 39286 window.requestFileSystem = 39287 window.requestFileSystem || window.webkitRequestFileSystem; 39288 window.requestFileSystem( 39289 window.TEMPORARY, 39290 arrayBuffer.byteLength, 39291 function(fs) { 39292 fs.root.getFile(fileName, { create: true }, function(fileEntry) { 39293 fileEntry.createWriter(function(writer) { 39294 var dataView = new DataView(arrayBuffer); 39295 var blob = new Blob([dataView], { type: 'font/opentype' }); 39296 writer.write(blob); 39297 39298 writer.addEventListener( 39299 'writeend', 39300 function() { 39301 // Navigating to the file will download it. 39302 location.href = fileEntry.toURL(); 39303 }, 39304 false 39305 ); 39306 }); 39307 }); 39308 }, 39309 function(err) { 39310 throw new Error(err.name + ': ' + err.message); 39311 } 39312 ); 39313 } else { 39314 var fs = _dereq_('fs'); 39315 var buffer = arrayBufferToNodeBuffer(arrayBuffer); 39316 fs.writeFileSync(fileName, buffer); 39317 } 39318 }; 39319 /** 39320 * @private 39321 */ 39322 Font.prototype.fsSelectionValues = { 39323 ITALIC: 0x001, //1 39324 UNDERSCORE: 0x002, //2 39325 NEGATIVE: 0x004, //4 39326 OUTLINED: 0x008, //8 39327 STRIKEOUT: 0x010, //16 39328 BOLD: 0x020, //32 39329 REGULAR: 0x040, //64 39330 USER_TYPO_METRICS: 0x080, //128 39331 WWS: 0x100, //256 39332 OBLIQUE: 0x200 //512 39333 }; 39334 39335 /** 39336 * @private 39337 */ 39338 Font.prototype.usWidthClasses = { 39339 ULTRA_CONDENSED: 1, 39340 EXTRA_CONDENSED: 2, 39341 CONDENSED: 3, 39342 SEMI_CONDENSED: 4, 39343 MEDIUM: 5, 39344 SEMI_EXPANDED: 6, 39345 EXPANDED: 7, 39346 EXTRA_EXPANDED: 8, 39347 ULTRA_EXPANDED: 9 39348 }; 39349 39350 /** 39351 * @private 39352 */ 39353 Font.prototype.usWeightClasses = { 39354 THIN: 100, 39355 EXTRA_LIGHT: 200, 39356 LIGHT: 300, 39357 NORMAL: 400, 39358 MEDIUM: 500, 39359 SEMI_BOLD: 600, 39360 BOLD: 700, 39361 EXTRA_BOLD: 800, 39362 BLACK: 900 39363 }; 39364 39365 // The `fvar` table stores font variation axes and instances. 39366 39367 function addName(name, names) { 39368 var nameString = JSON.stringify(name); 39369 var nameID = 256; 39370 for (var nameKey in names) { 39371 var n = parseInt(nameKey); 39372 if (!n || n < 256) { 39373 continue; 39374 } 39375 39376 if (JSON.stringify(names[nameKey]) === nameString) { 39377 return n; 39378 } 39379 39380 if (nameID <= n) { 39381 nameID = n + 1; 39382 } 39383 } 39384 39385 names[nameID] = name; 39386 return nameID; 39387 } 39388 39389 function makeFvarAxis(n, axis, names) { 39390 var nameID = addName(axis.name, names); 39391 return [ 39392 { name: 'tag_' + n, type: 'TAG', value: axis.tag }, 39393 { name: 'minValue_' + n, type: 'FIXED', value: axis.minValue << 16 }, 39394 { 39395 name: 'defaultValue_' + n, 39396 type: 'FIXED', 39397 value: axis.defaultValue << 16 39398 }, 39399 { name: 'maxValue_' + n, type: 'FIXED', value: axis.maxValue << 16 },
39400 { name: 'flags_' + n, type: 'USHORT', value: 0 }, 39401 { name: 'nameID_' + n, type: 'USHORT', value: nameID } 39402 ]; 39403 } 39404 39405 function parseFvarAxis(data, start, names) { 39406 var axis = {}; 39407 var p = new parse.Parser(data, start); 39408 axis.tag = p.parseTag(); 39409 axis.minValue = p.parseFixed(); 39410 axis.defaultValue = p.parseFixed(); 39411 axis.maxValue = p.parseFixed(); 39412 p.skip('uShort', 1); // reserved for flags; no values defined 39413 axis.name = names[p.parseUShort()] || {}; 39414 return axis; 39415 } 39416 39417 function makeFvarInstance(n, inst, axes, names) { 39418 var nameID = addName(inst.name, names); 39419 var fields = [ 39420 { name: 'nameID_' + n, type: 'USHORT', value: nameID }, 39421 { name: 'flags_' + n, type: 'USHORT', value: 0 } 39422 ]; 39423 39424 for (var i = 0; i < axes.length; ++i) { 39425 var axisTag = axes[i].tag; 39426 fields.push({ 39427 name: 'axis_' + n + ' ' + axisTag, 39428 type: 'FIXED', 39429 value: inst.coordinates[axisTag] << 16 39430 }); 39431 } 39432 39433 return fields; 39434 } 39435 39436 function parseFvarInstance(data, start, axes, names) { 39437 var inst = {}; 39438 var p = new parse.Parser(data, start); 39439 inst.name = names[p.parseUShort()] || {};
39440 p.skip('uShort', 1); // reserved for flags; no values defined 39441 39442 inst.coordinates = {}; 39443 for (var i = 0; i < axes.length; ++i) { 39444 inst.coordinates[axes[i].tag] = p.parseFixed(); 39445 } 39446 39447 return inst; 39448 } 39449 39450 function makeFvarTable(fvar, names) { 39451 var result = new table.Table('fvar', [ 39452 { name: 'version', type: 'ULONG', value: 0x10000 }, 39453 { name: 'offsetToData', type: 'USHORT', value: 0 }, 39454 { name: 'countSizePairs', type: 'USHORT', value: 2 }, 39455 { name: 'axisCount', type: 'USHORT', value: fvar.axes.length }, 39456 { name: 'axisSize', type: 'USHORT', value: 20 }, 39457 { name: 'instanceCount', type: 'USHORT', value: fvar.instances.length }, 39458 { name: 'instanceSize', type: 'USHORT', value: 4 + fvar.axes.length * 4 } 39459 ]); 39460 result.offsetToData = result.sizeOf(); 39461 39462 for (var i = 0; i < fvar.axes.length; i++) { 39463 result.fields = result.fields.concat( 39464 makeFvarAxis(i, fvar.axes[i], names) 39465 ); 39466 } 39467 39468 for (var j = 0; j < fvar.instances.length; j++) { 39469 result.fields = result.fields.concat( 39470 makeFvarInstance(j, fvar.instances[j], fvar.axes, names) 39471 ); 39472 } 39473 39474 return result; 39475 } 39476 39477 function parseFvarTable(data, start, names) { 39478 var p = new parse.Parser(data, start); 39479 var tableVersion = p.parseULong(); 39480 check.argument( 39481 tableVersion === 0x00010000, 39482 'Unsupported fvar table version.' 39483 ); 39484 var offsetToData = p.parseOffset16(); 39485 // Skip countSizePairs.
vendor: 4,372 bytes, lines 39486-39584
39486 p.skip('uShort', 1); 39487 var axisCount = p.parseUShort(); 39488 var axisSize = p.parseUShort(); 39489 var instanceCount = p.parseUShort(); 39490 var instanceSize = p.parseUShort(); 39491 39492 var axes = []; 39493 for (var i = 0; i < axisCount; i++) { 39494 axes.push( 39495 parseFvarAxis(data, start + offsetToData + i * axisSize, names) 39496 ); 39497 } 39498 39499 var instances = []; 39500 var instanceStart = start + offsetToData + axisCount * axisSize; 39501 for (var j = 0; j < instanceCount; j++) { 39502 instances.push( 39503 parseFvarInstance(data, instanceStart + j * instanceSize, axes, names) 39504 ); 39505 } 39506 39507 return { axes: axes, instances: instances }; 39508 } 39509 39510 var fvar = { make: makeFvarTable, parse: parseFvarTable }; 39511 39512 // The `GPOS` table contains kerning pairs, among other things. 39513 39514 var subtableParsers$1 = new Array(10); // subtableParsers[0] is unused 39515 39516 // https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#lookup-type-1-single-adjustment-positioning-subtable 39517 // this = Parser instance 39518 subtableParsers$1[1] = function parseLookup1() { 39519 var start = this.offset + this.relativeOffset; 39520 var posformat = this.parseUShort(); 39521 if (posformat === 1) { 39522 return { 39523 posFormat: 1, 39524 coverage: this.parsePointer(Parser.coverage), 39525 value: this.parseValueRecord() 39526 }; 39527 } else if (posformat === 2) { 39528 return { 39529 posFormat: 2, 39530 coverage: this.parsePointer(Parser.coverage), 39531 values: this.parseValueRecordList() 39532 }; 39533 } 39534 check.assert( 39535 false, 39536 '0x' + start.toString(16) + ': GPOS lookup type 1 format must be 1 or 2.' 39537 ); 39538 }; 39539 39540 // https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#lookup-type-2-pair-adjustment-positioning-subtable 39541 subtableParsers$1[2] = function parseLookup2() { 39542 var start = this.offset + this.relativeOffset; 39543 var posFormat = this.parseUShort(); 39544 check.assert( 39545 posFormat === 1 || posFormat === 2, 39546 '0x' + start.toString(16) + ': GPOS lookup type 2 format must be 1 or 2.' 39547 ); 39548 var coverage = this.parsePointer(Parser.coverage); 39549 var valueFormat1 = this.parseUShort(); 39550 var valueFormat2 = this.parseUShort(); 39551 if (posFormat === 1) { 39552 // Adjustments for Glyph Pairs 39553 return { 39554 posFormat: posFormat, 39555 coverage: coverage, 39556 valueFormat1: valueFormat1, 39557 valueFormat2: valueFormat2, 39558 pairSets: this.parseList( 39559 Parser.pointer( 39560 Parser.list(function() { 39561 return { 39562 // pairValueRecord 39563 secondGlyph: this.parseUShort(), 39564 value1: this.parseValueRecord(valueFormat1), 39565 value2: this.parseValueRecord(valueFormat2) 39566 }; 39567 }) 39568 ) 39569 ) 39570 }; 39571 } else if (posFormat === 2) { 39572 var classDef1 = this.parsePointer(Parser.classDef); 39573 var classDef2 = this.parsePointer(Parser.classDef); 39574 var class1Count = this.parseUShort(); 39575 var class2Count = this.parseUShort(); 39576 return { 39577 // Class Pair Adjustment 39578 posFormat: posFormat, 39579 coverage: coverage, 39580 valueFormat1: valueFormat1, 39581 valueFormat2: valueFormat2, 39582 classDef1: classDef1, 39583 classDef2: classDef2, 39584 class1Count: class1Count,
39585 class2Count: class2Count, 39586 classRecords: this.parseList( 39587 class1Count, 39588 Parser.list(class2Count, function() { 39589 return { 39590 value1: this.parseValueRecord(valueFormat1), 39591 value2: this.parseValueRecord(valueFormat2) 39592 }; 39593 }) 39594 ) 39595 }; 39596 } 39597 }; 39598 39599 subtableParsers$1[3] = function parseLookup3() { 39600 return { error: 'GPOS Lookup 3 not supported' }; 39601 }; 39602 subtableParsers$1[4] = function parseLookup4() { 39603 return { error: 'GPOS Lookup 4 not supported' }; 39604 }; 39605 subtableParsers$1[5] = function parseLookup5() { 39606 return { error: 'GPOS Lookup 5 not supported' }; 39607 }; 39608 subtableParsers$1[6] = function parseLookup6() { 39609 return { error: 'GPOS Lookup 6 n
39609ot supported' }; 39610 }; 39611 subtableParsers$1[7] = function parseLookup7() { 39612 return { error: 'GPOS Lookup 7 not supported' }; 39613 }; 39614 subtableParsers$1[8] = function parseLookup8() { 39615 return { error: 'GPOS Lookup 8 not supported' }; 39616 }; 39617 subtableParsers$1[9] = function parseLookup9() { 39618 return { error: 'GPOS Lookup 9 not supported' }; 39619 }; 39620 39621 // https://docs.microsoft.com/en-us/typography/opentype/spec/gpos 39622 function parseGposTable(data, start) { 39623 start = start || 0; 39624 var p = new Parser(data, start); 39625 var tableVersion = p.parseVersion(1); 39626 check.argument( 39627 tableVersion === 1 || tableVersion === 1.1, 39628 'Unsupported GPOS table version ' + tableVersion 39629 ); 39630 39631 if (tableVersion === 1) { 39632 return { 39633 version: tableVersion, 39634 scripts: p.parseScriptList(), 39635 features: p.parseFeatureList(), 39636 lookups: p.parseLookupList(subtableParsers$1) 39637 }; 39638 } else { 39639 return { 39640 version: tableVersion, 39641 scripts: p.parseScriptList(), 39642 features: p.parseFeatureList(), 39643 lookups: p.parseLookupList(subtableParsers$1), 39644 variations: p.parseFeatureVariationsList() 39645 }; 39646 } 39647 } 39648 39649 // GPOS Writing ////////////////////////////////////////////// 39650 // NOT SUPPORTED 39651 var subtableMakers$1 = new Array(10); 39652 39653 function makeGposTable(gpos) { 39654 return new table.Table('GPOS', [ 39655 { name: 'version', type: 'ULONG', value: 0x10000 }, 39656 { 39657 name: 'scripts', 39658 type: 'TABLE', 39659 value: new table.ScriptList(gpos.scripts) 39660 }, 39661 { 39662 name: 'features', 39663 type: 'TABLE', 39664 value: new table.FeatureList(gpos.features) 39665 }, 39666 { 39667 name: 'lookups', 39668 type: 'TABLE', 39669 value: new table.LookupList(gpos.lookups, subtableMakers$1) 39670 } 39671 ]); 39672 } 39673 39674 var gpos = { parse: parseGposTable, make: makeGposTable }; 39675 39676 // The `kern` table contains kerning pairs. 39677 39678 function parseWindowsKernTable(p) { 39679 var pairs = {}; 39680 // Skip nTables. 39681 p.skip('uShort'); 39682 var subtableVersion = p.parseUShort(); 39683 check.argument( 39684 subtableVersion === 0, 39685 'Unsupported kern sub-table version.' 39686 ); 39687 // Skip subtableLength, subtableCoverage 39688 p.skip('uShort', 2); 39689 var nPairs = p.parseUShort(); 39690 // Skip searchRange, entrySelector, rangeShift. 39691 p.skip('uShort', 3); 39692 for (var i = 0; i < nPairs; i += 1) { 39693 var leftIndex = p.parseUShort(); 39694 var rightIndex = p.parseUShort(); 39695 var value = p.parseShort(); 39696 pairs[leftIndex + ',' + rightIndex] = value; 39697 } 39698 return pairs; 39699 } 39700 39701 function parseMacKernTable(p) { 39702 var pairs = {}; 39703 // The Mac kern table stores the version as a fixed (32 bits) but we only loaded the first 16 bits. 39704 // Skip the rest. 39705 p.skip('uShort'); 39706 var nTables = p.parseULong(); 39707 //check.argument(nTables === 1, 'Only 1 subtable is supported (got ' + nTables + ').'); 39708 if (nTables > 1) { 39709 console.warn('Only the first kern subtable is supported.'); 39710 } 39711 p.skip('uLong'); 39712 var coverage = p.parseUShort(); 39713 var subtableVersion = coverage & 0xff; 39714 p.skip('uShort'); 39715 if (subtableVersion === 0) { 39716 var nPairs = p.parseUShort();
39717 // Skip searchRange, entrySelector, rangeShift. 39718 p.skip('uShort', 3); 39719 for (var i = 0; i < nPairs; i += 1) { 39720 var leftIndex = p.parseUShort(); 39721 var rightIndex = p.parseUShort(); 39722 var value = p.parseShort(); 39723 pairs[leftIndex + ',' + rightIndex] = value; 39724 } 39725 } 39726 return pairs; 39727 } 39728 39729 // Parse the `kern` table which contains kerning pairs. 39730 function parseKernTable(data, start) { 39731 var p = new parse.Parser(data, start); 39732 var tableVersion = p.parseUShort(); 39733 if (tableVersion === 0) { 39734 return parseWindowsKernTable(p); 39735 } else if (tableVersion === 1) { 39736 return parseMacKernTable(p); 39737 } else { 39738 throw new Error('Unsupported kern table version (' + tableVersion + ').'); 39739 } 39740 } 39741 39742 var kern = { parse: parseKernTable }; 39743 39744 // The `loca` table stores the offsets to the locations of the glyphs in the font. 39745 39746 // Parse the `loca` table. This table stores the offsets to the locations of the glyphs in the font, 39747 // relative to the beginning of the glyphData table. 39748 // The number of glyphs stored in the `loca` table is specified in the `maxp` table (under numGlyphs) 39749 // The loca table has two versions: a short version where offsets are stored as uShorts, and a long 39750 // version where offsets are stored as uLongs. The `head` table specifies which version to use 39751 // (under indexToLocFormat). 39752 function parseLocaTable(data, start, numGlyphs, shortVersion) { 39753 var p = new parse.Parser(data, start); 39754 var parseFn = shortVersion ? p.parseUShort : p.parseULong; 39755 // There is an extra entry after the last index element to compute the length of the last glyph. 39756 // That's why we use numGlyphs + 1. 39757 var glyphOffsets = []; 39758 for (var i = 0; i < numGlyphs + 1; i += 1) { 39759 var glyphOffset = parseFn.call(p); 39760 if (shortVersion) { 39761 // The short table version stores the actual offset divided by 2. 39762 glyphOffset *= 2; 39763 } 39764 39765 glyphOffsets.push(glyphOffset); 39766 } 39767 39768 return glyphOffsets; 39769 } 39770 39771 var loca = { parse: parseLocaTable }; 39772 39773 // opentype.js 39774 39775 /** 39776 * The opentype library. 39777 * @namespace opentype 39778 */ 39779 39780 // File loaders ///////////////////////////////////////////////////////// 39781 /** 39782 * Loads a font from a file. The callback throws an error message as the first parameter if it fails 39783 * and the font as an ArrayBuffer in the second parameter if it succeeds. 39784 * @param {string} path - The path of the file 39785 * @param {Function} callback - The function to call when the font load completes 39786 */ 39787 function loadFromFile(path, callback) { 39788 var fs = _dereq_('fs'); 39789 fs.readFile(path, function(err, buffer) { 39790 if (err) { 39791 return callback(err.message); 39792 } 39793 39794 callback(null, nodeBufferToArrayBuffer(buffer)); 39795 }); 39796 } 39797 /** 39798 * Loads a font from a URL. The callback throws an error message as the first parameter if it fails 39799 * and the font as an ArrayBuffer in the second parameter if it succeeds. 39800 * @param {string} url - The URL of the font file. 39801 * @param {Function} callback - The function to call when the font load completes 39802 */ 39803 function loadFromUrl(url, callback) { 39804 var request = new XMLHttpRequest(); 39805 request.open('get', url, true); 39806 request.responseType = 'arraybuffer'; 39807 request.onload = function() { 39808 if (request.response) { 39809 return callback(null, request.response); 39810 } else { 39811 return callback('Font could not be loaded: ' + request.statusText); 39812 } 39813 }; 39814 39815 request.onerror = function() { 39816 callback('Font could not be loaded'); 39817 }; 39818 39819 request.send(); 39820 } 39821 39822 // Table Directory Entries ////////////////////////////////////////////// 39823 /**
vendor: 10,809 bytes, lines 39824-40074
39824 * Parses OpenType table entries. 39825 * @param {DataView} 39826 * @param {Number} 39827 * @return {Object[]} 39828 */ 39829 function parseOpenTypeTableEntries(data, numTables) { 39830 var tableEntries = []; 39831 var p = 12; 39832 for (var i = 0; i < numTables; i += 1) { 39833 var tag = parse.getTag(data, p); 39834 var checksum = parse.getULong(data, p + 4); 39835 var offset = parse.getULong(data, p + 8); 39836 var length = parse.getULong(data, p + 12); 39837 tableEntries.push({ 39838 tag: tag, 39839 checksum: checksum, 39840 offset: offset, 39841 length: length, 39842 compression: false 39843 }); 39844 p += 16; 39845 } 39846 39847 return tableEntries; 39848 } 39849 39850 /** 39851 * Parses WOFF table entries. 39852 * @param {DataView} 39853 * @param {Number} 39854 * @return {Object[]} 39855 */ 39856 function parseWOFFTableEntries(data, numTables) { 39857 var tableEntries = []; 39858 var p = 44; // offset to the first table directory entry. 39859 for (var i = 0; i < numTables; i += 1) { 39860 var tag = parse.getTag(data, p); 39861 var offset = parse.getULong(data, p + 4); 39862 var compLength = parse.getULong(data, p + 8); 39863 var origLength = parse.getULong(data, p + 12); 39864 var compression = void 0; 39865 if (compLength < origLength) { 39866 compression = 'WOFF'; 39867 } else { 39868 compression = false; 39869 } 39870 39871 tableEntries.push({ 39872 tag: tag, 39873 offset: offset, 39874 compression: compression, 39875 compressedLength: compLength, 39876 length: origLength 39877 }); 39878 p += 20; 39879 } 39880 39881 return tableEntries; 39882 } 39883 39884 /** 39885 * @typedef TableData 39886 * @type Object 39887 * @property {DataView} data - The DataView 39888 * @property {number} offset - The data offset. 39889 */ 39890 39891 /** 39892 * @param {DataView} 39893 * @param {Object} 39894 * @return {TableData} 39895 */ 39896 function uncompressTable(data, tableEntry) { 39897 if (tableEntry.compression === 'WOFF') { 39898 var inBuffer = new Uint8Array( 39899 data.buffer, 39900 tableEntry.offset + 2, 39901 tableEntry.compressedLength - 2 39902 ); 39903 var outBuffer = new Uint8Array(tableEntry.length); 39904 tinyInflate(inBuffer, outBuffer); 39905 if (outBuffer.byteLength !== tableEntry.length) { 39906 throw new Error( 39907 'Decompression error: ' + 39908 tableEntry.tag + 39909 " decompressed length doesn't match recorded length" 39910 ); 39911 } 39912 39913 var view = new DataView(outBuffer.buffer, 0); 39914 return { data: view, offset: 0 }; 39915 } else { 39916 return { data: data, offset: tableEntry.offset }; 39917 } 39918 } 39919 39920 // Public API /////////////////////////////////////////////////////////// 39921 39922 /** 39923 * Parse the OpenType file data (as an ArrayBuffer) and return a Font object. 39924 * Throws an error if the font could not be parsed. 39925 * @param {ArrayBuffer} 39926 * @return {opentype.Font} 39927 */ 39928 function parseBuffer(buffer) { 39929 var indexToLocFormat; 39930 var ltagTable; 39931 39932 // Since the constructor can also be called to create new fonts from scratch, we indicate this 39933 // should be an empty font that we'll fill with our own data. 39934 var font = new Font({ empty: true }); 39935 39936 // OpenType fonts use big endian byte ordering. 39937 // We can't rely on typed array view types, because they operate with the endianness of the host computer. 39938 // Instead we use DataViews where we can specify endianness. 39939 var data = new DataView(buffer, 0); 39940 var numTables; 39941 var tableEntries = []; 39942 var signature = parse.getTag(data, 0); 39943 if ( 39944 signature === String.fromCharCode(0, 1, 0, 0) || 39945 signature === 'true' || 39946 signature === 'typ1' 39947 ) { 39948 font.outlinesFormat = 'truetype'; 39949 numTables = parse.getUShort(data, 4); 39950 tableEntries = parseOpenTypeTableEntries(data, numTables); 39951 } else if (signature === 'OTTO') { 39952 font.outlinesFormat = 'cff'; 39953 numTables = parse.getUShort(data, 4); 39954 tableEntries = parseOpenTypeTableEntries(data, numTables); 39955 } else if (signature === 'wOFF') { 39956 var flavor = parse.getTag(data, 4); 39957 if (flavor === String.fromCharCode(0, 1, 0, 0)) { 39958 font.outlinesFormat = 'truetype'; 39959 } else if (flavor === 'OTTO') { 39960 font.outlinesFormat = 'cff'; 39961 } else { 39962 throw new Error('Unsupported OpenType flavor ' + signature); 39963 } 39964 39965 numTables = parse.getUShort(data, 12); 39966 tableEntries = parseWOFFTableEntries(data, numTables); 39967 } else { 39968 throw new Error('Unsupported OpenType signature ' + signature); 39969 } 39970 39971 var cffTableEntry; 39972 var fvarTableEntry; 39973 var glyfTableEntry; 39974 var gposTableEntry; 39975 var gsubTableEntry; 39976 var hmtxTableEntry; 39977 var kernTableEntry; 39978 var locaTableEntry; 39979 var nameTableEntry; 39980 var metaTableEntry; 39981 var p; 39982 39983 for (var i = 0; i < numTables; i += 1) { 39984 var tableEntry = tableEntries[i]; 39985 var table = void 0; 39986 switch (tableEntry.tag) { 39987 case 'cmap': 39988 table = uncompressTable(data, tableEntry); 39989 font.tables.cmap = cmap.parse(table.data, table.offset); 39990 font.encoding = new CmapEncoding(font.tables.cmap); 39991 break; 39992 case 'cvt ': 39993 table = uncompressTable(data, tableEntry); 39994 p = new parse.Parser(table.data, table.offset); 39995 font.tables.cvt = p.parseShortList(tableEntry.length / 2); 39996 break; 39997 case 'fvar': 39998 fvarTableEntry = tableEntry; 39999 break; 40000 case 'fpgm': 40001 table = uncompressTable(data, tableEntry); 40002 p = new parse.Parser(table.data, table.offset); 40003 font.tables.fpgm = p.parseByteList(tableEntry.length); 40004 break; 40005 case 'head': 40006 table = uncompressTable(data, tableEntry); 40007 font.tables.head = head.parse(table.data, table.offset); 40008 font.unitsPerEm = font.tables.head.unitsPerEm; 40009 indexToLocFormat = font.tables.head.indexToLocFormat; 40010 break; 40011 case 'hhea': 40012 table = uncompressTable(data, tableEntry); 40013 font.tables.hhea = hhea.parse(table.data, table.offset); 40014 font.ascender = font.tables.hhea.ascender; 40015 font.descender = font.tables.hhea.descender; 40016 font.numberOfHMetrics = font.tables.hhea.numberOfHMetrics; 40017 break; 40018 case 'hmtx': 40019 hmtxTableEntry = tableEntry; 40020 break; 40021 case 'ltag': 40022 table = uncompressTable(data, tableEntry); 40023 ltagTable = ltag.parse(table.data, table.offset); 40024 break; 40025 case 'maxp': 40026 table = uncompressTable(data, tableEntry); 40027 font.tables.maxp = maxp.parse(table.data, table.offset); 40028 font.numGlyphs = font.tables.maxp.numGlyphs; 40029 break; 40030 case 'name': 40031 nameTableEntry = tableEntry; 40032 break; 40033 case 'OS/2': 40034 table = uncompressTable(data, tableEntry); 40035 font.tables.os2 = os2.parse(table.data, table.offset); 40036 break; 40037 case 'post': 40038 table = uncompressTable(data, tableEntry); 40039 font.tables.post = post.parse(table.data, table.offset); 40040 font.glyphNames = new GlyphNames(font.tables.post); 40041 break; 40042 case 'prep': 40043 table = uncompressTable(data, tableEntry); 40044 p = new parse.Parser(table.data, table.offset); 40045 font.tables.prep = p.parseByteList(tableEntry.length); 40046 break; 40047 case 'glyf': 40048 glyfTableEntry = tableEntry; 40049 break; 40050 case 'loca': 40051 locaTableEntry = tableEntry; 40052 break; 40053 case 'CFF ': 40054 cffTableEntry = tableEntry; 40055 break; 40056 case 'kern': 40057 kernTableEntry = tableEntry; 40058 break; 40059 case 'GPOS': 40060 gposTableEntry = tableEntry; 40061 break; 40062 case 'GSUB': 40063 gsubTableEntry = tableEntry; 40064 break; 40065 case 'meta': 40066 metaTableEntry = tableEntry; 40067 break; 40068 } 40069 } 40070 40071 var nameTable = uncompressTable(data, nameTableEntry); 40072 font.tables.name = _name.parse(nameTable.data, nameTable.offset, ltagTable); 40073 font.names = font.tables.name; 40074
40075 if (glyfTableEntry && locaTableEntry) { 40076 var shortVersion = indexToLocFormat === 0; 40077 var locaTable = uncompressTable(data, locaTableEntry); 40078 var locaOffsets = loca.parse( 40079 locaTable.data, 40080 locaTable.offset, 40081 font.numGlyphs, 40082 shortVersion 40083 ); 40084 var glyfTable = uncompressTable(data, glyfTableEntry); 40085 font.glyphs = glyf.parse( 40086 glyfTable.data, 40087 glyfTable.offset, 40088 locaOffsets, 40089 font 40090 ); 40091 } else if (cffTableEntry) { 40092 var cffTable = uncompressTable(data, cffTableEntry); 40093 cff.parse(cffTable.data, cffTable.offset, font); 40094 } else { 40095 throw new Error("Font doesn't contain TrueType or CFF outlines."); 40096 } 40097 40098 var hmtxTable = uncompressTable(data, hmtxTableEntry); 40099 hmtx.parse( 40100 hmtxTable.data, 40101 hmtxTable.offset, 40102 font.numberOfHMetrics, 40103 font.numGlyphs, 40104 font.glyphs 40105 ); 40106 addGlyphNames(font); 40107 40108 if (kernTableEntry) { 40109 var kernTable = uncompressTable(data, kernTableEntry); 40110 font.kerningPairs = kern.parse(kernTable.data, kernTable.offset); 40111 } else { 40112 font.kerningPairs = {}; 40113 } 40114 40115 if (gposTableEntry) { 40116 var gposTable = uncompressTable(data, gposTableEntry); 40117 font.tables.gpos = gpos.parse(gposTable.data, gposTable.offset); 40118 font.position.init(); 40119 } 40120 40121 if (gsubTableEntry) { 40122 var gsubTable = uncompressTable(data, gsubTableEntry); 40123 font.tables.gsub = gsub.parse(gsubTable.data, gsubTable.offset); 40124 } 40125 40126 if (fvarTableEntry) { 40127 var fvarTable = uncompressTable(data, fvarTableEntry); 40128 font.tables.fvar = fvar.parse( 40129 fvarTable.data, 40130 fvarTable.offset, 40131 font.names 40132 ); 40133 } 40134 40135 if (metaTableEntry) { 40136 var metaTable = uncompressTable(data, metaTableEntry); 40137 font.tables.meta = meta.parse(metaTable.data, metaTable.offset); 40138 font.metas = font.tables.meta; 40139 } 40140 40141 return font; 40142 } 40143 40144 /** 40145 * Asynchronously load the font from a URL or a filesystem. When done, call the callback 40146 * with two arguments `(err, font)`. The `err` will be null on success, 40147 * the `font` is a Font object. 40148 * We use the node.js callback convention so that 40149 * opentype.js can integrate with frameworks like async.js. 40150 * @alias opentype.load 40151 * @param {string} url - The URL of the font to load. 40152 * @param {Function} callback - The callback. 40153 */ 40154 function load(url, callback) { 40155 var isNode$$1 = typeof window === 'undefined'; 40156 var loadFn = isNode$$1 ? loadFromFile : loadFromUrl; 40157 loadFn(url, function(err, arrayBuffer) { 40158 if (err) { 40159 return callback(err); 40160 } 40161 var font; 40162 try { 40163 font = parseBuffer(arrayBuffer); 40164 } catch (e) { 40165 return callback(e, null); 40166 } 40167 return callback(null, font); 40168 }); 40169 } 40170 40171 /** 40172 * Synchronously load the font from a URL or file. 40173 * When done, returns the font object or throws an error. 40174 * @alias opentype.loadSync 40175 * @param {string} url - The URL of the font to load. 40176 * @return {opentype.Font} 40177 */ 40178 function loadSync(url) { 40179 var fs = _dereq_('fs'); 40180 var buffer = fs.readFileSync(url); 40181 return parseBuffer(nodeBufferToArrayBuffer(buffer)); 40182 } 40183 40184 exports.Font = Font; 40185 exports.Glyph = Glyph; 40186 exports.Path = Path; 40187 exports.BoundingBox = BoundingBox; 40188 exports._parse = parse; 40189 exports.parse = parseBuffer; 40190 exports.load = load; 40191 exports.loadSync = loadSync; 40192 40193 Object.defineProperty(exports, '__esModule', { value: true }); 40194 }); 40195 }.call(this, _dereq_('buffer').Buffer)); 40196 }, 40197 { buffer: 22, fs: 21 } 40198 ], 40199 35: [
vendor: 5,953 bytes, lines 40200-40349
40200 function(_dereq_, module, exports) { 40201 (function(process) { 40202 // .dirname, .basename, and .extname methods are extracted from Node.js v8.11.1, 40203 // backported and transplited with Babel, with backwards-compat fixes 40204 40205 // Copyright Joyent, Inc. and other Node contributors. 40206 // 40207 // Permission is hereby granted, free of charge, to any person obtaining a 40208 // copy of this software and associated documentation files (the 40209 // "Software"), to deal in the Software without restriction, including 40210 // without limitation the rights to use, copy, modify, merge, publish, 40211 // distribute, sublicense, and/or sell copies of the Software, and to permit 40212 // persons to whom the Software is furnished to do so, subject to the 40213 // following conditions: 40214 // 40215 // The above copyright notice and this permission notice shall be included 40216 // in all copies or substantial portions of the Software. 40217 // 40218 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 40219 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 40220 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 40221 // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 40222 // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 40223 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 40224 // USE OR OTHER DEALINGS IN THE SOFTWARE. 40225 40226 // resolves . and .. elements in a path array with directory names there 40227 // must be no slashes, empty elements, or device names (c:\) in the array 40228 // (so also no leading and trailing slashes - it does not distinguish 40229 // relative and absolute paths) 40230 function normalizeArray(parts, allowAboveRoot) { 40231 // if the path tries to go above the root, `up` ends up > 0 40232 var up = 0; 40233 for (var i = parts.length - 1; i >= 0; i--) { 40234 var last = parts[i]; 40235 if (last === '.') { 40236 parts.splice(i, 1); 40237 } else if (last === '..') { 40238 parts.splice(i, 1); 40239 up++; 40240 } else if (up) { 40241 parts.splice(i, 1); 40242 up--; 40243 } 40244 } 40245 40246 // if the path is allowed to go above the root, restore leading ..s 40247 if (allowAboveRoot) { 40248 for (; up--; up) { 40249 parts.unshift('..'); 40250 } 40251 } 40252 40253 return parts; 40254 } 40255 40256 // path.resolve([from ...], to) 40257 // posix version 40258 exports.resolve = function() { 40259 var resolvedPath = '', 40260 resolvedAbsolute = false; 40261 40262 for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { 40263 var path = i >= 0 ? arguments[i] : process.cwd(); 40264 40265 // Skip empty and invalid entries 40266 if (typeof path !== 'string') { 40267 throw new TypeError('Arguments to path.resolve must be strings'); 40268 } else if (!path) { 40269 continue; 40270 } 40271 40272 resolvedPath = path + '/' + resolvedPath; 40273 resolvedAbsolute = path.charAt(0) === '/'; 40274 } 40275 40276 // At this point the path should be resolved to a full absolute path, but 40277 // handle relative paths to be safe (might happen when process.cwd() fails) 40278 40279 // Normalize the path 40280 resolvedPath = normalizeArray( 40281 filter(resolvedPath.split('/'), function(p) { 40282 return !!p; 40283 }), 40284 !resolvedAbsolute 40285 ).join('/'); 40286 40287 return (resolvedAbsolute ? '/' : '') + resolvedPath || '.'; 40288 }; 40289 40290 // path.normalize(path) 40291 // posix version 40292 exports.normalize = function(path) { 40293 var isAbsolute = exports.isAbsolute(path), 40294 trailingSlash = substr(path, -1) === '/'; 40295 40296 // Normalize the path 40297 path = normalizeArray( 40298 filter(path.split('/'), function(p) { 40299 return !!p; 40300 }), 40301 !isAbsolute 40302 ).join('/'); 40303 40304 if (!path && !isAbsolute) { 40305 path = '.'; 40306 } 40307 if (path && trailingSlash) { 40308 path += '/'; 40309 } 40310 40311 return (isAbsolute ? '/' : '') + path; 40312 }; 40313 40314 // posix version 40315 exports.isAbsolute = function(path) { 40316 return path.charAt(0) === '/'; 40317 }; 40318 40319 // posix version 40320 exports.join = function() { 40321 var paths = Array.prototype.slice.call(arguments, 0); 40322 return exports.normalize( 40323 filter(paths, function(p, index) { 40324 if (typeof p !== 'string') { 40325 throw new TypeError('Arguments to path.join must be strings'); 40326 } 40327 return p; 40328 }).join('/') 40329 ); 40330 }; 40331 40332 // path.relative(from, to) 40333 // posix version 40334 exports.relative = function(from, to) { 40335 from = exports.resolve(from).substr(1); 40336 to = exports.resolve(to).substr(1); 40337 40338 function trim(arr) { 40339 var start = 0; 40340 for (; start < arr.length; start++) { 40341 if (arr[start] !== '') break; 40342 } 40343 40344 var end = arr.length - 1; 40345 for (; end >= 0; end--) { 40346 if (arr[end] !== '') break; 40347 } 40348 40349 if (start > end) return [];
vendor: 10,259 bytes, lines 40350-40611
40350 return arr.slice(start, end - start + 1); 40351 } 40352 40353 var fromParts = trim(from.split('/')); 40354 var toParts = trim(to.split('/')); 40355 40356 var length = Math.min(fromParts.length, toParts.length); 40357 var samePartsLength = length; 40358 for (var i = 0; i < length; i++) { 40359 if (fromParts[i] !== toParts[i]) { 40360 samePartsLength = i; 40361 break; 40362 } 40363 } 40364 40365 var outputParts = []; 40366 for (var i = samePartsLength; i < fromParts.length; i++) { 40367 outputParts.push('..'); 40368 } 40369 40370 outputParts = outputParts.concat(toParts.slice(samePartsLength)); 40371 40372 return outputParts.join('/'); 40373 }; 40374 40375 exports.sep = '/'; 40376 exports.delimiter = ':'; 40377 40378 exports.dirname = function(path) { 40379 if (typeof path !== 'string') path = path + ''; 40380 if (path.length === 0) return '.'; 40381 var code = path.charCodeAt(0); 40382 var hasRoot = code === 47 /*/*/; 40383 var end = -1; 40384 var matchedSlash = true; 40385 for (var i = path.length - 1; i >= 1; --i) { 40386 code = path.charCodeAt(i); 40387 if (code === 47 /*/*/) { 40388 if (!matchedSlash) { 40389 end = i; 40390 break; 40391 } 40392 } else { 40393 // We saw the first non-path separator 40394 matchedSlash = false; 40395 } 40396 } 40397 40398 if (end === -1) return hasRoot ? '/' : '.'; 40399 if (hasRoot && end === 1) { 40400 // return '//'; 40401 // Backwards-compat fix: 40402 return '/'; 40403 } 40404 return path.slice(0, end); 40405 }; 40406 40407 function basename(path) { 40408 if (typeof path !== 'string') path = path + ''; 40409 40410 var start = 0; 40411 var end = -1; 40412 var matchedSlash = true; 40413 var i; 40414 40415 for (i = path.length - 1; i >= 0; --i) { 40416 if (path.charCodeAt(i) === 47 /*/*/) { 40417 // If we reached a path separator that was not part of a set of path 40418 // separators at the end of the string, stop now 40419 if (!matchedSlash) { 40420 start = i + 1; 40421 break; 40422 } 40423 } else if (end === -1) { 40424 // We saw the first non-path separator, mark this as the end of our 40425 // path component 40426 matchedSlash = false; 40427 end = i + 1; 40428 } 40429 } 40430 40431 if (end === -1) return ''; 40432 return path.slice(start, end); 40433 } 40434 40435 // Uses a mixed approach for backwards-compatibility, as ext behavior changed 40436 // in new Node.js versions, so only basename() above is backported here 40437 exports.basename = function(path, ext) { 40438 var f = basename(path); 40439 if (ext && f.substr(-1 * ext.length) === ext) { 40440 f = f.substr(0, f.length - ext.length); 40441 } 40442 return f; 40443 }; 40444 40445 exports.extname = function(path) { 40446 if (typeof path !== 'string') path = path + ''; 40447 var startDot = -1; 40448 var startPart = 0; 40449 var end = -1; 40450 var matchedSlash = true; 40451 // Track the state of characters (if any) we see before our first dot and 40452 // after any path separator we find 40453 var preDotState = 0; 40454 for (var i = path.length - 1; i >= 0; --i) { 40455 var code = path.charCodeAt(i); 40456 if (code === 47 /*/*/) { 40457 // If we reached a path separator that was not part of a set of path 40458 // separators at the end of the string, stop now 40459 if (!matchedSlash) { 40460 startPart = i + 1; 40461 break; 40462 } 40463 continue; 40464 } 40465 if (end === -1) { 40466 // We saw the first non-path separator, mark this as the end of our 40467 // extension 40468 matchedSlash = false; 40469 end = i + 1; 40470 } 40471 if (code === 46 /*.*/) { 40472 // If this is our first dot, mark it as the start of our extension 40473 if (startDot === -1) startDot = i; 40474 else if (preDotState !== 1) preDotState = 1; 40475 } else if (startDot !== -1) { 40476 // We saw a non-dot and non-path separator before our dot, so we should 40477 // have a good chance at having a non-empty extension 40478 preDotState = -1; 40479 } 40480 } 40481 40482 if ( 40483 startDot === -1 || 40484 end === -1 || 40485 // We saw a non-dot character immediately before the dot 40486 preDotState === 0 || 40487 // The (right-most) trimmed path component is exactly '..' 40488 (preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) 40489 ) { 40490 return ''; 40491 } 40492 return path.slice(startDot, end); 40493 }; 40494 40495 function filter(xs, f) { 40496 if (xs.filter) return xs.filter(f); 40497 var res = []; 40498 for (var i = 0; i < xs.length; i++) { 40499 if (f(xs[i], i, xs)) res.push(xs[i]); 40500 } 40501 return res; 40502 } 40503 40504 // String.prototype.substr - negative index don't work in IE8 40505 var substr = 40506 'ab'.substr(-1) === 'b' 40507 ? function(str, start, len) { 40508 return str.substr(start, len); 40509 } 40510 : function(str, start, len) { 40511 if (start < 0) start = str.length + start; 40512 return str.substr(start, len); 40513 }; 40514 }.call(this, _dereq_('_process'))); 40515 }, 40516 { _process: 36 } 40517 ], 40518 36: [ 40519 function(_dereq_, module, exports) { 40520 // shim for using process in browser 40521 var process = (module.exports = {}); 40522 40523 // cached from whatever global is present so that test runners that stub it 40524 // don't break things. But we need to wrap it in a try catch in case it is 40525 // wrapped in strict mode code which doesn't define any globals. It's inside a 40526 // function because try/catches deoptimize in certain engines. 40527 40528 var cachedSetTimeout; 40529 var cachedClearTimeout; 40530 40531 function defaultSetTimout() { 40532 throw new Error('setTimeout has not been defined'); 40533 } 40534 function defaultClearTimeout() { 40535 throw new Error('clearTimeout has not been defined'); 40536 } 40537 (function() { 40538 try { 40539 if (typeof setTimeout === 'function') { 40540 cachedSetTimeout = setTimeout; 40541 } else { 40542 cachedSetTimeout = defaultSetTimout; 40543 } 40544 } catch (e) { 40545 cachedSetTimeout = defaultSetTimout; 40546 } 40547 try { 40548 if (typeof clearTimeout === 'function') { 40549 cachedClearTimeout = clearTimeout; 40550 } else { 40551 cachedClearTimeout = defaultClearTimeout; 40552 } 40553 } catch (e) { 40554 cachedClearTimeout = defaultClearTimeout; 40555 } 40556 })(); 40557 function runTimeout(fun) { 40558 if (cachedSetTimeout === setTimeout) { 40559 //normal enviroments in sane situations 40560 return setTimeout(fun, 0); 40561 } 40562 // if setTimeout wasn't available but was latter defined 40563 if ( 40564 (cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && 40565 setTimeout 40566 ) { 40567 cachedSetTimeout = setTimeout; 40568 return setTimeout(fun, 0); 40569 } 40570 try { 40571 // when when somebody has screwed with setTimeout but no I.E. maddness 40572 return cachedSetTimeout(fun, 0); 40573 } catch (e) { 40574 try { 40575 // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally 40576 return cachedSetTimeout.call(null, fun, 0); 40577 } catch (e) { 40578 // 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 40579 return cachedSetTimeout.call(this, fun, 0); 40580 } 40581 } 40582 } 40583 function runClearTimeout(marker) { 40584 if (cachedClearTimeout === clearTimeout) { 40585 //normal enviroments in sane situations 40586 return clearTimeout(marker); 40587 } 40588 // if clearTimeout wasn't available but was latter defined 40589 if ( 40590 (cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && 40591 clearTimeout 40592 ) { 40593 cachedClearTimeout = clearTimeout; 40594 return clearTimeout(marker); 40595 } 40596 try { 40597 // when when somebody has screwed with setTimeout but no I.E. maddness 40598 return cachedClearTimeout(marker); 40599 } catch (e) { 40600 try { 40601 // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally 40602 return cachedClearTimeout.call(null, marker); 40603 } catch (e) { 40604 // 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. 40605 // Some versions of I.E. have different rules for clearTimeout vs setTimeout 40606 return cachedClearTimeout.call(this, marker); 40607 } 40608 } 40609 } 40610 var queue = []; 40611 var draining = false;
40612 var currentQueue; 40613 var queueIndex = -1; 40614 40615 function cleanUpNextTick() { 40616 if (!draining || !currentQueue) { 40617 return; 40618 } 40619 draining = false; 40620 if (currentQueue.length) { 40621 queue = currentQueue.concat(queue); 40622 } else { 40623 queueIndex = -1; 40624 } 40625 if (queue.length) { 40626 drainQueue(); 40627 } 40628 } 40629 40630 function drainQueue() { 40631 if (draining) { 40632 return; 40633 } 40634 var timeout = runTimeout(cleanUpNextTick); 40635 draining = true; 40636 40637 var len = queue.length; 40638 while (len) { 40639 currentQueue = queue; 40640 queue = []; 40641 while (++queueIndex < len) { 40642 if (currentQueue) { 40643 currentQueue[queueIndex].run(); 40644 } 40645 } 40646 queueIndex = -1; 40647 len = queue.length; 40648 } 40649 currentQueue = null; 40650 draining = false; 40651 runClearTimeout(timeout); 40652 } 40653 40654 process.nextTick = function(fun) { 40655 var args = new Array(arguments.length - 1); 40656 if (arguments.length > 1) { 40657 for (var i = 1; i < arguments.length; i++) { 40658 args[i - 1] = arguments[i]; 40659 } 40660 } 40661 queue.push(new Item(fun, args)); 40662 if (queue.length === 1 && !draining) { 40663 runTimeout(drainQueue); 40664 } 40665 }; 40666 40667 // v8 likes predictible objects 40668 function Item(fun, array) { 40669 this.fun = fun; 40670 this.array = array; 40671 } 40672 Item.prototype.run = function() { 40673 this.fun.apply(null, this.array); 40674 }; 40675 process.title = 'browser'; 40676 process.browser = true; 40677 process.env = {}; 40678 process.argv = []; 40679 process.version = ''; // empty string to avoid regexp issues 40680 process.versions = {}; 40681 40682 function noop() {} 40683 40684 process.on = noop; 40685 process.addListener = noop; 40686 process.once = noop; 40687 process.off = noop; 40688 process.removeListener = noop; 40689 process.removeAllListeners = noop; 40690 process.emit = noop; 40691 process.prependListener = noop; 40692 process.prependOnceListener = noop; 40693 40694 process.listeners = function(name) { 40695 return []; 40696 }; 40697 40698 process.binding = function(name) { 40699 throw new Error('process.binding is not supported'); 40700 }; 40701 40702 process.cwd = function() { 40703 return '/'; 40704 }; 40705 process.chdir = function(dir) { 40706 throw new Error('process.chdir is not supported'); 40707 }; 40708 process.umask = function() { 40709 return 0; 40710 }; 40711 }, 40712 {} 40713 ], 40714 37: [ 40715 function(_dereq_, module, exports) { 40716 (function(self) { 40717 'use strict'; 40718 40719 if (self.fetch) { 40720 return; 40721 } 40722 40723 var support = { 40724 searchParams: 'URLSearchParams' in self, 40725 iterable: 'Symbol' in self && 'iterator' in Symbol, 40726 blob: 40727 'FileReader' in self && 40728 'Blob' in self && 40729 (function() { 40730 try { 40731 new Blob(); 40732 return true; 40733 } catch (e) { 40734 return false; 40735 } 40736 })(), 40737 formData: 'FormData' in self, 40738 arrayBuffer: 'ArrayBuffer' in self 40739 }; 40740 40741 if (support.arrayBuffer) { 40742 var viewClasses = [ 40743 '[object Int8Array]', 40744 '[object Uint8Array]', 40745 '[object Uint8ClampedArray]', 40746 '[object Int16Array]', 40747 '[object Uint16Array]', 40748 '[object Int32Array]', 40749 '[object Uint32Array]', 40750 '[object Float32Array]',
vendor: 5,930 bytes, lines 40751-40933
40751 '[object Float64Array]' 40752 ]; 40753 40754 var isDataView = function(obj) { 40755 return obj && DataView.prototype.isPrototypeOf(obj); 40756 }; 40757 40758 var isArrayBufferView = 40759 ArrayBuffer.isView || 40760 function(obj) { 40761 return ( 40762 obj && viewClasses.indexOf(Object.prototype.toString.call(obj)) > -1 40763 ); 40764 }; 40765 } 40766 40767 function normalizeName(name) { 40768 if (typeof name !== 'string') { 40769 name = String(name); 40770 } 40771 if (/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(name)) { 40772 throw new TypeError('Invalid character in header field name'); 40773 } 40774 return name.toLowerCase(); 40775 } 40776 40777 function normalizeValue(value) { 40778 if (typeof value !== 'string') { 40779 value = String(value); 40780 } 40781 return value; 40782 } 40783 40784 // Build a destructive iterator for the value list 40785 function iteratorFor(items) { 40786 var iterator = { 40787 next: function() { 40788 var value = items.shift(); 40789 return { done: value === undefined, value: value }; 40790 } 40791 }; 40792 40793 if (support.iterable) { 40794 iterator[Symbol.iterator] = function() { 40795 return iterator; 40796 }; 40797 } 40798 40799 return iterator; 40800 } 40801 40802 function Headers(headers) { 40803 this.map = {}; 40804 40805 if (headers instanceof Headers) { 40806 headers.forEach(function(value, name) { 40807 this.append(name, value); 40808 }, this); 40809 } else if (Array.isArray(headers)) { 40810 headers.forEach(function(header) { 40811 this.append(header[0], header[1]); 40812 }, this); 40813 } else if (headers) { 40814 Object.getOwnPropertyNames(headers).forEach(function(name) { 40815 this.append(name, headers[name]); 40816 }, this); 40817 } 40818 } 40819 40820 Headers.prototype.append = function(name, value) { 40821 name = normalizeName(name); 40822 value = normalizeValue(value); 40823 var oldValue = this.map[name]; 40824 this.map[name] = oldValue ? oldValue + ',' + value : value; 40825 }; 40826 40827 Headers.prototype['delete'] = function(name) { 40828 delete this.map[normalizeName(name)]; 40829 }; 40830 40831 Headers.prototype.get = function(name) { 40832 name = normalizeName(name); 40833 return this.has(name) ? this.map[name] : null; 40834 }; 40835 40836 Headers.prototype.has = function(name) { 40837 return this.map.hasOwnProperty(normalizeName(name)); 40838 }; 40839 40840 Headers.prototype.set = function(name, value) { 40841 this.map[normalizeName(name)] = normalizeValue(value); 40842 }; 40843 40844 Headers.prototype.forEach = function(callback, thisArg) { 40845 for (var name in this.map) { 40846 if (this.map.hasOwnProperty(name)) { 40847 callback.call(thisArg, this.map[name], name, this); 40848 } 40849 } 40850 }; 40851 40852 Headers.prototype.keys = function() { 40853 var items = []; 40854 this.forEach(function(value, name) { 40855 items.push(name); 40856 }); 40857 return iteratorFor(items); 40858 }; 40859 40860 Headers.prototype.values = function() { 40861 var items = []; 40862 this.forEach(function(value) { 40863 items.push(value); 40864 }); 40865 return iteratorFor(items); 40866 }; 40867 40868 Headers.prototype.entries = function() { 40869 var items = []; 40870 this.forEach(function(value, name) { 40871 items.push([name, value]); 40872 }); 40873 return iteratorFor(items); 40874 }; 40875 40876 if (support.iterable) { 40877 Headers.prototype[Symbol.iterator] = Headers.prototype.entries; 40878 } 40879 40880 function consumed(body) { 40881 if (body.bodyUsed) { 40882 return Promise.reject(new TypeError('Already read')); 40883 } 40884 body.bodyUsed = true; 40885 } 40886 40887 function fileReaderReady(reader) { 40888 return new Promise(function(resolve, reject) { 40889 reader.onload = function() { 40890 resolve(reader.result); 40891 }; 40892 reader.onerror = function() { 40893 reject(reader.error); 40894 }; 40895 }); 40896 } 40897 40898 function readBlobAsArrayBuffer(blob) { 40899 var reader = new FileReader(); 40900 var promise = fileReaderReady(reader); 40901 reader.readAsArrayBuffer(blob); 40902 return promise; 40903 } 40904 40905 function readBlobAsText(blob) { 40906 var reader = new FileReader(); 40907 var promise = fileReaderReady(reader); 40908 reader.readAsText(blob); 40909 return promise; 40910 } 40911 40912 function readArrayBufferAsText(buf) { 40913 var view = new Uint8Array(buf); 40914 var chars = new Array(view.length); 40915 40916 for (var i = 0; i < view.length; i++) { 40917 chars[i] = String.fromCharCode(view[i]); 40918 } 40919 return chars.join(''); 40920 } 40921 40922 function bufferClone(buf) { 40923 if (buf.slice) { 40924 return buf.slice(0); 40925 } else { 40926 var view = new Uint8Array(buf.byteLength); 40927 view.set(new Uint8Array(buf)); 40928 return view.buffer; 40929 } 40930 } 40931 40932 function Body() { 40933 this.bodyUsed = false;
vendor: 4,237 bytes, lines 40934-41039
40934 40935 this._initBody = function(body) { 40936 this._bodyInit = body; 40937 if (!body) { 40938 this._bodyText = ''; 40939 } else if (typeof body === 'string') { 40940 this._bodyText = body; 40941 } else if (support.blob && Blob.prototype.isPrototypeOf(body)) { 40942 this._bodyBlob = body; 40943 } else if (support.formData && FormData.prototype.isPrototypeOf(body)) { 40944 this._bodyFormData = body; 40945 } else if ( 40946 support.searchParams && 40947 URLSearchParams.prototype.isPrototypeOf(body) 40948 ) { 40949 this._bodyText = body.toString(); 40950 } else if (support.arrayBuffer && support.blob && isDataView(body)) { 40951 this._bodyArrayBuffer = bufferClone(body.buffer); 40952 // IE 10-11 can't handle a DataView body. 40953 this._bodyInit = new Blob([this._bodyArrayBuffer]); 40954 } else if ( 40955 support.arrayBuffer && 40956 (ArrayBuffer.prototype.isPrototypeOf(body) || isArrayBufferView(body)) 40957 ) { 40958 this._bodyArrayBuffer = bufferClone(body); 40959 } else { 40960 throw new Error('unsupported BodyInit type'); 40961 } 40962 40963 if (!this.headers.get('content-type')) { 40964 if (typeof body === 'string') { 40965 this.headers.set('content-type', 'text/plain;charset=UTF-8'); 40966 } else if (this._bodyBlob && this._bodyBlob.type) { 40967 this.headers.set('content-type', this._bodyBlob.type); 40968 } else if ( 40969 support.searchParams && 40970 URLSearchParams.prototype.isPrototypeOf(body) 40971 ) { 40972 this.headers.set( 40973 'content-type', 40974 'application/x-www-form-urlencoded;charset=UTF-8' 40975 ); 40976 } 40977 } 40978 }; 40979 40980 if (support.blob) { 40981 this.blob = function() { 40982 var rejected = consumed(this); 40983 if (rejected) { 40984 return rejected; 40985 } 40986 40987 if (this._bodyBlob) { 40988 return Promise.resolve(this._bodyBlob); 40989 } else if (this._bodyArrayBuffer) { 40990 return Promise.resolve(new Blob([this._bodyArrayBuffer])); 40991 } else if (this._bodyFormData) { 40992 throw new Error('could not read FormData body as blob'); 40993 } else { 40994 return Promise.resolve(new Blob([this._bodyText])); 40995 } 40996 }; 40997 40998 this.arrayBuffer = function() { 40999 if (this._bodyArrayBuffer) { 41000 return consumed(this) || Promise.resolve(this._bodyArrayBuffer); 41001 } else { 41002 return this.blob().then(readBlobAsArrayBuffer); 41003 } 41004 }; 41005 } 41006 41007 this.text = function() { 41008 var rejected = consumed(this); 41009 if (rejected) { 41010 return rejected; 41011 } 41012 41013 if (this._bodyBlob) { 41014 return readBlobAsText(this._bodyBlob); 41015 } else if (this._bodyArrayBuffer) { 41016 return Promise.resolve(readArrayBufferAsText(this._bodyArrayBuffer)); 41017 } else if (this._bodyFormData) { 41018 throw new Error('could not read FormData body as text'); 41019 } else { 41020 return Promise.resolve(this._bodyText); 41021 } 41022 }; 41023 41024 if (support.formData) { 41025 this.formData = function() { 41026 return this.text().then(decode); 41027 }; 41028 } 41029 41030 this.json = function() { 41031 return this.text().then(JSON.parse); 41032 }; 41033 41034 return this; 41035 } 41036 41037 // HTTP methods whose capitalization should be normalized 41038 var methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT']; 41039
vendor: 4,793 bytes, lines 41040-41166
41040 function normalizeMethod(method) { 41041 var upcased = method.toUpperCase(); 41042 return methods.indexOf(upcased) > -1 ? upcased : method; 41043 } 41044 41045 function Request(input, options) { 41046 options = options || {}; 41047 var body = options.body; 41048 41049 if (input instanceof Request) { 41050 if (input.bodyUsed) { 41051 throw new TypeError('Already read'); 41052 } 41053 this.url = input.url; 41054 this.credentials = input.credentials; 41055 if (!options.headers) { 41056 this.headers = new Headers(input.headers); 41057 } 41058 this.method = input.method; 41059 this.mode = input.mode; 41060 if (!body && input._bodyInit != null) { 41061 body = input._bodyInit; 41062 input.bodyUsed = true; 41063 } 41064 } else { 41065 this.url = String(input); 41066 } 41067 41068 this.credentials = options.credentials || this.credentials || 'omit'; 41069 if (options.headers || !this.headers) { 41070 this.headers = new Headers(options.headers); 41071 } 41072 this.method = normalizeMethod(options.method || this.method || 'GET'); 41073 this.mode = options.mode || this.mode || null; 41074 this.referrer = null; 41075 41076 if ((this.method === 'GET' || this.method === 'HEAD') && body) { 41077 throw new TypeError('Body not allowed for GET or HEAD requests'); 41078 } 41079 this._initBody(body); 41080 } 41081 41082 Request.prototype.clone = function() { 41083 return new Request(this, { body: this._bodyInit }); 41084 }; 41085 41086 function decode(body) { 41087 var form = new FormData(); 41088 body 41089 .trim() 41090 .split('&') 41091 .forEach(function(bytes) { 41092 if (bytes) { 41093 var split = bytes.split('='); 41094 var name = split.shift().replace(/\+/g, ' '); 41095 var value = split.join('=').replace(/\+/g, ' '); 41096 form.append(decodeURIComponent(name), decodeURIComponent(value)); 41097 } 41098 }); 41099 return form; 41100 } 41101 41102 function parseHeaders(rawHeaders) { 41103 var headers = new Headers(); 41104 // Replace instances of \r\n and \n followed by at least one space or horizontal tab with a space 41105 // https://tools.ietf.org/html/rfc7230#section-3.2 41106 var preProcessedHeaders = rawHeaders.replace(/\r?\n[\t ]+/g, ' '); 41107 preProcessedHeaders.split(/\r?\n/).forEach(function(line) { 41108 var parts = line.split(':'); 41109 var key = parts.shift().trim(); 41110 if (key) { 41111 var value = parts.join(':').trim(); 41112 headers.append(key, value); 41113 } 41114 }); 41115 return headers; 41116 } 41117 41118 Body.call(Request.prototype); 41119 41120 function Response(bodyInit, options) { 41121 if (!options) { 41122 options = {}; 41123 } 41124 41125 this.type = 'default'; 41126 this.status = options.status === undefined ? 200 : options.status; 41127 this.ok = this.status >= 200 && this.status < 300; 41128 this.statusText = 'statusText' in options ? options.statusText : 'OK'; 41129 this.headers = new Headers(options.headers); 41130 this.url = options.url || ''; 41131 this._initBody(bodyInit); 41132 } 41133 41134 Body.call(Response.prototype); 41135 41136 Response.prototype.clone = function() { 41137 return new Response(this._bodyInit, { 41138 status: this.status, 41139 statusText: this.statusText, 41140 headers: new Headers(this.headers), 41141 url: this.url 41142 }); 41143 }; 41144 41145 Response.error = function() { 41146 var response = new Response(null, { status: 0, statusText: '' }); 41147 response.type = 'error'; 41148 return response; 41149 }; 41150 41151 var redirectStatuses = [301, 302, 303, 307, 308]; 41152 41153 Response.redirect = function(url, status) { 41154 if (redirectStatuses.indexOf(status) === -1) { 41155 throw new RangeError('Invalid status code'); 41156 } 41157 41158 return new Response(null, { status: status, headers: { location: url } }); 41159 }; 41160 41161 self.Headers = Headers; 41162 self.Request = Request; 41163 self.Response = Response; 41164 41165 self.fetch = function(input, init) { 41166 return new Promise(function(resolve, reject) {
41167 var request = new Request(input, init); 41168 var xhr = new XMLHttpRequest(); 41169 41170 xhr.onload = function() { 41171 var options = { 41172 status: xhr.status, 41173 statusText: xhr.statusText, 41174 headers: parseHeaders(xhr.getAllResponseHeaders() || '') 41175 }; 41176 options.url = 41177 'responseURL' in xhr 41178 ? xhr.responseURL 41179 : options.headers.get('X-Request-URL'); 41180 var body = 'response' in xhr ? xhr.response : xhr.responseText; 41181 resolve(new Response(body, options)); 41182 }; 41183 41184 xhr.onerror = function() { 41185 reject(new TypeError('Network request failed')); 41186 }; 41187 41188 xhr.ontimeout = function() { 41189 reject(new TypeError('Network request failed')); 41190 }; 41191 41192 xhr.open(request.method, request.url, true); 41193 41194 if (request.credentials === 'include') { 41195 xhr.withCredentials = true; 41196 } else if (request.credentials === 'omit') { 41197 xhr.withCredentials = false; 41198 } 41199 41200 if ('responseType' in xhr && support.blob) { 41201 xhr.responseType = 'blob'; 41202 } 41203 41204 request.headers.forEach(function(value, name) { 41205 xhr.setRequestHeader(name, value); 41206 }); 41207 41208 xhr.send( 41209 typeof request._bodyInit === 'undefined' ? null : request._bodyInit 41210 ); 41211 }); 41212 }; 41213 self.fetch.polyfill = true; 41214 })(typeof self !== 'undefined' ? self : this); 41215 }, 41216 {} 41217 ], 41218 38: [ 41219 function(_dereq_, module, exports) { 41220 'use strict'; 41221 Object.defineProperty(exports, '__esModule', { value: true }); 41222 exports.default = void 0; 41223 41224 var _main = _interopRequireDefault(_dereq_('../core/main')); 41225 var _color_conversion = _interopRequireDefault( 41226 _dereq_('../color/color_conversion') 41227 ); 41228 function _interopRequireDefault(obj) { 41229 return obj && obj.__esModule ? obj : { default: obj }; 41230 } /** //stores the original hsb values 41231 * @module Environment 41232 * @submodule Environment 41233 * @for p5 41234 * @requires core 41235 */ 41236 var originalHSB; //stores values for color name exceptions 41237 var colorExceptions = [ 41238 { 41239 h: 0, 41240 s: 0, 41241 b: 0.8275, 41242 name: 'gray' 41243 }, 41244 41245 { 41246 h: 0, 41247 s: 0, 41248 b: 0.8627, 41249 name: 'gray' 41250 }, 41251 41252 { 41253 h: 0, 41254 s: 0, 41255 b: 0.7529, 41256 name: 'gray' 41257 }, 41258 41259 { 41260 h: 0.0167, 41261 s: 0.1176, 41262 b: 1, 41263 name: 'light pink' 41264 } 41265 ]; 41266 41267 //stores values for color names 41268 var colorLookUp = [ 41269 { 41270 h: 0, 41271 s: 0, 41272 b: 0, 41273 name: 'black' 41274 }, 41275 41276 { 41277 h: 0, 41278 s: 0, 41279 b: 0.5, 41280 name: 'gray' 41281 }, 41282 41283 { 41284 h: 0, 41285 s: 0, 41286 b: 1, 41287 name: 'white' 41288 }, 41289 41290 { 41291 h: 0, 41292 s: 0.5, 41293 b: 0.5, 41294 name: 'dark maroon' 41295 }, 41296 41297 { 41298 h: 0, 41299 s: 0.5, 41300 b: 1, 41301 name: 'salmon pink' 41302 }, 41303 41304 { 41305 h: 0, 41306 s: 1, 41307 b: 0, 41308 name: 'black' 41309 }, 41310 41311 { 41312 h: 0, 41313 s: 1, 41314 b: 0.5, 41315 name: 'dark red' 41316 }, 41317 41318 { 41319 h: 0, 41320 s: 1, 41321 b: 1, 41322 name: 'red' 41323 }, 41324 41325 { 41326 h: 5, 41327 s: 0, 41328 b: 1, 41329 name: 'very light peach' 41330 }, 41331 41332 { 41333 h: 5, 41334 s: 0.5, 41335 b: 0.5, 41336 name: 'brown' 41337 }, 41338 41339 { 41340 h: 5, 41341 s: 0.5, 41342 b: 1, 41343 name: 'peach' 41344 }, 41345 41346 { 41347 h: 5, 41348 s: 1, 41349 b: 0.5, 41350 name: 'brick red' 41351 }, 41352 41353 { 41354 h: 5, 41355 s: 1, 41356 b: 1, 41357 name: 'crimson' 41358 }, 41359 41360 { 41361 h: 10, 41362 s: 0, 41363 b: 1, 41364 name: 'light peach' 41365 }, 41366 41367 { 41368 h: 10, 41369 s: 0.5, 41370 b: 0.5, 41371 name: 'brown' 41372 }, 41373 41374 { 41375 h: 10, 41376 s: 0.5, 41377 b: 1, 41378 name: 'light orange' 41379 }, 41380 41381 { 41382 h: 10, 41383 s: 1, 41384 b: 0.5, 41385 name: 'brown' 41386 }, 41387 41388 { 41389 h: 10, 41390 s: 1, 41391 b: 1, 41392 name: 'orange' 41393 }, 41394 41395 { 41396 h: 15, 41397 s: 0, 41398 b: 1, 41399 name: 'very light yellow' 41400 }, 41401 41402 { 41403 h: 15, 41404 s: 0.5, 41405 b: 0.5, 41406 name: 'olive green' 41407 }, 41408 41409 { 41410 h: 15, 41411 s: 0.5, 41412 b: 1, 41413 name: 'light yellow' 41414 }, 41415 41416 { 41417 h: 15, 41418 s: 1, 41419 b: 0, 41420 name: 'dark olive green' 41421 }, 41422 41423 { 41424 h: 15, 41425 s: 1, 41426 b: 0.5, 41427 name: 'olive green' 41428 }, 41429 41430 { 41431 h: 15, 41432 s: 1, 41433 b: 1, 41434 name: 'yellow' 41435 }, 41436 41437 { 41438 h: 20, 41439 s: 0, 41440 b: 1, 41441 name: 'very light yellow' 41442 }, 41443 41444 { 41445 h: 20, 41446 s: 0.5, 41447 b: 0.5, 41448 name: 'olive green' 41449 }, 41450 41451 { 41452 h: 20, 41453 s: 0.5, 41454 b: 1, 41455 name: 'light yellow green' 41456 }, 41457 41458 { 41459 h: 20, 41460 s: 1, 41461 b: 0, 41462 name: 'dark olive green' 41463 }, 41464 41465 { 41466 h: 20, 41467 s: 1, 41468 b: 0.5, 41469 name: 'dark yellow green' 41470 }, 41471 41472 { 41473 h: 20, 41474 s: 1, 41475 b: 1, 41476 name: 'yellow green' 41477 }, 41478 41479 { 41480 h: 25, 41481 s: 0.5, 41482 b: 0.5, 41483 name: 'dark yellow green' 41484 }, 41485 41486 { 41487 h: 25, 41488 s: 0.5, 41489 b: 1, 41490 name: 'light green' 41491 }, 41492 41493 { 41494 h: 25, 41495 s: 1, 41496 b: 0.5, 41497 name: 'dark green' 41498 }, 41499 41500 { 41501 h: 25, 41502 s: 1, 41503 b: 1, 41504 name: 'green' 41505 }, 41506 41507 { 41508 h: 30, 41509 s: 0.5, 41510 b: 1, 41511 name: 'light green' 41512 }, 41513 41514 { 41515 h: 30, 41516 s: 1, 41517 b: 0.5, 41518 name: 'dark green' 41519 }, 41520 41521 { 41522 h: 30, 41523 s: 1, 41524 b: 1, 41525 name: 'green' 41526 }, 41527 41528 { 41529 h: 35, 41530 s: 0, 41531 b: 0.5, 41532 name: 'light green' 41533 }, 41534 41535 { 41536 h: 35, 41537 s: 0, 41538 b: 1, 41539 name: 'very light green' 41540 }, 41541 41542 { 41543 h: 35, 41544 s: 0.5, 41545 b: 0.5, 41546 name: 'dark green' 41547 }, 41548 41549 { 41550 h: 35, 41551 s: 0.5, 41552 b: 1, 41553 name: 'light green' 41554 }, 41555 41556 { 41557 h: 35, 41558 s: 1, 41559 b: 0, 41560 name: 'very dark green' 41561 }, 41562 41563 { 41564 h: 35, 41565 s: 1, 41566 b: 0.5, 41567 name: 'dark green' 41568 }, 41569 41570 { 41571 h: 35, 41572 s: 1, 41573 b: 1, 41574 name: 'green' 41575 }, 41576 41577 { 41578 h: 40, 41579 s: 0, 41580 b: 1, 41581 name: 'very light green' 41582 }, 41583 41584 { 41585 h: 40, 41586 s: 0.5, 41587 b: 0.5, 41588 name: 'dark green' 41589 }, 41590 41591 { 41592 h: 40, 41593 s: 0.5, 41594 b: 1, 41595 name: 'light green' 41596 }, 41597 41598 { 41599 h: 40, 41600 s: 1, 41601 b: 0.5, 41602 name: 'dark green' 41603 }, 41604 41605 { 41606 h: 40, 41607 s: 1, 41608 b: 1, 41609 name: 'green' 41610 }, 41611 41612 { 41613 h: 45, 41614 s: 0.5, 41615 b: 1, 41616 name: 'light turquoise' 41617 }, 41618 41619 { 41620 h: 45, 41621 s: 1, 41622 b: 0.5, 41623 name: 'dark turquoise' 41624 }, 41625 41626 { 41627 h: 45, 41628 s: 1, 41629 b: 1, 41630 name: 'turquoise' 41631 }, 41632 41633 { 41634 h: 50, 41635 s: 0, 41636 b: 1, 41637 name: 'light sky blue' 41638 }, 41639 41640 { 41641 h: 50, 41642 s: 0.5, 41643 b: 0.5, 41644 name: 'dark cyan' 41645 }, 41646 41647 { 41648 h: 50, 41649 s: 0.5, 41650 b: 1, 41651 name: 'light cyan' 41652 }, 41653 41654 { 41655 h: 50, 41656 s: 1, 41657 b: 0.5, 41658 name: 'dark cyan' 41659 }, 41660 41661 { 41662 h: 50, 41663 s: 1, 41664 b: 1, 41665 name: 'cyan' 41666 }, 41667 41668 { 41669 h: 55, 41670 s: 0, 41671 b: 1, 41672 name: 'light sky blue' 41673 }, 41674 41675 { 41676 h: 55, 41677 s: 0.5, 41678 b: 1, 41679 name: 'light sky blue' 41680 }, 41681 41682 { 41683 h: 55, 41684 s: 1, 41685 b: 0.5, 41686 name: 'dark blue' 41687 }, 41688 41689 { 41690 h: 55, 41691 s: 1, 41692 b: 1, 41693 name: 'sky blue' 41694 }, 41695 41696 { 41697 h: 60, 41698 s: 0, 41699 b: 0.5, 41700 name: 'gray' 41701 }, 41702 41703 { 41704 h: 60, 41705 s: 0, 41706 b: 1, 41707 name: 'very light blue' 41708 }, 41709 41710 { 41711 h: 60, 41712 s: 0.5, 41713 b: 0.5, 41714 name: 'blue' 41715 }, 41716 41717 { 41718 h: 60, 41719 s: 0.5, 41720 b: 1, 41721 name: 'light blue' 41722 }, 41723 41724 { 41725 h: 60, 41726 s: 1, 41727 b: 0.5, 41728 name: 'navy blue' 41729 }, 41730 41731 { 41732 h: 60, 41733 s: 1, 41734 b: 1, 41735 name: 'blue' 41736 }, 41737 41738 { 41739 h: 65, 41740 s: 0, 41741 b: 1, 41742 name: 'lavender' 41743 }, 41744 41745 { 41746 h: 65, 41747 s: 0.5, 41748 b: 0.5, 41749 name: 'navy blue' 41750 }, 41751 41752 { 41753 h: 65, 41754 s: 0.5, 41755 b: 1, 41756 name: 'light purple' 41757 }, 41758 41759 { 41760 h: 65, 41761 s: 1, 41762 b: 0.5, 41763 name: 'dark navy blue' 41764 }, 41765 41766 { 41767 h: 65, 41768 s: 1, 41769 b: 1, 41770 name: 'blue' 41771 }, 41772 41773 { 41774 h: 70, 41775 s: 0, 41776 b: 1, 41777 name: 'lavender' 41778 }, 41779 41780 { 41781 h: 70, 41782 s: 0.5, 41783 b: 0.5, 41784 name: 'navy blue' 41785 }, 41786 41787 { 41788 h: 70, 41789 s: 0.5, 41790 b: 1, 41791 name: 'lavender blue' 41792 }, 41793 41794 { 41795 h: 70, 41796 s: 1, 41797 b: 0.5, 41798 name: 'dark navy blue' 41799 }, 41800 41801 { 41802 h: 70, 41803 s: 1, 41804 b: 1, 41805 name: 'blue' 41806 }, 41807 41808 { 41809 h: 75, 41810 s: 0.5, 41811 b: 1, 41812 name: 'lavender' 41813 }, 41814 41815 { 41816 h: 75, 41817 s: 1, 41818 b: 0.5, 41819 name: 'dark purple' 41820 }, 41821 41822 { 41823 h: 75, 41824 s: 1, 41825 b: 1, 41826 name: 'purple' 41827 }, 41828 41829 { 41830 h: 80, 41831 s: 0.5, 41832 b: 1, 41833 name: 'pinkish purple' 41834 }, 41835 41836 { 41837 h: 80, 41838 s: 1, 41839 b: 0.5, 41840 name: 'dark purple' 41841 }, 41842 41843 { 41844 h: 80, 41845 s: 1, 41846 b: 1, 41847 name: 'purple' 41848 }, 41849 41850 { 41851 h: 85, 41852 s: 0, 41853 b: 1, 41854 name: 'light pink' 41855 }, 41856 41857 { 41858 h: 85, 41859 s: 0.5, 41860 b: 0.5, 41861 name: 'purple' 41862 }, 41863 41864 { 41865 h: 85, 41866 s: 0.5, 41867 b: 1, 41868 name: 'light fuchsia' 41869 }, 41870 41871 { 41872 h: 85, 41873 s: 1, 41874 b: 0.5, 41875 name: 'dark fuchsia' 41876 }, 41877 41878 { 41879 h: 85, 41880 s: 1, 41881 b: 1, 41882 name: 'fuchsia' 41883 }, 41884 41885 { 41886 h: 90, 41887 s: 0.5, 41888 b: 0.5, 41889 name: 'dark fuchsia' 41890 }, 41891 41892 { 41893 h: 90, 41894 s: 0.5, 41895 b: 1, 41896 name: 'hot pink' 41897 }, 41898 41899 { 41900 h: 90, 41901 s: 1, 41902 b: 0.5, 41903 name: 'dark fuchsia' 41904 }, 41905 41906 { 41907 h: 90, 41908 s: 1, 41909 b: 1, 41910 name: 'fuchsia' 41911 }, 41912 41913 { 41914 h: 95, 41915 s: 0, 41916 b: 1, 41917 name: 'pink' 41918 }, 41919 41920 { 41921 h: 95, 41922 s: 0.5, 41923 b: 1, 41924 name: 'light pink' 41925 }, 41926 41927 { 41928 h: 95, 41929 s: 1, 41930 b: 0.5, 41931 name: 'dark magenta' 41932 }, 41933 41934 { 41935 h: 95, 41936 s: 1, 41937 b: 1, 41938 name: 'magenta' 41939 } 41940 ]; 41941 41942 //returns text with color name 41943 function _calculateColor(hsb) { 41944 var colortext; 41945 //round hue 41946 if (hsb[0] !== 0) { 41947 hsb[0] = Math.round(hsb[0] * 100); 41948 var hue = hsb[0].toString().split(''); 41949 var last = hue.length - 1; 41950 hue[last] = parseInt(hue[last]); 41951 //if last digit of hue is < 2.5 make it 0 41952 if (hue[last] < 2.5) { 41953 hue[last] = 0; 41954 //if last digit of hue is >= 2.5 and less than 7.5 make it 5 41955 } else if (hue[last] >= 2.5 && hue[last] < 7.5) { 41956 hue[last] = 5; 41957 } 41958 //if hue only has two digits 41959 if (hue.length === 2) { 41960 hue[0] = parseInt(hue[0]); 41961 //if last is greater than 7.5 41962 if (hue[last] >= 7.5) { 41963 //add one to the tens 41964 hue[last] = 0; 41965 hue[0] = hue[0] + 1; 41966 } 41967 hsb[0] = hue[0] * 10 + hue[1]; 41968 } else { 41969 if (hue[last] >= 7.5) { 41970 hsb[0] = 10; 41971 } else { 41972
41972 hsb[0] = hue[last]; 41973 } 41974 } 41975 } 41976 //map brightness from 0 to 1 41977 hsb[2] = hsb[2] / 255; 41978 //round saturation and brightness 41979 for (var i = hsb.length - 1; i >= 1; i--) { 41980 if (hsb[i] <= 0.25) { 41981 hsb[i] = 0; 41982 } else if (hsb[i] > 0.25 && hsb[i] < 0.75) { 41983 hsb[i] = 0.5; 41984 } else { 41985 hsb[i] = 1; 41986 } 41987 } 41988 //after rounding, if the values are hue 0, saturation 0 and brightness 1 41989 //look at color exceptions which includes several tones from white to gray 41990 if (hsb[0] === 0 && hsb[1] === 0 && hsb[2] === 1) { 41991 //round original hsb values 41992 for (var _i = 2; _i >= 0; _i--) { 41993 originalHSB[_i] = Math.round(originalHSB[_i] * 10000) / 10000; 41994 } 41995 //compare with the values in the colorExceptions array 41996 for (var e = 0; e < colorExceptions.length; e++) { 41997 if ( 41998 colorExceptions[e].h === originalHSB[0] && 41999 colorExceptions[e].s === originalHSB[1] && 42000 colorExceptions[e].b === originalHSB[2] 42001 ) { 42002 colortext = colorExceptions[e].name; 42003 break; 42004 } else { 42005 //if there is no match return white 42006 colortext = 'white'; 42007 } 42008 } 42009 } else { 42010 //otherwise, compare with values in colorLookUp 42011 for (var _i2 = 0; _i2 < colorLookUp.length; _i2++) { 42012 if ( 42013 colorLookUp[_i2].h === hsb[0] && 42014 colorLookUp[_i2].s === hsb[1] && 42015 colorLookUp[_i2].b === hsb[2] 42016 ) { 42017 colortext = colorLookUp[_i2].name; 42018 break; 42019 } 42020 } 42021 } 42022 return colortext; 42023 } 42024 42025 //gets rgba and returs a color name 42026 _main.default.prototype._rgbColorName = function(arg) { 42027 //conversts rgba to hsb 42028 var hsb = _color_conversion.default._rgbaToHSBA(arg); 42029 //stores hsb in global variable 42030 originalHSB = hsb; 42031 //calculate color name 42032 return _calculateColor([hsb[0], hsb[1], hsb[2]]); 42033 }; 42034 var _default = _main.default; 42035 exports.default = _default; 42036 }, 42037 { '../color/color_conversion': 44, '../core/main': 59 } 42038 ], 42039 39: [ 42040 function(_dereq_, module, exports) { 42041 'use strict'; 42042 Object.defineProperty(exports, '__esModule', { value: true }); 42043 exports.default = void 0; 42044 42045 var _main = _interopRequireDefault(_dereq_('../core/main')); 42046 function _interopRequireDefault(obj) { 42047 return obj && obj.__esModule ? obj : { default: obj }; 42048 } 42049 /** 42050 * @module Environment 42051 * @submodule Environment 42052 * @for p5 42053 * @requires core 42054 */ var descContainer = '_Description'; //Fallback container 42055 var fallbackDescId = '_fallbackDesc'; //Fallback description 42056 var fallbackTableId = '_fallbackTable'; //Fallback Table 42057 var fallbackTableElId = '_fte_'; //Fallback Table Element 42058 var labelContainer = '_Label'; //Label container 42059 var labelDescId = '_labelDesc'; //Label description 42060 var labelTableId = '_labelTable'; //Label Table 42061 var labelTableElId = '_lte_'; //Label Table Element 42062 /** 42063 * Creates a screen reader accessible description for the canvas. 42064 * The first parameter should be a string with a description of the canvas. 42065 * The second parameter is optional. If specified, it determines how the 42066 * description is displayed. 42067 * 42068 * <code class="language-javascript">describe(text, LABEL)</code> displays 42069 * the description to all users as a <a 42070 * href="https://en.wikipedia.org/wiki/Museum_label" target="_blank"> 42071 * tombstone or exhibit label/caption</a> in a 42072 * <code class="language-javascript"><div class="p5Label"></div></code> 42073 * adjacent to the canvas. You can style it as you wish in your CSS. 42074 * 42075 * <code class="language-javascript">describe(text, FALLBACK)</code> makes the 42076 * description accessible to screen-reader users only, in 42077 * <a href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Hit_regions_and_accessibility" target="_blank"> 42078 * a sub DOM inside the canvas element</a>. If a second parameter is not 42079 * specified, by default, the description will only be available to 42080 * screen-reader users. 42081 * 42082 * @method describe 42083 * @param {String} text description of the canvas 42084 * @param {Constant} [display] either LABEL or FALLBACK (Optional) 42085 * 42086 * @example 42087 * <div> 42088 * <code> 42089 * describe('pink square with red heart in the bottom right corner', LABEL); 42090 * background('pink'); 42091 * fill('red'); 42092 * noStroke(); 42093 * ellipse(67, 67, 20, 20); 42094 * ellipse(83, 67, 20, 20); 42095 * triangle(91, 73, 75, 95, 59, 73); 42096 * </code> 42097 * </div> 42098 * 42099 * <div> 42100 * <code> 42101 * let x = 0; 42102 * function draw() { 42103 * if (x > 100) { 42104 * x = 0; 42105 * } 42106 * background(220); 42107 * fill(0, 255, 0); 42108 * ellipse(x, 50, 40, 40); 42109 * x = x + 0.1; 42110 * describe('green circle at x pos ' + round(x) + ' moving to the right'); 42111 * } 42112 * </code> 42113 * </div> 42114 * 42115 */ _main.default.prototype.describe = function(text, display) { 42116 _main.default._validateParameters('describe', arguments); 42117 if (typeof text !== 'string') { 42118 return; 42119 } 42120 var cnvId = this.canvas.id; 42121 //calls function that adds punctuation for better screen reading 42122 text = _descriptionText(text); 42123 //if there is no dummyDOM 42124 if (!this.dummyDOM) { 42125 this.dummyDOM = document.getElementById(cnvId).parentNode; 42126 } 42127 if (!this.descriptions) { 42128 this.descriptions = {}; 42129 } 42130 //check if html structure for description is ready 42131 if (this.descriptions.fallback) { 42132 //check if text is different from current description 42133 if (this.descriptions.fallback.innerHTML !== text) { 42134 //update description 42135 this.descriptions.fallback.innerHTML = text; 42136 } 42137 } else { 42138 //create fallback html structure 42139 this._describeHTML('fallback', text); 42140 } 42141 //if display is LABEL 42142 if (display === this.LABEL) { 42143 //check if html structure for label is ready 42144 if (this.descriptions.label) { 42145 //check if text is different from current label 42146 if (this.descriptions.label.innerHTML !== text) { 42147 //update label description 42148 this.descriptions.label.innerHTML = text; 42149 } 42150 } else { 42151 //create label html structure 42152 this._describeHTML('label', text); 42153 } 42154 } 42155 }; 42156 42157 /** 42158 * This function creates a screen-reader accessible 42159 * description for elements âshapes or groups of shapes that create 42160 * meaning togetherâ in the canvas. The first paramater should 42161 * be the name of the element. The second parameter should be a string 42162 * with a description of the element. The third parameter is optional. 42163 * If specified, it determines how the element description is displayed. 42164 * 42165 * <code class="language-javascript">describeElement(name, text, LABEL)</code> 42166 * displays the element description to all users as a 42167 * <a href="https://en.wikipedia.org/wiki/Museum_label" target="_blank"> 42168 * tombstone or exhibit label/caption</a> in a 42169 * <code class="language-javascript"><div class="p5Label"></div></code> 42170 * adjacent to the canvas. You can style it as you wish in your CSS. 42171 * 42172 * <code class="language-javascript">describeElement(name, text, FALLBACK)</code> 42173 * makes the element description accessible to screen-reader users 42174 * only, in <a href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Hit_regions_and_accessibility" target="_blank"> 42175 * a sub DOM inside the canvas element</a>. If a second parameter is not 42176 * specified, by default, the element description will only be available 42177 * to screen-reader users. 42178 * 42179 * @method describeElement 42180 * @param {String} name name of the element 42181 * @param {String} text description of the element 42182 * @param {Constant} [display] either LABEL or FALLBACK (Optional) 42183 * 42184 * @example 42185 * <div> 42186 * <code> 42187 * describe('Heart and yellow circle over pink background', LABEL); 42188 * noStroke(); 42189 * background('pink'); 42190 * describeElement('Circle', 'Yellow circle in the top left corner', LABEL); 42191 * fill('yellow'); 42192 * ellipse(25, 25, 40, 40); 42193 * describeElement('Heart', 'red heart in the bottom right corner', LABEL); 42194 * fill('red'); 42195 * ellipse(66.6, 66.6, 20, 20); 42196 * ellipse(83.2, 66.6, 20, 20); 42197 * triangle(91.2, 72.6, 75, 95, 58.6, 72.6); 42198 * </code> 42199 * </div> 42200 */ 42201 42202 _main.default.prototype.describeElement = function(name, text, display) { 42203 _main.default._validateParameters('describeElement', arguments); 42204 if (typeof text !== 'string' || typeof name !== 'string') { 42205 return; 42206 } 42207 var cnvId = this.canvas.id; 42208 //calls function that adds punctuation for better screen reading 42209 text = _descriptionText(text); 42210 //calls function that adds punctuation for better screen reading 42211 var elementName = _elementName(name); 42212 //remove any special characters from name to use it as html id 42213 name = name.replace(/[^a-zA-Z0-9 ]/g, ''); 42214 //store element description 42215 var inner = '<th scope="row">' 42216 .concat(elementName, '</th><td>') 42217 .concat(text, '</td>'); 42218 //if there is no dummyDOM 42219 if (!this.dummyDOM) { 42220 this.dummyDOM = document.getElementById(cnvId).parentNode; 42221 } 42222 if (!this.descriptions) { 42223 this.descriptions = { fallbackElements: {} }; 42224 } else if (!this.descriptions.fallbackElements) { 42225 this.descriptions.fallbackElements = {}; 42226 } 42227 //check if html structure for element description is ready 42228 if (this.descriptions.fallbackElements[name]) { 42229 //if current element description is not the same as inner 42230 if (this.descriptions.fallbackElements[name].innerHTML !== inner) { 42231 //update element description 42232 this.descriptions.fallbackElements[name].innerHTML = inner; 42233 } 42234 } else { 42235 //create fallback html structure 42236 this._describeElementHTML('fallback', name, inner); 42237 } 42238 //if display is LABEL 42239 if (display === this.LABEL) { 42240 if (!this.descriptions.labelElements) { 42241 this.descriptions.labelElements = {}; 42242 } 42243 //if html structure for label element description is ready 42244 if (this.descriptions.labelElements[name]) { 42245 //if label element description is different 42246 if (this.descriptions.labelElements[name].innerHTML !== inner) { 42247 //update label element description 42248 this.descriptions.labelElements[name].innerHTML = inner; 42249 } 42250 } else { 42251 //create label element html structure 42252 this._describeElementHTML('label', name, inner); 42253 } 42254 } 42255 }; 42256 42257 /* 42258 * 42259 * Helper functions for describe() and describeElement(). 42260 * 42261 */ 42262 42263 // check that text is not LABEL or FALLBACK and ensure text ends with punctuation mark 42264 function _descriptionText(text) { 42265 if (text === 'label' || text === 'fallback') { 42266 throw new Error('description should not be LABEL or FALLBACK'); 42267 } 42268 //if string does not end with '.' 42269 if ( 42270 !text.endsWith('.') && 42271 !text.endsWith(';') && 42272 !text.endsWith(',') && 42273 !text.endsWith('?') && 42274 !text.endsWith('!') 42275 ) { 42276 //add '.' to the end of string 42277 text = text + '.'; 42278 } 42279 return text; 42280 } 42281 42282 /* 42283 * Helper functions for describe() 42284 */ 42285 42286 //creates HTML structure for canvas descriptions 42287 _main.default.prototype._describeHTML = function(type, text) { 42288 var cnvId = this.canvas.id; 42289 if (type === 'fallback') { 42290 //if there is no description container 42291 if (!this.dummyDOM.querySelector('#'.concat(cnvId + descContainer))) { 42292 //if there are no accessible outputs (see textOutput() and gridOutput()) 42293 var html = '<div id="' 42294 .concat(cnvId) 42295 .concat( 42296 descContainer, 42297 '" role="region" aria-label="Canvas Description"><p id="' 42298 ) 42299 .concat(cnvId) 42300 .concat(fallbackDescId, '"></p></div>'); 42301 if (!this.dummyDOM.querySelector('#'.concat(cnvId, 'accessibleOutput'))) { 42302 //create description container + <p> for fallback description 42303 this.dummyDOM.querySelector('#'.concat(cnvId)).innerHTML = html; 42304 } else { 42305 //create description container + <p> for fallback description before outputs 42306 this.dummyDOM 42307 .querySelector('#'.concat(cnvId, 'accessibleOutput')) 42308 .insertAdjacentHTML('beforebegin', html); 42309 } 42310 } else { 42311 //if describeElement() has already created the container and added a table of elements 42312 //create fallback description <p> before the table 42313 this.dummyDOM 42314 .querySelector('#' + cnvId + fallbackTableId) 42315 .insertAdjacentHTML( 42316 'beforebegin', 42317 '<p id="'.concat(cnvId + fallbackDescId, '"></p>') 42318 ); 42319 } 42320 //if the container for the description exists 42321 this.descriptions.fallback = this.dummyDOM.querySelector( 42322 '#'.concat(cnvId).concat(fallbackDescId) 42323 ); 42324 42325 this.descriptions.fallback.innerHTML = text; 42326 return; 42327 } else if (type === 'label') { 42328 //if there is no label container 42329 if (!this.dummyDOM.querySelector('#'.concat(cnvId + labelContainer))) { 42330 var _html = '<div id="' 42331 .concat(cnvId) 42332 .concat(labelContainer, '" class="p5Label"><p id="') 42333 .concat(cnvId) 42334 .concat(labelDescId, '"></p></div>'); 42335 //if there are no accessible outputs (see textOutput() and gridOutput()) 42336 if ( 42337 !this.dummyDOM.querySelector('#'.concat(cnvId, 'accessibleOutputLabel')) 42338 ) { 42339 //create label container + <p> for label description 42340 this.dummyDOM 42341 .querySelector('#' + cnvId) 42342
42342 .insertAdjacentHTML('afterend', _html); 42343 } else { 42344 //create label container + <p> for label description before outputs 42345 this.dummyDOM 42346 .querySelector('#'.concat(cnvId, 'accessibleOutputLabel')) 42347 .insertAdjacentHTML('beforebegin', _html); 42348 } 42349 } else if (this.dummyDOM.querySelector('#'.concat(cnvId + labelTableId))) { 42350 //if describeElement() has already created the container and added a table of elements 42351 //create label description <p> before the table 42352 this.dummyDOM 42353 .querySelector('#'.concat(cnvId + labelTableId)) 42354 .insertAdjacentHTML( 42355 'beforebegin', 42356 '<p id="'.concat(cnvId).concat(labelDescId, '"></p>') 42357 ); 42358 } 42359 this.descriptions.label = this.dummyDOM.querySelector( 42360 '#' + cnvId + labelDescId 42361 ); 42362 42363 this.descriptions.label.innerHTML = text; 42364 return; 42365 } 42366 }; 42367 42368 /* 42369 * Helper functions for describeElement(). 42370 */ 42371 42372 //check that name is not LABEL or FALLBACK and ensure text ends with colon 42373 function _elementName(name) { 42374 if (name === 'label' || name === 'fallback') { 42375 throw new Error('element name should not be LABEL or FALLBACK'); 42376 } 42377 //check if last character of string n is '.', ';', or ',' 42378 if (name.endsWith('.') || name.endsWith(';') || name.endsWith(',')) { 42379 //replace last character with ':' 42380 name = name.replace(/.$/, ':'); 42381 } else if (!name.endsWith(':')) { 42382 //if string n does not end with ':' 42383 //add ':'' at the end of string 42384 name = name + ':'; 42385 } 42386 return name; 42387 } 42388 42389 //creates HTML structure for element descriptions 42390 _main.default.prototype._describeElementHTML = function(type, name, text) { 42391 var cnvId = this.canvas.id; 42392 if (type === 'fallback') { 42393 //if there is no description container 42394 if (!this.dummyDOM.querySelector('#'.concat(cnvId + descContainer))) { 42395 //if there are no accessible outputs (see textOutput() and gridOutput()) 42396 var html = '<div id="' 42397 .concat(cnvId) 42398 .concat( 42399 descContainer, 42400 '" role="region" aria-label="Canvas Description"><table id="' 42401 ) 42402 .concat(cnvId) 42403 .concat( 42404 fallbackTableId, 42405 '"><caption>Canvas elements and their descriptions</caption></table></div>' 42406 ); 42407 if (!this.dummyDOM.querySelector('#'.concat(cnvId, 'accessibleOutput'))) { 42408 //create container + table for element descriptions 42409 this.dummyDOM.querySelector('#' + cnvId).innerHTML = html; 42410 } else { 42411 //create container + table for element descriptions before outputs 42412 this.dummyDOM 42413 .querySelector('#'.concat(cnvId, 'accessibleOutput')) 42414 .insertAdjacentHTML('beforebegin', html); 42415 } 42416 } else if (!this.dummyDOM.querySelector('#' + cnvId + fallbackTableId)) { 42417 //if describe() has already created the container and added a description 42418 //and there is no table create fallback table for element description after 42419 //fallback description 42420 this.dummyDOM 42421 .querySelector('#' + cnvId + fallbackDescId) 42422 .insertAdjacentHTML( 42423 'afterend', 42424 '<table id="' 42425 .concat(cnvId) 42426 .concat( 42427 fallbackTableId, 42428 '"><caption>Canvas elements and their descriptions</caption></table>' 42429 ) 42430 ); 42431 } 42432 //create a table row for the element 42433 var tableRow = document.createElement('tr'); 42434 tableRow.id = cnvId + fallbackTableElId + name; 42435 this.dummyDOM 42436 .querySelector('#' + cnvId + fallbackTableId) 42437 .appendChild(tableRow); 42438 //update element description 42439 this.descriptions.fallbackElements[name] = this.dummyDOM.querySelector( 42440 '#' 42441 .concat(cnvId) 42442 .concat(fallbackTableElId) 42443 .concat(name) 42444 ); 42445 42446 this.descriptions.fallbackElements[name].innerHTML = text; 42447 return; 42448 } else if (type === 'label') { 42449 //If display is LABEL creates a div adjacent to the canvas element with 42450 //a table, a row header cell with the name of the elements, 42451 //and adds the description of the element in adjecent cell. 42452 //if there is no label description container 42453 if (!this.dummyDOM.querySelector('#'.concat(cnvId + labelContainer))) { 42454 //if there are no accessible outputs (see textOutput() and gridOutput()) 42455 var _html2 = '<div id="' 42456 .concat(cnvId) 42457 .concat(labelContainer, '" class="p5Label"><table id="') 42458 .concat(cnvId) 42459 .concat(labelTableId, '"></table></div>'); 42460 if ( 42461 !this.dummyDOM.querySelector('#'.concat(cnvId, 'accessibleOutputLabel')) 42462 ) { 42463 //create container + table for element descriptions 42464 this.dummyDOM 42465 .querySelector('#' + cnvId) 42466 .insertAdjacentHTML('afterend', _html2); 42467 } else { 42468 //create container + table for element descriptions before outputs 42469 this.dummyDOM 42470 .querySelector('#'.concat(cnvId, 'accessibleOutputLabel')) 42471 .insertAdjacentHTML('beforebegin', _html2); 42472 } 42473 } else if (!this.dummyDOM.querySelector('#'.concat(cnvId + labelTableId))) { 42474 //if describe() has already created the label container and added a description 42475 //and there is no table create label table for element description after 42476 //label description 42477 this.dummyDOM
42478 .querySelector('#' + cnvId + labelDescId) 42479 .insertAdjacentHTML( 42480 'afterend', 42481 '<table id="'.concat(cnvId + labelTableId, '"></table>') 42482 ); 42483 } 42484 //create a table row for the element label description 42485 var _tableRow = document.createElement('tr'); 42486 _tableRow.id = cnvId + labelTableElId + name; 42487 this.dummyDOM 42488 .querySelector('#' + cnvId + labelTableId) 42489 .appendChild(_tableRow); 42490 //update element label description 42491 this.descriptions.labelElements[name] = this.dummyDOM.querySelector( 42492 '#' 42493 .concat(cnvId) 42494 .concat(labelTableElId) 42495 .concat(name) 42496 ); 42497 42498 this.descriptions.labelElements[name].innerHTML = text; 42499 } 42500 }; 42501 var _default = _main.default; 42502 exports.default = _default; 42503 }, 42504 { '../core/main': 59 } 42505 ], 42506 40: [ 42507 function(_dereq_, module, exports) { 42508 'use strict'; 42509 Object.defineProperty(exports, '__esModule', { value: true }); 42510 exports.default = void 0; 42511 42512 var _main = _interopRequireDefault(_dereq_('../core/main')); 42513 function _interopRequireDefault(obj) { 42514 return obj && obj.__esModule ? obj : { default: obj }; 42515 } /** //the functions in this file support updating the grid output 42516 * @module Environment 42517 * @submodule Environment 42518 * @for p5 42519 * @requires core 42520 */ 42521 //updates gridOutput 42522 _main.default.prototype._updateGridOutput = function(idT) { 42523 //if html structure is not there yet 42524 if (!this.dummyDOM.querySelector('#'.concat(idT, '_summary'))) { 42525 return; 42526 } 42527 var current = this._accessibleOutputs[idT]; 42528 //create shape details list 42529 var innerShapeDetails = _gridShapeDetails(idT, this.ingredients.shapes); 42530 //create summary 42531 var innerSummary = _gridSummary( 42532 innerShapeDetails.numShapes, 42533 this.ingredients.colors.background, 42534 this.width, 42535 this.height 42536 ); 42537 42538 //create grid map 42539 var innerMap = _gridMap(idT, this.ingredients.shapes); 42540 //if it is different from current summary 42541 if (innerSummary !== current.summary.innerHTML) { 42542 //update 42543 current.summary.innerHTML = innerSummary; 42544 } 42545 //if it is different from current map 42546 if (innerMap !== current.map.innerHTML) { 42547 //update 42548 current.map.innerHTML = innerMap; 42549 } 42550 //if it is different from current shape details 42551 if (innerShapeDetails.details !== current.shapeDetails.innerHTML) { 42552 //update 42553 current.shapeDetails.innerHTML = innerShapeDetails.details; 42554 } 42555 this._accessibleOutputs[idT] = current; 42556 }; 42557 42558 //creates spatial grid that maps the location of shapes 42559 function _gridMap(idT, ingredients) { 42560 var shapeNumber = 0; 42561 var table = ''; 42562 //create an array of arrays 10*10 of empty cells 42563 var cells = Array.apply(null, Array(10)).map(function() {}); 42564 for (var r in cells) { 42565 cells[r] = Array.apply(null, Array(10)).map(function() {}); 42566 } 42567 for (var x in ingredients) { 42568 for (var y in ingredients[x]) { 42569 var fill = void 0; 42570 if (x !== 'line') { 42571 fill = '<a href="#' 42572 .concat(idT, 'shape') 42573 .concat(shapeNumber, '">') 42574 .concat(ingredients[x][y].color, ' ') 42575 .concat(x, '</a>'); 42576 } else { 42577 fill = '<a href="#' 42578 .concat(idT, 'shape') 42579 .concat(shapeNumber, '">') 42580 .concat(ingredients[x][y].color, ' ') 42581 .concat(x, ' midpoint</a>'); 42582 } 42583 //if empty cell of location of shape is undefined 42584 if (!cells[ingredients[x][y].loc.locY][ingredients[x][y].loc.locX]) { 42585 //fill it with shape info 42586 cells[ingredients[x][y].loc.locY][ingredients[x][y].loc.locX] = fill; 42587 //if a shape is already in that location 42588 } else { 42589 //add it 42590 cells[ingredients[x][y].loc.locY][ingredients[x][y].loc.locX] = 42591 cells[ingredients[x][y].loc.locY][ingredients[x][y].loc.locX] + 42592 ' ' + 42593 fill; 42594 } 42595 shapeNumber++; 42596 } 42597 } 42598 //make table based on array 42599 for (var _r in cells) { 42600 var row = '<tr>'; 42601 for (var c in cells[_r]) { 42602 row = row + '<td>'; 42603 if (cells[_r][c] !== undefined) { 42604 row = row + cells[_r][c]; 42605 } 42606 row = row + '</td>'; 42607 } 42608 table = table + row + '</tr>'; 42609 } 42610 return table; 42611 } 42612 42613 //creates grid summary 42614 function _gridSummary(numShapes, background, width, height) { 42615 var text = '' 42616 .concat(background, ' canvas, ') 42617 .concat(width, ' by ') 42618 .concat(height, ' pixels, contains ') 42619 .concat(numShapes[0]); 42620 42621 if (numShapes[0] === 1) { 42622 text = ''.concat(text, ' shape: ').concat(numShapes[1]); 42623 } else { 42624 text = ''.concat(text, ' shapes: ').concat(numShapes[1]); 42625 } 42626 return text; 42627 } 42628 42629 //creates list of shapes 42630 function _gridShapeDetails(idT, ingredients) { 42631 var shapeDetails = ''; 42632 var shapes = ''; 42633 var totalShapes = 0; 42634 //goes trhough every shape type in ingredients 42635 for (var x in ingredients) { 42636 var shapeNum = 0; 42637 for (var y in ingredients[x]) { 42638 //it creates a line in a list 42639 var line = '<li id="' 42640 .concat(idT, 'shape') 42641 .concat(totalShapes, '">') 42642 .concat(ingredients[x][y].color, ' ') 42643 .concat(x, ','); 42644 if (x === 'line') { 42645 line = 42646 line + 42647 ' location = ' 42648 .concat(ingredients[x][y].pos, ', length = ') 42649 .concat(ingredients[x][y].length, ' pixels'); 42650 } else { 42651 line = line + ' location = '.concat(ingredients[x][y].pos); 42652 if (x !== 'point') { 42653 line = line + ', area = '.concat(ingredients[x][y].area, ' %'); 42654 } 42655 line = line + '</li>'; 42656 } 42657 shapeDetails = shapeDetails + line; 42658 shapeNum++; 42659 totalShapes++; 42660 } 42661 if (shapeNum > 1) { 42662 shapes = '' 42663 .concat(shapes, ' ') 42664 .concat(shapeNum, ' ') 42665 .concat(x, 's'); 42666 } else { 42667 shapes = '' 42668 .concat(shapes, ' ') 42669 .concat(shapeNum, ' ') 42670 .concat(x); 42671 } 42672 } 42673 return { numShapes: [totalShapes, shapes], details: shapeDetails }; 42674 } 42675 var _default = _main.default; 42676 exports.default = _default; 42677 }, 42678 { '../core/main': 59 } 42679 ], 42680 41: [
42681 function(_dereq_, module, exports) { 42682 'use strict'; 42683 Object.defineProperty(exports, '__esModule', { value: true }); 42684 exports.default = void 0; 42685 42686 var _main = _interopRequireDefault(_dereq_('../core/main')); 42687 function _interopRequireDefault(obj) { 42688 return obj && obj.__esModule ? obj : { default: obj }; 42689 } 42690 /** 42691 * @module Environment 42692 * @submodule Environment 42693 * @for p5 42694 * @requires core 42695 */ /** 42696 * <code class="language-javascript">textOutput()</code> creates a screenreader 42697 * accessible output that describes the shapes present on the canvas. 42698 * The general description of the canvas includes canvas size, 42699 * canvas color, and number of elements in the canvas 42700 * (example: 'Your output is a, 400 by 400 pixels, lavender blue 42701 * canvas containing the following 4 shapes:'). This description 42702 * is followed by a list of shapes where the color, position, and area 42703 * of each shape are described (example: "orange ellipse at top left 42704 * covering 1% of the canvas"). Each element can be selected to get 42705 * more details. A table of elements is also provided. In this table, 42706 * shape, color, location, coordinates and area are described 42707 * (example: "orange ellipse location=top left area=2"). 42708 * 42709 * <code class="language-javascript">textOutput()</code> and <code class="language-javascript">texOutput(FALLBACK)</code> 42710 * make the output available in <a href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Hit_regions_and_accessibility" target="_blank"> 42711 * a sub DOM inside the canvas element</a> which is accessible to screen readers. 42712 * <code class="language-javascript">textOutput(LABEL)</code> creates an 42713 * additional div with the output adjacent to the canvas, this is useful 42714 * for non-screen reader users that might want to display the output outside 42715 * of the canvas' sub DOM as they code. However, using LABEL will create 42716 * unnecessary redundancy for screen reader users. We recommend using LABEL 42717 * only as part of the development process of a sketch and removing it before 42718 * publishing or sharing with screen reader users. 42719 * 42720 * @method textOutput 42721 * @param {Constant} [display] either FALLBACK or LABEL (Optional) 42722 * 42723 * @example 42724 * <div> 42725 * <code> 42726 * textOutput(); 42727 * background(148, 196, 0); 42728 * fill(255, 0, 0); 42729 * ellipse(20, 20, 20, 20); 42730 * fill(0, 0, 255); 42731 * rect(50, 50, 50, 50); 42732 * </code> 42733 * </div> 42734 * 42735 * 42736 * <div> 42737 * <code> 42738 * let x = 0; 42739 * function draw() { 42740 * textOutput(); 42741 * background(148, 196, 0); 42742 * fill(255, 0, 0); 42743 * ellipse(x, 20, 20, 20); 42744 * fill(0, 0, 255); 42745 * rect(50, 50, 50, 50); 42746 * ellipse(20, 20, 20, 20); 42747 * x += 0.1; 42748 * } 42749 * </code> 42750 * </div> 42751 * 42752 */ _main.default.prototype.textOutput = function(display) { 42753 _main.default._validateParameters('textOutput', arguments); 42754 //if textOutput is already true 42755 if (this._accessibleOutputs.text) { 42756 return; 42757 } else { 42758 //make textOutput true 42759 this._accessibleOutputs.text = true; 42760 //create output for fallback 42761 this._createOutput('textOutput', 'Fallback'); 42762 if (display === this.LABEL) { 42763 //make textOutput label true 42764 this._accessibleOutputs.textLabel = true; 42765 //create output for label 42766 this._createOutput('textOutput', 'Label'); 42767 } 42768 } 42769 }; 42770 42771 /** 42772 * <code class="language-javascript">gridOutput()</code> lays out the 42773 * content of the canvas in the form of a grid (html table) based 42774 * on the spatial location of each shape. A brief 42775 * description of the canvas is available before the table output. 42776 * This description includes: color of the background, size of the canvas, 42777 * number of objects, and object types (example: "lavender blue canvas is 42778 * 200 by 200 and contains 4 objects - 3 ellipses 1 rectangle"). The grid 42779 * describes the content spatially, each element is placed on a cell of the 42780 * table depending on its position. Within each cell an element the color 42781 * and type of shape of that element are available (example: "orange ellipse"). 42782 * These descriptions can be selected individually to get more details. 42783 * A list of elements where shape, color, location, and area are described 42784 * (example: "orange ellipse location=top left area=1%") is also available. 42785 * 42786 * <code class="language-javascript">gridOutput()</code> and <code class="language-javascript">gridOutput(FALLBACK)</code> 42787 * make the output available in <a href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Hit_regions_and_accessibility" target="_blank"> 42788 * a sub DOM inside the canvas element</a> which is accessible to screen readers. 42789 * <code class="language-javascript">gridOutput(LABEL)</code> creates an 42790 * additional div with the output adjacent to the canvas, this is useful 42791 * for non-screen reader users that might want to display the output outside 42792 * of the canvas' sub DOM as they code. However, using LABEL will create 42793 * unnecessary redundancy for screen reader users. We recommend using LABEL 42794 * only as part of the development process of a sketch and removing it before 42795 * publishing or sharing with screen reader users. 42796 * 42797 * @method gridOutput 42798 * @param {Constant} [display] either FALLBACK or LABEL (Optional) 42799 * 42800 * @example 42801 * <div> 42802 * <code> 42803 * gridOutput(); 42804 * background(148, 196, 0); 42805 * fill(255, 0, 0); 42806 * ellipse(20, 20, 20, 20); 42807 * fill(0, 0, 255); 42808 * rect(50, 50, 50, 50); 42809 * </code> 42810 * </div> 42811 * 42812 * 42813 * <div> 42814 * <code> 42815 * let x = 0; 42816 * function draw() { 42817 * gridOutput(); 42818 * background(148, 196, 0); 42819 * fill(255, 0, 0); 42820 * ellipse(x, 20, 20, 20); 42821 * fill(0, 0, 255); 42822 * rect(50, 50, 50, 50); 42823 * ellipse(20, 20, 20, 20); 42824 * x += 0.1; 42825 * } 42826 * </code> 42827 * </div> 42828 * 42829 */ 42830 42831 _main.default.prototype.gridOutput = function(display) { 42832 _main.default._validateParameters('gridOutput', arguments); 42833 //if gridOutput is already true 42834 if (this._accessibleOutputs.grid) { 42835 return; 42836 } else { 42837 //make gridOutput true 42838 this._accessibleOutputs.grid = true; 42839 //create output for fallback 42840 this._createOutput('gridOutput', 'Fallback'); 42841 if (display === this.LABEL) { 42842 //make gridOutput label true 42843 this._accessibleOutputs.gridLabel = true; 42844 //create output for label 42845 this._createOutput('gridOutput', 'Label'); 42846 } 42847 } 42848 }; 42849 42850 //helper function returns true when accessible outputs are true 42851 _main.default.prototype._addAccsOutput = function() { 42852 //if there are no accessible outputs create object with all false 42853 if (!this._accessibleOutputs) { 42854 this._accessibleOutputs = { 42855 text: false, 42856 grid: false, 42857 textLabel: false, 42858 gridLabel: false 42859 }; 42860 } 42861 return this._accessibleOutputs.grid || this._accessibleOutputs.text; 42862 }; 42863 42864 //helper function that creates html structure for accessible outputs 42865 _main.default.prototype._createOutput = function(type, display) { 42866 var cnvId = this.canvas.id; 42867 //if there are no ingredients create object. this object stores data for the outputs 42868 if (!this.ingredients) { 42869 this.ingredients = { 42870 shapes: {}, 42871 colors: { background: 'white', fill: 'white', stroke: 'black' }, 42872 pShapes: '' 42873 }; 42874 } 42875 //if there is no dummyDOM create it 42876 if (!this.dummyDOM) { 42877 this.dummyDOM = document.getElementById(cnvId).parentNode; 42878 } 42879 var cIdT, container, inner; 42880 var query = ''; 42881 if (display === 'Fallback') { 42882 cIdT = cnvId + type; 42883 container = cnvId + 'accessibleOutput'; 42884 if (!this.dummyDOM.querySelector('#'.concat(container))) { 42885 //if there is no canvas description (see describe() and describeElement()) 42886 if (!this.dummyDOM.querySelector('#'.concat(cnvId, '_Description'))) { 42887 //create html structure inside of canvas 42888 this.dummyDOM.querySelector( 42889 '#'.concat(cnvId) 42890 ).innerHTML = '<div id="'.concat( 42891 container, 42892 '" role="region" aria-label="Canvas Outputs"></div>' 42893 ); 42894 } else { 42895 //create html structure after canvas description container 42896 this.dummyDOM 42897 .querySelector('#'.concat(cnvId, '_Description')) 42898 .insertAdjacentHTML( 42899 'afterend', 42900 '<div id="'.concat( 42901 container, 42902 '" role="region" aria-label="Canvas Outputs"></div>' 42903 ) 42904 ); 42905 } 42906 } 42907 } else if (display === 'Label') { 42908 query = display; 42909 cIdT = cnvId + type + display; 42910 container = cnvId + 'accessibleOutput' + display; 42911 if (!this.dummyDOM.querySelector('#'.concat(container))) { 42912 //if there is no canvas description label (see describe() and describeElement()) 42913 if (!this.dummyDOM.querySelector('#'.concat(cnvId, '_Label'))) { 42914 //create html structure adjacent to canvas 42915 this.dummyDOM 42916 .querySelector('#'.concat(cnvId)) 42917 .insertAdjacentHTML( 42918 'afterend', 42919 '<div id="'.concat(container, '"></div>') 42920 ); 42921 } else { 42922 //create html structure after canvas label 42923 this.dummyDOM 42924 .querySelector('#'.concat(cnvId, '_Label')) 42925 .insertAdjacentHTML( 42926 'afterend', 42927 '<div id="'.concat(container, '"></div>') 42928 ); 42929 } 42930 } 42931 } 42932 //create an object to store the latest output. this object is used in _updateTextOutput() and _updateGridOutput() 42933 this._accessibleOutputs[cIdT] = {}; 42934 if (type === 'textOutput') { 42935 query = '#'.concat(cnvId, 'gridOutput').concat(query); //query is used to check if gridOutput already exists 42936 inner = '<div id="' 42937 .concat(cIdT, '">Text Output<div id="') 42938 .concat(cIdT, 'Summary" aria-label="text output summary"><p id="') 42939 .concat(cIdT, '_summary"></p><ul id="') 42940 .concat(cIdT, '_list"></ul></div><table id="') 42941 .concat( 42942 cIdT, 42943 '_shapeDetails" summary="text output shape details"></table></div>' 42944 ); 42945 //if gridOutput already exists 42946 if (this.dummyDOM.querySelector(query)) { 42947 //create textOutput before gridOutput 42948 this.dummyDOM.querySelector(query).insertAdjacentHTML('beforebegin', inner); 42949 } else { 42950 //create output inside of container 42951 this.dummyDOM.querySelector('#'.concat(container)).innerHTML = inner; 42952 } 42953 //store output html elements 42954 this._accessibleOutputs[cIdT].list = this.dummyDOM.querySelector( 42955 '#'.concat(cIdT, '_list') 42956 ); 42957 } else if (type === 'gridOutput') { 42958 query = '#'.concat(cnvId, 'textOutput').concat(query); //query is used to check if textOutput already exists 42959 inner = '<div id="' 42960 .concat(cIdT, '">Grid Output<p id="') 42961 .concat(cIdT, '_summary" aria-label="grid output summary"><table id="') 42962 .concat(cIdT, '_map" summary="grid output content"></table><ul id="') 42963 .concat( 42964 cIdT, 42965 '_shapeDetails" aria-label="grid output shape details"></ul></div>' 42966 ); 42967 //if textOutput already exists 42968 if (this.dummyDOM.querySelector(query)) { 42969 //create gridOutput after textOutput 42970 this.dummyDOM.querySelector(query).insertAdjacentHTML('afterend', inner); 42971 } else { 42972 //create output inside of container 42973 this.dummyDOM.querySelector('#'.concat(container)).innerHTML = inner; 42974 } 42975 //store output html elements 42976 this._accessibleOutputs[cIdT].map = this.dummyDOM.querySelector( 42977 '#'.concat(cIdT, '_map') 42978 ); 42979 } 42980 this._accessibleOutputs[cIdT].shapeDetails = this.dummyDOM.querySelector( 42981 '#'.concat(cIdT, '_shapeDetails') 42982 ); 42983 42984 this._accessibleOutputs[cIdT].summary = this.dummyDOM.querySelector( 42985 '#'.concat(cIdT, '_summary') 42986 ); 42987 }; 42988 42989 //this function is called at the end of setup and draw if using 42990 //accessibleOutputs and calls update functions of outputs 42991 _main.default.prototype._updateAccsOutput = function() { 42992 var cnvId = this.canvas.id; 42993 //if the shapes are not the same as before 42994 if (JSON.stringify(this.ingredients.shapes) !== this.ingredients.pShapes) {
42995 //save current shapes as string in pShapes 42996 this.ingredients.pShapes = JSON.stringify(this.ingredients.shapes); 42997 if (this._accessibleOutputs.text) { 42998 this._updateTextOutput(cnvId + 'textOutput'); 42999 } 43000 if (this._accessibleOutputs.grid) { 43001 this._updateGridOutput(cnvId + 'gridOutput'); 43002 } 43003 if (this._accessibleOutputs.textLabel) { 43004 this._updateTextOutput(cnvId + 'textOutputLabel'); 43005 } 43006 if (this._accessibleOutputs.gridLabel) { 43007 this._updateGridOutput(cnvId + 'gridOutputLabel'); 43008 } 43009 } 43010 }; 43011 43012 //helper function that resets all ingredients when background is called 43013 //and saves background color name 43014 _main.default.prototype._accsBackground = function(args) { 43015 //save current shapes as string in pShapes 43016 this.ingredients.pShapes = JSON.stringify(this.ingredients.shapes); 43017 //empty shapes JSON 43018 this.ingredients.shapes = {}; 43019 //update background different 43020 if (this.ingredients.colors.backgroundRGBA !== args) { 43021 this.ingredients.colors.backgroundRGBA = args; 43022 this.ingredients.colors.background = this._rgbColorName(args); 43023 } 43024 }; 43025 43026 //helper function that gets fill and stroke of shapes 43027 _main.default.prototype._accsCanvasColors = function(f, args) { 43028 if (f === 'fill') { 43029 //update fill different 43030 if (this.ingredients.colors.fillRGBA !== args) { 43031 this.ingredients.colors.fillRGBA = args; 43032 this.ingredients.colors.fill = this._rgbColorName(args); 43033 } 43034 } else if (f === 'stroke') { 43035 //update stroke if different 43036 if (this.ingredients.colors.strokeRGBA !== args) { 43037 this.ingredients.colors.strokeRGBA = args; 43038 this.ingredients.colors.stroke = this._rgbColorName(args); 43039 } 43040 } 43041 }; 43042 43043 //builds ingredients.shapes used for building outputs 43044 _main.default.prototype._accsOutput = function(f, args) { 43045 if (f === 'ellipse' && args[2] === args[3]) { 43046 f = 'circle'; 43047 } else if (f === 'rectangle' && args[2] === args[3]) { 43048 f = 'square'; 43049 } 43050 var include = {}; 43051 var add = true; 43052 var middle = _getMiddle(f, args); 43053 if (f === 'line') { 43054 //make color stroke 43055 include.color = this.ingredients.colors.stroke; 43056 //get lenght 43057 include.length = Math.round(this.dist(args[0], args[1], args[2], args[3])); 43058 //get position of end points 43059 var p1 = _getPos([args[0], [1]], this.width, this.height); 43060 var p2 = _getPos([args[2], [3]], this.width, this.height); 43061 include.loc = _canvasLocator(middle, this.width, this.height); 43062 if (p1 === p2) { 43063 include.pos = 'at '.concat(p1); 43064 } else { 43065 include.pos = 'from '.concat(p1, ' to ').concat(p2); 43066 } 43067 } else { 43068 if (f === 'point') { 43069 //make color stroke 43070 include.color = this.ingredients.colors.stroke; 43071 } else { 43072 //make color fill 43073 include.color = this.ingredients.colors.fill; 43074 //get area of shape 43075 include.area = _getArea(f, args, this.width, this.height); 43076 } 43077 //get middle of shapes 43078 //calculate position using middle of shape 43079 include.pos = _getPos(middle, this.width, this.height); 43080 //calculate location using middle of shape 43081 include.loc = _canvasLocator(middle, this.width, this.height); 43082 } 43083 //if it is the first time this shape is created 43084 if (!this.ingredients.shapes[f]) { 43085 this.ingredients.shapes[f] = [include]; 43086 //if other shapes of this type have been created 43087 } else if (this.ingredients.shapes[f] !== [include]) { 43088 //for every shape of this type 43089 for (var y in this.ingredients.shapes[f]) { 43090 //compare it with current shape and if it already exists make add false 43091 if ( 43092 JSON.stringify(this.ingredients.shapes[f][y]) === JSON.stringify(include) 43093 ) { 43094 add = false;
43095 } 43096 } 43097 //add shape by pushing it to the end 43098 if (add === true) { 43099 this.ingredients.shapes[f].push(include); 43100 } 43101 } 43102 }; 43103 43104 //gets middle point / centroid of shape 43105 function _getMiddle(f, args) { 43106 var x, y; 43107 if ( 43108 f === 'rectangle' || 43109 f === 'ellipse' || 43110 f === 'arc' || 43111 f === 'circle' || 43112 f === 'square' 43113 ) { 43114 x = Math.round(args[0] + args[2] / 2); 43115 y = Math.round(args[1] + args[3] / 2); 43116 } else if (f === 'triangle') { 43117 x = (args[0] + args[2] + args[4]) / 3; 43118 y = (args[1] + args[3] + args[5]) / 3; 43119 } else if (f === 'quadrilateral') { 43120 x = (args[0] + args[2] + args[4] + args[6]) / 4; 43121 y = (args[1] + args[3] + args[5] + args[7]) / 4; 43122 } else if (f === 'line') { 43123 x = (args[0] + args[2]) / 2; 43124 y = (args[1] + args[3]) / 2; 43125 } else { 43126 x = args[0]; 43127 y = args[1]; 43128 } 43129 return [x, y]; 43130 } 43131 43132 //gets position of shape in the canvas 43133 function _getPos(args, canvasWidth, canvasHeight) { 43134 if (args[0] < 0.4 * canvasWidth) { 43135 if (args[1] < 0.4 * canvasHeight) { 43136 return 'top left'; 43137 } else if (args[1] > 0.6 * canvasHeight) { 43138 return 'bottom left'; 43139 } else { 43140 return 'mid left'; 43141 } 43142 } else if (args[0] > 0.6 * canvasWidth) { 43143 if (args[1] < 0.4 * canvasHeight) { 43144 return 'top right'; 43145 } else if (args[1] > 0.6 * canvasHeight) { 43146 return 'bottom right'; 43147 } else { 43148 return 'mid right'; 43149 } 43150 } else { 43151 if (args[1] < 0.4 * canvasHeight) { 43152 return 'top middle'; 43153 } else if (args[1] > 0.6 * canvasHeight) { 43154 return 'bottom middle'; 43155 } else { 43156 return 'middle'; 43157 } 43158 } 43159 } 43160 43161 //locates shape in a 10*10 grid 43162 function _canvasLocator(args, canvasWidth, canvasHeight) { 43163 var noRows = 10; 43164 var noCols = 10; 43165 var locX = Math.floor(args[0] / canvasWidth * noRows); 43166 var locY = Math.floor(args[1] / canvasHeight * noCols); 43167 if (locX === noRows) { 43168 locX = locX - 1; 43169 } 43170 if (locY === noCols) { 43171 locY = locY - 1; 43172 } 43173 return { 43174 locX: locX, 43175 locY: locY 43176 }; 43177 } 43178 43179 //calculates area of shape 43180 function _getArea(objectType, shapeArgs, canvasWidth, canvasHeight) { 43181 var objectArea = 0; 43182 if (objectType === 'arc') { 43183 // area of full ellipse = PI * horizontal radius * vertical radius. 43184 // therefore, area of arc = difference bet. arc's start and end radians * horizontal radius * vertical radius. 43185 // the below expression is adjusted for negative values and differences in arc's start and end radians over PI*2 43186 var arcSizeInRadians = 43187 ((shapeArgs[5] - shapeArgs[4]) % (Math.PI * 2) + Math.PI * 2) % 43188 (Math.PI * 2); 43189 objectArea = arcSizeInRadians * shapeArgs[2] * shapeArgs[3] / 8; 43190 if (shapeArgs[6] === 'open' || shapeArgs[6] === 'chord') { 43191 // when the arc's mode is OPEN or CHORD, we need to account for the area of the triangle that is formed to close the arc 43192 // (Ax( By â Cy) + Bx(Cy â Ay) + Cx(Ay â By ) )/2 43193 var Ax = shapeArgs[0]; 43194 var Ay = shapeArgs[1]; 43195 var Bx = 43196 shapeArgs[0] + shapeArgs[2] / 2 * Math.cos(shapeArgs[4]).toFixed(2); 43197 var By = 43198 shapeArgs[1] + shapeArgs[3] / 2 * Math.sin(shapeArgs[4]).toFixed(2); 43199 var Cx = 43200 shapeArgs[0] + shapeArgs[2] / 2 * Math.cos(shapeArgs[5]).toFixed(2); 43201 var Cy = 43202 shapeArgs[1] + shapeArgs[3] / 2 * Math.sin(shapeArgs[5]).toFixed(2); 43203 var areaOfExtraTriangle = 43204 Math.abs(Ax * (By - Cy) + Bx * (Cy - Ay) + Cx * (Ay - By)) / 2; 43205 if (arcSizeInRadians > Math.PI) { 43206 objectArea = objectArea + areaOfExtraTriangle; 43207 } else { 43208 objectArea = objectArea - areaOfExtraTriangle; 43209 } 43210 } 43211 } else if (objectType === 'ellipse' || objectType === 'circle') { 43212 objectArea = 3.14 * shapeArgs[2] / 2 * shapeArgs[3] / 2; 43213 } else if (objectType === 'line') { 43214 objectArea = 0; 43215 } else if (objectType === 'point') { 43216 objectArea = 0; 43217 } else if (objectType === 'quadrilateral') { 43218 // ((x4+x1)*(y4-y1)+(x1+x2)*(y1-y2)+(x2+x3)*(y2-y3)+(x3+x4)*(y3-y4))/2 43219 objectArea = 43220 Math.abs( 43221 (shapeArgs[6] + shapeArgs[0]) * (shapeArgs[7] - shapeArgs[1]) + 43222 (shapeArgs[0] + shapeArgs[2]) * (shapeArgs[1] - shapeArgs[3]) + 43223 (shapeArgs[2] + shapeArgs[4]) * (shapeArgs[3] - shapeArgs[5]) + 43224 (shapeArgs[4] + shapeArgs[6]) * (shapeArgs[5] - shapeArgs[7]) 43225 ) / 2; 43226 } else if (objectType === 'rectangle' || objectType === 'square') { 43227 objectArea = shapeArgs[2] * shapeArgs[3]; 43228 } else if (objectType === 'triangle') { 43229 objectArea = 43230 Math.abs( 43231 shapeArgs[0] * (shapeArgs[3] - shapeArgs[5]) + 43232 shapeArgs[2] * (shapeArgs[5] - shapeArgs[1]) + 43233 shapeArgs[4] * (shapeArgs[1] - shapeArgs[3]) 43234 ) / 2; 43235 // (Ax( By â Cy) + Bx(Cy â Ay) + Cx(Ay â By ))/2 43236 } 43237 43238 return Math.round(objectArea * 100 / (canvasWidth * canvasHeight)); 43239 } 43240 var _default = _main.default; 43241 exports.default = _default; 43242 }, 43243 { '../core/main': 59 } 43244 ], 43245 42: [
43246 function(_dereq_, module, exports) { 43247 'use strict'; 43248 Object.defineProperty(exports, '__esModule', { value: true }); 43249 exports.default = void 0; 43250 43251 var _main = _interopRequireDefault(_dereq_('../core/main')); 43252 function _interopRequireDefault(obj) { 43253 return obj && obj.__esModule ? obj : { default: obj }; 43254 } /** //the functions in this file support updating the text output 43255 * @module Environment 43256 * @submodule Environment 43257 * @for p5 43258 * @requires core 43259 */ 43260 //updates textOutput 43261 _main.default.prototype._updateTextOutput = function(idT) { 43262 //if html structure is not there yet 43263 if (!this.dummyDOM.querySelector('#'.concat(idT, '_summary'))) { 43264 return; 43265 } 43266 var current = this._accessibleOutputs[idT]; 43267 //create shape list 43268 var innerList = _shapeList(idT, this.ingredients.shapes); 43269 //create output summary 43270 var innerSummary = _textSummary( 43271 innerList.numShapes, 43272 this.ingredients.colors.background, 43273 this.width, 43274 this.height 43275 ); 43276 43277 //create shape details 43278 var innerShapeDetails = _shapeDetails(idT, this.ingredients.shapes); 43279 //if it is different from current summary 43280 if (innerSummary !== current.summary.innerHTML) { 43281 //update 43282 current.summary.innerHTML = innerSummary; 43283 } 43284 //if it is different from current shape list 43285 if (innerList.listShapes !== current.list.innerHTML) { 43286 //update 43287 current.list.innerHTML = innerList.listShapes; 43288 } 43289 //if it is different from current shape details 43290 if (innerShapeDetails !== current.shapeDetails.innerHTML) { 43291 //update 43292 current.shapeDetails.innerHTML = innerShapeDetails; 43293 } 43294 this._accessibleOutputs[idT] = current; 43295 }; 43296 43297 //Builds textOutput summary 43298 function _textSummary(numShapes, background, width, height) { 43299 var text = 'Your output is a, ' 43300 .concat(width, ' by ') 43301 .concat(height, ' pixels, ') 43302 .concat(background, ' canvas containing the following'); 43303 if (numShapes === 1) { 43304 text = ''.concat(text, ' shape:'); 43305 } else { 43306 text = ''.concat(text, ' ').concat(numShapes, ' shapes:'); 43307 } 43308 return text; 43309 } 43310 43311 //Builds textOutput table with shape details 43312 function _shapeDetails(idT, ingredients) { 43313 var shapeDetails = ''; 43314 var shapeNumber = 0; 43315 //goes trhough every shape type in ingredients 43316 for (var x in ingredients) { 43317 //and for every shape 43318 for (var y in ingredients[x]) { 43319 //it creates a table row 43320 var row = '<tr id="' 43321 .concat(idT, 'shape') 43322 .concat(shapeNumber, '"><th>') 43323 .concat(ingredients[x][y].color, ' ') 43324 .concat(x, '</th>'); 43325 if (x === 'line') { 43326 row = 43327 row + 43328 '<td>location = ' 43329 .concat(ingredients[x][y].pos, '</td><td>length = ') 43330 .concat(ingredients[x][y].length, ' pixels</td></tr>'); 43331 } else { 43332 row = row + '<td>location = '.concat(ingredients[x][y].pos, '</td>'); 43333 if (x !== 'point') { 43334 row = row + '<td> area = '.concat(ingredients[x][y].area, '%</td>'); 43335 } 43336 row = row + '</tr>'; 43337 } 43338 shapeDetails = shapeDetails + row; 43339 shapeNumber++; 43340 } 43341 } 43342 return shapeDetails; 43343 } 43344 43345 //Builds textOutput shape list 43346 function _shapeList(idT, ingredients) { 43347 var shapeList = ''; 43348 var shapeNumber = 0; 43349 //goes trhough every shape type in ingredients 43350 for (var x in ingredients) { 43351 for (var y in ingredients[x]) { 43352 //it creates a line in a list 43353 var _line = '<li><a href="#' 43354 .concat(idT, 'shape') 43355 .concat(shapeNumber, '">') 43356 .concat(ingredients[x][y].color, ' ') 43357 .concat(x, '</a>'); 43358 if (x === 'line') { 43359 _line = 43360 _line + 43361 ', ' 43362 .concat(ingredients[x][y].pos, ', ') 43363 .concat(ingredients[x][y].length, ' pixels long.</li>'); 43364 } else { 43365 _line = _line + ', at '.concat(ingredients[x][y].pos); 43366 if (x !== 'point') { 43367 _line = 43368 _line + 43369 ', covering '.concat(ingredients[x][y].area, '% of the canvas'); 43370 } 43371 _line = _line + '.</li>'; 43372 } 43373 shapeList = shapeList + _line; 43374 shapeNumber++; 43375 } 43376 } 43377 return { numShapes: shapeNumber, listShapes: shapeList }; 43378 } 43379 var _default = _main.default; 43380 exports.default = _default; 43381 }, 43382 { '../core/main': 59 } 43383 ], 43384 43: [
43385 function(_dereq_, module, exports) { 43386 'use strict'; 43387 var _main = _interopRequireDefault(_dereq_('./core/main')); 43388 _dereq_('./core/constants'); 43389 _dereq_('./core/environment'); 43390 _dereq_('./core/friendly_errors/stacktrace'); 43391 _dereq_('./core/friendly_errors/validate_params'); 43392 _dereq_('./core/friendly_errors/file_errors'); 43393 _dereq_('./core/friendly_errors/fes_core'); 43394 _dereq_('./core/helpers'); 43395 _dereq_('./core/legacy'); 43396 _dereq_('./core/preload'); 43397 _dereq_('./core/p5.Element'); 43398 _dereq_('./core/p5.Graphics'); 43399 _dereq_('./core/p5.Renderer'); 43400 _dereq_('./core/p5.Renderer2D'); 43401 _dereq_('./core/rendering'); 43402 _dereq_('./core/shim'); 43403 _dereq_('./core/structure'); 43404 _dereq_('./core/transform'); 43405 _dereq_('./core/shape/2d_primitives'); 43406 _dereq_('./core/shape/attributes'); 43407 _dereq_('./core/shape/curves'); 43408 _dereq_('./core/shape/vertex'); 43409 43410 _dereq_('./accessibility/outputs'); 43411 _dereq_('./accessibility/textOutput'); 43412 _dereq_('./accessibility/gridOutput'); 43413 _dereq_('./accessibility/color_namer'); 43414 43415 _dereq_('./color/color_conversion'); 43416 _dereq_('./color/creating_reading'); 43417 _dereq_('./color/p5.Color'); 43418 _dereq_('./color/setting'); 43419 43420 _dereq_('./data/p5.TypedDict'); 43421 _dereq_('./data/local_storage.js'); 43422 43423 _dereq_('./dom/dom'); 43424 43425 _dereq_('./accessibility/describe'); 43426 43427 _dereq_('./events/acceleration'); 43428 _dereq_('./events/keyboard'); 43429 _dereq_('./events/mouse'); 43430 _dereq_('./events/touch'); 43431 43432 _dereq_('./image/filters'); 43433 _dereq_('./image/image'); 43434 _dereq_('./image/loading_displaying'); 43435 _dereq_('./image/p5.Image'); 43436 _dereq_('./image/pixels'); 43437 43438 _dereq_('./io/files'); 43439 _dereq_('./io/p5.Table'); 43440 _dereq_('./io/p5.TableRow'); 43441 _dereq_('./io/p5.XML'); 43442 43443 _dereq_('./math/calculation'); 43444 _dereq_('./math/math'); 43445 _dereq_('./math/noise'); 43446 _dereq_('./math/p5.Vector'); 43447 _dereq_('./math/random'); 43448 _dereq_('./math/trigonometry'); 43449 43450 _dereq_('./typography/attributes'); 43451 _dereq_('./typography/loading_displaying'); 43452 _dereq_('./typography/p5.Font'); 43453 43454 _dereq_('./utilities/array_functions'); 43455 _dereq_('./utilities/conversion'); 43456 _dereq_('./utilities/string_functions'); 43457 _dereq_('./utilities/time_date'); 43458 43459 _dereq_('./webgl/3d_primitives'); 43460 _dereq_('./webgl/interaction'); 43461 _dereq_('./webgl/light'); 43462 _dereq_('./webgl/loading'); 43463 _dereq_('./webgl/material'); 43464 _dereq_('./webgl/p5.Camera'); 43465 _dereq_('./webgl/p5.Geometry'); 43466 _dereq_('./webgl/p5.Matrix'); 43467 _dereq_('./webgl/p5.RendererGL.Immediate'); 43468 _dereq_('./webgl/p5.RendererGL'); 43469 _dereq_('./webgl/p5.RendererGL.Retained'); 43470 _dereq_('./webgl/p5.Shader'); 43471 _dereq_('./webgl/p5.RenderBuffer'); 43472 _dereq_('./webgl/p5.Texture'); 43473 _dereq_('./webgl/text'); 43474 43475 _dereq_('./core/init'); 43476 function _interopRequireDefault(obj) { 43477 return obj && obj.__esModule ? obj : { default: obj }; 43478 } // core 43479 //accessibility 43480 // color 43481 // data 43482 // DOM 43483 // accessibility 43484 // events 43485 // image 43486 // io 43487 // math 43488 // typography 43489 // utilities 43490 // webgl 43491 module.exports = _main.default; 43492 }, 43493 { 43494 './accessibility/color_namer': 38, 43495 './accessibility/describe': 39, 43496 './accessibility/gridOutput': 40, 43497 './accessibility/outputs': 41, 43498 './accessibility/textOutput': 42, 43499 './color/color_conversion': 44, 43500 './color/creating_reading': 45, 43501 './color/p5.Color': 46, 43502 './color/setting': 47, 43503 './core/constants': 48, 43504 './core/environment': 49, 43505 './core/friendly_errors/fes_core': 51, 43506 './core/friendly_errors/file_errors': 52, 43507 './core/friendly_errors/stacktrace': 53, 43508 './core/friendly_errors/validate_params': 54, 43509 './core/helpers': 55, 43510 './core/init': 56, 43511 './core/legacy': 58, 43512 './core/main': 59, 43513 './core/p5.Element': 60, 43514 './core/p5.Graphics': 61, 43515 './core/p5.Renderer': 62, 43516 './core/p5.Renderer2D': 63, 43517 './core/preload': 64, 43518 './core/rendering': 65, 43519 './core/shape/2d_primitives': 66, 43520 './core/shape/attributes': 67, 43521 './core/shape/curves': 68, 43522 './core/shape/vertex': 69, 43523 './core/shim': 70, 43524 './core/structure': 71, 43525 './core/transform': 72, 43526 './data/local_storage.js': 73, 43527 './data/p5.TypedDict': 74, 43528 './dom/dom': 75, 43529 './events/acceleration': 76, 43530 './events/keyboard': 77, 43531 './events/mouse': 78, 43532 './events/touch': 79, 43533 './image/filters': 80, 43534 './image/image': 81, 43535 './image/loading_displaying': 82, 43536 './image/p5.Image': 83, 43537 './image/pixels': 84, 43538 './io/files': 85, 43539 './io/p5.Table': 86, 43540 './io/p5.TableRow': 87, 43541 './io/p5.XML': 88, 43542 './math/calculation': 89, 43543 './math/math': 90, 43544 './math/noise': 91, 43545 './math/p5.Vector': 92, 43546 './math/random': 93, 43547 './math/trigonometry': 94, 43548 './typography/attributes': 95, 43549 './typography/loading_displaying': 96, 43550 './typography/p5.Font': 97, 43551 './utilities/array_functions': 98, 43552 './utilities/conversion': 99, 43553 './utilities/string_functions': 100, 43554 './utilities/time_date': 101,
43555 './webgl/3d_primitives': 102, 43556 './webgl/interaction': 103, 43557 './webgl/light': 104, 43558 './webgl/loading': 105, 43559 './webgl/material': 106, 43560 './webgl/p5.Camera': 107, 43561 './webgl/p5.Geometry': 108, 43562 './webgl/p5.Matrix': 109, 43563 './webgl/p5.RenderBuffer': 110, 43564 './webgl/p5.RendererGL': 113, 43565 './webgl/p5.RendererGL.Immediate': 111, 43566 './webgl/p5.RendererGL.Retained': 112, 43567 './webgl/p5.Shader': 114, 43568 './webgl/p5.Texture': 115, 43569 './webgl/text': 116 43570 } 43571 ], 43572 44: [ 43573 function(_dereq_, module, exports) { 43574 'use strict'; 43575 Object.defineProperty(exports, '__esModule', { value: true }); 43576 exports.default = void 0; 43577 43578 var _main = _interopRequireDefault(_dereq_('../core/main')); 43579 function _interopRequireDefault(obj) { 43580 return obj && obj.__esModule ? obj : { default: obj }; 43581 } 43582 /** 43583 * @module Color 43584 * @submodule Color Conversion 43585 * @for p5 43586 * @requires core 43587 */ /** 43588 * Conversions adapted from <http://www.easyrgb.com/en/math.php>. 43589 * 43590 * In these functions, hue is always in the range [0, 1], just like all other 43591 * components are in the range [0, 1]. 'Brightness' and 'value' are used 43592 * interchangeably. 43593 */ _main.default.ColorConversion = {}; 43594 /** 43595 * Convert an HSBA array to HSLA. 43596 */ _main.default.ColorConversion._hsbaToHSLA = function(hsba) { 43597 var hue = hsba[0]; 43598 var sat = hsba[1]; 43599 var val = hsba[2]; // Calculate lightness. 43600 var li = (2 - sat) * val / 2; // Convert saturation. 43601 if (li !== 0) { 43602 if (li === 1) { 43603 sat = 0; 43604 } else if (li < 0.5) { 43605 sat = sat / (2 - sat); 43606 } else { 43607 sat = sat * val / (2 - li * 2); 43608 } 43609 } 43610 43611 // Hue and alpha stay the same. 43612 return [hue, sat, li, hsba[3]]; 43613 }; 43614 43615 /** 43616 * Convert an HSBA array to RGBA. 43617 */ 43618 _main.default.ColorConversion._hsbaToRGBA = function(hsba) { 43619 var hue = hsba[0] * 6; // We will split hue into 6 sectors. 43620 var sat = hsba[1]; 43621 var val = hsba[2]; 43622 43623 var RGBA = []; 43624 43625 if (sat === 0) { 43626 RGBA = [val, val, val, hsba[3]]; // Return early if grayscale. 43627 } else { 43628 var sector = Math.floor(hue); 43629 var tint1 = val * (1 - sat); 43630 var tint2 = val * (1 - sat * (hue - sector)); 43631 var tint3 = val * (1 - sat * (1 + sector - hue)); 43632 var red, green, blue; 43633 if (sector === 1) { 43634 // Yellow to green. 43635 red = tint2; 43636 green = val; 43637 blue = tint1; 43638 } else if (sector === 2) { 43639 // Green to cyan. 43640 red = tint1; 43641 green = val; 43642 blue = tint3; 43643 } else if (sector === 3) { 43644 // Cyan to blue. 43645 red = tint1; 43646 green = tint2; 43647 blue = val; 43648 } else if (sector === 4) { 43649 // Blue to magenta. 43650 red = tint3; 43651 green = tint1; 43652 blue = val; 43653 } else if (sector === 5) { 43654 // Magenta to red. 43655 red = val; 43656 green = tint1; 43657 blue = tint2; 43658 } else { 43659 // Red to yellow (sector could be 0 or 6). 43660 red = val; 43661 green = tint3; 43662 blue = tint1; 43663 } 43664 RGBA = [red, green, blue, hsba[3]]; 43665 } 43666 43667 return RGBA; 43668 }; 43669 43670 /** 43671 * Convert an HSLA array to HSBA. 43672 */ 43673 _main.default.ColorConversion._hslaToHSBA = function(hsla) { 43674 var hue = hsla[0]; 43675 var sat = hsla[1]; 43676 var li = hsla[2]; 43677 43678 // Calculate brightness. 43679 var val; 43680 if (li < 0.5) { 43681 val = (1 + sat) * li; 43682 } else { 43683 val = li + sat - li * sat; 43684 } 43685 43686 // Convert saturation. 43687 sat = 2 * (val - li) / val; 43688 43689 // Hue and alpha stay the same. 43690 return [hue, sat, val, hsla[3]]; 43691 }; 43692 43693 /** 43694 * Convert an HSLA array to RGBA. 43695 * 43696 * We need to change basis from HSLA to something that can be more easily be 43697 * projected onto RGBA. We will choose hue and brightness as our first two 43698 * components, and pick a convenient third one ('zest') so that we don't need 43699 * to calculate formal HSBA saturation. 43700 */ 43701 _main.default.ColorConversion._hslaToRGBA = function(hsla) { 43702 var hue = hsla[0] * 6; // We will split hue into 6 sectors. 43703 var sat = hsla[1]; 43704 var li = hsla[2]; 43705 43706 var RGBA = []; 43707 43708 if (sat === 0) { 43709 RGBA = [li, li, li, hsla[3]]; // Return early if grayscale. 43710 } else { 43711 // Calculate brightness. 43712 var val; 43713 if (li < 0.5) { 43714 val = (1 + sat) * li; 43715 } else { 43716 val = li + sat - li * sat; 43717 } 43718 43719 // Define zest. 43720 var zest = 2 * li - val; 43721 43722 // Implement projection (project onto green by default). 43723 var hzvToRGB = function hzvToRGB(hue, zest, val) { 43724 if (hue < 0) { 43725 // Hue must wrap to allow projection onto red and blue. 43726 hue += 6; 43727 } else if (hue >= 6) { 43728 hue -= 6; 43729 } 43730 if (hue < 1) { 43731 // Red to yellow (increasing green). 43732 return zest + (val - zest) * hue; 43733 } else if (hue < 3) { 43734 // Yellow to cyan (greatest green). 43735 return val; 43736 } else if (hue < 4) { 43737 // Cyan to blue (decreasing green). 43738 return zest + (val - zest) * (4 - hue); 43739 } else { 43740 // Blue to red (least green). 43741 return zest; 43742 } 43743 }; 43744 43745 // Perform projections, offsetting hue as necessary. 43746 RGBA = [ 43747 hzvToRGB(hue + 2, zest, val), 43748 hzvToRGB(hue, zest, val), 43749 hzvToRGB(hue - 2, zest, val), 43750 hsla[3] 43751 ]; 43752 } 43753 43754 return RGBA; 43755 }; 43756 43757 /** 43758 * Convert an RGBA array to HSBA. 43759 */ 43760 _main.default.ColorConversion._rgbaToHSBA = function(rgba) { 43761 var red = rgba[0]; 43762 var green = rgba[1]; 43763 var blue = rgba[2]; 43764 43765 var val = Math.max(red, green, blue); 43766 var chroma = val - Math.min(red, green, blue); 43767 43768 var hue, sat; 43769 if (chroma === 0) { 43770 // Return early if grayscale. 43771 hue = 0; 43772 sat = 0; 43773 } else { 43774 sat = chroma / val; 43775 if (red === val) { 43776 // Magenta to yellow. 43777 hue = (green - blue) / chroma; 43778 } else if (green === val) { 43779 // Yellow to cyan. 43780 hue = 2 + (blue - red) / chroma; 43781 } else if (blue === val) { 43782 // Cyan to magenta. 43783 hue = 4 + (red - green) / chroma; 43784 } 43785 if (hue < 0) { 43786 // Confine hue to the interval [0, 1). 43787 hue += 6; 43788 } else if (hue >= 6) { 43789 hue -= 6; 43790 } 43791 } 43792 43793 return [hue / 6, sat, val, rgba[3]]; 43794 }; 43795 43796 /** 43797 * Convert an RGBA array to HSLA. 43798 */ 43799 _main.default.ColorConversion._rgbaToHSLA = function(rgba) { 43800 var red = rgba[0]; 43801 var green = rgba[1]; 43802 var blue = rgba[2]; 43803 43804 var val = Math.max(red, green, blue); 43805 var min = Math.min(red, green, blue); 43806 var li = val + min; // We will halve this later. 43807 var chroma = val - min; 43808 43809 var hue, sat; 43810 if (chroma === 0) { 43811 // Return early if grayscale. 43812 hue = 0; 43813 sat = 0; 43814 } else { 43815 if (li < 1) { 43816 sat = chroma / li; 43817 } else { 43818 sat = chroma / (2 - li); 43819 } 43820 if (red === val) { 43821 // Magenta to yellow. 43822 hue = (green - blue) / chroma; 43823 } else if (green === val) { 43824 // Yellow to cyan. 43825 hue = 2 + (blue - red) / chroma; 43826 } else if (blue === val) { 43827 // Cyan to magenta. 43828 hue = 4 + (red - green) / chroma; 43829 } 43830 if (hue < 0) { 43831 // Confine hue to the interval [0, 1). 43832 hue += 6; 43833 } else if (hue >= 6) { 43834 hue -= 6; 43835 } 43836 } 43837 43838 return [hue / 6, sat, li / 2, rgba[3]]; 43839 }; 43840 var _default = _main.default.ColorConversion; 43841 exports.default = _default; 43842 }, 43843 { '../core/main': 59 } 43844 ], 43845 45: [
43846 function(_dereq_, module, exports) { 43847 'use strict'; 43848 function _typeof(obj) { 43849 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') { 43850 _typeof = function _typeof(obj) { 43851 return typeof obj; 43852 }; 43853 } else { 43854 _typeof = function _typeof(obj) { 43855 return obj && 43856 typeof Symbol === 'function' && 43857 obj.constructor === Symbol && 43858 obj !== Symbol.prototype 43859 ? 'symbol' 43860 : typeof obj; 43861 }; 43862 } 43863 return _typeof(obj); 43864 } 43865 Object.defineProperty(exports, '__esModule', { value: true }); 43866 exports.default = void 0; 43867 43868 var _main = _interopRequireDefault(_dereq_('../core/main')); 43869 var constants = _interopRequireWildcard(_dereq_('../core/constants')); 43870 _dereq_('./p5.Color'); 43871 _dereq_('../core/friendly_errors/validate_params'); 43872 _dereq_('../core/friendly_errors/file_errors'); 43873 _dereq_('../core/friendly_errors/fes_core'); 43874 function _getRequireWildcardCache() { 43875 if (typeof WeakMap !== 'function') return null; 43876 var cache = new WeakMap(); 43877 _getRequireWildcardCache = function _getRequireWildcardCache() { 43878 return cache; 43879 }; 43880 return cache; 43881 } 43882 function _interopRequireWildcard(obj) { 43883 if (obj && obj.__esModule) { 43884 return obj; 43885 } 43886 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) { 43887 return { default: obj }; 43888 } 43889 var cache = _getRequireWildcardCache(); 43890 if (cache && cache.has(obj)) { 43891 return cache.get(obj); 43892 } 43893 var newObj = {}; 43894 var hasPropertyDescriptor = 43895 Object.defineProperty && Object.getOwnPropertyDescriptor; 43896 for (var key in obj) { 43897 if (Object.prototype.hasOwnProperty.call(obj, key)) { 43898 var desc = hasPropertyDescriptor 43899 ? Object.getOwnPropertyDescriptor(obj, key) 43900 : null; 43901 if (desc && (desc.get || desc.set)) { 43902 Object.defineProperty(newObj, key, desc); 43903 } else { 43904 newObj[key] = obj[key]; 43905 } 43906 } 43907 } 43908 newObj.default = obj; 43909 if (cache) { 43910 cache.set(obj, newObj); 43911 } 43912 return newObj; 43913 } 43914 function _interopRequireDefault(obj) { 43915 return obj && obj.__esModule ? obj : { default: obj }; 43916 } 43917 /** 43918 * @module Color 43919 * @submodule Creating & Reading 43920 * @for p5 43921 * @requires core 43922 * @requires constants 43923 */ /** 43924 * Extracts the alpha value from a color or pixel array. 43925 * 43926 * @method alpha 43927 * @param {p5.Color|Number[]|String} color <a href="#/p5.Color">p5.Color</a> object, color components, 43928 * or CSS color 43929 * @return {Number} the alpha value 43930 * 43931 * @example 43932 * <div> 43933 * <code> 43934 * noStroke(); 43935 * let c = color(0, 126, 255, 102); 43936 * fill(c); 43937 * rect(15, 15, 35, 70); 43938 * let value = alpha(c); // Sets 'value' to 102 43939 * fill(value); 43940 * rect(50, 15, 35, 70); 43941 * </code> 43942 * </div> 43943 * 43944 * @alt 43945 * Left half of canvas light blue and right half light charcoal grey. 43946 */ _main.default.prototype.alpha = function(c) { 43947 _main.default._validateParameters('alpha', arguments); 43948 return this.color(c)._getAlpha(); 43949 }; 43950 43951 /** 43952 * Extracts the blue value from a color or pixel array. 43953 * 43954 * @method blue 43955 * @param {p5.Color|Number[]|String} color <a href="#/p5.Color">p5.Color</a> object, color components, 43956 * or CSS color 43957 * @return {Number} the blue value 43958 * @example 43959 * <div> 43960 * <code> 43961 * let c = color(175, 100, 220); 43962 * fill(c); 43963 * rect(15, 20, 35, 60); // Draw left rectangle 43964 * let blueValue = blue(c); 43965 * fill(0, 0, blueValue); 43966 * rect(50, 20, 35, 60); // Draw right rectangle 43967 * </code> 43968 * </div> 43969 * 43970 * @alt 43971 * Left half of canvas light purple and right half a royal blue. 43972 */ 43973 _main.default.prototype.blue = function(c) { 43974 _main.default._validateParameters('blue', arguments); 43975 return this.color(c)._getBlue(); 43976 }; 43977 43978 /** 43979 * Extracts the HSB brightness value from a color or pixel array. 43980 * 43981 * @method brightness 43982 * @param {p5.Color|Number[]|String} color <a href="#/p5.Color">p5.Color</a> object, color components, 43983 * or CSS color 43984 * @return {Number} the brightness value 43985 * 43986 * @example 43987 * <div> 43988 * <code> 43989 * noStroke(); 43990 * colorMode(HSB, 255); 43991 * let c = color(0, 126, 255); 43992 * fill(c); 43993 * rect(15, 20, 35, 60); 43994 * let value = brightness(c); // Sets 'value' to 255 43995 * fill(value); 43996 * rect(50, 20, 35, 60); 43997 * </code> 43998 * </div> 43999 * 44000 * <div> 44001 * <code> 44002 * noStroke(); 44003 * colorMode(HSB, 255); 44004 * let c = color('hsb(60, 100%, 50%)'); 44005 * fill(c); 44006 * rect(15, 20, 35, 60); 44007 * let value = brightness(c); // A 'value' of 50% is 127.5 44008 * fill(value); 44009 * rect(50, 20, 35, 60); 44010 * </code> 44011 * </div> 44012 * 44013 * @alt 44014 * Left half of canvas salmon pink and the right half with it's brightness colored white. 44015 * Left half of canvas olive colored and the right half with it's brightness color gray. 44016 */ 44017 _main.default.prototype.brightness = function(c) { 44018 _main.default._validateParameters('brightness', arguments); 44019 return this.color(c)._getBrightness(); 44020 }; 44021 44022 /** 44023 * Creates colors for storing in variables of the color datatype. The 44024 * parameters are interpreted as RGB or HSB values depending on the 44025 * current <a href="#/p5/colorMode">colorMode()</a>. The default mode is RGB values from 0 to 255 44026 * and, therefore, the function call color(255, 204, 0) will return a 44027 * bright yellow color. 44028 * 44029 * Note that if only one value is provided to <a href="#/p5/color">color()</a>, it will be interpreted 44030 * as a grayscale value. Add a second value, and it will be used for alpha 44031 * transparency. When three values are specified, they are interpreted as 44032 * either RGB or HSB values. Adding a fourth value applies alpha 44033 * transparency. 44034 *
44035 * If a single string argument is provided, RGB, RGBA and Hex CSS color 44036 * strings and all named color strings are supported. In this case, an alpha 44037 * number value as a second argument is not supported, the RGBA form should be 44038 * used. 44039 * 44040 * @method color 44041 * @param {Number} gray number specifying value between white and black. 44042 * @param {Number} [alpha] alpha value relative to current color range 44043 * (default is 0-255) 44044 * @return {p5.Color} resulting color 44045 * 44046 * @example 44047 * <div> 44048 * <code> 44049 * let c = color(255, 204, 0); 44050 * fill(c); 44051 * noStroke(); 44052 * rect(30, 20, 55, 55); 44053 * </code> 44054 * </div> 44055 * 44056 * <div> 44057 * <code> 44058 * let c = color(255, 204, 0); 44059 * fill(c); 44060 * noStroke(); 44061 * ellipse(25, 25, 80, 80); // Draw left circle 44062 * // Using only one value generates a grayscale value. 44063 * c = color(65); 44064 * fill(c); 44065 * ellipse(75, 75, 80, 80); 44066 * </code> 44067 * </div> 44068 * 44069 * <div> 44070 * <code> 44071 * // You can use named SVG & CSS colors 44072 * let c = color('magenta'); 44073 * fill(c); 44074 * noStroke(); 44075 * rect(20, 20, 60, 60); 44076 * </code> 44077 * </div> 44078 * 44079 * <div> 44080 * <code> 44081 * // Example of hex color codes 44082 * noStroke(); 44083 * let c = color('#0f0'); 44084 * fill(c); 44085 * rect(0, 10, 45, 80); 44086 * c = color('#00ff00'); 44087 * fill(c); 44088 * rect(55, 10, 45, 80); 44089 * </code> 44090 * </div> 44091 * 44092 * <div> 44093 * <code> 44094 * // RGB and RGBA color strings are also supported 44095 * // these all set to the same color (solid blue) 44096 * let c; 44097 * noStroke(); 44098 * c = color('rgb(0,0,255)'); 44099 * fill(c); 44100 * rect(10, 10, 35, 35); // Draw rectangle 44101 * c = color('rgb(0%, 0%, 100%)'); 44102 * fill(c); 44103 * rect(55, 10, 35, 35); // Draw rectangle 44104 * c = color('rgba(0, 0, 255, 1)'); 44105 * fill(c); 44106 * rect(10, 55, 35, 35); // Draw rectangle 44107 * c = color('rgba(0%, 0%, 100%, 1)'); 44108 * fill(c); 44109 * rect(55, 55, 35, 35); // Draw rectangle 44110 * </code> 44111 * </div> 44112 * 44113 * <div> 44114 * <code> 44115 * // HSL color can also be specified by value 44116 * let c = color('hsl(160, 100%, 50%)'); 44117 * noStroke(); 44118 * fill(c); 44119 * rect(0, 10, 45, 80); // Draw rectangle 44120 * c = color('hsla(160, 100%, 50%, 0.5)'); 44121 * fill(c); 44122 * rect(55, 10, 45, 80); // Draw rectangle 44123 * </code> 44124 * </div> 44125 * 44126 * <div> 44127 * <code> 44128 * // HSB color can also be specified 44129 * let c = color('hsb(160, 100%, 50%)'); 44130 * noStroke(); 44131 * fill(c); 44132 * rect(0, 10, 45, 80); // Draw rectangle 44133 * c = color('hsba(160, 100%, 50%, 0.5)'); 44134 * fill(c); 44135 * rect(55, 10, 45, 80); // Draw rectangle 44136 * </code> 44137 * </div> 44138 * 44139 * <div> 44140 * <code> 44141 * noStroke(); 44142 * let c = color(50, 55, 100); 44143 * fill(c); 44144 * rect(0, 10, 45, 80); // Draw left rect 44145 * colorMode(HSB, 100); 44146 * c = color(50, 55, 100); 44147 * fill(c); 44148 * rect(55, 10, 45, 80); 44149 * </code> 44150 * </div> 44151 * 44152 * @alt 44153 * Yellow rect in middle right of canvas, with 55 pixel width and height. 44154 * Yellow ellipse in top left of canvas, black ellipse in bottom right,both 80x80. 44155 * Bright fuchsia rect in middle of canvas, 60 pixel width and height. 44156 * Two bright green rects on opposite sides of the canvas, both 45x80. 44157 * Four blue rects in each corner of the canvas, each are 35x35. 44158 * Bright sea green rect on left and darker rect on right of canvas, both 45x80. 44159 * Dark green rect on left and lighter green rect on right of canvas, both 45x80. 44160 * Dark blue rect on left and light teal rect on right of canvas, both 45x80. 44161 */ 44162 44163 /** 44164 * @method color 44165 * @param {Number} v1 red or hue value relative to 44166 * the current color range 44167 * @param {Number} v2 green or saturation value 44168 * relative to the current color range 44169 * @param {Number} v3 blue or brightness value 44170 * relative to the current color range 44171 * @param {Number} [alpha] 44172 * @return {p5.Color} 44173 */ 44174 44175 /** 44176 * @method color 44177 * @param {String} value a color string 44178 * @return {p5.Color} 44179 */ 44180 44181 /** 44182 * @method color 44183 * @param {Number[]} values an array containing the red,green,blue & 44184 * and alpha components of the color 44185 * @return {p5.Color} 44186 */ 44187 44188 /** 44189 * @method color 44190 * @param {p5.Color} color 44191 * @return {p5.Color} 44192 */ 44193 _main.default.prototype.color = function() { 44194 _main.default._validateParameters('color', arguments); 44195 if (arguments[0] instanceof _main.default.Color) { 44196 return arguments[0];
44196 // Do nothing if argument is already a color object. 44197 } 44198 44199 var args = arguments[0] instanceof Array ? arguments[0] : arguments; 44200 return new _main.default.Color(this, args); 44201 }; 44202 44203 /** 44204 * Extracts the green value from a color or pixel array. 44205 * 44206 * @method green 44207 * @param {p5.Color|Number[]|String} color <a href="#/p5.Color">p5.Color</a> object, color components, 44208 * or CSS color 44209 * @return {Number} the green value 44210 * @example 44211 * <div> 44212 * <code> 44213 * let c = color(20, 75, 200); // Define color 'c' 44214 * fill(c); // Use color variable 'c' as fill color 44215 * rect(15, 20, 35, 60); // Draw left rectangle 44216 * 44217 * let greenValue = green(c); // Get green in 'c' 44218 * print(greenValue); // Print "75.0" 44219 * fill(0, greenValue, 0); // Use 'greenValue' in new fill 44220 * rect(50, 20, 35, 60); // Draw right rectangle 44221 * </code> 44222 * </div> 44223 * 44224 * @alt 44225 * blue rect on left and green on right, both with black outlines & 35x60. 44226 */ 44227 _main.default.prototype.green = function(c) { 44228 _main.default._validateParameters('green', arguments); 44229 return this.color(c)._getGreen(); 44230 }; 44231 44232 /** 44233 * Extracts the hue value from a color or pixel array. 44234 * 44235 * Hue exists in both HSB and HSL. This function will return the 44236 * HSB-normalized hue when supplied with an HSB color object (or when supplied 44237 * with a pixel array while the color mode is HSB), but will default to the 44238 * HSL-normalized hue otherwise. (The values will only be different if the 44239 * maximum hue setting for each system is different.) 44240 * 44241 * @method hue 44242 * @param {p5.Color|Number[]|String} color <a href="#/p5.Color">p5.Color</a> object, color components, 44243 * or CSS color 44244 * @return {Number} the hue 44245 * @example 44246 * <div> 44247 * <code> 44248 * noStroke(); 44249 * colorMode(HSB, 255); 44250 * let c = color(0, 126, 255); 44251 * fill(c); 44252 * rect(15, 20, 35, 60); 44253 * let value = hue(c); // Sets 'value' to "0" 44254 * fill(value); 44255 * rect(50, 20, 35, 60); 44256 * </code> 44257 * </div> 44258 * 44259 * @alt 44260 * salmon pink rect on left and black on right, both 35x60. 44261 */ 44262 _main.default.prototype.hue = function(c) { 44263 _main.default._validateParameters('hue', arguments); 44264 return this.color(c)._getHue(); 44265 }; 44266 44267 /** 44268 * Blends two colors to find a third color somewhere between them. The amt 44269 * parameter is the amount to interpolate between the two values where 0.0 44270 * equal to the first color, 0.1 is very near the first color, 0.5 is halfway 44271 * in between, etc. An amount below 0 will be treated as 0. Likewise, amounts 44272 * above 1 will be capped at 1. This is different from the behavior of <a href="#/p5/lerp">lerp()</a>, 44273 * but necessary because otherwise numbers outside the range will produce 44274 * strange and unexpected colors. 44275 * 44276 * The way that colors are interpolated depends on the current color mode. 44277 * 44278 * @method lerpColor 44279 * @param {p5.Color} c1 interpolate from this color 44280 * @param {p5.Color} c2 interpolate to this color 44281 * @param {Number} amt number between 0 and 1 44282 * @return {p5.Color} interpolated color 44283 * 44284 * @example 44285 * <div> 44286 * <code> 44287 * colorMode(RGB); 44288 * stroke(255); 44289 * background(51); 44290 * let from = color(218, 165, 32); 44291 * let to = color(72, 61, 139); 44292 * colorMode(RGB); // Try changing to HSB. 44293 * let interA = lerpColor(from, to, 0.33); 44294 * let interB = lerpColor(from, to, 0.66); 44295 * fill(from); 44296 * rect(10, 20, 20, 60); 44297 * fill(interA); 44298 * rect(30, 20, 20, 60); 44299 * fill(interB); 44300 * rect(50, 20, 20, 60); 44301 * fill(to); 44302 * rect(70, 20, 20, 60); 44303 * </code> 44304 * </div> 44305 * 44306 * @alt 44307 * 4 rects one tan, brown, brownish purple, purple, with white outlines & 20x60 44308 */ 44309 44310 _main.default.prototype.lerpColor = function(c1, c2, amt) { 44311 _main.default._validateParameters('lerpColor', arguments); 44312 var mode = this._colorMode; 44313 var maxes = this._colorMaxes; 44314 var l0, l1, l2, l3; 44315 var fromArray, toArray; 44316 44317 if (mode === constants.RGB) { 44318 fromArray = c1.levels.map(function(level) { 44319 return level / 255; 44320 }); 44321 toArray = c2.levels.map(function(level) { 44322 return level / 255; 44323 }); 44324 } else if (mode === constants.HSB) { 44325 c1._getBrightness(); // Cache hsba so it definitely exists. 44326 c2._getBrightness(); 44327 fromArray = c1.hsba; 44328 toArray = c2.hsba; 44329 } else if (mode === constants.HSL) { 44330 c1._getLightness();
44330 // Cache hsla so it definitely exists. 44331 c2._getLightness(); 44332 fromArray = c1.hsla; 44333 toArray = c2.hsla; 44334 } else { 44335 throw new Error(''.concat(mode, 'cannot be used for interpolation.')); 44336 } 44337 44338 // Prevent extrapolation. 44339 amt = Math.max(Math.min(amt, 1), 0); 44340 44341 // Define lerp here itself if user isn't using math module. 44342 // Maintains the definition as found in math/calculation.js 44343 if (typeof this.lerp === 'undefined') { 44344 this.lerp = function(start, stop, amt) { 44345 return amt * (stop - start) + start; 44346 }; 44347 } 44348 44349 // Perform interpolation. 44350 l0 = this.lerp(fromArray[0], toArray[0], amt); 44351 l1 = this.lerp(fromArray[1], toArray[1], amt); 44352 l2 = this.lerp(fromArray[2], toArray[2], amt); 44353 l3 = this.lerp(fromArray[3], toArray[3], amt); 44354 44355 // Scale components. 44356 l0 *= maxes[mode][0]; 44357 l1 *= maxes[mode][1]; 44358 l2 *= maxes[mode][2]; 44359 l3 *= maxes[mode][3]; 44360 44361 return this.color(l0, l1, l2, l3); 44362 }; 44363 44364 /** 44365 * Extracts the HSL lightness value from a color or pixel array. 44366 * 44367 * @method lightness 44368 * @param {p5.Color|Number[]|String} color <a href="#/p5.Color">p5.Color</a> object, color components, 44369 * or CSS color 44370 * @return {Number} the lightness 44371 * 44372 * @example 44373 * <div> 44374 * <code> 44375 * noStroke(); 44376 * colorMode(HSL); 44377 * let c = color(156, 100, 50, 1); 44378 * fill(c); 44379 * rect(15, 20, 35, 60); 44380 * let value = lightness(c); // Sets 'value' to 50 44381 * fill(value); 44382 * rect(50, 20, 35, 60); 44383 * </code> 44384 * </div> 44385 * 44386 * @alt 44387 * light pastel green rect on left and dark grey rect on right, both 35x60. 44388 */ 44389 _main.default.prototype.lightness = function(c) { 44390 _main.default._validateParameters('lightness', arguments); 44391 return this.color(c)._getLightness(); 44392 }; 44393 44394 /** 44395 * Extracts the red value from a color or pixel array. 44396 * 44397 * @method red 44398 * @param {p5.Color|Number[]|String} color <a href="#/p5.Color">p5.Color</a> object, color components, 44399 * or CSS color 44400 * @return {Number} the red value 44401 * @example 44402 * <div> 44403 * <code> 44404 * let c = color(255, 204, 0); // Define color 'c' 44405 * fill(c); // Use color variable 'c' as fill color 44406 * rect(15, 20, 35, 60); // Draw left rectangle 44407 * 44408 * let redValue = red(c); // Get red in 'c' 44409 * print(redValue); // Print "255.0" 44410 * fill(redValue, 0, 0); // Use 'redValue' in new fill 44411 * rect(50, 20, 35, 60); // Draw right rectangle 44412 * </code> 44413 * </div> 44414 * 44415 * <div class="norender"> 44416 * <code> 44417 * colorMode(RGB, 255); // Sets the range for red, green, and blue to 255 44418 * let c = color(127, 255, 0); 44419 * colorMode(RGB, 1); // Sets the range for red, green, and blue to 1 44420 * let myColor = red(c); 44421 * print(myColor); // 0.4980392156862745 44422 * </code> 44423 * </div> 44424 * 44425 * @alt 44426 * yellow rect on left and red rect on right, both with black outlines and 35x60. 44427 * grey canvas 44428 */ 44429 _main.default.prototype.red = function(c) { 44430 _main.default._validateParameters('red', arguments); 44431 return this.color(c)._getRed(); 44432 }; 44433 44434 /** 44435 * Extracts the saturation value from a color or pixel array. 44436 * 44437 * Saturation is scaled differently in HSB and HSL. This function will return 44438 * the HSB saturation when supplied with an HSB color object (or when supplied 44439 * with a pixel array while the color mode is HSB), but will default to the 44440 * HSL saturation otherwise. 44441 * 44442 * @method saturation 44443 * @param {p5.Color|Number[]|String} color <a href="#/p5.Color">p5.Color</a> object, color components, 44444 * or CSS color 44445 * @return {Number} the saturation value 44446 * @example 44447 * <div> 44448 * <code> 44449 * noStroke(); 44450 * colorMode(HSB, 255); 44451 * let c = color(0, 126, 255); 44452 * fill(c); 44453 * rect(15, 20, 35, 60); 44454 * let value = saturation(c); // Sets 'value' to 126 44455 * fill(value); 44456 * rect(50, 20, 35, 60); 44457 * </code> 44458 * </div> 44459 * 44460 * @alt 44461 *deep pink rect on left and grey rect on right, both 35x60. 44462 */ 44463 _main.default.prototype.saturation = function(c) { 44464 _main.default._validateParameters('saturation', arguments); 44465 return this.color(c)._getSaturation(); 44466 }; 44467 var _default = _main.default; 44468 exports.default = _default; 44469 }, 44470 { 44471 '../core/constants': 48, 44472 '../core/friendly_errors/fes_core': 51, 44473 '../core/friendly_errors/file_errors': 52, 44474 '../core/friendly_errors/validate_params': 54, 44475 '../core/main': 59, 44476 './p5.Color': 46 44477 } 44478 ], 44479 46: [
44480 function(_dereq_, module, exports) { 44481 'use strict'; 44482 function _typeof(obj) { 44483 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') { 44484 _typeof = function _typeof(obj) { 44485 return typeof obj; 44486 }; 44487 } else { 44488 _typeof = function _typeof(obj) { 44489 return obj && 44490 typeof Symbol === 'function' && 44491 obj.constructor === Symbol && 44492 obj !== Symbol.prototype 44493 ? 'symbol' 44494 : typeof obj; 44495 }; 44496 } 44497 return _typeof(obj); 44498 } 44499 Object.defineProperty(exports, '__esModule', { value: true }); 44500 exports.default = void 0; 44501 44502 var _main = _interopRequireDefault(_dereq_('../core/main')); 44503 var constants = _interopRequireWildcard(_dereq_('../core/constants')); 44504 var _color_conversion = _interopRequireDefault(_dereq_('./color_conversion')); 44505 function _getRequireWildcardCache() { 44506 if (typeof WeakMap !== 'function') return null; 44507 var cache = new WeakMap(); 44508 _getRequireWildcardCache = function _getRequireWildcardCache() { 44509 return cache; 44510 }; 44511 return cache; 44512 } 44513 function _interopRequireWildcard(obj) { 44514 if (obj && obj.__esModule) { 44515 return obj; 44516 } 44517 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) { 44518 return { default: obj }; 44519 } 44520 var cache = _getRequireWildcardCache(); 44521 if (cache && cache.has(obj)) { 44522 return cache.get(obj); 44523 } 44524 var newObj = {}; 44525 var hasPropertyDescriptor = 44526 Object.defineProperty && Object.getOwnPropertyDescriptor; 44527 for (var key in obj) { 44528 if (Object.prototype.hasOwnProperty.call(obj, key)) { 44529 var desc = hasPropertyDescriptor 44530 ? Object.getOwnPropertyDescriptor(obj, key) 44531 : null; 44532 if (desc && (desc.get || desc.set)) { 44533 Object.defineProperty(newObj, key, desc); 44534 } else { 44535 newObj[key] = obj[key]; 44536 } 44537 } 44538 } 44539 newObj.default = obj; 44540 if (cache) { 44541 cache.set(obj, newObj); 44542 } 44543 return newObj; 44544 } 44545 function _interopRequireDefault(obj) { 44546 return obj && obj.__esModule ? obj : { default: obj }; 44547 } 44548 /** 44549 * @module Color 44550 * @submodule Creating & Reading 44551 * @for p5 44552 * @requires core 44553 * @requires constants 44554 * @requires color_conversion 44555 */ /** 44556 * Each color stores the color mode and level maxes that was applied at the 44557 * time of its construction. These are used to interpret the input arguments 44558 * (at construction and later for that instance of color) and to format the 44559 * output e.g. when <a href="#/p5/saturation">saturation()</a> is requested. 44560 * 44561 * Internally, we store an array representing the ideal RGBA values in floating 44562 * point form, normalized from 0 to 1. From this we calculate the closest 44563 * screen color (RGBA levels from 0 to 255) and expose this to the renderer. 44564 * 44565 * We also cache normalized, floating point components of the color in various 44566 * representations as they are calculated. This is done to prevent repeating a 44567 * conversion that has already been performed. 44568 * 44569 * @class p5.Color 44570 * @constructor 44571 */ _main.default.Color = function(pInst, vals) { 44572 // Record color mode and maxes at time of construction. 44573 this._storeModeAndMaxes(pInst._colorMode, pInst._colorMaxes); // Calculate normalized RGBA values. 44574 if ( 44575 this.mode !== constants.RGB && 44576 this.mode !== constants.HSL && 44577 this.mode !== constants.HSB 44578 ) { 44579 throw new Error(''.concat(this.mode, ' is an invali
44579d colorMode.')); 44580 } else { 44581 this._array = _main.default.Color._parseInputs.apply(this, vals); 44582 } 44583 44584 // Expose closest screen color. 44585 this._calculateLevels(); 44586 return this; 44587 }; 44588 44589 /** 44590 * This function returns the color formatted as a string. This can be useful 44591 * for debugging, or for using p5.js with other libraries. 44592 * 44593 * @method toString 44594 * @param {String} [format] How the color string will be formatted. 44595 * Leaving this empty formats the string as rgba(r, g, b, a). 44596 * '#rgb' '#rgba' '#rrggbb' and '#rrggbbaa' format as hexadecimal color codes. 44597 * 'rgb' 'hsb' and 'hsl' return the color formatted in the specified color mode. 44598 * 'rgba' 'hsba' and 'hsla' are the same as above but with alpha channels. 44599 * 'rgb%' 'hsb%' 'hsl%' 'rgba%' 'hsba%' and 'hsla%' format as percentages. 44600 * @return {String} the formatted string 44601 * 44602 * @example 44603 * <div> 44604 * <code> 44605 * createCanvas(200, 100); 44606 * let myColor; 44607 * stroke(255); 44608 * myColor = color(100, 100, 250); 44609 * fill(myColor); 44610 * rotate(HALF_PI); 44611 * text(myColor.toString(), 0, -5); 44612 * text(myColor.toString('#rrggbb'), 0, -30); 44613 * text(myColor.toString('rgba%'), 0, -55); 44614 * </code> 44615 * </div> 44616 * 44617 * <div> 44618 * <code> 44619 * let myColor = color(100, 130, 250); 44620 * text(myColor.toString('#rrggbb'), 25, 25); 44621 * </code> 44622 * </div> 44623 * 44624 * @alt 44625 * A canvas with 3 text representation of their color. 44626 */ 44627 _main.default.Color.prototype.toString = function(format) { 44628 var a = this.levels; 44629 var f = this._array; 44630 var alpha = f[3]; // String representation uses normalized alpha 44631 44632 switch (format) { 44633 case '#rrggbb': 44634 return '#'.concat( 44635 a[0] < 16 ? '0'.concat(a[0].toString(16)) : a[0].toString(16), 44636 a[1] < 16 ? '0'.concat(a[1].toString(16)) : a[1].toString(16), 44637 a[2] < 16 ? '0'.concat(a[2].toString(16)) : a[2].toString(16) 44638 ); 44639 44640 case '#rrggbbaa': 44641 return '#'.concat( 44642 a[0] < 16 ? '0'.concat(a[0].toString(16)) : a[0].toString(16), 44643 a[1] < 16 ? '0'.concat(a[1].toString(16)) : a[1].toString(16), 44644 a[2] < 16 ? '0'.concat(a[2].toString(16)) : a[2].toString(16), 44645 a[3] < 16 ? '0'.concat(a[2].toString(16)) : a[3].toString(16) 44646 ); 44647 44648 case '#rgb': 44649 return '#'.concat( 44650 Math.round(f[0] * 15).toString(16), 44651 Math.round(f[1] * 15).toString(16), 44652 Math.round(f[2] * 15).toString(16) 44653 ); 44654 44655 case '#rgba': 44656 return '#'.concat( 44657 Math.round(f[0] * 15).toString(16), 44658 Math.round(f[1] * 15).toString(16), 44659 Math.round(f[2] * 15).toString(16), 44660 Math.round(f[3] * 15).toString(16) 44661 ); 44662 44663 case 'rgb': 44664 return 'rgb('.concat(a[0], ', ', a[1], ', ', a[2], ')'); 44665 44666 case 'rgb%': 44667 return 'rgb('.concat( 44668 (100 * f[0]).toPrecision(3), 44669 '%, ', 44670 (100 * f[1]).toPrecision(3), 44671 '%, ', 44672 (100 * f[2]).toPrecision(3), 44673 '%)' 44674 ); 44675 44676 case 'rgba%': 44677 return 'rgba('.concat( 44678 (100 * f[0]).toPrecision(3), 44679 '%, ', 44680 (100 * f[1]).toPrecision(3), 44681 '%, ', 44682 (100 * f[2]).toPrecision(3), 44683 '%, ', 44684 (100 * f[3]).toPrecision(3), 44685 '%)' 44686 ); 44687 44688 case 'hsb': 44689 case 'hsv': 44690 if (!this.hsba) 44691 this.hsba = _color_conversion.default._rgbaToHSBA(this._array); 44692 return 'hsb('.concat(
44693 this.hsba[0] * this.maxes[constants.HSB][0], 44694 ', ', 44695 this.hsba[1] * this.maxes[constants.HSB][1], 44696 ', ', 44697 this.hsba[2] * this.maxes[constants.HSB][2], 44698 ')' 44699 ); 44700 44701 case 'hsb%': 44702 case 'hsv%': 44703 if (!this.hsba) 44704 this.hsba = _color_conversion.default._rgbaToHSBA(this._array); 44705 return 'hsb('.concat( 44706 (100 * this.hsba[0]).toPrecision(3), 44707 '%, ', 44708 (100 * this.hsba[1]).toPrecision(3), 44709 '%, ', 44710 (100 * this.hsba[2]).toPrecision(3), 44711 '%)' 44712 ); 44713 44714 case 'hsba': 44715 case 'hsva': 44716 if (!this.hsba) 44717 this.hsba = _color_conversion.default._rgbaToHSBA(this._array); 44718 return 'hsba('.concat( 44719 this.hsba[0] * this.maxes[constants.HSB][0], 44720 ', ', 44721 this.hsba[1] * this.maxes[constants.HSB][1], 44722 ', ', 44723 this.hsba[2] * this.maxes[constants.HSB][2], 44724 ', ', 44725 alpha, 44726 ')' 44727 ); 44728 44729 case 'hsba%': 44730 case 'hsva%': 44731 if (!this.hsba) 44732 this.hsba = _color_conversion.default._rgbaToHSBA(this._array); 44733 return 'hsba('.concat( 44734 (100 * this.hsba[0]).toPrecision(3), 44735 '%, ', 44736 (100 * this.hsba[1]).toPrecision(3), 44737 '%, ', 44738 (100 * this.hsba[2]).toPrecision(3), 44739 '%, ', 44740 (100 * alpha).toPrecision(3), 44741 '%)' 44742 ); 44743 44744 case 'hsl': 44745 if (!this.hsla) 44746 this.hsla = _color_conversion.default._rgbaToHSLA(this._array); 44747 return 'hsl('.concat( 44748 this.hsla[0] * this.maxes[constants.HSL][0], 44749 ', ', 44750 this.hsla[1] * this.maxes[constants.HSL][1], 44751 ', ', 44752 this.hsla[2] * this.maxes[constants.HSL][2], 44753 ')' 44754 ); 44755 44756 case 'hsl%': 44757 if (!this.hsla) 44758 this.hsla = _color_conversion.default._rgbaToHSLA(this._array); 44759 return 'hsl('.concat( 44760 (100 * this.hsla[0]).toPrecision(3), 44761 '%, ', 44762 (100 * this.hsla[1]).toPrecision(3), 44763 '%, ', 44764 (100 * this.hsla[2]).toPrecision(3), 44765 '%)' 44766 ); 44767 44768 case 'hsla': 44769 if (!this.hsla) 44770 this.hsla = _color_conversion.default._rgbaToHSLA(this._array); 44771 return 'hsla('.concat( 44772 this.hsla[0] * this.maxes[constants.HSL][0], 44773 ', ', 44774 this.hsla[1] * this.maxes[constants.HSL][1], 44775 ', ', 44776 this.hsla[2] * this.maxes[constants.HSL][2], 44777 ', ', 44778 alpha, 44779 ')' 44780 ); 44781 44782 case 'hsla%': 44783 if (!this.hsla) 44784 this.hsla = _color_conversion.default._rgbaToHSLA(this._array); 44785 return 'hsl('.concat( 44786 (100 * this.hsla[0]).toPrecision(3), 44787 '%, ', 44788 (100 * this.hsla[1]).toPrecision(3), 44789 '%, ', 44790 (100 * this.hsla[2]).toPrecision(3), 44791 '%, ', 44792 (100 * alpha).toPrecision(3), 44793 '%)' 44794 ); 44795 44796 case 'rgba': 44797 default: 44798 return 'rgba('.concat(a[0], ',', a[1], ',', a[2], ',', alpha, ')'); 44799 } 44800 }; 44801 44802 /** 44803 * The setRed function sets the red component of a color. 44804 * The range depends on your color mode, in the default RGB mode it's between 0 and 255. 44805 * @method setRed 44806 * @param {Number} red the new red value 44807 * @example 44808 * <div> 44809 * <code> 44810 * let backgroundColor; 44811 * 44812 * function setup() { 44813 * backgroundColor = color(100, 50, 150); 44814 * } 44815 * 44816 * function draw() { 44817 * backgroundColor.setRed(128 + 128 * sin(millis() / 1000)); 44818 * background(backgroundColor); 44819 * } 44820 * </code> 44821 * </div> 44822 * 44823 * @alt 44824 * canvas with gradually changing background color 44825 */ 44826 _main.default.Color.prototype.setRed = function(new_red) {
44827 this._array[0] = new_red / this.maxes[constants.RGB][0]; 44828 this._calculateLevels(); 44829 }; 44830 44831 /** 44832 * The setGreen function sets the green component of a color. 44833 * The range depends on your color mode, in the default RGB mode it's between 0 and 255. 44834 * @method setGreen 44835 * @param {Number} green the new green value 44836 * @example 44837 * <div> 44838 * <code> 44839 * let backgroundColor = color(100, 50, 150); 44840 * function draw() { 44841 * backgroundColor.setGreen(128 + 128 * sin(millis() / 1000)); 44842 * background(backgroundColor); 44843 * } 44844 * </code> 44845 * </div> 44846 * 44847 * @alt 44848 * canvas with gradually changing background color 44849 **/ 44850 _main.default.Color.prototype.setGreen = function(new_green) { 44851 this._array[1] = new_green / this.maxes[constants.RGB][1]; 44852 this._calculateLevels(); 44853 }; 44854 44855 /** 44856 * The setBlue function sets the blue component of a color. 44857 * The range depends on your color mode, in the default RGB mode it's between 0 and 255. 44858 * @method setBlue 44859 * @param {Number} blue the new blue value 44860 * @example 44861 * <div> 44862 * <code> 44863 * let backgroundColor = color(100, 50, 150); 44864 * function draw() { 44865 * backgroundColor.setBlue(128 + 128 * sin(millis() / 1000)); 44866 * background(backgroundColor); 44867 * } 44868 * </code> 44869 * </div> 44870 * 44871 * @alt 44872 * canvas with gradually changing background color 44873 **/ 44874 _main.default.Color.prototype.setBlue = function(new_blue) { 44875 this._array[2] = new_blue / this.maxes[constants.RGB][2]; 44876 this._calculateLevels(); 44877 }; 44878 44879 /** 44880 * The setAlpha function sets the transparency (alpha) value of a color. 44881 * The range depends on your color mode, in the default RGB mode it's between 0 and 255. 44882 * @method setAlpha 44883 * @param {Number} alpha the new alpha value 44884 * @example 44885 * <div> 44886 * <code> 44887 * function draw() { 44888 * clear(); 44889 * background(200); 44890 * squareColor = color(100, 50, 100); 44891 * squareColor.setAlpha(128 + 128 * sin(millis() / 1000)); 44892 * fill(squareColor); 44893 * rect(13, 13, width - 26, height - 26); 44894 * } 44895 * </code> 44896 * </div> 44897 * 44898 * @alt 44899 * a square with gradually changing opacity on a gray background 44900 **/ 44901 _main.default.Color.prototype.setAlpha = function(new_alpha) { 44902 this._array[3] = new_alpha / this.maxes[this.mode][3]; 44903 this._calculateLevels(); 44904 }; 44905 44906 // calculates and stores the closest screen levels 44907 _main.default.Color.prototype._calculateLevels = function() { 44908 var array = this._array; 44909 // (loop backwards for performance) 44910 var levels = (this.levels = new Array(array.length)); 44911 for (var i = array.length - 1; i >= 0; --i) { 44912 levels[i] = Math.round(array[i] * 255); 44913 } 44914 }; 44915 44916 _main.default.Color.prototype._getAlpha = function() { 44917 return this._array[3] * this.maxes[this.mode][3]; 44918 }; 44919 44920 // stores the color mode and maxes in this instance of Color 44921 // for later use (by _parseInputs()) 44922 _main.default.Color.prototype._storeModeAndMaxes = function(new_mode, new_maxes) { 44923 this.mode = new_mode; 44924 this.maxes = new_maxes; 44925 }; 44926 44927 _main.default.Color.prototype._getMode = function() { 44928 return this.mode; 44929 }; 44930 44931 _main.default.Color.prototype._getMaxes = function() { 44932 return this.maxes; 44933 }; 44934 44935 _main.default.Color.prototype._getBlue = function() {
44936 return this._array[2] * this.maxes[constants.RGB][2]; 44937 }; 44938 44939 _main.default.Color.prototype._getBrightness = function() { 44940 if (!this.hsba) { 44941 this.hsba = _color_conversion.default._rgbaToHSBA(this._array); 44942 } 44943 return this.hsba[2] * this.maxes[constants.HSB][2]; 44944 }; 44945 44946 _main.default.Color.prototype._getGreen = function() { 44947 return this._array[1] * this.maxes[constants.RGB][1]; 44948 }; 44949 44950 /** 44951 * Hue is the same in HSB and HSL, but the maximum value may be different. 44952 * This function will return the HSB-normalized saturation when supplied with 44953 * an HSB color object, but will default to the HSL-normalized saturation 44954 * otherwise. 44955 */ 44956 _main.default.Color.prototype._getHue = function() { 44957 if (this.mode === constants.HSB) { 44958 if (!this.hsba) { 44959 this.hsba = _color_conversion.default._rgbaToHSBA(this._array); 44960 } 44961 return this.hsba[0] * this.maxes[constants.HSB][0]; 44962 } else { 44963 if (!this.hsla) { 44964 this.hsla = _color_conversion.default._rgbaToHSLA(this._array); 44965 } 44966 return this.hsla[0] * this.maxes[constants.HSL][0]; 44967 } 44968 }; 44969 44970 _main.default.Color.prototype._getLightness = function() { 44971 if (!this.hsla) { 44972 this.hsla = _color_conversion.default._rgbaToHSLA(this._array); 44973 } 44974 return this.hsla[2] * this.maxes[constants.HSL][2]; 44975 }; 44976 44977 _main.default.Color.prototype._getRed = function() { 44978 return this._array[0] * this.maxes[constants.RGB][0]; 44979 }; 44980 44981 /** 44982 * Saturation is scaled differently in HSB and HSL. This function will return 44983 * the HSB saturation when supplied with an HSB color object, but will default 44984 * to the HSL saturation otherwise. 44985 */ 44986 _main.default.Color.prototype._getSaturation = function() { 44987 if (this.mode === constants.HSB) { 44988 if (!this.hsba) { 44989 this.hsba = _color_conversion.default._rgbaToHSBA(this._array); 44990 } 44991 return this.hsba[1] * this.maxes[constants.HSB][1]; 44992 } else { 44993 if (!this.hsla) { 44994 this.hsla = _color_conversion.default._rgbaToHSLA(this._array); 44995 } 44996 return this.hsla[1] * this.maxes[constants.HSL][1]; 44997 } 44998 }; 44999 45000 /** 45001 * CSS named colors. 45002 */ 45003 var namedColors = { 45004 aliceblue: '#f0f8ff', 45005 antiquewhite: '#faebd7', 45006 aqua: '#00ffff', 45007 aquamarine: '#7fffd4', 45008 azure: '#f0ffff', 45009 beige: '#f5f5dc', 45010 bisque: '#ffe4c4', 45011 black: '#000000', 45012 blanchedalmond: '#ffebcd', 45013 blue: '#0000ff', 45014 blueviolet: '#8a2be2', 45015 brown: '#a52a2a', 45016 burlywood: '#deb887', 45017 cadetblue: '#5f9ea0', 45018 chartreuse: '#7fff00', 45019 chocolate: '#d2691e', 45020 coral: '#ff7f50', 45021 cornflowerblue: '#6495ed', 45022 cornsilk: '#fff8dc', 45023 crimson: '#dc143c', 45024 cyan: '#00ffff', 45025 darkblue: '#00008b', 45026 darkcyan: '#008b8b', 45027 darkgoldenrod: '#b8860b', 45028 darkgray: '#a9a9a9', 45029 darkgreen: '#006400', 45030 darkgrey: '#a9a9a9', 45031 darkkhaki: '#bdb76b', 45032 darkmagenta: '#8b008b', 45033 darkolivegreen: '#556b2f', 45034 darkorange: '#ff8c00', 45035 darkorchid: '#9932cc', 45036 darkred: '#8b0000', 45037 darksalmon: '#e9967a', 45038 darkseagreen: '#8fbc8f', 45039 darkslateblue: '#483d8b', 45040 darkslategray: '#2f4f4f', 45041 darkslategrey: '#2f4f4f', 45042 darkturquoise: '#00ced1', 45043 darkviolet: '#9400d3', 45044 deeppink: '#ff1493', 45045 deepskyblue: '#00bfff', 45046 dimgray: '#696969', 45047 dimgrey: '#696969', 45048 dodgerblue: '#1e90ff', 45049 firebrick: '#b22222', 45050 floralwhite: '#fffaf0', 45051 forestgreen: '#228b22', 45052 fuchsia: '#ff00ff', 45053 gainsboro: '#dcdcdc', 45054 ghostwhite: '#f8f8ff',
45055 gold: '#ffd700', 45056 goldenrod: '#daa520', 45057 gray: '#808080', 45058 green: '#008000', 45059 greenyellow: '#adff2f', 45060 grey: '#808080', 45061 honeydew: '#f0fff0', 45062 hotpink: '#ff69b4', 45063 indianred: '#cd5c5c', 45064 indigo: '#4b0082', 45065 ivory: '#fffff0', 45066 khaki: '#f0e68c', 45067 lavender: '#e6e6fa', 45068 lavenderblush: '#fff0f5', 45069 lawngreen: '#7cfc00', 45070 lemonchiffon: '#fffacd', 45071 lightblue: '#add8e6', 45072 lightcoral: '#f08080', 45073 lightcyan: '#e0ffff', 45074 lightgoldenrodyellow: '#fafad2', 45075 lightgray: '#d3d3d3', 45076 lightgreen: '#90ee90', 45077 lightgrey: '#d3d3d3', 45078 lightpink: '#ffb6c1', 45079 lightsalmon: '#ffa07a', 45080 lightseagreen: '#20b2aa', 45081 lightskyblue: '#87cefa', 45082 lightslategray: '#778899', 45083 lightslategrey: '#778899', 45084 lightsteelblue: '#b0c4de', 45085 lightyellow: '#ffffe0', 45086 lime: '#00ff00', 45087 limegreen: '#32cd32', 45088 linen: '#faf0e6', 45089 magenta: '#ff00ff', 45090 maroon: '#800000', 45091 mediumaquamarine: '#66cdaa', 45092 mediumblue: '#0000cd', 45093 mediumorchid: '#ba55d3', 45094 mediumpurple: '#9370db', 45095 mediumseagreen: '#3cb371', 45096 mediumslateblue: '#7b68ee', 45097 mediumspringgreen: '#00fa9a', 45098 mediumturquoise: '#48d1cc', 45099 mediumvioletred: '#c71585', 45100 midnightblue: '#191970', 45101 mintcream: '#f5fffa', 45102 mistyrose: '#ffe4e1', 45103 moccasin: '#ffe4b5', 45104 navajowhite: '#ffdead', 45105 navy: '#000080', 45106 oldlace: '#fdf5e6', 45107 olive: '#808000', 45108 olivedrab: '#6b8e23', 45109 orange: '#ffa500', 45110 orangered: '#ff4500', 45111 orchid: '#da70d6', 45112 palegoldenrod: '#eee8aa', 45113 palegreen: '#98fb98', 45114 paleturquoise: '#afeeee', 45115 palevioletred: '#db7093', 45116 papayawhip: '#ffefd5', 45117 peachpuff: '#ffdab9', 45118 peru: '#cd853f', 45119 pink: '#ffc0cb', 45120 plum: '#dda0dd', 45121 powderblue: '#b0e0e6', 45122 purple: '#800080', 45123 rebeccapurple: '#663399', 45124 red: '#ff0000', 45125 rosybrown: '#bc8f8f', 45126 royalblue: '#4169e1', 45127 saddlebrown: '#8b4513', 45128 salmon: '#fa8072', 45129 sandybrown: '#f4a460', 45130 seagreen: '#2e8b57', 45131 seashell: '#fff5ee', 45132 sienna: '#a0522d', 45133 silver: '#c0c0c0', 45134 skyblue: '#87ceeb', 45135 slateblue: '#6a5acd', 45136 slategray: '#708090', 45137 slategrey: '#708090', 45138 snow: '#fffafa', 45139 springgreen: '#00ff7f', 45140 steelblue: '#4682b4', 45141 tan: '#d2b48c', 45142 teal: '#008080', 45143 thistle: '#d8bfd8', 45144 tomato: '#ff6347', 45145 turquoise: '#40e0d0', 45146 violet: '#ee82ee', 45147 wheat: '#f5deb3', 45148 white: '#ffffff', 45149 whitesmoke: '#f5f5f5', 45150 yellow: '#ffff00', 45151 yellowgreen: '#9acd32' 45152 }; 45153 45154 /** 45155 * These regular expressions are used to build up the patterns for matching 45156 * viable CSS color strings: fragmenting the regexes in this way increases the 45157 * legibility and comprehensibility of the code. 45158 * 45159 * Note that RGB values of .9 are not parsed by IE, but are supported here for 45160 * color string consistency. 45161 */ 45162 var WHITESPACE = /\s*/; // Match zero or more whitespace characters. 45163 var INTEGER = /(\d{1,3})/; // Match integers: 79, 255, etc. 45164 var DECIMAL = /((?:\d+(?:\.\d+)?)|(?:\.\d+))/; // Match 129.6, 79, .9, etc. 45165 var PERCENT = new RegExp(''.concat(DECIMAL.source, '%')); // Match 12.9%, 79%, .9%, etc. 45166 45167 /** 45168 * Full color string patterns. The capture groups are necessary. 45169 */ 45170 var colorPatterns = { 45171 // Match colors in format #XXX, e.g. #416. 45172 HEX3: /^#([a-f0-9])([a-f0-9])([a-f0-9])$/i, 45173 45174 // Match colors in format #XXXX, e.g. #5123. 45175 HEX4: /^#([a-f0-9])([a-f0-9])([a-f0-9])([a-f0-9])$/i, 45176 45177 // Match colors in format #XXXXXX, e.g. #b4d455. 45178 HEX6: /^#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})$/i, 45179 45180 // Match colors in format #XXXXXXXX, e.g. #b4d45535. 45181 HEX8: /^#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})$/i, 45182 45183 // Match colors in format rgb(R, G, B), e.g. rgb(255, 0, 128). 45184 RGB: new RegExp( 45185 [ 45186 '^rgb\\(', 45187 INTEGER.source, 45188 ',', 45189 INTEGER.source, 45190 ',', 45191 INTEGER.source, 45192 '\\)$' 45193 ].join(WHITESPACE.source), 45194 'i' 45195 ), 45196 45197 // Match colors in format rgb(R%, G%, B%), e.g. rgb(100%, 0%, 28.9%). 45198 RGB_PERCENT: new RegExp( 45199 [ 45200 '^rgb\\(', 45201 PERCENT.source, 45202 ',', 45203 PERCENT.source, 45204 ',', 45205 PERCENT.source, 45206 '\\)$' 45207 ].join(WHITESPACE.source), 45208 'i' 45209 ), 45210 45211 // Match colors in format rgb(R, G, B, A), e.g. rgb(255, 0, 128, 0.25). 45212 RGBA: new RegExp( 45213 [ 45214 '^rgba\\(', 45215 INTEGER.source, 45216 ',', 45217 INTEGER.source, 45218 ',', 45219 INTEGER.source, 45220 ',', 45221 DECIMAL.source, 45222 '\\)$' 45223 ].join(WHITESPACE.source), 45224 'i' 45225 ), 45226 45227 // Match colors in format rgb(R%, G%, B%, A), e.g. rgb(100%, 0%, 28.9%, 0.5). 45228 RGBA_PERCENT: new RegExp( 45229 [ 45230 '^rgba\\(', 45231 PERCENT.source, 45232 ',', 45233 PERCENT.source, 45234 ',', 45235 PERCENT.source, 45236 ',', 45237 DECIMAL.source, 45238 '\\)$' 45239 ].join(WHITESPACE.source), 45240 'i' 45241 ), 45242 45243 // Match colors in format hsla(H, S%, L%), e.g. hsl(100, 40%, 28.9%).
45244 HSL: new RegExp( 45245 [ 45246 '^hsl\\(', 45247 INTEGER.source, 45248 ',', 45249 PERCENT.source, 45250 ',', 45251 PERCENT.source, 45252 '\\)$' 45253 ].join(WHITESPACE.source), 45254 'i' 45255 ), 45256 45257 // Match colors in format hsla(H, S%, L%, A), e.g. hsla(100, 40%, 28.9%, 0.5). 45258 HSLA: new RegExp( 45259 [ 45260 '^hsla\\(', 45261 INTEGER.source, 45262 ',', 45263 PERCENT.source, 45264 ',', 45265 PERCENT.source, 45266 ',', 45267 DECIMAL.source, 45268 '\\)$' 45269 ].join(WHITESPACE.source), 45270 'i' 45271 ), 45272 45273 // Match colors in format hsb(H, S%, B%), e.g. hsb(100, 40%, 28.9%). 45274 HSB: new RegExp( 45275 [ 45276 '^hsb\\(', 45277 INTEGER.source, 45278 ',', 45279 PERCENT.source, 45280 ',', 45281 PERCENT.source, 45282 '\\)$' 45283 ].join(WHITESPACE.source), 45284 'i' 45285 ), 45286 45287 // Match colors in format hsba(H, S%, B%, A), e.g. hsba(100, 40%, 28.9%, 0.5). 45288 HSBA: new RegExp( 45289 [ 45290 '^hsba\\(', 45291 INTEGER.source, 45292 ',', 45293 PERCENT.source, 45294 ',', 45295 PERCENT.source, 45296 ',', 45297 DECIMAL.source, 45298 '\\)$' 45299 ].join(WHITESPACE.source), 45300 'i' 45301 ) 45302 }; 45303 45304 /** 45305 * For a number of different inputs, returns a color formatted as [r, g, b, a] 45306 * arrays, with each component normalized between 0 and 1. 45307 * 45308 * @private 45309 * @param {Array} [...args] An 'array-like' object that represents a list of 45310 * arguments 45311 * @return {Number[]} a color formatted as [r, g, b, a] 45312 * Example: 45313 * input ==> output 45314 * g ==> [g, g, g, 255] 45315 * g,a ==> [g, g, g, a] 45316 * r, g, b ==> [r, g, b, 255] 45317 * r, g, b, a ==> [r, g, b, a] 45318 * [g] ==> [g, g, g, 255] 45319 * [g, a] ==> [g, g, g, a] 45320 * [r, g, b] ==> [r, g, b, 255] 45321 * [r, g, b, a] ==> [r, g, b, a] 45322 * @example 45323 * <div> 45324 * <code> 45325 * // todo 45326 * </code> 45327 * </div> 45328 * 45329 * @alt 45330 * //todo 45331 */ 45332 _main.default.Color._parseInputs = function(r, g, b, a) { 45333 var numArgs = arguments.length; 45334 var mode = this.mode; 45335 var maxes = this.maxes[mode]; 45336 var results = []; 45337 var i; 45338 45339 if (numArgs >= 3) { 45340 // Argument is a list of component values. 45341 45342 results[0] = r / maxes[0]; 45343 results[1] = g / maxes[1]; 45344 results[2] = b / maxes[2]; 45345 45346 // Alpha may be undefined, so default it to 100%. 45347 if (typeof a === 'number') { 45348 results[3] = a / maxes[3]; 45349 } else { 45350 results[3] = 1; 45351 } 45352 45353 // Constrain components to the range [0,1]. 45354 // (loop backwards for performance) 45355 for (i = results.length - 1; i >= 0; --i) { 45356 var result = results[i]; 45357 if (result < 0) { 45358 results[i] = 0; 45359 } else if (result > 1) { 45360 results[i] = 1; 45361 } 45362 } 45363 45364 // Convert to RGBA and return. 45365 if (mode === constants.HSL) { 45366 return _color_conversion.default._hslaToRGBA(results); 45367 } else if (mode === constants.HSB) { 45368 return _color_conversion.default._hsbaToRGBA(results); 45369 } else { 45370 return results; 45371 } 45372 } else if (numArgs === 1 && typeof r === 'string') { 45373 var str = r.trim().toLowerCase(); 45374 45375 // Return if string is a named colour. 45376 if (namedColors[str]) { 45377 return _main.default.Color._parseInputs.call(this, namedColors[str]); 45378 } 45379 45380 // Try RGBA pattern matching. 45381 if (colorPatterns.HEX3.test(str)) { 45382 // #rgb 45383 results = colorPatterns.HEX3.exec(str) 45384 .slice(1) 45385 .map(function(color) {
45386 return parseInt(color + color, 16) / 255; 45387 }); 45388 results[3] = 1; 45389 return results; 45390 } else if (colorPatterns.HEX6.test(str)) { 45391 // #rrggbb 45392 results = colorPatterns.HEX6.exec(str) 45393 .slice(1) 45394 .map(function(color) { 45395 return parseInt(color, 16) / 255; 45396 }); 45397 results[3] = 1; 45398 return results; 45399 } else if (colorPatterns.HEX4.test(str)) { 45400 // #rgba 45401 results = colorPatterns.HEX4.exec(str) 45402 .slice(1) 45403 .map(function(color) { 45404 return parseInt(color + color, 16) / 255; 45405 }); 45406 return results; 45407 } else if (colorPatterns.HEX8.test(str)) { 45408 // #rrggbbaa 45409 results = colorPatterns.HEX8.exec(str) 45410 .slice(1) 45411 .map(function(color) { 45412 return parseInt(color, 16) / 255; 45413 }); 45414 return results; 45415 } else if (colorPatterns.RGB.test(str)) { 45416 // rgb(R,G,B) 45417 results = colorPatterns.RGB.exec(str) 45418 .slice(1) 45419 .map(function(color) { 45420 return color / 255; 45421 }); 45422 results[3] = 1; 45423 return results; 45424 } else if (colorPatterns.RGB_PERCENT.test(str)) { 45425 // rgb(R%,G%,B%) 45426 results = colorPatterns.RGB_PERCENT.exec(str) 45427 .slice(1) 45428 .map(function(color) { 45429 return parseFloat(color) / 100; 45430 }); 45431 results[3] = 1; 45432 return results; 45433 } else if (colorPatterns.RGBA.test(str)) { 45434 // rgba(R,G,B,A) 45435 results = colorPatterns.RGBA.exec(str) 45436 .slice(1) 45437 .map(function(color, idx) { 45438 if (idx === 3) { 45439 return parseFloat(color); 45440 } 45441 return color / 255; 45442 }); 45443 return results; 45444 } else if (colorPatterns.RGBA_PERCENT.test(str)) { 45445 // rgba(R%,G%,B%,A%) 45446 results = colorPatterns.RGBA_PERCENT.exec(str) 45447 .slice(1) 45448 .map(function(color, idx) { 45449 if (idx === 3) { 45450 return parseFloat(color); 45451 } 45452 return parseFloat(color) / 100; 45453 }); 45454 return results; 45455 } 45456 45457 // Try HSLA pattern matching. 45458 if (colorPatterns.HSL.test(str)) { 45459 // hsl(H,S,L) 45460 results = colorPatterns.HSL.exec(str) 45461 .slice(1) 45462 .map(function(color, idx) { 45463 if (idx === 0) { 45464 return parseInt(color, 10) / 360; 45465 } 45466 return parseInt(color, 10) / 100; 45467 }); 45468 results[3] = 1; 45469 } else if (colorPatterns.HSLA.test(str)) { 45470 // hsla(H,S,L,A) 45471 results = colorPatterns.HSLA.exec(str) 45472 .slice(1) 45473 .map(function(color, idx) { 45474 if (idx === 0) { 45475 return parseInt(color, 10) / 360; 45476 } else if (idx === 3) { 45477 return parseFloat(color); 45478 } 45479 return parseInt(color, 10) / 100; 45480 }); 45481 } 45482 results = results.map(function(value) { 45483 return Math.max(Math.min(value, 1), 0); 45484 }); 45485 if (results.length) { 45486 return _color_conversion.default._hslaToRGBA(results); 45487 } 45488 45489 // Try HSBA pattern matching. 45490 if (colorPatterns.HSB.test(str)) { 45491 // hsb(H,S,B) 45492 results = colorPatterns.HSB.exec(str) 45493 .slice(1) 45494 .map(function(color, idx) { 45495 if (idx === 0) { 45496 return parseInt(color, 10) / 360; 45497 } 45498 return parseInt(color, 10) / 100; 45499 }); 45500 results[3] = 1; 45501 } else if (colorPatterns.HSBA.test(str)) { 45502 // hsba(H,S,B,A) 45503 results = colorPatterns.HSBA.exec(str) 45504 .slice(1) 45505 .map(function(color, idx) { 45506 if (idx === 0) { 45507 return parseInt(color, 10) / 360; 45508 } else if (idx === 3) { 45509 return parseFloat(color); 45510 } 45511 return parseInt(color, 10) / 100; 45512 }); 45513 } 45514 45515 if (results.length) { 45516 // (loop backwards for performance) 45517 for (i = results.length - 1; i >= 0; --i) { 45518 results[i] = Math.max(Math.min(results[i], 1), 0); 45519 } 45520 45521 return _color_conversion.default._hsbaToRGBA(results); 45522 } 45523
45524 // Input did not match any CSS color pattern: default to white. 45525 results = [1, 1, 1, 1]; 45526 } else if ((numArgs === 1 || numArgs === 2) && typeof r === 'number') { 45527 // 'Grayscale' mode. 45528 45529 /** 45530 * For HSB and HSL, interpret the gray level as a brightness/lightness 45531 * value (they are equivalent when chroma is zero). For RGB, normalize the 45532 * gray level according to the blue maximum. 45533 */ 45534 results[0] = r / maxes[2]; 45535 results[1] = r / maxes[2]; 45536 results[2] = r / maxes[2]; 45537 45538 // Alpha may be undefined, so default it to 100%. 45539 if (typeof g === 'number') { 45540 results[3] = g / maxes[3]; 45541 } else { 45542 results[3] = 1; 45543 } 45544 45545 // Constrain components to the range [0,1]. 45546 results = results.map(function(value) { 45547 return Math.max(Math.min(value, 1), 0); 45548 }); 45549 } else { 45550 throw new Error(''.concat(arguments, 'is not a valid color representation.')); 45551 } 45552 45553 return results; 45554 }; 45555 var _default = _main.default.Color; 45556 exports.default = _default; 45557 }, 45558 { '../core/constants': 48, '../core/main': 59, './color_conversion': 44 } 45559 ], 45560 47: [ 45561 function(_dereq_, module, exports) { 45562 'use strict'; 45563 function _typeof(obj) { 45564 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') { 45565 _typeof = function _typeof(obj) { 45566 return typeof obj; 45567 }; 45568 } else { 45569 _typeof = function _typeof(obj) { 45570 return obj && 45571 typeof Symbol === 'function' && 45572 obj.constructor === Symbol && 45573 obj !== Symbol.prototype 45574 ? 'symbol' 45575 : typeof obj; 45576 }; 45577 } 45578 return _typeof(obj); 45579 } 45580 Object.defineProperty(exports, '__esModule', { value: true }); 45581 exports.default = void 0; 45582 45583 var _main = _interopRequireDefault(_dereq_('../core/main')); 45584 var constants = _interopRequireWildcard(_dereq_('../core/constants')); 45585 _dereq_('./p5.Color'); 45586 function _getRequireWildcardCache() { 45587 if (typeof WeakMap !== 'function') return null; 45588 var cache = new WeakMap(); 45589 _getRequireWildcardCache = function _getRequireWildcardCache() { 45590 return cache; 45591 }; 45592 return cache; 45593 } 45594 function _interopRequireWildcard(obj) { 45595 if (obj && obj.__esModule) { 45596 return obj; 45597 } 45598 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) { 45599 return { default: obj }; 45600 } 45601 var cache = _getRequireWildcardCache(); 45602 if (cache && cache.has(obj)) { 45603 return cache.get(obj); 45604 } 45605 var newObj = {}; 45606 var hasPropertyDescriptor = 45607 Object.defineProperty && Object.getOwnPropertyDescriptor; 45608 for (var key in obj) { 45609 if (Object.prototype.hasOwnProperty.call(obj, key)) { 45610 var desc = hasPropertyDescriptor 45611 ? Object.getOwnPropertyDescriptor(obj, key) 45612 : null; 45613 if (desc && (desc.get || desc.set)) { 45614 Object.defineProperty(newObj, key, desc); 45615 } else { 45616 newObj[key] = obj[key]; 45617 } 45618 } 45619 } 45620 newObj.default = obj; 45621 if (cache) { 45622 cache.set(obj, newObj); 45623 } 45624 return newObj; 45625 } 45626 function _interopRequireDefault(obj) { 45627 return obj && obj.__esModule ? obj : { default: obj }; 45628 } /** 45629 * @method background 45630 * @param {Number} gray specifies a value between white and black 45631 * @param {Number} [a] 45632 * @chainable 45633 */ /** 45634 * @module Color 45635 * @submodule Setting 45636 * @for p5 45637 * @requires core 45638 * @requires constants 45639 */ /** 45640 * The <a href="#/p5/background">background()</a> function sets the color used 45641 * for the background of the p5.js canvas. The default background is transparent. 45642 * This function is typically used within <a href="#/p5/draw">draw()</a> to clear 45643 * the display window at the beginning of each frame, but it can be used inside 45644 * <a href="#/p5/setup">setup()</a> to set the background on the first frame of 45645 * animation or if the background need only be set once. 45646 * 45647 * The color is either specified in terms of the RGB, HSB, or HSL color depending 45648 * on the current <a href="#/p5/colorMode">
45648colorMode</a>. (The default color space 45649 * is RGB, with each value in the range from 0 to 255). The alpha range by default 45650 * is also 0 to 255.<br><br> 45651 * 45652 * If a single string argument is provided, RGB, RGBA and Hex CSS color strings 45653 * and all named color strings are supported. In this case, an alpha number 45654 * value as a second argument is not supported, the RGBA form should be used. 45655 * 45656 * A <a href="#/p5.Color">p5.Color</a> object can also be provided to set the background color. 45657 * 45658 * A <a href="#/p5.Image">p5.Image</a> can also be provided to set the background image. 45659 * 45660 * @method background 45661 * @param {p5.Color} color any value created by the <a href="#/p5/color">color()</a> function 45662 * @chainable 45663 * 45664 * @example 45665 * <div> 45666 * <code> 45667 * // Grayscale integer value 45668 * background(51); 45669 * </code> 45670 * </div> 45671 * 45672 * <div> 45673 * <code> 45674 * // R, G & B integer values 45675 * background(255, 204, 0); 45676 * </code> 45677 * </div> 45678 * 45679 * <div> 45680 * <code> 45681 * // H, S & B integer values 45682 * colorMode(HSB); 45683 * background(255, 204, 100); 45684 * </code> 45685 * </div> 45686 * 45687 * <div> 45688 * <code> 45689 * // Named SVG/CSS color string 45690 * background('red'); 45691 * </code> 45692 * </div> 45693 * 45694 * <div> 45695 * <code> 45696 * // three-digit hexadecimal RGB notation 45697 * background('#fae'); 45698 * </code> 45699 * </div> 45700 * 45701 * <div> 45702 * <code> 45703 * // six-digit hexadecimal RGB notation 45704 * background('#222222'); 45705 * </code> 45706 * </div> 45707 * 45708 * <div> 45709 * <code> 45710 * // integer RGB notation 45711 * background('rgb(0,255,0)'); 45712 * </code> 45713 * </div> 45714 * 45715 * <div> 45716 * <code> 45717 * // integer RGBA notation 45718 * background('rgba(0,255,0, 0.25)'); 45719 * </code> 45720 * </div> 45721 * 45722 * <div> 45723 * <code> 45724 * // percentage RGB notation 45725 * background('rgb(100%,0%,10%)'); 45726 * </code> 45727 * </div> 45728 * 45729 * <div> 45730 * <code> 45731 * // percentage RGBA notation 45732 * background('rgba(100%,0%,100%,0.5)'); 45733 * </code> 45734 * </div> 45735 * 45736 * <div> 45737 * <code> 45738 * // p5 Color object 45739 * background(color(0, 0, 255)); 45740 * </code> 45741 * </div> 45742 * 45743 * @alt 45744 * canvas with darkest charcoal grey background. 45745 * canvas with yellow background. 45746 * canvas with royal blue background. 45747 * canvas with red background. 45748 * canvas with pink background. 45749 * canvas with black background. 45750 * canvas with bright green background. 45751 * canvas with soft green background. 45752 * canvas with red background. 45753 * canvas with light purple background. 45754 * canvas with blue background. 45755 */ /** 45756 * @method background 45757 * @param {String} colorstring color string, possible formats include: integer 45758 * rgb() or rgba(), percentage rgb() or rgba(), 45759 * 3-digit hex, 6-digit hex 45760 * @param {Number} [a] opacity of the background relative to current 45761 * color range (default is 0-255) 45762 * @chainable 45763 */ 45764 45765 /** 45766 * @method background 45767 * @param {Number} v1 red or hue value (depending on the current color 45768 * mode) 45769 * @param {Number} v2 green or saturation value (depending on the current 45770 * color mode) 45771 * @param {Number} v3 blue or brightness value (depending on the current 45772 * color mode) 45773 * @param {Number} [a] 45774 * @chainable 45775 */ 45776 45777 /** 45778 * @method background 45779 * @param {Number[]} values an array containing the red, green, blue 45780 * and alpha components of the color 45781 * @chainable 45782 */ 45783 45784 /** 45785 * @method background 45786 * @param {p5.Image} image image created with <a href="#/p5/loadImage">loadImage()</a> or <a href="#/p5/createImage">createImage()</a>, 45787 * to set as background 45788 * (must be same size as the sketch window) 45789 * @param {Number} [a] 45790 * @chainable 45791 */ 45792 _main.default.prototype.background = function() { 45793 var _this$_renderer; 45794 (_this$_renderer = this._renderer).background.apply(_this$_renderer, arguments); 45795 return this; 45796 }; 45797 45798 /** 45799 * Clears the pixels within a buffer. This function only clears the canvas. 45800 * It will not clear objects created by createX() methods such as 45801 * <a href="#/p5/createVideo">createVideo()</a> or <a href="#/p5/createDiv">createDiv()</a>. 45802 * Unlike the main graphics context, pixels in additional graphics areas created 45803 * with <a href="#/p5/createGraphics">createGraphics()</a> can be entirely 45804 * or partially transparent. This function clears everything to make all of 45805 * the pixels 100% transparent. 45806 * 45807 * @method clear 45808 * @chainable 45809 * @example 45810 * <div> 45811 * <code> 45812 * // Clear the screen on mouse press. 45813 * function draw() { 45814 * ellipse(mouseX, mouseY, 20, 20); 45815 * } 45816 * function mousePressed() { 45817 * clear(); 45818 * background(128); 45819 * } 45820 * </code> 45821 * </div> 45822 * 45823 * @alt 45824 * small white ellipses are continually drawn at mouse's x and y coordinates. 45825 */ 45826 45827 _main.default.prototype.clear = function() { 45828 this._renderer.clear(); 45829 return this; 45830 }; 45831 45832 /** 45833 * <a href="#/p5/colorMode">colorMode()</a> changes the way p5.js interprets 45834 * color data. By default, the parameters for <a href="#/p5/fill">fill()</a>, 45835 * <a href="#/p5/stroke">stroke()</a>, <a href="#/p5/background">background()</a>, 45836 * and <a href="#/p5/color">color()</a> are defined by values between 0 and 255 45837 * using the RGB color model. This is equivalent to setting colorMode(RGB, 255). 45838 * Setting colorMode(HSB) lets you use the HSB system instead. By default, this 45839 * is colorMode(HSB, 360, 100, 100, 1). You can also use HSL. 45840 * 45841 * Note: existing color objects remember the mode that they were created in, 45842 * so you can change modes as you like without affecting their appearance. 45843 * 45844 * @method colorMode 45845 * @param {Constant} mode either RGB, HSB or HSL, corresponding to 45846 * Red/Green/Blue and Hue/Saturation/Brightness 45847 * (or Lightness) 45848 * @param {Number} [max] range for all values 45849 * @chainable 45850 * 45851 * @example 45852 * <div> 45853 * <code> 45854 * noStroke(); 45855 * colorMode(RGB, 100); 45856 * for (let i = 0; i < 100; i++) { 45857 * for (let j = 0; j < 100; j++) { 45858 * stroke(i, j, 0); 45859 * point(i, j); 45860 * } 45861 * } 45862 * </code> 45863 * </div> 45864 * 45865 * <div> 45866 * <code> 45867 * noStroke(); 45868 * colorMode(HSB, 100); 45869 * for (let i = 0; i < 100; i++) { 45870 * for (let j = 0; j < 100; j++) { 45871 * stroke(i, j, 100); 45872 * point(i, j); 45873 * } 45874 * } 45875 * </code> 45876 * </div> 45877 * 45878 * <div> 45879 * <code> 45880 * colorMode(RGB, 255); 45881 * let c = color(127, 255, 0); 45882 * colorMode(RGB, 1); 45883 * let myColor = c._getRed(); 45884 * text(myColor, 10, 10, 80, 80); 45885 * </code> 45886 * </div> 45887 * 45888 * <div> 45889 * <code> 45890 * noFill(); 45891 * colorMode(RGB, 255, 255, 255, 1); 45892 * background(255); 45893 * strokeWeight(4); 45894 * stroke(255, 0, 10, 0.3); 45895 * ellipse(40, 40, 50, 50); 45896 * ellipse(50, 50, 40, 40); 45897 * </code> 45898 * </div> 45899 * 45900 * @alt 45901 *Green to red gradient from bottom L to top R. shading originates from top left. 45902 *Rainbow gradient from left to right. Brightness increasing to white at top. 45903 *unknown image. 45904 *50x50 ellipse at middle L & 40x40 ellipse at center. Translucent pink outlines. 45905 */ 45906 45907 /** 45908 * @method colorMode 45909 * @param {Constant} mode 45910 * @param {Number} max1 range for the red or hue depending on the 45911 * current color mode 45912 * @param {Number} max2 range for the green or saturation depending 45913 * on the current color mode 45914 * @param {Number} max3 range for the blue or brightness/lightness 45915 * depending on the current color mode 45916 * @param {Number} [maxA] range for the alpha 45917 * @chainable 45918 */ 45919 _main.default.prototype.colorMode = function(mode, max1, max2, max3, maxA) { 45920 _main.default._validateParameters('colorMode', arguments); 45921 if ( 45922 mode === constants.RGB || 45923 mode === constants.HSB || 45924 mode === constants.HSL 45925 ) { 45926 // Set color mode. 45927 this._colorMode = mode; 45928 45929 // Set color maxes. 45930 var maxes = this._colorMaxes[mode]; 45931 if (arguments.length === 2) { 45932 maxes[0] = max1; // Red 45933 maxes[1] = max1; // Green 45934 maxes[2] = max1; // Blue 45935 maxes[3] = max1; // Alpha 45936 } else if (arguments.length === 4) { 45937 maxes[0] = max1; // Red 45938 maxes[1] = max2; // Green 45939 maxes[2] = max3; // Blue 45940 } else if (arguments.length === 5) { 45941 maxes[0] = max1; // Red 45942 maxes[1] = max2; // Green 45943 maxes[2] = max3; // Blue 45944 maxes[3] = maxA; // Alpha 45945 } 45946 } 45947 45948 return this; 45949 }; 45950 45951 /** 45952 * Sets the color used to fill shapes. For example, if you run fill(204, 102, 0), 45953 * all shapes drawn after the fill command will be filled with the color orange. 45954 * This color is either specified in terms of the RGB or HSB color depending on 45955 * the current <a href="#/p5/colorMode">colorMode()</a>. (The default color space 45956 * is RGB, with each value in the range from 0 to 255). The alpha range by default 45957 * is also 0 to 255. 45958 *
45959 * If a single string argument is provided, RGB, RGBA and Hex CSS color strings 45960 * and all named color strings are supported. In this case, an alpha number 45961 * value as a second argument is not supported, the RGBA form should be used. 45962 * 45963 * A p5 <a href="#/p5.Color">Color</a> object can also be provided to set the fill color. 45964 * 45965 * @method fill 45966 * @param {Number} v1 red or hue value relative to 45967 * the current color range 45968 * @param {Number} v2 green or saturation value 45969 * relative to the current color range 45970 * @param {Number} v3 blue or brightness value 45971 * relative to the current color range 45972 * @param {Number} [alpha] 45973 * @chainable 45974 * @example 45975 * <div> 45976 * <code> 45977 * // Grayscale integer value 45978 * fill(51); 45979 * rect(20, 20, 60, 60); 45980 * </code> 45981 * </div> 45982 * 45983 * <div> 45984 * <code> 45985 * // R, G & B integer values 45986 * fill(255, 204, 0); 45987 * rect(20, 20, 60, 60); 45988 * </code> 45989 * </div> 45990 * 45991 * <div> 45992 * <code> 45993 * // H, S & B integer values 45994 * colorMode(HSB); 45995 * fill(255, 204, 100); 45996 * rect(20, 20, 60, 60); 45997 * </code> 45998 * </div> 45999 * 46000 * <div> 46001 * <code> 46002 * // Named SVG/CSS color string 46003 * fill('red'); 46004 * rect(20, 20, 60, 60); 46005 * </code> 46006 * </div> 46007 * 46008 * <div> 46009 * <code> 46010 * // three-digit hexadecimal RGB notation 46011 * fill('#fae'); 46012 * rect(20, 20, 60, 60); 46013 * </code> 46014 * </div> 46015 * 46016 * <div> 46017 * <code> 46018 * // six-digit hexadecimal RGB notation 46019 * fill('#222222'); 46020 * rect(20, 20, 60, 60); 46021 * </code> 46022 * </div> 46023 * 46024 * <div> 46025 * <code> 46026 * // integer RGB notation 46027 * fill('rgb(0,255,0)'); 46028 * rect(20, 20, 60, 60); 46029 * </code> 46030 * </div> 46031 * 46032 * <div> 46033 * <code> 46034 * // integer RGBA notation 46035 * fill('rgba(0,255,0, 0.25)'); 46036 * rect(20, 20, 60, 60); 46037 * </code> 46038 * </div> 46039 * 46040 * <div> 46041 * <code> 46042 * // percentage RGB notation 46043 * fill('rgb(100%,0%,10%)'); 46044 * rect(20, 20, 60, 60); 46045 * </code> 46046 * </div> 46047 * 46048 * <div> 46049 * <code> 46050 * // percentage RGBA notation 46051 * fill('rgba(100%,0%,100%,0.5)'); 46052 * rect(20, 20, 60, 60); 46053 * </code> 46054 * </div> 46055 * 46056 * <div> 46057 * <code> 46058 * // p5 Color object 46059 * fill(color(0, 0, 255)); 46060 * rect(20, 20, 60, 60); 46061 * </code> 46062 * </div> 46063 * 46064 * @alt 46065 * 60x60 dark charcoal grey rect with black outline in center of canvas. 46066 * 60x60 yellow rect with black outline in center of canvas. 46067 * 60x60 royal blue rect with black outline in center of canvas. 46068 * 60x60 red rect with black outline in center of canvas. 46069 * 60x60 pink rect with black outline in center of canvas. 46070 * 60x60 black rect with black outline in center of canvas. 46071 * 60x60 light green rect with black outline in center of canvas. 46072 * 60x60 soft green rect with black outline in center of canvas. 46073 * 60x60 red rect with black outline in center of canvas. 46074 * 60x60 dark fuchsia rect with black outline in center of canvas. 46075 * 60x60 blue rect with black outline in center of canvas. 46076 */ 46077 46078 /** 46079 * @method fill 46080 * @param {String} value a color string 46081 * @chainable 46082 */ 46083 46084 /** 46085 * @method fill 46086 * @param {Number} gray a gray value 46087 * @param {Number} [alpha] 46088 * @chainable 46089 */ 46090 46091 /** 46092 * @method fill 46093 * @param {Number[]} values an array containing the red,green,blue & 46094 * and alpha components of the color 46095 * @chainable 46096 */ 46097 46098 /** 46099 * @method fill 46100 * @param {p5.Color} color the fill color 46101 * @chainable 46102 */ 46103 _main.default.prototype.fill = function() { 46104 var _this$_renderer2; 46105 this._renderer._setProperty('_fillSet', true); 46106 this._renderer._setProperty('_doFill', true); 46107 (_this$_renderer2 = this._renderer).fill.apply(_this$_renderer2, arguments); 46108 return this; 46109 }; 46110 46111 /** 46112 * Disables filling geometry. If both <a href="#/p5/noStroke">noStroke()</a> and <a href="#/p5/noFill">noFill()</a> are called, 46113 * nothing will be drawn to the screen. 46114 * 46115 * @method noFill 46116 * @chainable 46117 * @example 46118 * <div> 46119 * <code> 46120 * rect(15, 10, 55, 55); 46121 * noFill(); 46122 * rect(20, 20, 60, 60); 46123 * </code> 46124 * </div> 46125 * 46126 * <div modernizr='webgl'> 46127 * <code> 46128 * function setup() { 46129 * createCanvas(100, 100, WEBGL); 46130 * } 46131 * 46132 * function draw() { 46133 * background(0); 46134 * noFill(); 46135 * stroke(100, 100, 240); 46136 * rotateX(frameCount * 0.01); 46137 * rotateY(frameCount * 0.01); 46138 * box(45, 45, 45); 46139 * } 46140 * </code> 46141 * </div> 46142 * 46143 * @alt 46144 * white rect top middle and noFill rect center. Both 60x60 with black outlines. 46145 * black canvas with purple cube wireframe spinning 46146 */ 46147 _main.default.prototype.noFill = function() { 46148 this._renderer._setProperty('_doFill', false); 46149 return this; 46150 }; 46151 46152 /** 46153 * Disables drawing the stroke (outline). If both <a href="#/p5/noStroke">noStroke()</a> and <a href="#/p5/noFill">noFill()</a> 46154 * are called, nothing will be drawn to the screen. 46155 * 46156 * @method noStroke 46157 * @chainable 46158 * @example 46159 * <div> 46160 * <code> 46161 * noStroke(); 46162 * rect(20, 20, 60, 60); 46163 * </code> 46164 * </div> 46165 * 46166 * <div modernizr='webgl'> 46167 * <code> 46168 * function setup() { 46169 * createCanvas(100, 100, WEBGL); 46170 * } 46171 * 46172 * function draw() { 46173 * background(0); 46174 * noStroke(); 46175 * fill(240, 150, 150); 46176 * rotateX(frameCount * 0.01); 46177 * rotateY(frameCount * 0.01); 46178 * box(45, 45, 45); 46179 * } 46180 * </code> 46181 * </div> 46182 * 46183 * @alt 46184 * 60x60 white rect at center. no outline. 46185 * black canvas with pink cube spinning 46186 */ 46187 _main.default.prototype.noStroke = function() { 46188 this._renderer._setProperty('_doStroke', false); 46189 return this; 46190 }; 46191 46192 /** 46193 * Sets the color used to draw lines and borders around shapes. This color 46194 * is either specified in terms of the RGB or HSB color depending on the 46195 * current <a href="#/p5/colorMode">colorMode()</a> (the default color space 46196 * is RGB, with each value in the range from 0 to 255). The alpha range by 46197 * default is also 0 to 255. 46198 *
46199 * If a single string argument is provided, RGB, RGBA and Hex CSS color 46200 * strings and all named color strings are supported. In this case, an alpha 46201 * number value as a second argument is not supported, the RGBA form should be 46202 * used. 46203 * 46204 * A p5 <a href="#/p5.Color">Color</a> object can also be provided to set the stroke color. 46205 * 46206 * @method stroke 46207 * @param {Number} v1 red or hue value relative to 46208 * the current color range 46209 * @param {Number} v2 green or saturation value 46210 * relative to the current color range 46211 * @param {Number} v3 blue or brightness value 46212 * relative to the current color range 46213 * @param {Number} [alpha] 46214 * @chainable 46215 * 46216 * @example 46217 * <div> 46218 * <code> 46219 * // Grayscale integer value 46220 * strokeWeight(4); 46221 * stroke(51); 46222 * rect(20, 20, 60, 60); 46223 * </code> 46224 * </div> 46225 * 46226 * <div> 46227 * <code> 46228 * // R, G & B integer values 46229 * stroke(255, 204, 0); 46230 * strokeWeight(4); 46231 * rect(20, 20, 60, 60); 46232 * </code> 46233 * </div> 46234 * 46235 * <div> 46236 * <code> 46237 * // H, S & B integer values 46238 * colorMode(HSB); 46239 * strokeWeight(4); 46240 * stroke(255, 204, 100); 46241 * rect(20, 20, 60, 60); 46242 * </code> 46243 * </div> 46244 * 46245 * <div> 46246 * <code> 46247 * // Named SVG/CSS color string 46248 * stroke('red'); 46249 * strokeWeight(4); 46250 * rect(20, 20, 60, 60); 46251 * </code> 46252 * </div> 46253 * 46254 * <div> 46255 * <code> 46256 * // three-digit hexadecimal RGB notation 46257 * stroke('#fae'); 46258 * strokeWeight(4); 46259 * rect(20, 20, 60, 60); 46260 * </code> 46261 * </div> 46262 * 46263 * <div> 46264 * <code> 46265 * // six-digit hexadecimal RGB notation 46266 * stroke('#222222'); 46267 * strokeWeight(4); 46268 * rect(20, 20, 60, 60); 46269 * </code> 46270 * </div> 46271 * 46272 * <div> 46273 * <code> 46274 * // integer RGB notation 46275 * stroke('rgb(0,255,0)'); 46276 * strokeWeight(4); 46277 * rect(20, 20, 60, 60); 46278 * </code> 46279 * </div> 46280 * 46281 * <div> 46282 * <code> 46283 * // integer RGBA notation 46284 * stroke('rgba(0,255,0,0.25)'); 46285 * strokeWeight(4); 46286 * rect(20, 20, 60, 60); 46287 * </code> 46288 * </div> 46289 * 46290 * <div> 46291 * <code> 46292 * // percentage RGB notation 46293 * stroke('rgb(100%,0%,10%)'); 46294 * strokeWeight(4); 46295 * rect(20, 20, 60, 60); 46296 * </code> 46297 * </div> 46298 * 46299 * <div> 46300 * <code> 46301 * // percentage RGBA notation 46302 * stroke('rgba(100%,0%,100%,0.5)'); 46303 * strokeWeight(4); 46304 * rect(20, 20, 60, 60); 46305 * </code> 46306 * </div> 46307 * 46308 * <div> 46309 * <code> 46310 * // p5 Color object 46311 * stroke(color(0, 0, 255)); 46312 * strokeWeight(4); 46313 * rect(20, 20, 60, 60); 46314 * </code> 46315 * </div> 46316 * 46317 * @alt 46318 * 60x60 white rect at center. Dark charcoal grey outline. 46319 * 60x60 white rect at center. Yellow outline. 46320 * 60x60 white rect at center. Royal blue outline. 46321 * 60x60 white rect at center. Red outline. 46322 * 60x60 white rect at center. Pink outline. 46323 * 60x60 white rect at center. Black outline. 46324 * 60x60 white rect at center. Bright green outline. 46325 * 60x60 white rect at center. Soft green outline. 46326 * 60x60 white rect at center. Red outline. 46327 * 60x60 white rect at center. Dark fuchsia outline. 46328 * 60x60 white rect at center. Blue outline. 46329 */ 46330 46331 /** 46332 * @method stroke 46333 * @param {String} value a color string 46334 * @chainable 46335 */ 46336 46337 /** 46338 * @method stroke 46339 * @param {Number} gray a gray value 46340 * @param {Number} [alpha] 46341 * @chainable 46342 */ 46343 46344 /** 46345 * @method stroke 46346 * @param {Number[]} values an array containing the red,green,blue & 46347 * and alpha components of the color 46348 * @chainable 46349 */ 46350 46351 /** 46352 * @method stroke 46353 * @param {p5.Color} color the stroke color 46354 * @chainable 46355 */ 46356 46357 _main.default.prototype.stroke = function() { 46358 var _this$_renderer3; 46359 this._renderer._setProperty('_strokeSet', true); 46360 this._renderer._setProperty('_doStroke', true); 46361 (_this$_renderer3 = this._renderer).stroke.apply(_this$_renderer3, arguments); 46362 return this; 46363 }; 46364 46365 /** 46366 * All drawing that follows <a href="#/p5/erase">erase()</a> will subtract from 46367 * the canvas.Erased areas will reveal the web page underneath the canvas.Erasing 46368 * can be canceled with <a href="#/p5/noErase">noErase()</a>. 46369 * 46370 * Drawing done with <a href="#/p5/image">image()</a> and <a href="#/p5/background"> 46371 * background()</a> in between <a href="#/p5/erase">erase()</a> and 46372 * <a href="#/p5/noErase">noErase()</a> will not erase the canvas but works as usual. 46373 * 46374 * @method erase 46375 * @param {Number} [strengthFill] A number (0-255) for the strength of erasing for a shape's fill. 46376 * This will default to 255 when no argument is given, which 46377 * is full strength. 46378 * @param {Number} [strengthStroke] A number (0-255) for the strength of erasing for a shape's stroke. 46379 * This will default to 255 when no argument is given, which 46380 * is full strength. 46381 * 46382 * @chainable 46383 * @example 46384 * <div> 46385 * <code> 46386 * background(100, 100, 250); 46387 * fill(250, 100, 100); 46388 * rect(20, 20, 60, 60); 46389 * erase(); 46390 * ellipse(25, 30, 30); 46391 * noErase(); 46392 * </code> 46393 * </div> 46394 * 46395 * <div> 46396 * <code> 46397 * background(150, 250, 150); 46398 * fill(100, 100, 250); 46399 * rect(20, 20, 60, 60); 46400 * strokeWeight(5); 46401 * erase(150, 255); 46402 * triangle(50, 10, 70, 50, 90, 10); 46403 * noErase(); 46404 * </code> 46405 * </div> 46406 * 46407 * <div> 46408 * <code> 46409 * function setup() { 46410 * smooth(); 46411 * createCanvas(100, 100, WEBGL); 46412 * // Make a <p> element and put it behind the canvas 46413 * let p = createP('I am a dom element'); 46414 * p.center(); 46415 * p.style('font-size', '20px'); 46416 * p.style('text-align', 'center'); 46417 * p.style('z-index', '-9999'); 46418 * } 46419 * 46420 * function draw() { 46421 * background(250, 250, 150); 46422 * fill(15, 195, 185); 46423 * noStroke(); 46424 * sphere(30); 46425 * erase(); 46426 * rotateY(frameCount * 0.02); 46427 * translate(0, 0, 40); 46428 * torus(15, 5); 46429 * noErase(); 46430 * } 46431 * </code> 46432 * </div> 46433 * 46434 * @alt 46435 * 60x60 centered pink rect, purple background. Elliptical area in top-left of rect is erased white. 46436 * 60x60 centered purple rect, mint green background. Triangle in top-right is partially erased with fully erased outline. 46437 * 60x60 centered teal sphere, yellow background. Torus rotating around sphere erases to reveal black text underneath. 46438 */ 46439 _main.default.prototype.erase = function() { 46440 var opacityFill = 46441 arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 255; 46442 var opacityStroke = 46443 arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 255; 46444 this._renderer.erase(opacityFill, opacityStroke); 46445 46446 return this; 46447 }; 46448 46449 /** 46450 * Ends erasing that was started with <a href="#/p5/erase">erase()</a>. 46451 * The <a href="#/p5/fill">fill()</a>, <a href="#/p5/stroke">stroke()</a>, and 46452 * <a href="#/p5/blendMode">blendMode()</a> settings will return to what they were 46453 * prior to calling <a href="#/p5/erase">erase()</a>. 46454 * 46455 * @method noErase 46456 * @chainable 46457 * @example 46458 * <div> 46459 * <code> 46460 * background(235, 145, 15); 46461 * noStroke(); 46462 * fill(30, 45, 220); 46463 * rect(30, 10, 10, 80); 46464 * erase(); 46465 * ellipse(50, 50, 60); 46466 * noErase(); 46467 * rect(70, 10, 10, 80); 46468 * </code> 46469 * </div> 46470 * 46471 * @alt 46472 * Orange background, with two tall blue rectangles. A centered ellipse erased the first blue rect but not the second. 46473 */ 46474 46475 _main.default.prototype.noErase = function() { 46476 this._renderer.noErase(); 46477 return this; 46478 }; 46479 var _default = _main.default; 46480 exports.default = _default; 46481 }, 46482 { '../core/constants': 48, '../core/main': 59, './p5.Color': 46 } 46483 ], 46484 48: [
46485 function(_dereq_, module, exports) { 46486 'use strict'; 46487 Object.defineProperty(exports, '__esModule', { value: true }); 46488 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 = exp
46488orts.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; 46489 exports.FALLBACK = exports.LABEL = 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; /** 46490 * @module Constants 46491 * @submodule Constants 46492 * @for p5 46493 */ 46494 46495 var _PI = Math.PI; 46496 46497 // GRAPHICS RENDERER 46498 /** 46499 * The default, two-dimensional renderer. 46500 * @property {String} P2D 46501 * @final 46502 */ 46503 var P2D = 'p2d'; 46504 /** 46505 * One of the two render modes in p5.js: P2D (default renderer) and WEBGL 46506 * Enables 3D render by introducing the third dimension: Z 46507 * @property {String} WEBGL 46508 * @final 46509 */ exports.P2D = P2D; 46510 var WEBGL = 'webgl'; 46511 46512 // ENVIRONMENT 46513 /** 46514 * @property {String} ARROW 46515 * @final 46516 */ exports.WEBGL = WEBGL; 46517 var ARROW = 'default'; 46518 /** 46519 * @property {String} CROSS 46520 * @final 46521 */ exports.ARROW = ARROW; 46522 var CROSS = 'crosshair'; 46523 /** 46524 * @property {String} HAND 46525 * @final 46526 */ exports.CROSS = CROSS; 46527 var HAND = 'pointer'; 46528 /** 46529 * @property {String} MOVE 46530 * @final 46531 */ exports.HAND = HAND; 46532 var MOVE = 'move'; 46533 /** 46534 * @property {String} TEXT 46535 * @final 46536 */ exports.MOVE = MOVE; 46537 var TEXT = 'text'; 46538 /** 46539 * @property {String} WAIT 46540 * @final 46541 */ exports.TEXT = TEXT; 46542 var WAIT = 'wait'; 46543 46544 // TRIGONOMETRY 46545 46546 /** 46547 * HALF_PI is a mathematical constant with the value 46548 * 1.57079632679489661923. It is half the ratio of the 46549 * circumference of a circle to its diameter. It is useful in 46550 * combination with the trigonometric functions <a href="#/p5/sin">sin()</a> and <a href="#/p5/cos">cos()</a>. 46551 * 46552 * @property {Number} HALF_PI 46553 * @final 46554 * 46555 * @example 46556 * <div><code> 46557 * arc(50, 50, 80, 80, 0, HALF_PI); 46558 * </code></div> 46559 * 46560 * @alt 46561 * 80x80 white quarter-circle with curve toward bottom right of canvas. 46562 */ exports.WAIT = WAIT; 46563 var HALF_PI = _PI / 2; 46564 /** 46565 * PI is a mathematical constant with the value 46566 * 3.14159265358979323846. It is the ratio of the circumference 46567 * of a circle to its diameter. It is useful in combination with 46568 * the trigonometric functions <a href="#/p5/sin">sin()</a> and <a href="#/p5/cos">cos()</a>. 46569 * 46570 * @property {Number} PI 46571 * @final 46572 * 46573 * @example 46574 * <div><code> 46575 * arc(50, 50, 80, 80, 0, PI); 46576 * </code></div> 46577 * 46578 * @alt 46579 * white half-circle with curve toward bottom of canvas. 46580 */ exports.HALF_PI = HALF_PI; 46581 var PI = _PI; 46582 /** 46583 * QUARTER_PI is a mathematical constant with the value 0.7853982. 46584 * It is one quarter the ratio of the circumference of a circle to 46585 * its diameter. It is useful in combination with the trigonometric 46586 * functions <a href="#/p5/sin">sin()</a> and <a href="#/p5/cos">cos()</a>. 46587 * 46588 * @property {Number} QUARTER_PI 46589 * @final 46590 * 46591 * @example 46592 * <div><code> 46593 * arc(50, 50, 80, 80, 0, QUARTER_PI); 46594 * </code></div> 46595 * 46596 * @alt 46597 * white eighth-circle rotated about 40 degrees with curve bottom right canvas. 46598 */ exports.PI = PI; 46599 var QUARTER_PI = _PI / 4; 46600 /** 46601 * TAU is an alias for TWO_PI, a mathematical constant with the 46602 * value 6.28318530717958647693. It is twice the ratio of the 46603 * circumference of a circle to its diameter. It is useful in 46604 * combination with the trigonometric functions <a href="#/p5/sin">sin()</a> and <a href="#/p5/cos">cos()</a>. 46605 * 46606 * @property {Number} TAU 46607 * @final 46608 * 46609 * @example 46610 * <div><code> 46611 * arc(50, 50, 80, 80, 0, TAU); 46612 * </code></div> 46613 * 46614 * @alt 46615 * 80x80 white ellipse shape in center of canvas.
46616 */ exports.QUARTER_PI = QUARTER_PI; 46617 var TAU = _PI * 2; 46618 /** 46619 * TWO_PI is a mathematical constant with the value 46620 * 6.28318530717958647693. It is twice the ratio of the 46621 * circumference of a circle to its diameter. It is useful in 46622 * combination with the trigonometric functions <a href="#/p5/sin">sin()</a> and <a href="#/p5/cos">cos()</a>. 46623 * 46624 * @property {Number} TWO_PI 46625 * @final 46626 * 46627 * @example 46628 * <div><code> 46629 * arc(50, 50, 80, 80, 0, TWO_PI); 46630 * </code></div> 46631 * 46632 * @alt 46633 * 80x80 white ellipse shape in center of canvas. 46634 */ exports.TAU = TAU; 46635 var TWO_PI = _PI * 2; 46636 /** 46637 * Constant to be used with <a href="#/p5/angleMode">angleMode()</a> function, to set the mode which 46638 * p5.js interprates and calculates angles (either DEGREES or RADIANS). 46639 * @property {String} DEGREES 46640 * @final 46641 * 46642 * @example 46643 * <div class='norender'><code> 46644 * function setup() { 46645 * angleMode(DEGREES); 46646 * } 46647 * </code></div> 46648 */ exports.TWO_PI = TWO_PI; 46649 var DEGREES = 'degrees'; 46650 /** 46651 * Constant to be used with <a href="#/p5/angleMode">angleMode()</a> function, to set the mode which 46652 * p5.js interprates and calculates angles (either RADIANS or DEGREES). 46653 * @property {String} RADIANS 46654 * @final 46655 * 46656 * @example 46657 * <div class='norender'><code> 46658 * function setup() { 46659 * angleMode(RADIANS); 46660 * } 46661 * </code></div> 46662 */ exports.DEGREES = DEGREES; 46663 var RADIANS = 'radians'; 46664 exports.RADIANS = RADIANS; 46665 var DEG_TO_RAD = _PI / 180.0; 46666 exports.DEG_TO_RAD = DEG_TO_RAD; 46667 var RAD_TO_DEG = 180.0 / _PI; 46668 46669 // SHAPE 46670 /** 46671 * @property {String} CORNER 46672 * @final 46673 */ exports.RAD_TO_DEG = RAD_TO_DEG; 46674 var CORNER = 'corner'; 46675 /** 46676 * @property {String} CORNERS 46677 * @final 46678 */ exports.CORNER = CORNER; 46679 var CORNERS = 'corners'; 46680 /** 46681 * @property {String} RADIUS 46682 * @final 46683 */ exports.CORNERS = CORNERS; 46684 var RADIUS = 'radius'; 46685 /** 46686 * @property {String} RIGHT 46687 * @final 46688 */ exports.RADIUS = RADIUS; 46689 var RIGHT = 'right'; 46690 /** 46691 * @property {String} LEFT 46692 * @final 46693 */ exports.RIGHT = RIGHT; 46694 var LEFT = 'left'; 46695 /** 46696 * @property {String} CENTER 46697 * @final 46698 */ exports.LEFT = LEFT; 46699 var CENTER = 'center'; 46700 /** 46701 * @property {String} TOP 46702 * @final 46703 */ exports.CENTER = CENTER; 46704 var TOP = 'top'; 46705 /** 46706 * @property {String} BOTTOM 46707 * @final 46708 */ exports.TOP = TOP; 46709 var BOTTOM = 'bottom'; 46710 /** 46711 * @property {String} BASELINE 46712 * @final 46713 * @default alphabetic 46714 */ exports.BOTTOM = BOTTOM; 46715 var BASELINE = 'alphabetic'; 46716 /** 46717 * @property {Number} POINTS 46718 * @final 46719 * @default 0x0000 46720 */ exports.BASELINE = BASELINE; 46721 var POINTS = 0x0000; 46722 /** 46723 * @property {Number} LINES 46724 * @final 46725 * @default 0x0001 46726 */ exports.POINTS = POINTS; 46727 var LINES = 0x0001; 46728 /** 46729 * @property {Number} LINE_STRIP 46730 * @final 46731 * @default 0x0003 46732 */ exports.LINES = LINES; 46733 var LINE_STRIP = 0x0003; 46734 /** 46735 * @property {Number} LINE_LOOP 46736 * @final 46737 * @default 0x0002 46738 */ exports.LINE_STRIP = LINE_STRIP; 46739 var LINE_LOOP = 0x0002; 46740 /** 46741 * @property {Number} TRIANGLES 46742 * @final 46743 * @default 0x0004 46744 */ exports.LINE_LOOP = LINE_LOOP; 46745 var TRIANGLES = 0x0004; 46746 /** 46747 * @property {Number} TRIANGLE_FAN 46748 * @final 46749 * @default 0x0006 46750 */ exports.TRIANGLES = TRIANGLES; 46751 var TRIANGLE_FAN = 0x0006; 46752 /** 46753 * @property {Number} TRIANGLE_STRIP 46754 * @final 46755 * @default 0x0005 46756 */ exports.TRIANGLE_FAN = TRIANGLE_FAN; 46757 var TRIANGLE_STRIP = 0x0005; 46758 /** 46759 * @property {String} QUADS 46760 * @final 46761 */ exports.TRIANGLE_STRIP = TRIANGLE_STRIP; 46762 var QUADS = 'quads'; 46763 /** 46764 * @property {String} QUAD_STRIP 46765 * @final 46766 * @default quad_strip 46767 */ exports.QUADS = QUADS; 46768 var QUAD_STRIP = 'quad_strip'; 46769 /** 46770 * @property {String} TESS 46771 * @final 46772 * @default tess 46773 */ exports.QUAD_STRIP = QUAD_STRIP; 46774 var TESS = 'tess'; 46775 /** 46776 * @property {String} CLOSE 46777 * @final 46778 */ exports.TESS = TESS; 46779 var CLOSE = 'close'; 46780 /** 46781 * @property {String} OPEN 46782 * @final 46783 */ exports.CLOSE = CLOSE; 46784 var OPEN = 'open'; 46785 /** 46786 * @property {String} CHORD 46787 * @final 46788 */ exports.OPEN = OPEN; 46789 var CHORD = 'chord'; 46790 /** 46791 * @property {String} PIE 46792 * @final 46793 */ exports.CHORD = CHORD; 46794 var PIE = 'pie'; 46795 /** 46796 * @property {String} PROJECT 46797 * @final 46798 * @default square 46799 */ exports.PIE = PIE; 46800 var PROJECT = 'square'; // PEND: careful this is counterintuitive 46801 /** 46802 * @property {String} SQUARE 46803 * @final 46804 * @default butt 46805 */ exports.PROJECT = PROJECT; 46806 var SQUARE = 'butt'; 46807 /** 46808 * @property {String} ROUND 46809 * @final 46810 */ exports.SQUARE = SQUARE; 46811 var ROUND = 'round'; 46812 /** 46813 * @property {String} BEVEL 46814 * @final 46815 */ exports.ROUND = ROUND; 46816 var BEVEL = 'bevel'; 46817 /** 46818 * @property {String} MITER 46819 * @final 46820 */ exports.BEVEL = BEVEL; 46821 var MITER = 'miter'; 46822 46823 // COLOR 46824 /** 46825 * @property {String} RGB 46826 * @final 46827 */ exports.MITER = MITER; 46828 var RGB = 'rgb'; 46829 /** 46830 * HSB (hue, saturation, brightness) is a type of color model. 46831 * You can learn more about it at 46832 * <a href="https://learnui.design/blog/the-hsb-color-system-practicioners-primer.html">HSB</a>. 46833 * 46834 * @property {String} HSB 46835 * @final 46836 */ exports.RGB = RGB; 46837 var HSB = 'hsb'; 46838 /** 46839 * @property {String} HSL 46840 * @final 46841 */ exports.HSB = HSB; 46842 var HSL = 'hsl'; 46843 46844 // DOM EXTENSION 46845 /** 46846 * AUTO allows us to automatically set the width or height of an element (but not both), 46847 * based on the current height and width of the element. Only one parameter can 46848 * be passed to the <a href="/#/p5.Element/size">size</a> function as AUTO, at a time. 46849 * 46850 * @property {String} AUTO 46851 * @final 46852 */ exports.HSL = HSL; 46853 var AUTO = 'auto'; 46854 46855 /** 46856 * @property {Number} ALT 46857 * @final 46858 */ 46859 // INPUT 46860 exports.AUTO = AUTO; 46861 var ALT = 18; 46862 /** 46863 * @property {Number} BACKSPACE 46864 * @final 46865 */ exports.ALT = ALT; 46866 var BACKSPACE = 8; 46867 /** 46868 * @property {Number} CONTROL 46869 * @final 46870 */ exports.BACKSPACE = BACKSPACE; 46871 var CONTROL = 17; 46872 /** 46873 * @property {Number} DELETE 46874 * @final 46875 */ exports.CONTROL = CONTROL; 46876 var DELETE = 46; 46877 /** 46878 * @property {Number} DOWN_ARROW 46879 * @final 46880 */ exports.DELETE = DELETE; 46881 var DOWN_ARROW = 40; 46882 /** 46883 * @property {Number} ENTER 46884 * @final 46885 */ exports.DOWN_ARROW = DOWN_ARROW; 46886 var ENTER = 13; 46887 /** 46888 * @property {Number} ESCAPE 46889 * @final
46890 */ exports.ENTER = ENTER; 46891 var ESCAPE = 27; 46892 /** 46893 * @property {Number} LEFT_ARROW 46894 * @final 46895 */ exports.ESCAPE = ESCAPE; 46896 var LEFT_ARROW = 37; 46897 /** 46898 * @property {Number} OPTION 46899 * @final 46900 */ exports.LEFT_ARROW = LEFT_ARROW; 46901 var OPTION = 18; 46902 /** 46903 * @property {Number} RETURN 46904 * @final 46905 */ exports.OPTION = OPTION; 46906 var RETURN = 13; 46907 /** 46908 * @property {Number} RIGHT_ARROW 46909 * @final 46910 */ exports.RETURN = RETURN; 46911 var RIGHT_ARROW = 39; 46912 /** 46913 * @property {Number} SHIFT 46914 * @final 46915 */ exports.RIGHT_ARROW = RIGHT_ARROW; 46916 var SHIFT = 16; 46917 /** 46918 * @property {Number} TAB 46919 * @final 46920 */ exports.SHIFT = SHIFT; 46921 var TAB = 9; 46922 /** 46923 * @property {Number} UP_ARROW 46924 * @final 46925 */ exports.TAB = TAB; 46926 var UP_ARROW = 38; 46927 46928 // RENDERING 46929 /** 46930 * @property {String} BLEND 46931 * @final 46932 * @default source-over 46933 */ exports.UP_ARROW = UP_ARROW; 46934 var BLEND = 'source-over'; 46935 /** 46936 * @property {String} REMOVE 46937 * @final 46938 * @default destination-out 46939 */ exports.BLEND = BLEND; 46940 var REMOVE = 'destination-out'; 46941 /** 46942 * @property {String} ADD 46943 * @final 46944 * @default lighter 46945 */ exports.REMOVE = REMOVE; 46946 var ADD = 'lighter'; 46947 //ADD: 'add', // 46948 //SUBTRACT: 'subtract', // 46949 /** 46950 * @property {String} DARKEST 46951 * @final 46952 */ exports.ADD = ADD; 46953 var DARKEST = 'darken'; 46954 /** 46955 * @property {String} LIGHTEST 46956 * @final 46957 * @default lighten 46958 */ exports.DARKEST = DARKEST; 46959 var LIGHTEST = 'lighten'; 46960 /** 46961 * @property {String} DIFFERENCE 46962 * @final 46963 */ exports.LIGHTEST = LIGHTEST; 46964 var DIFFERENCE = 'difference'; 46965 /** 46966 * @property {String} SUBTRACT 46967 * @final 46968 */ exports.DIFFERENCE = DIFFERENCE; 46969 var SUBTRACT = 'subtract'; 46970 /** 46971 * @property {String} EXCLUSION 46972 * @final 46973 */ exports.SUBTRACT = SUBTRACT; 46974 var EXCLUSION = 'exclusion'; 46975 /** 46976 * @property {String} MULTIPLY 46977 * @final 46978 */ exports.EXCLUSION = EXCLUSION; 46979 var MULTIPLY = 'multiply'; 46980 /** 46981 * @property {String} SCREEN 46982 * @final 46983 */ exports.MULTIPLY = MULTIPLY; 46984 var SCREEN = 'screen'; 46985 /** 46986 * @property {String} REPLACE 46987 * @final 46988 * @default copy 46989 */ exports.SCREEN = SCREEN; 46990 var REPLACE = 'copy'; 46991 /** 46992 * @property {String} OVERLAY 46993 * @final 46994 */ exports.REPLACE = REPLACE; 46995 var OVERLAY = 'overlay'; 46996 /** 46997 * @property {String} HARD_LIGHT 46998 * @final 46999 */ exports.OVERLAY = OVERLAY; 47000 var HARD_LIGHT = 'hard-light'; 47001 /** 47002 * @property {String} SOFT_LIGHT 47003 * @final 47004 */ exports.HARD_LIGHT = HARD_LIGHT; 47005 var SOFT_LIGHT = 'soft-light'; 47006 /** 47007 * @property {String} DODGE 47008 * @final 47009 * @default color-dodge 47010 */ exports.SOFT_LIGHT = SOFT_LIGHT; 47011 var DODGE = 'color-dodge'; 47012 /** 47013 * @property {String} BURN 47014 * @final 47015 * @default color-burn 47016 */ exports.DODGE = DODGE; 47017 var BURN = 'color-burn'; 47018 47019 // FILTERS 47020 /** 47021 * @property {String} THRESHOLD 47022 * @final 47023 */ exports.BURN = BURN; 47024 var THRESHOLD = 'threshold'; 47025 /** 47026 * @property {String} GRAY 47027 * @final 47028 */ exports.THRESHOLD = THRESHOLD; 47029 var GRAY = 'gray'; 47030 /** 47031 * @property {String} OPAQUE 47032 * @final 47033 */ exports.GRAY = GRAY; 47034 var OPAQUE = 'opaque'; 47035 /** 47036 * @property {String} INVERT 47037 * @final 47038 */ exports.OPAQUE = OPAQUE; 47039 var INVERT = 'invert'; 47040 /** 47041 * @property {String} POSTERIZE 47042 * @final 47043 */ exports.INVERT = INVERT;
47044 var POSTERIZE = 'posterize'; 47045 /** 47046 * @property {String} DILATE 47047 * @final 47048 */ exports.POSTERIZE = POSTERIZE; 47049 var DILATE = 'dilate'; 47050 /** 47051 * @property {String} ERODE 47052 * @final 47053 */ exports.DILATE = DILATE; 47054 var ERODE = 'erode'; 47055 /** 47056 * @property {String} BLUR 47057 * @final 47058 */ exports.ERODE = ERODE; 47059 var BLUR = 'blur'; 47060 47061 // TYPOGRAPHY 47062 /** 47063 * @property {String} NORMAL 47064 * @final 47065 */ exports.BLUR = BLUR; 47066 var NORMAL = 'normal'; 47067 /** 47068 * @property {String} ITALIC 47069 * @final 47070 */ exports.NORMAL = NORMAL; 47071 var ITALIC = 'italic'; 47072 /** 47073 * @property {String} BOLD 47074 * @final 47075 */ exports.ITALIC = ITALIC; 47076 var BOLD = 'bold'; 47077 /** 47078 * @property {String} BOLDITALIC 47079 * @final 47080 */ exports.BOLD = BOLD; 47081 var BOLDITALIC = 'bold italic'; 47082 47083 // TYPOGRAPHY-INTERNAL 47084 exports.BOLDITALIC = BOLDITALIC; 47085 var _DEFAULT_TEXT_FILL = '#000000'; 47086 exports._DEFAULT_TEXT_FILL = _DEFAULT_TEXT_FILL; 47087 var _DEFAULT_LEADMULT = 1.25; 47088 exports._DEFAULT_LEADMULT = _DEFAULT_LEADMULT; 47089 var _CTX_MIDDLE = 'middle'; 47090 47091 // VERTICES 47092 /** 47093 * @property {String} LINEAR 47094 * @final 47095 */ exports._CTX_MIDDLE = _CTX_MIDDLE; 47096 var LINEAR = 'linear'; 47097 /** 47098 * @property {String} QUADRATIC 47099 * @final 47100 */ exports.LINEAR = LINEAR; 47101 var QUADRATIC = 'quadratic'; 47102 /** 47103 * @property {String} BEZIER 47104 * @final 47105 */ exports.QUADRATIC = QUADRATIC; 47106 var BEZIER = 'bezier'; 47107 /** 47108 * @property {String} CURVE 47109 * @final 47110 */ exports.BEZIER = BEZIER; 47111 var CURVE = 'curve'; 47112 47113 // WEBGL DRAWMODES 47114 /** 47115 * @property {String} STROKE 47116 * @final 47117 */ exports.CURVE = CURVE; 47118 var STROKE = 'stroke'; 47119 /** 47120 * @property {String} FILL 47121 * @final 47122 */ exports.STROKE = STROKE; 47123 var FILL = 'fill'; 47124 /** 47125 * @property {String} TEXTURE 47126 * @final 47127 */ exports.FILL = FILL; 47128 var TEXTURE = 'texture'; 47129 /** 47130 * @property {String} IMMEDIATE 47131 * @final 47132 */ exports.TEXTURE = TEXTURE; 47133 var IMMEDIATE = 'immediate'; 47134 47135 // WEBGL TEXTURE MODE 47136 // NORMAL already exists for typography 47137 /** 47138 * @property {String} IMAGE 47139 * @final 47140 */ exports.IMMEDIATE = IMMEDIATE; 47141 var IMAGE = 'image'; 47142 47143 // WEBGL TEXTURE WRAP AND FILTERING 47144 // LINEAR already exists above 47145 /** 47146 * @property {String} NEAREST 47147 * @final 47148 */ exports.IMAGE = IMAGE; 47149 var NEAREST = 'nearest'; 47150 /** 47151 * @property {String} REPEAT 47152 * @final 47153 */ exports.NEAREST = NEAREST; 47154 var REPEAT = 'repeat'; 47155 /** 47156 * @property {String} CLAMP 47157 * @final 47158 */ exports.REPEAT = REPEAT; 47159 var CLAMP = 'clamp'; 47160 /** 47161 * @property {String} MIRROR 47162 * @final 47163 */ exports.CLAMP = CLAMP; 47164 var MIRROR = 'mirror'; 47165 47166 // DEVICE-ORIENTATION 47167 /** 47168 * @property {String} LANDSCAPE 47169 * @final 47170 */ exports.MIRROR = MIRROR; 47171 var LANDSCAPE = 'landscape'; 47172 /** 47173 * @property {String} PORTRAIT 47174 * @final 47175 */ exports.LANDSCAPE = LANDSCAPE; 47176 var PORTRAIT = 'portrait'; 47177 47178 // DEFAULTS 47179 exports.PORTRAIT = PORTRAIT; 47180 var _DEFAULT_STROKE = '#000000'; 47181 exports._DEFAULT_STROKE = _DEFAULT_STROKE; 47182 var _DEFAULT_FILL = '#FFFFFF'; 47183 47184 /** 47185 * @property {String} GRID 47186 * @final 47187 */ exports._DEFAULT_FILL = _DEFAULT_FILL; 47188 var GRID = 'grid'; 47189 47190 /** 47191 * @property {String} AXES 47192 * @final 47193 */ exports.GRID = GRID; 47194 var AXES = 'axes'; 47195 47196 /** 47197 * @property {String} LABEL 47198 * @final 47199 */ exports.AXES = AXES; 47200 var LABEL = 'label'; 47201 /** 47202 * @property {String} FALLBACK 47203 * @final 47204 */ exports.LABEL = LABEL; 47205 var FALLBACK = 'fallback'; 47206 exports.FALLBACK = FALLBACK; 47207 }, 47208 {} 47209 ], 47210 49: [
47211 function(_dereq_, module, exports) { 47212 'use strict'; 47213 function _typeof(obj) { 47214 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') { 47215 _typeof = function _typeof(obj) { 47216 return typeof obj; 47217 }; 47218 } else { 47219 _typeof = function _typeof(obj) { 47220 return obj && 47221 typeof Symbol === 'function' && 47222 obj.constructor === Symbol && 47223 obj !== Symbol.prototype 47224 ? 'symbol' 47225 : typeof obj; 47226 }; 47227 } 47228 return _typeof(obj); 47229 } 47230 Object.defineProperty(exports, '__esModule', { value: true }); 47231 exports.default = void 0; 47232 47233 var _main = _interopRequireDefault(_dereq_('./main')); 47234 var C = _interopRequireWildcard(_dereq_('./constants')); 47235 function _getRequireWildcardCache() { 47236 if (typeof WeakMap !== 'function') return null; 47237 var cache = new WeakMap(); 47238 _getRequireWildcardCache = function _getRequireWildcardCache() { 47239 return cache; 47240 }; 47241 return cache; 47242 } 47243 function _interopRequireWildcard(obj) { 47244 if (obj && obj.__esModule) { 47245 return obj; 47246 } 47247 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) { 47248 return { default: obj }; 47249 } 47250 var cache = _getRequireWildcardCache(); 47251 if (cache && cache.has(obj)) { 47252 return cache.get(obj); 47253 } 47254 var newObj = {}; 47255 var hasPropertyDescriptor = 47256 Object.defineProperty && Object.getOwnPropertyDescriptor; 47257 for (var key in obj) { 47258 if (Object.prototype.hasOwnProperty.call(obj, key)) { 47259 var desc = hasPropertyDescriptor 47260 ? Object.getOwnPropertyDescriptor(obj, key) 47261 : null; 47262 if (desc && (desc.get || desc.set)) { 47263 Object.defineProperty(newObj, key, desc); 47264 } else { 47265 newObj[key] = obj[key]; 47266 } 47267 } 47268 } 47269 newObj.default = obj; 47270 if (cache) { 47271 cache.set(obj, newObj); 47272 } 47273 return newObj; 47274 } 47275 function _interopRequireDefault(obj) { 47276 return obj && obj.__esModule ? obj : { default: obj }; 47277 } 47278 /** 47279 * @module Environment 47280 * @submodule Environment 47281 * @for p5 47282 * @requires core 47283 * @requires constants 47284 */ var standardCursors = [C.ARROW, C.CROSS, C.HAND, C.MOVE, C.TEXT, C.WAIT]; 47285 _main.default.prototype._frameRate = 0; 47286 _main.default.prototype._lastFrameTime = window.performance.now(); 47287 _main.default.prototype._targetFrameRate = 60; 47288 47289 var _windowPrint = window.print; 47290 47291 /** 47292 * The <a href="#/p5/print">print()</a> function writes to the console area of 47293 * your browser. This function is often helpful for looking at the data a program 47294 * is producing. This function creates a new line of text for each call to 47295 * the function. Individual elements can be separated with quotes ("") and joined 47296 * with the addition operator (+). 47297 * 47298 * Note that calling print() without any arguments invokes the window.print() 47299 * function which opens the browser's print dialog. To print a blank line 47300 * to console you can write print('\n'). 47301 * 47302 * @method print 47303 * @param {Any} contents any combination of Number, String, Object, Boolean, 47304 * Array to print 47305 * @example 47306 * <div><code class='norender'> 47307 * let x = 10; 47308 * print('The value of x is ' + x); 47309 * // prints "The value of x is 10" 47310 * </code></div> 47311 * 47312 * @alt 47313 * default grey canvas 47314 */ 47315 _main.default.prototype.print = function() { 47316 if (!arguments.length) { 47317 _windowPrint(); 47318 } else { 47319 var _console;
47320 (_console = console).log.apply(_console, arguments); 47321 } 47322 }; 47323 47324 /** 47325 * The system variable <a href="#/p5/frameCount">frameCount</a> contains the 47326 * number of frames that have been displayed since the program started. Inside 47327 * <a href="#/p5/setup">setup()</a> the value is 0, after the first iteration 47328 * of draw it is 1, etc. 47329 * 47330 * @property {Integer} frameCount 47331 * @readOnly 47332 * @example 47333 * <div><code> 47334 * function setup() { 47335 * frameRate(30); 47336 * textSize(30); 47337 * textAlign(CENTER); 47338 * } 47339 * 47340 * function draw() { 47341 * background(200); 47342 * text(frameCount, width / 2, height / 2); 47343 * } 47344 * </code></div> 47345 * 47346 * @alt 47347 * numbers rapidly counting upward with frame count set to 30. 47348 */ 47349 _main.default.prototype.frameCount = 0; 47350 47351 /** 47352 * The system variable <a href="#/p5/deltaTime">deltaTime</a> contains the time 47353 * difference between the beginning of the previous frame and the beginning 47354 * of the current frame in milliseconds. 47355 * 47356 * This variable is useful for creating time sensitive animation or physics 47357 * calculation that should stay constant regardless of frame rate. 47358 * 47359 * @property {Integer} deltaTime 47360 * @readOnly 47361 * @example 47362 * <div><code> 47363 * let rectX = 0; 47364 * let fr = 30; //starting FPS 47365 * let clr; 47366 * 47367 * function setup() { 47368 * background(200); 47369 * frameRate(fr); // Attempt to refresh at starting FPS 47370 * clr = color(255, 0, 0); 47371 * } 47372 * 47373 * function draw() { 47374 * background(200); 47375 * rectX = rectX + 1 * (deltaTime / 50); // Move Rectangle in relation to deltaTime 47376 * 47377 * if (rectX >= width) { 47378 * // If you go off screen. 47379 * if (fr === 30) { 47380 * clr = color(0, 0, 255); 47381 * fr = 10; 47382 * frameRate(fr); // make frameRate 10 FPS 47383 * } else { 47384 * clr = color(255, 0, 0); 47385 * fr = 30; 47386 * frameRate(fr); // make frameRate 30 FPS 47387 * } 47388 * rectX = 0; 47389 * } 47390 * fill(clr); 47391 * rect(rectX, 40, 20, 20); 47392 * } 47393 * </code></div> 47394 * 47395 * @alt 47396 * red rect moves left to right, followed by blue rect moving at the same speed 47397 * with a lower frame rate. Loops. 47398 */ 47399 _main.default.prototype.deltaTime = 0; 47400 47401 /** 47402 * Confirms if the window a p5.js program is in is "focused," meaning that 47403 * the sketch will accept mouse or keyboard input. This variable is 47404 * "true" if the window is focused and "false" if not. 47405 * 47406 * @property {Boolean} focused 47407 * @readOnly 47408 * @example 47409 * <div><code> 47410 * // To demonstrate, put two windows side by side. 47411 * // Click on the window that the p5 sketch isn't in! 47412 * function draw() { 47413 * background(200); 47414 * noStroke(); 47415 * fill(0, 200, 0); 47416 * ellipse(25, 25, 50, 50); 47417 * 47418 * if (!focused) { 47419 // or "if (focused === false)" 47420 * stroke(200, 0, 0); 47421 * line(0, 0, 100, 100); 47422 * line(100, 0, 0, 100); 47423 * } 47424 * } 47425 * </code></div> 47426 * 47427 * @alt 47428 * green 50x50 ellipse at top left. Red X covers canvas when page focus changes 47429 */
47430 _main.default.prototype.focused = document.hasFocus(); 47431 47432 /** 47433 * Sets the cursor to a predefined symbol or an image, or makes it visible 47434 * if already hidden. If you are trying to set an image as the cursor, the 47435 * recommended size is 16x16 or 32x32 pixels. The values for parameters x and y 47436 * must be less than the dimensions of the image. 47437 * 47438 * @method cursor 47439 * @param {String|Constant} type Built-In: either ARROW, CROSS, HAND, MOVE, TEXT and WAIT 47440 * Native CSS properties: 'grab', 'progress', 'cell' etc. 47441 * External: path for cursor's images 47442 * (Allowed File extensions: .cur, .gif, .jpg, .jpeg, .png) 47443 * For more information on Native CSS cursors and url visit: 47444 * https://developer.mozilla.org/en-US/docs/Web/CSS/cursor 47445 * @param {Number} [x] the horizontal active spot of the cursor (must be less than 32) 47446 * @param {Number} [y] the vertical active spot of the cursor (must be less than 32) 47447 * @example 47448 * <div><code> 47449 * // Move the mouse across the quadrants 47450 * // to see the cursor change 47451 * function draw() { 47452 * line(width / 2, 0, width / 2, height); 47453 * line(0, height / 2, width, height / 2); 47454 * if (mouseX < 50 && mouseY < 50) { 47455 * cursor(CROSS); 47456 * } else if (mouseX > 50 && mouseY < 50) { 47457 * cursor('progress'); 47458 * } else if (mouseX > 50 && mouseY > 50) { 47459 * cursor('https://avatars0.githubusercontent.com/u/1617169?s=16'); 47460 * } else { 47461 * cursor('grab'); 47462 * } 47463 * } 47464 * </code></div> 47465 * 47466 * @alt 47467 * canvas is divided into four quadrants. cursor on first is a cross, second is a progress, 47468 * third is a custom cursor using path to the cursor and fourth is a grab. 47469 */ 47470 _main.default.prototype.cursor = function(type, x, y) { 47471 var cursor = 'auto'; 47472 var canvas = this._curElement.elt; 47473 if (standardCursors.includes(type)) { 47474 // Standard css cursor 47475 cursor = type; 47476 } else if (typeof type === 'string') { 47477 var coords = ''; 47478 if (x && y && typeof x === 'number' && typeof y === 'number') { 47479 // Note that x and y values must be unit-less positive integers < 32 47480 // https://developer.mozilla.org/en-US/docs/Web/CSS/cursor 47481 coords = ''.concat(x, ' ').concat(y); 47482 } 47483 if ( 47484 type.substring(0, 7) === 'http://' || 47485 type.substring(0, 8) === 'https://' 47486 ) { 47487 // Image (absolute url) 47488 cursor = 'url('.concat(type, ') ').concat(coords, ', auto'); 47489 } else if (/\.(cur|jpg|jpeg|gif|png|CUR|JPG|JPEG|GIF|PNG)$/.test(type)) { 47490 // Image file (relative path) - Separated for performance reasons 47491 cursor = 'url('.concat(type, ') ').concat(coords, ', auto'); 47492 } else { 47493 // Any valid string for the css cursor property 47494 cursor = type; 47495 } 47496 } 47497 canvas.style.cursor = cursor; 47498 }; 47499 47500 /** 47501 * Specifies the number of frames to be displayed every second. For example, 47502 * the function call frameRate(30) will attempt to refresh 30 times a second. 47503 * If the processor is not fast enough to maintain the specified rate, the 47504 * frame rate will not be achieved. Setting the frame rate within 47505 * <a href="#/p5/setup">setup()</a> is recommended. The default frame rate is 47506 * based on the frame rate of the display (here also called "refresh rate"), 47507 * which is set to 60 frames per second on most computers. A frame rate of 24 47508 * frames per second (usual for movies) or above will be enough for smooth 47509 * animations. This is the same as setFrameRate(val). 47510 * 47511 * Calling <a href="#/p5/frameRate">frameRate()</a> with no arguments returns 47512 * the current framerate. The draw function must run at least once before it will 47513 * return a value. This is the same as <a href="#/p5/getFrameRate">getFrameRate()</a>. 47514 * 47515 * Calling <a href="#/p5/frameRate">frameRate()</a> with arguments that are not 47516 * of the type numbers or are non positive also returns current framerate. 47517 * 47518 * @method frameRate 47519 * @param {Number} fps number of frames to be displayed every second 47520 * @chainable 47521 * 47522 * @example 47523 * 47524 * <div><code> 47525 * let rectX = 0; 47526 * let fr = 30; //starting FPS 47527 * let clr; 47528 * 47529 * function setup() { 47530 * background(200); 47531 * frameRate(fr); // Attempt to refresh at starting FPS 47532 * clr = color(255, 0, 0); 47533 * } 47534 * 47535 * function draw() { 47536 * background(200); 47537 * rectX = rectX += 1; // Move Rectangle 47538 * 47539 * if (rectX >= width) { 47540 // If you go off screen. 47541 * if (fr === 30) { 47542 * clr = color(0, 0, 255); 47543 * fr = 10; 47544 * frameRate(fr); // make frameRate 10 FPS 47545 * } else { 47546 * clr = color(255, 0, 0); 47547 * fr = 30; 47548 * frameRate(fr); // make frameRate 30 FPS 47549 * } 47550 * rectX = 0; 47551 * } 47552 * fill(clr);
47553 * rect(rectX, 40, 20, 20); 47554 * } 47555 * </code></div> 47556 * 47557 * @alt 47558 * blue rect moves left to right, followed by red rect moving faster. Loops. 47559 */ 47560 /** 47561 * @method frameRate 47562 * @return {Number} current frameRate 47563 */ 47564 _main.default.prototype.frameRate = function(fps) { 47565 _main.default._validateParameters('frameRate', arguments); 47566 if (typeof fps !== 'number' || fps < 0) { 47567 return this._frameRate; 47568 } else { 47569 this._setProperty('_targetFrameRate', fps); 47570 if (fps === 0) { 47571 this._setProperty('_frameRate', fps); 47572 } 47573 return this; 47574 } 47575 }; 47576 47577 /** 47578 * Returns the current framerate. 47579 * 47580 * @private 47581 * @return {Number} current frameRate 47582 */ 47583 _main.default.prototype.getFrameRate = function() { 47584 return this.frameRate(); 47585 }; 47586 47587 /** 47588 * Specifies the number of frames to be displayed every second. For example, 47589 * the function call frameRate(30) will attempt to refresh 30 times a second. 47590 * If the processor is not fast enough to maintain the specified rate, the 47591 * frame rate will not be achieved. Setting the frame rate within <a href="#/p5/setup">setup()</a> is 47592 * recommended. The default rate is 60 frames per second. 47593 * 47594 * Calling <a href="#/p5/frameRate">frameRate()</a> with no arguments returns the current framerate. 47595 * 47596 * @private 47597 * @param {Number} [fps] number of frames to be displayed every second 47598 */ 47599 _main.default.prototype.setFrameRate = function(fps) { 47600 return this.frameRate(fps); 47601 }; 47602 47603 /** 47604 * Hides the cursor from view. 47605 * 47606 * @method noCursor 47607 * @example 47608 * <div><code> 47609 * function setup() { 47610 * noCursor(); 47611 * } 47612 * 47613 * function draw() { 47614 * background(200); 47615 * ellipse(mouseX, mouseY, 10, 10); 47616 * } 47617 * </code></div> 47618 * 47619 * @alt 47620 * cursor becomes 10x 10 white ellipse the moves with mouse x and y. 47621 */ 47622 _main.default.prototype.noCursor = function() { 47623 this._curElement.elt.style.cursor = 'none'; 47624 }; 47625 47626 /** 47627 * System variable that stores the width of the screen display according to The 47628 * default <a href="#/p5/pixelDensity">pixelDensity</a>. This is used to run a 47629 * full-screen program on any display size. To return actual screen size, 47630 * multiply this by pixelDensity. 47631 * 47632 * @property {Number} displayWidth 47633 * @readOnly 47634 * @example 47635 * <div class="norender"><code> 47636 * createCanvas(displayWidth, displayHeight); 47637 * </code></div> 47638 * 47639 * @alt 47640 * This example does not render anything. 47641 */ 47642 _main.default.prototype.displayWidth = screen.width; 47643 47644 /** 47645 * System variable that stores the height of the screen display according to The 47646 * default <a href="#/p5/pixelDensity">pixelDensity</a>. This is used to run a 47647 * full-screen program on any display size. To return actual screen size, 47648 * multiply this by pixelDensity. 47649 * 47650 * @property {Number} displayHeight 47651 * @readOnly 47652 * @example 47653 * <div class="norender"><code> 47654 * createCanvas(displayWidth, displayHeight); 47655 * </code></div> 47656 * 47657 * @alt 47658 * This example does not render anything. 47659 */ 47660 _main.default.prototype.displayHeight = screen.height; 47661 47662 /** 47663 * System variable that stores the width of the inner window, it maps to 47664 * window.innerWidth. 47665 * 47666 * @property {Number} windowWidth 47667 * @readOnly 47668 * @example 47669 * <div class="norender"><code> 47670 * createCanvas(windowWidth, windowHeight); 47671 * </code></div> 47672 * 47673 * @alt 47674 * This example does not render anything. 47675 */ 47676 _main.default.prototype.windowWidth = getWindowWidth(); 47677 /** 47678 * System variable that stores the height of the inner window, it maps to 47679 * window.innerHeight. 47680 * 47681 * @property {Number} windowHeight 47682 * @readOnly 47683 * @example 47684 * <div class="norender"><code> 47685 * createCanvas(windowWidth, windowHeight); 47686 * </code></div> 47687 * 47688 * @alt 47689 * This example does not render anything. 47690 */ 47691 _main.default.prototype.windowHeight = getWindowHeight(); 47692 47693 /** 47694 * The <a href="#/p5/windowResized">windowResized()</a> function is called once 47695 * every time the browser window is resized. This is a good place to resize the 47696 * canvas or do any other adjustments to accommodate the new window size. 47697 * 47698 * @method windowResized 47699 * @example 47700 * <div class="norender"><code> 47701 * function setup() { 47702 * createCanvas(windowWidth, windowHeight); 47703 * } 47704 * 47705 * function draw() { 47706 * background(0, 100, 200); 47707 * } 47708 * 47709 * function windowResized() { 47710 * resizeCanvas(windowWidth, windowHeight); 47711 * } 47712 * </code></div> 47713 * @alt 47714 * This example does not render anything. 47715 */ 47716 _main.default.prototype._onresize = function(e) { 47717 this._setProperty('windowWidth', getWindowWidth()); 47718 this._setProperty('windowHeight', getWindowHeight()); 47719 var context = this._isGlobal ? window : this; 47720 var executeDefault; 47721 if (typeof context.windowResized === 'function') { 47722 executeDefault = context.windowResized(e); 47723 if (executeDefault !== undefined && !executeDefault) { 47724 e.preventDefault(); 47725 } 47726 } 47727 }; 47728 47729 function getWindowWidth() { 47730 return ( 47731 window.innerWidth || 47732 (document.documentElement && document.documentElement.clientWidth) || 47733 (document.body && document.body.clientWidth) || 47734 0 47735 ); 47736 } 47737 47738 function getWindowHeight() { 47739 return ( 47740 window.innerHeight || 47741 (document.documentElement && document.documentElement.clientHeight) || 47742 (document.body && document.body.clientHeight) || 47743 0 47744 ); 47745 } 47746 47747 /** 47748 * System variable that stores the width of the drawing canvas. This value 47749 * is set by the first parameter of the <a href="#/p5/createCanvas">createCanvas()</a> function. 47750 * For example, the function call createCanvas(320, 240) sets the width 47751 * variable to the value 320. The value of width defaults to 100 if 47752 * <a href="#/p5/createCanvas">createCanvas()</a> is not used in a program. 47753 * 47754 * @property {Number} width 47755 * @readOnly 47756 */ 47757 _main.default.prototype.width = 0; 47758 47759 /** 47760 * System variable that stores the height of the drawing canvas. This value 47761 * is set by the second parameter of the <a href="#/p5/createCanvas">createCanvas()</a> function. For 47762 * example, the function call createCanvas(320, 240) sets the height 47763 * variable to the value 240. The value of height defaults to 100 if 47764 * <a href="#/p5/createCanvas">createCanvas()</a> is not used in a program. 47765 * 47766 * @property {Number} height 47767 * @readOnly 47768 */ 47769 _main.default.prototype.height = 0; 47770 47771 /** 47772 * If argument is given, sets the sketch to fullscreen or not based on the 47773 * value of the argument. If no argument is given, returns the current 47774 * fullscreen state. Note that due to browser restrictions this can only 47775 * be called on user input, for example, on mouse press like the example 47776 * below. 47777 * 47778 * @method fullscreen 47779 * @param {Boolean} [val] whether the sketch should be in fullscreen mode 47780 * or not 47781 * @return {Boolean} current fullscreen state 47782 * @example 47783 * <div> 47784 * <code> 47785 * // Clicking in the box toggles fullscreen on and off. 47786 * function setup() { 47787 * background(200); 47788 * } 47789 * function mousePressed() { 47790 * if (mouseX > 0 && mouseX < 100 && mouseY > 0 && mouseY < 100) { 47791 * let fs = fullscreen(); 47792 * fullscreen(!fs); 47793 * } 47794 * } 47795 * </code> 47796 * </div> 47797 * 47798 * @alt 47799 * This example does not render anything. 47800 */ 47801 _main.default.prototype.fullscreen = function(val) { 47802 _main.default._validateParameters('fullscreen', arguments); 47803 // no arguments, return fullscreen or not 47804 if (typeof val === 'undefined') { 47805 return ( 47806 document.fullscreenElement || 47807 document.webkitFullscreenElement || 47808 document.mozFullScreenElement || 47809 document.msFullscreenElement 47810 ); 47811 } else { 47812 // otherwise set to fullscreen or not 47813 if (val) { 47814 launchFullscreen(document.documentElement); 47815 } else { 47816 exitFullscreen(); 47817 } 47818 } 47819 }; 47820 47821 /** 47822 * Sets the pixel scaling for high pixel density displays. By default 47823 * pixel density is set to match display density, call pixelDensity(1) 47824 * to turn this off. Calling <a href="#/p5/pixelDensity">pixelDensity()</a> with no arguments returns 47825 * the current pixel density of the sketch. 47826 * 47827 * @method pixelDensity 47828 * @param {Number} val whether or how much the sketch should scale 47829 * @chainable 47830 * @example 47831 * <div> 47832 * <code> 47833 * function setup() { 47834 * pixelDensity(1); 47835 * createCanvas(100, 100); 47836 * background(200); 47837 * ellipse(width / 2, height / 2, 50, 50); 47838 * } 47839 * </code> 47840 * </div> 47841 * 47842 * <div> 47843 * <code> 47844 * function setup() { 47845 * pixelDensity(3.0); 47846 * createCanvas(100, 100); 47847 * background(200); 47848 * ellipse(width / 2, height / 2, 50, 50); 47849 * } 47850 * </code> 47851 * </div> 47852 * 47853 * @alt 47854 * fuzzy 50x50 white ellipse with black outline in center of canvas. 47855 * sharp 50x50 white ellipse with black outline in center of canvas. 47856 */ 47857 /** 47858 * @method pixelDensity 47859 * @returns {Number} current pixel density of the sketch 47860 */ 47861 _main.default.prototype.pixelDensity = function(val) { 47862 _main.default._validateParameters('pixelDensity', arguments); 47863 var returnValue; 47864 if (typeof val === 'number') { 47865 if (val !== this._pixelDensity) { 47866 this._pixelDensity = val; 47867 } 47868 returnValue = this; 47869 this.resizeCanvas(this.width, this.height, true); // as a side effect, it will clear the canvas 47870 } else { 47871 returnValue = this._pixelDensity; 47872 } 47873 return returnValue; 47874 }; 47875 47876 /** 47877 * Returns the pixel density of the current display the sketch is running on. 47878 * 47879 * @method displayDensity 47880 * @returns {Number} current pixel density of the display 47881 * @example 47882 * <div> 47883 * <code> 47884 * function setup() { 47885 * let density = displayDensity(); 47886 * pixelDensity(density); 47887 * createCanvas(100, 100); 47888 * background(200); 47889 * ellipse(width / 2, height / 2, 50, 50); 47890 * } 47891 * </code> 47892 * </div> 47893 * 47894 * @alt 47895 * 50x50 white ellipse with black outline in center of canvas. 47896 */ 47897 _main.default.prototype.displayDensity = function() { 47898 return window.devicePixelRatio; 47899 }; 47900 47901 function launchFullscreen(element) { 47902 var enabled = 47903 document.fullscreenEnabled || 47904 document.webkitFullscreenEnabled || 47905 document.mozFullScreenEnabled || 47906 document.msFullscreenEnabled; 47907 if (!enabled) { 47908 throw new Error('Fullscreen not enabled in this browser.'); 47909 } 47910 if (element.requestFullscreen) { 47911 element.requestFullscreen(); 47912 } else if (element.mozRequestFullScreen) { 47913 element.mozRequestFullScreen(); 47914 } else if (element.webkitRequestFullscreen) { 47915 element.webkitRequestFullscreen(); 47916 } else if (element.msRequestFullscreen) { 47917 element.msRequestFullscreen(); 47918 } 47919 } 47920 47921 function exitFullscreen() { 47922 if (document.exitFullscreen) { 47923 document.exitFullscreen(); 47924 } else if (document.mozCancelFullScreen) { 47925 document.mozCancelFullScreen(); 47926 } else if (document.webkitExitFullscreen) { 47927 document.webkitExitFullscreen(); 47928 } else if (document.msExitFullscreen) { 47929 document.msExitFullscreen(); 47930 } 47931 } 47932 47933 /** 47934 * Gets the current URL. 47935 * @method getURL 47936 * @return {String} url 47937 * @example 47938 * <div> 47939 * <code> 47940 * let url; 47941 * let x = 100; 47942 * 47943 * function setup() { 47944 * fill(0); 47945 * noStroke();
47946 * url = getURL(); 47947 * } 47948 * 47949 * function draw() { 47950 * background(200); 47951 * text(url, x, height / 2); 47952 * x--; 47953 * } 47954 * </code> 47955 * </div> 47956 * 47957 * @alt 47958 * current url (http://p5js.org/reference/#/p5/getURL) moves right to left. 47959 */ 47960 _main.default.prototype.getURL = function() { 47961 return location.href; 47962 }; 47963 /** 47964 * Gets the current URL path as an array. 47965 * @method getURLPath 47966 * @return {String[]} path components 47967 * @example 47968 * <div class='norender'><code> 47969 * function setup() { 47970 * let urlPath = getURLPath(); 47971 * for (let i = 0; i < urlPath.length; i++) { 47972 * text(urlPath[i], 10, i * 20 + 20); 47973 * } 47974 * } 47975 * </code></div> 47976 * 47977 * @alt 47978 * This example does not render anything. 47979 */ 47980 _main.default.prototype.getURLPath = function() { 47981 return location.pathname.split('/').filter(function(v) { 47982 return v !== ''; 47983 }); 47984 }; 47985 /** 47986 * Gets the current URL params as an Object. 47987 * @method getURLParams 47988 * @return {Object} URL params 47989 * @example 47990 * <div class='norender notest'> 47991 * <code> 47992 * // Example: http://p5js.org?year=2014&month=May&day=15 47993 * 47994 * function setup() { 47995 * let params = getURLParams(); 47996 * text(params.day, 10, 20); 47997 * text(params.month, 10, 40); 47998 * text(params.year, 10, 60); 47999 * } 48000 * </code> 48001 * </div> 48002 * 48003 * @alt 48004 * This example does not render anything. 48005 */ 48006 _main.default.prototype.getURLParams = function() { 48007 var re = /[?&]([^&=]+)(?:[&=])([^&=]+)/gim; 48008 var m; 48009 var v = {}; 48010 while ((m = re.exec(location.search)) != null) { 48011 if (m.index === re.lastIndex) { 48012 re.lastIndex++; 48013 } 48014 v[m[1]] = m[2]; 48015 } 48016 return v; 48017 }; 48018 var _default = _main.default; 48019 exports.default = _default; 48020 }, 48021 { './constants': 48, './main': 59 } 48022 ], 48023 50: [ 48024 function(_dereq_, module, exports) { 48025 'use strict'; 48026 Object.defineProperty(exports, '__esModule', { value: true }); 48027 exports.default = void 0; // Different browsers may use different error strings for the same error. 48028 // Extracting info from them is much easier and cleaner if we have a predefined 48029 // lookup against which we try and match the errors obtained from the browser, 48030 // classify them into types and extract the required information. The contents 48031 // of this file serve as that lookup. The FES can use this to give a simplified 48032 // explanation for all kinds of errors. 48033 var strings = { 48034 ReferenceError: [ 48035 { 48036 msg: '{{}} is not defined', 48037 type: 'NOTDEFINED', 48038 browser: 'all' 48039 }, 48040 48041 { 48042 msg: "Can't find variable: {{}}", 48043 type: 'NOTDEFINED', 48044 browser: 'Safari' 48045 } 48046 ], 48047 48048 SyntaxError: [ 48049 { 48050 msg: 'illegal character', 48051 type: 'INVALIDTOKEN', 48052 browser: 'Firefox' 48053 }, 48054 48055 { 48056 msg: 'Invalid character', 48057 type: 'INVALIDTOKEN', 48058 browser: 'Safari' 48059 }, 48060 48061 { 48062 msg: 'Invalid or unexpected token', 48063 type: 'INVALIDTOKEN', 48064 browser: 'Chrome' 48065 }, 48066 48067 { 48068 msg: "Unexpected token '{{.}}'", 48069 type: 'UNEXPECTEDTOKEN', 48070 browser: 'Chrome' 48071 }, 48072 48073 { 48074 msg: "expected {{.}}, got '{{.}}'", 48075 type: 'UNEXPECTEDTOKEN', 48076 browser: 'Chrome' 48077 } 48078 ], 48079 48080 TypeError: [ 48081 { 48082 msg: '{{.}} is not a function', 48083 type: 'NOTFUNC', 48084 browser: 'all' 48085 } 48086 ] 48087 }; 48088 var _default = strings; 48089 exports.default = _default; 48090 }, 48091 {} 48092 ], 48093 51: [
48094 function(_dereq_, module, exports) { 48095 'use strict'; 48096 Object.defineProperty(exports, '__esModule', { value: true }); 48097 exports.default = void 0; 48098 48099 var _main = _interopRequireDefault(_dereq_('../main')); 48100 var _internationalization = _dereq_('../internationalization'); 48101 function _interopRequireDefault(obj) { 48102 return obj && obj.__esModule ? obj : { default: obj }; 48103 } 48104 function _slicedToArray(arr, i) { 48105 return ( 48106 _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest() 48107 ); 48108 } 48109 function _nonIterableRest() { 48110 throw new TypeError('Invalid attempt to destructure non-iterable instance'); 48111 } 48112 function _iterableToArrayLimit(arr, i) { 48113 if ( 48114 !( 48115 Symbol.iterator in Object(arr) || 48116 Object.prototype.toString.call(arr) === '[object Arguments]' 48117 ) 48118 ) { 48119 return; 48120 } 48121 var _arr = []; 48122 var _n = true; 48123 var _d = false; 48124 var _e = undefined; 48125 try { 48126 for ( 48127 var _i = arr[Symbol.iterator](), _s; 48128 !(_n = (_s = _i.next()).done); 48129 _n = true 48130 ) { 48131 _arr.push(_s.value); 48132 if (i && _arr.length === i) break; 48133 } 48134 } catch (err) { 48135 _d = true; 48136 _e = err; 48137 } finally { 48138 try { 48139 if (!_n && _i['return'] != null) _i['return'](); 48140 } finally { 48141 if (_d) throw _e; 48142 } 48143 } 48144 return _arr; 48145 } 48146 function _arrayWithHoles(arr) { 48147 if (Array.isArray(arr)) return arr; 48148 } 48149 function _typeof(obj) { 48150 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') { 48151 _typeof = function _typeof(obj) { 48152 return typeof obj; 48153 }; 48154 } else { 48155 _typeof = function _typeof(obj) { 48156 return obj && 48157 typeof Symbol === 'function' && 48158 obj.constructor === Symbol && 48159 obj !== Symbol.prototype 48160 ? 'symbol' 48161 : typeof obj; 48162 }; 48163 } 48164 return _typeof(obj); 48165 } 48166 48167 // p5.js blue, p5.js orange, auto dark green; fallback p5.js darkened magenta 48168 // See testColors below for all the color codes and names 48169 var typeColors = ['#2D7BB6', '#EE9900', '#4DB200', '#C83C00']; 48170 var misusedAtTopLevelCode = null; 48171 var defineMisusedAtTopLevelCode = null; 48172 48173 // the threshold for the maximum allowed levenshtein distance 48174 // used in misspelling detection 48175 var EDIT_DIST_THRESHOLD = 2; 48176 48177 // to enable or disable styling (color, font-size, etc. ) for fes messages 48178 var ENABLE_FES_STYLING = false; 48179 48180 if (typeof IS_MINIFIED !== 'undefined') { 48181 _main.default._friendlyError = _main.default._checkForUserDefinedFunctions = _main.default._fesErrorMonitor = function() {}; 48182 } else { 48183 var doFriendlyWelcome = false; // TEMP until we get it all working LM 48184 48185 var errorTable = _dereq_('./browser_errors').default; 48186 48187 // -- Borrowed from jQuery 1.11.3 -- 48188 var class2type = {}; 48189 var _toString = class2type.toString; 48190 var names = [ 48191 'Boolean', 48192 'Number', 48193 'String', 48194 'Function', 48195 'Array', 48196 'Date', 48197 'RegExp', 48198 'Object', 48199 'Error' 48200 ]; 48201 48202 for (var n = 0; n < names.length; n++) { 48203 class2type['[object '.concat(names[n], ']')] = names[n].toLowerCase(); 48204 } 48205 var getType = function getType(obj) { 48206 if (obj == null) { 48207 return ''.concat(obj); 48208 } 48209 return _typeof(obj) === 'object' || typeof obj === 'function' 48210 ? class2type[_toString.call(obj)] || 'object' 48211 : _typeof(obj); 48212 }; 48213 48214 // -- End borrow -- 48215 48216 // entry points into user-defined code 48217 var entryPoints = [ 48218 'setup', 48219 'draw', 48220 'preload', 48221 'deviceMoved', 48222 'deviceTurned', 48223 'deviceShaken', 48224 'doubleClicked', 48225 'mousePressed', 48226 'mouseReleased', 48227 'mouseMoved', 48228 'mouseDragged', 48229 'mouseClicked', 48230 'mouseWheel', 48231 'touchStarted', 48232 'touchMoved', 48233 'touchEnded', 48234 'keyPressed', 48235 'keyReleased', 48236 'keyTyped', 48237 'windowResized' 48238 ]; 48239 48240 var friendlyWelcome = function friendlyWelcome() { 48241 // p5.js brand - magenta: #ED225D 48242 //const astrixBgColor = 'transparent'; 48243 //const astrixTxtColor = '#ED225D'; 48244 //const welcomeBgColor = '#ED225D'; 48245 //const welcomeTextColor = 'white'; 48246 var welcomeMessage = (0, _internationalization.translator)('fes.pre', { 48247 message: (0, _internationalization.translator)('fes.welcome') 48248 }); 48249 48250 console.log( 48251 ' _ \n' + 48252 ' /\\| |/\\ \n' + 48253 " \\ ` ' / \n" +
48254 ' / , . \\ \n' + 48255 ' \\/|_|\\/ ' + 48256 '\n\n' + 48257 welcomeMessage 48258 ); 48259 }; 48260 48261 /** 48262 * Takes a message and a p5 function func, and adds a link pointing to 48263 * the reference documentation of func at the end of the message 48264 * 48265 * @method mapToReference 48266 * @private 48267 * @param {String} message the words to be said 48268 * @param {String} [func] the name of the function to link 48269 * 48270 * @returns {String} 48271 */ 48272 var mapToReference = function mapToReference(message, func) { 48273 var msgWithReference = ''; 48274 if (func == null || func.substring(0, 4) === 'load') { 48275 msgWithReference = message; 48276 } else { 48277 var methodParts = func.split('.'); 48278 var referenceSection = 48279 methodParts.length > 1 48280 ? ''.concat(methodParts[0], '.').concat(methodParts[1]) 48281 : 'p5'; 48282 48283 var funcName = 48284 methodParts.length === 1 ? func : methodParts.slice(2).join('/'); 48285 msgWithReference = '' 48286 .concat(message, ' (http://p5js.org/reference/#/') 48287 .concat(referenceSection, '/') 48288 .concat(funcName, ')'); 48289 } 48290 return msgWithReference; 48291 }; 48292 48293 /** 48294 * Prints out a fancy, colorful message to the console log 48295 * 48296 * @method report 48297 * @private 48298 * @param {String} message the words to be said 48299 * @param {String} [func] the name of the function to link 48300 * @param {Number|String} [color] CSS color string or error type 48301 * 48302 * @return console logs 48303 */ 48304 var report = function report(message, func, color) { 48305 // if p5._fesLogger is set ( i.e we are running tests ), use that 48306 // instead of console.log 48307 var log = 48308 _main.default._fesLogger == null 48309 ? console.log.bind(console) 48310 : _main.default._fesLogger; 48311 48312 if (doFriendlyWelcome) { 48313 friendlyWelcome(); 48314 doFriendlyWelcome = false; 48315 } 48316 if ('undefined' === getType(color)) { 48317 color = '#B40033'; // dark magenta 48318 } else if (getType(color) === 'number') { 48319 // Type to color 48320 color = typeColors[color]; 48321 } 48322 48323 // Add a link to the reference docs of func at the end of the message 48324 message = mapToReference(message, func); 48325 var style = [ 48326 'color: '.concat(color), 48327 'font-family: Arial', 48328 'font-size: larger' 48329 ]; 48330 var prefixedMsg = (0, _internationalization.translator)('fes.pre', { 48331 message: message 48332 }); 48333 48334 if (ENABLE_FES_STYLING) { 48335 log('%c' + prefixedMsg, style.join(';')); 48336 } else { 48337 log(prefixedMsg); 48338 } 48339 }; 48340 /** 48341 * This is a generic method that can be called from anywhere in the p5 48342 * library to alert users to a common error. 48343 * 48344 * @method _friendlyError 48345 * @private 48346 * @param {Number} message message to be printed 48347 * @param {String} [method] name of method 48348 * @param {Number|String} [color] CSS color string or error type (Optional) 48349 */ 48350 _main.default._friendlyError = function(message, method, color) { 48351 report(message, method, color); 48352 }; 48353 48354 /** 48355 * This is called internally if there is a error with autoplay. 48356 * 48357 * @method _friendlyAutoplayError 48358 * @private 48359 */ 48360 _main.default._friendlyAutoplayError = function(src) { 48361 var message = (0, _internationalization.translator)('fes.autoplay', { 48362 src: src, 48363 link: 'https://developer.mozilla.org/docs/Web/Media/Autoplay_guide' 48364 }); 48365 48366 console.log( 48367 (0, _internationalization.translator)('fes.pre', { message: message }) 48368 ); 48369 }; 48370 48371 /** 48372 * An implementation of 48373 * https://en.wikipedia.org/wiki/Wagner%E2%80%93Fischer_algorithm to 48374 * compute the Levenshtein distance. It gives a measure of how dissimilar 48375 * two strings are. If the "distance" between them is small enough, it is 48376 * reasonable to think that one is the misspelled ver
48376sion of the other. 48377 * @method computeEditDistance 48378 * @private 48379 * @param {String} w1 the first word 48380 * @param {String} w2 the second word 48381 * 48382 * @returns {Number} the "distance" between the two words, a smaller value 48383 * indicates that the words are similar 48384 */ 48385 var computeEditDistance = function computeEditDistance(w1, w2) { 48386 var l1 = w1.length, 48387 l2 = w2.length; 48388 if (l1 === 0) return w2; 48389 if (l2 === 0) return w1; 48390 48391 var prev = []; 48392 var cur = []; 48393 48394 for (var j = 0; j < l2 + 1; j++) { 48395 cur[j] = j; 48396 } 48397 48398 prev = cur; 48399 48400 for (var i = 1; i < l1 + 1; i++) { 48401 cur = []; 48402 for (var _j = 0; _j < l2 + 1; _j++) { 48403 if (_j === 0) { 48404 cur[_j] = i; 48405 } else { 48406 var a1 = w1[i - 1], 48407 a2 = w2[_j - 1]; 48408 var temp = 999999; 48409 var cost = a1.toLowerCase() === a2.toLowerCase() ? 0 : 1; 48410 temp = temp > cost + prev[_j - 1] ? cost + prev[_j - 1] : temp; 48411 temp = temp > 1 + cur[_j - 1] ? 1 + cur[_j - 1] : temp; 48412 temp = temp > 1 + prev[_j] ? 1 + prev[_j] : temp; 48413 cur[_j] = temp; 48414 } 48415 } 48416 prev = cur; 48417 } 48418 48419 return cur[l2]; 48420 }; 48421 48422 /** 48423 * checks if the various functions such as setup, draw, preload have been 48424 * defined with capitalization mistakes 48425 * @method checkForUserDefinedFunctions 48426 * @private 48427 * @param {*} context The current default context. It's set to window in 48428 * "global mode" and to a p5 instance in "instance mode" 48429 */ 48430 var checkForUserDefinedFunctions = function checkForUserDefinedFunctions( 48431 context 48432 ) { 48433 if (_main.default.disableFriendlyErrors) return; 48434 48435 // if using instance mode, this function would be called with the current 48436 // instance as context 48437 var instanceMode = context instanceof _main.default; 48438 context = instanceMode ? context : window; 48439 var fnNames = entryPoints; 48440 48441 var fxns = {}; 48442 // lowercasename -> actualName mapping 48443 fnNames.forEach(function(symbol) { 48444 fxns[symbol.toLowerCase()] = symbol; 48445 }); 48446 48447 for ( 48448 var _i = 0, _Object$keys = Object.keys(context); 48449 _i < _Object$keys.length; 48450 _i++ 48451 ) { 48452 var prop = _Object$keys[_i]; 48453 var lowercase = prop.toLowerCase(); 48454 48455 // check if the lowercase property name has an entry in fxns, if the 48456 // actual name with correct capitalization doesnt exist in context, 48457 // and if the user-defined symbol is of the type function 48458 if ( 48459 fxns[lowercase] && 48460 !context[fxns[lowercase]] && 48461 typeof context[prop] === 'function' 48462 ) { 48463 var msg = (0, _internationalization.translator)( 48464 'fes.checkUserDefinedFns', 48465 { 48466 name: prop, 48467 actualName: fxns[lowercase] 48468 } 48469 ); 48470 48471 report(msg, fxns[lowercase]); 48472 } 48473 } 48474 }; 48475 48476 /** 48477 * compares the the symbol caught in the ReferenceErrror to everything 48478 * in misusedAtTopLevel ( all public p5 properties ). The use of 48479 * misusedAtTopLevel here is for convenience as it was an array that was 48480 * already defined when spelling check was implemented. For this particular 48481 * use-case, it's a misnomer. 48482 * 48483 * @method handleMisspelling 48484 * @private 48485 * @param {String} errSym the symbol to whose spelling to check 48486 * @param {Error} error the ReferenceError object 48487 * 48488 * @returns {Boolean} a boolean value indicating if this error was likely due 48489 * to a mis-spelling 48490 */ 48491 var handleMisspelling = function handleMisspelling(errSym, error) { 48492 if (!misusedAtTopLevelCode) { 48493 defineMisusedAtTopLevelCode(); 48494 } 48495 48496 var distanceMap = {}; 48497 var min = 999999; 48498 // compute the levenshtein distance for the symbol against all known 48499 // public p5 properties. Find the property with the minimum distance 48500 misusedAtTopLevelCode.forEach(function(symbol) { 48501 var dist = computeEditDistance(errSym, symbol.name); 48502 if (distanceMap[dist]) distanceMap[dist].push(symbol);
48503 else distanceMap[dist] = [symbol]; 48504 48505 if (dist < min) min = dist; 48506 }); 48507 48508 // if the closest match has more "distance" than the max allowed threshold 48509 if (min > Math.min(EDIT_DIST_THRESHOLD, errSym.length)) return false; 48510 48511 // Show a message only if the caught symbol and the matched property name 48512 // differ in their name ( either letter difference or difference of case ) 48513 var matchedSymbols = distanceMap[min].filter(function(symbol) { 48514 return symbol.name !== errSym; 48515 }); 48516 48517 if (matchedSymbols.length !== 0) { 48518 var parsed = _main.default._getErrorStackParser().parse(error); 48519 var locationObj; 48520 if ( 48521 parsed && 48522 parsed[0] && 48523 parsed[0].fileName && 48524 parsed[0].lineNumber && 48525 parsed[0].columnNumber 48526 ) { 48527 locationObj = { 48528 location: '' 48529 .concat(parsed[0].fileName, ':') 48530 .concat(parsed[0].lineNumber, ':') 48531 .concat(parsed[0].columnNumber), 48532 48533 file: parsed[0].fileName.split('/').slice(-1), 48534 line: parsed[0].lineNumber 48535 }; 48536 } 48537 48538 var msg; 48539 if (matchedSymbols.length === 1) { 48540 // To be used when there is only one closest match. The count parameter 48541 // allows i18n to pick between the keys "fes.misspelling" and 48542 // "fes.misspelling__plural" 48543 msg = (0, _internationalization.translator)('fes.misspelling', { 48544 name: errSym, 48545 actualName: matchedSymbols[0].name, 48546 type: matchedSymbols[0].type, 48547 location: locationObj 48548 ? (0, _internationalization.translator)('fes.location', locationObj) 48549 : '', 48550 count: matchedSymbols.length 48551 }); 48552 } else { 48553 // To be used when there are multiple closest matches. Gives each 48554 // suggestion on its own line, the function name followed by a link to 48555 // reference documentation 48556 var suggestions = matchedSymbols 48557 .map(function(symbol) { 48558 var message = 48559 'â¶ï¸ ' + symbol.name + (symbol.type === 'function' ? '()' : ''); 48560 return mapToReference(message, symbol.name); 48561 }) 48562 .join('\n'); 48563 48564 msg = (0, _internationalization.translator)('fes.misspelling', { 48565 name: errSym, 48566 suggestions: suggestions, 48567 location: locationObj 48568 ? (0, _internationalization.translator)('fes.location', locationObj) 48569 : '', 48570 count: matchedSymbols.length 48571 }); 48572 } 48573 48574 // If there is only one closest match, tell _friendlyError to also add 48575 // a link to the reference documentation. In case of multiple matches, 48576 // this is already done in the suggestions variable, one link for each 48577 // suggestion. 48578 report( 48579 msg, 48580 matchedSymbols.length === 1 ? matchedSymbols[0].name : undefined 48581 ); 48582 48583 return true; 48584 } 48585 return false; 48586 }; 48587 48588 /** 48589 * prints a friendly stacktrace which only includes user-written functions 48590 * and is easier for newcomers to understand 48591 * @method printFriendlyStack 48592 * @private 48593 * @param {Array} friendlyStack 48594 */ 48595 var printFriendlyStack = function printFriendlyStack(friendlyStack) { 48596 var log = 48597 _main.default._fesLogger && typeof _main.default._fesLogger === 'function' 48598 ? _main.default._fesLogger 48599 : console.log.bind(console); 48600 if (friendlyStack.length > 1) { 48601 var stacktraceMsg = ''; 48602 friendlyStack.forEach(function(frame, idx) { 48603 var location = '' 48604 .concat(frame.fileName, ':') 48605 .concat(frame.lineNumber, ':') 48606 .concat(frame.columnNumber); 48607 48608 var frameMsg, 48609 translationObj = { 48610 func: frame.functionName, 48611 line: frame.lineNumber, 48612 location: location, 48613 file: frame.fileName.split('/').slice(-1) 48614 }; 48615 48616 if (idx === 0) { 48617 frameMsg = (0, _internationalization.translator)( 48618 'fes.globalErrors.stackTop', 48619 translationObj 48620 ); 48621 } else { 48622 frameMsg = (0, _internationalization.translator)( 48623 'fes.globalErrors.stackSubseq', 48624 translationObj 48625 ); 48626 } 48627 stacktraceMsg += frameMsg; 48628 }); 48629 log(stacktraceMsg); 48630 } 48631 }; 48632 48633 /** 48634 * Takes a stacktrace array and filters out all frames that show internal p5 48635 * details. It also uses this processed stack to figure out if the error 48636 * error happened internally within the library, and if the error was due to 48637 * a non-loadX() method being used in preload 48638 * "Internally" here means that the error exact location of the error (the
48639 * top of the stack) is a piece of code write in the p5.js library (which may 48640 * or may not have been called from the user's sketch) 48641 * 48642 * @method processStack 48643 * @private 48644 * @param {Error} error 48645 * @param {Array} stacktrace 48646 * 48647 * @returns {Array} An array with two elements, [isInternal, friendlyStack] 48648 * isInternal: a boolean indicating if the error happened internally 48649 * friendlyStack: the simplified stacktrace, with internal details filtered 48650 */ 48651 var processStack = function processStack(error, stacktrace) { 48652 // cannot process a stacktrace that doesn't exist 48653 if (!stacktrace) return [false, null]; 48654 48655 stacktrace.forEach(function(frame) { 48656 frame.functionName = frame.functionName || ''; 48657 }); 48658 48659 // isInternal - Did this error happen inside the library 48660 var isInternal = false; 48661 var p5FileName, friendlyStack, currentEntryPoint; 48662 for (var i = stacktrace.length - 1; i >= 0; i--) { 48663 var splitted = stacktrace[i].functionName.split('.'); 48664 if (entryPoints.includes(splitted[splitted.length - 1])) { 48665 // remove everything below an entry point function (setup, draw, etc). 48666 // (it's usually the internal initialization calls) 48667 friendlyStack = stacktrace.slice(0, i + 1); 48668 currentEntryPoint = splitted[splitted.length - 1]; 48669 for (var j = 0; j < i; j++) { 48670 // Due to the current build process, all p5 functions have 48671 // _main.default in their names in the final build. This is the 48672 // easiest way to check if a function is inside the p5 library 48673 if (stacktrace[j].functionName.search('_main.default') !== -1) { 48674 isInternal = true; 48675 p5FileName = stacktrace[j].fileName; 48676 break; 48677 } 48678 } 48679 break; 48680 } 48681 } 48682 48683 // in some cases ( errors in promises, callbacks, etc), no entry-point 48684 // function may be found in the stacktrace. In that case just use the 48685 // entire stacktrace for friendlyStack 48686 if (!friendlyStack) friendlyStack = stacktrace; 48687 48688 if (isInternal) { 48689 // the frameIndex property is added before the filter, so frameIndex 48690 // corresponds to the index of a frame in the original stacktrace. 48691 // Then we filter out all frames which belong to the file that contains 48692 // the p5 library 48693 friendlyStack = friendlyStack 48694 .map(function(frame, index) { 48695 frame.frameIndex = index; 48696 return frame; 48697 }) 48698 .filter(function(frame) { 48699 return frame.fileName !== p5FileName; 48700 }); 48701 48702 // a weird case, if for some reason we can't identify the function called 48703 // from user's code 48704 if (friendlyStack.length === 0) return [true, null]; 48705 48706 // get the function just above the topmost frame in the friendlyStack. 48707 // i.e the name of the library function called from user's code 48708 var func = stacktrace[friendlyStack[0].frameIndex - 1].functionName 48709 .split('.') 48710 .slice(-1)[0]; 48711 48712 // Try and get the location (line no.) from the top element of the stack 48713 var locationObj; 48714 if ( 48715 friendlyStack[0].fileName && 48716 friendlyStack[0].lineNumber && 48717 friendlyStack[0].columnNumber 48718 ) { 48719 locationObj = { 48720 location: '' 48721 .concat(friendlyStack[0].fileName, ':') 48722 .concat(friendlyStack[0].lineNumber, ':') 48723 .concat(friendlyStack[0].columnNumber), 48724 file: friendlyStack[0].fileName.split('/').slice(-1), 48725 line: friendlyStack[0].lineNumber 48726 }; 48727 48728 // if already handled by another part of the FES, don't handle again 48729 if (_main.default._fesLogCache[locationObj.location]) return [true, null]; 48730 } 48731 48732 // Check if the error is due to a non loadX method being used incorrectly 48733 // in preload 48734 if ( 48735 currentEntryPoint === 'preload' && 48736 _main.default.prototype._preloadMethods[func] == null 48737 ) { 48738 report( 48739 (0, _internationalization.translator)('fes.wrongPreload', { 48740 func: func, 48741 location: locationObj 48742 ? (0, _internationalization.translator)('fes.location', locationObj) 48743 : '', 48744 error: error.message 48745 }), 48746 48747 'preload' 48748 ); 48749 } else { 48750 // Library error 48751 report( 48752 (0, _internationalization.translator)('fes.libraryError', { 48753 func: func, 48754 location: locationObj 48755 ? (0, _internationalization.translator)('fes.location', locationObj) 48756 : '', 48757 error: error.message 48758 }), 48759 48760 func 48761 ); 48762 } 48763 48764 // Finally, if it's an internal error, print the friendlyStack 48765 // ( fesErrorMonitor won't handle this error ) 48766 if (friendlyStack && friendlyStack.length) { 48767 printFriendlyStack(friendlyStack); 48768 } 48769 } 48770 return [isInternal, friendlyStack]; 48771 }; 48772 48773 /** 48774 * The main function for handling global errors. Called when an error 48775 * happens and is responsible for detecting the type of error that 48776 * has happened and showing the appropriate message 48777 * 48778 * @method fesErrorMonitor
48779 * @private 48780 * @param {*} e The object to extract error details from 48781 */ 48782 var fesErrorMonitor = function fesErrorMonitor(e) { 48783 if (_main.default.disableFriendlyErrors) return; 48784 // Try to get the error object from e 48785 var error; 48786 if (e instanceof Error) { 48787 error = e; 48788 } else if (e instanceof ErrorEvent) { 48789 error = e.error; 48790 } else if (e instanceof PromiseRejectionEvent) { 48791 error = e.reason; 48792 if (!(error instanceof Error)) return; 48793 } 48794 if (!error) return; 48795 48796 var stacktrace = _main.default._getErrorStackParser().parse(error); 48797 // process the stacktrace from the browser and simplify it to give 48798 // friendlyStack. 48799 var _processStack = processStack(error, stacktrace), 48800 _processStack2 = _slicedToArray(_processStack, 2), 48801 isInternal = _processStack2[0], 48802 friendlyStack = _processStack2[1]; 48803 48804 // if this is an internal library error, the type of the error is not relevant, 48805 // only the user code that lead to it is. 48806 if (isInternal) { 48807 return; 48808 } 48809 48810 var errList = errorTable[error.name]; 48811 if (!errList) return; // this type of error can't be handled yet 48812 var matchedError; 48813 var _iteratorNormalCompletion = true; 48814 var _didIteratorError = false; 48815 var _iteratorError = undefined; 48816 try { 48817 for ( 48818 var _iterator = errList[Symbol.iterator](), _step; 48819 !(_iteratorNormalCompletion = (_step = _iterator.next()).done); 48820 _iteratorNormalCompletion = true 48821 ) { 48822 var obj = _step.value; 48823 var string = obj.msg; 48824 // capture the primary symbol mentioned in the error 48825 string = string.replace(new RegExp('{{}}', 'g'), '([a-zA-Z0-9_]+)'); 48826 string = string.replace(new RegExp('{{.}}', 'g'), '(.+)'); 48827 string = string.replace(new RegExp('{}', 'g'), '(?:[a-zA-Z0-9_]+)'); 48828 var matched = error.message.match(string); 48829 48830 if (matched) { 48831 matchedError = Object.assign({}, obj); 48832 matchedError.match = matched; 48833 break; 48834 } 48835 } 48836 } catch (err) { 48837 _didIteratorError = true; 48838 _iteratorError = err; 48839 } finally { 48840 try { 48841 if (!_iteratorNormalCompletion && _iterator.return != null) { 48842 _iterator.return(); 48843 } 48844 } finally { 48845 if (_didIteratorError) { 48846 throw _iteratorError; 48847 } 48848 } 48849 } 48850 48851 if (!matchedError) return; 48852 48853 // Try and get the location from the top element of the stack 48854 var locationObj; 48855 if ( 48856 stacktrace && 48857 stacktrace[0].fileName && 48858 stacktrace[0].lineNumber && 48859 stacktrace[0].columnNumber 48860 ) { 48861 locationObj = { 48862 location: '' 48863 .concat(stacktrace[0].fileName, ':') 48864 .concat(stacktrace[0].lineNumber, ':') 48865 .concat(stacktrace[0].columnNumber), 48866 48867 file: stacktrace[0].fileName.split('/').slice(-1), 48868 line: friendlyStack[0].lineNumber 48869 }; 48870 } 48871 48872 switch (error.name) { 48873 case 'SyntaxError': { 48874 // We can't really do much with syntax errors other than try to use 48875 // a simpler framing of the error message. The stack isn't available 48876 // for syntax errors 48877 switch (matchedError.type) {
48878 case 'INVALIDTOKEN': { 48879 var url = 48880 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Illegal_character#What_went_wrong'; 48881 report( 48882 (0, _internationalization.translator)( 48883 'fes.globalErrors.syntax.invalidToken', 48884 { 48885 url: url 48886 } 48887 ) 48888 ); 48889 48890 break; 48891 } 48892 case 'UNEXPECTEDTOKEN': { 48893 var _url = 48894 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Unexpected_token#What_went_wrong'; 48895 report( 48896 (0, _internationalization.translator)( 48897 'fes.globalErrors.syntax.unexpectedToken', 48898 { 48899 url: _url 48900 } 48901 ) 48902 ); 48903 48904 break; 48905 } 48906 } 48907 48908 break; 48909 } 48910 case 'ReferenceError': { 48911 switch (matchedError.type) { 48912 case 'NOTDEFINED': { 48913 var errSym = matchedError.match[1]; 48914 48915 if (errSym && handleMisspelling(errSym, error)) { 48916 break; 48917 } 48918 48919 // if the flow gets this far, this is likely not a misspelling 48920 // of a p5 property/function 48921 var url1 = 'https://p5js.org/examples/data-variable-scope.html'; 48922 var url2 = 48923 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_Defined#What_went_wrong'; 48924 report( 48925 (0, _internationalization.translator)( 48926 'fes.globalErrors.reference.notDefined', 48927 { 48928 url1: url1, 48929 url2: url2, 48930 symbol: errSym, 48931 location: locationObj 48932 ? (0, _internationalization.translator)( 48933 'fes.location', 48934 locationObj 48935 ) 48936 : '' 48937 } 48938 ) 48939 ); 48940 48941 if (friendlyStack) printFriendlyStack(friendlyStack); 48942 break; 48943 } 48944 } 48945 48946 break; 48947 } 48948 48949 case 'TypeError': { 48950 switch (matchedError.type) { 48951 case 'NOTFUNC': { 48952 var _errSym = matchedError.match[1]; 48953 var splitSym = _errSym.split('.'); 48954 var _url2 = 48955 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_a_function#What_went_wrong'; 48956 48957 // if errSym is aa.bb.cc , symbol would be cc and obj would aa.bb 48958 var translationObj = { 48959 url: _url2, 48960 symbol: splitSym[splitSym.length - 1], 48961 obj: splitSym.slice(0, splitSym.length - 1).join('.'), 48962 location: locationObj 48963 ? (0, _internationalization.translator)( 48964 'fes.location', 48965 locationObj 48966 ) 48967 : '' 48968 }; 48969 48970 // There are two cases to handle here. When the function is called 48971 // as a property of an object and when it's called independently. 48972 // Both have different explanations. 48973 if (splitSym.length > 1) { 48974 report( 48975 (0, _internationalization.translator)( 48976 'fes.globalErrors.type.notfuncObj', 48977 translationObj 48978 ) 48979 ); 48980 } else { 48981 report( 48982 (0, _internationalization.translator)( 48983 'fes.globalErrors.type.notfunc', 48984 translationObj 48985 ) 48986 ); 48987 } 48988 48989 if (friendlyStack) printFriendlyStack(friendlyStack); 48990 break; 48991 } 48992 } 48993 } 48994 } 48995 }; 48996 48997 _main.default._fesErrorMonitor = fesErrorMonitor; 48998 _main.default._checkForUserDefinedFunctions = checkForUserDefinedFunctions; 48999 49000 // logger for testing purposes. 49001 _main.default._fesLogger = null; 49002 _main.default._fesLogCache = {}; 49003 49004 window.addEventListener('load', checkForUserDefinedFunctions, false); 49005 window.addEventListener('error', _main.default._fesErrorMonitor, false); 49006 window.addEventListener( 49007 'unhandledrejection', 49008 _main.default._fesErrorMonitor, 49009 false 49010 ); 49011 49012 /** 49013 * Prints out all the colors in the color pallete with white text. 49014 * For color blindness testing. 49015 */ 49016 /* function testColors() { 49017 const str = 'A box of biscuits, a box of mixed biscuits and a biscuit mixer'; 49018 report(str, 'print', '#ED225D'); // p5.js magenta 49019 report(str, 'print', '#2D7BB6'); // p5.js blue 49020 report(str, 'print', '#EE9900'); // p5.js orange 49021 report(str, 'print', '#A67F59'); // p5.js light brown 49022 report(str, 'print', '#704F21'); // p5.js gold 49023 report(str, 'print', '#1CC581'); // auto cyan 49024 report(str, 'print', '#FF6625'); // auto orange 49025 report(str, 'print', '#79EB22'); // auto green 49026 report(str, 'print', '#B40033'); // p5.js darkened magenta 49027 report(str, 'print', '#084B7F'); // p5.js darkened blue 49028 report(str, 'print', '#945F00'); // p5.js darkened orange 49029 report(str, 'print', '#6B441D'); // p5.js darkened brown 49030 report(str, 'print', '#2E1B00'); // p5.js darkened gold 49031 report(str, 'print', '#008851'); // auto dark cyan 49032 report(str, 'print', '#C83C00'); // auto dark orange 49033 report(str, 'print', '#4DB200'); // auto dark green 49034 } */ 49035 } 49036 49037 // This is a lazily-defined list of p5 symbols that may be
49038 // misused by beginners at top-level code, outside of setup/draw. We'd like 49039 // to detect these errors and help the user by suggesting they move them 49040 // into setup/draw. 49041 // 49042 // For more details, see https://github.com/processing/p5.js/issues/1121. 49043 misusedAtTopLevelCode = null; 49044 var FAQ_URL = 49045 'https://github.com/processing/p5.js/wiki/p5.js-overview#why-cant-i-assign-variables-using-p5-functions-and-variables-before-setup'; 49046 49047 defineMisusedAtTopLevelCode = function defineMisusedAtTopLevelCode() { 49048 var uniqueNamesFound = {}; 49049 49050 var getSymbols = function getSymbols(obj) { 49051 return Object.getOwnPropertyNames(obj) 49052 .filter(function(name) { 49053 if (name[0] === '_') { 49054 return false; 49055 } 49056 if (name in uniqueNamesFound) { 49057 return false; 49058 } 49059 49060 uniqueNamesFound[name] = true; 49061 49062 return true; 49063 }) 49064 .map(function(name) { 49065 var type; 49066 49067 if (typeof obj[name] === 'function') { 49068 type = 'function'; 49069 } else if (name === name.toUpperCase()) { 49070 type = 'constant'; 49071 } else { 49072 type = 'variable'; 49073 } 49074 49075 return { name: name, type: type }; 49076 }); 49077 }; 49078 49079 misusedAtTopLevelCode = [].concat( 49080 getSymbols(_main.default.prototype), 49081 // At present, p5 only adds its constants to p5.prototype during 49082 // construction, which may not have happened at the time a 49083 // ReferenceError is thrown, so we'll manually add them to our list. 49084 getSymbols(_dereq_('../constants')) 49085 ); 49086 49087 // This will ultimately ensure that we report the most specific error 49088 // possible to the user, e.g. advising them about HALF_PI instead of PI 49089 // when their code misuses the former. 49090 misusedAtTopLevelCode.sort(function(a, b) { 49091 return b.name.length - a.name.length; 49092 }); 49093 }; 49094 49095 var helpForMisusedAtTopLevelCode = function helpForMisusedAtTopLevelCode(e, log) { 49096 if (!log) { 49097 log = console.log.bind(console); 49098 } 49099 49100 if (!misusedAtTopLevelCode) { 49101 defineMisusedAtTopLevelCode(); 49102 } 49103 49104 // If we find that we're logging lots of false positives, we can 49105 // uncomment the following code to avoid displaying anything if the 49106 // user's code isn't likely to be using p5's global mode. (Note that 49107 // setup/draw are more likely to be defined due to JS function hoisting.) 49108 // 49109 //if (!('setup' in window || 'draw' in window)) { 49110 // return; 49111 //} 49112 49113 misusedAtTopLevelCode.some(function(symbol) { 49114 // Note that while just checking for the occurrence of the 49115 // symbol name in the error message could result in false positives, 49116 // a more rigorous test is difficult because different browsers 49117 // log different messages, and the format of those messages may 49118 // change over time. 49119 // 49120 // For example, if the user uses 'PI' in their code, it may result 49121 // in any one of the following messages: 49122 // 49123 // * 'PI' is undefined (Microsoft Edge) 49124 // * ReferenceError: PI is undefined (Firefox) 49125 // * Uncaught ReferenceError: PI is not defined (Chrome) 49126 49127 if ( 49128 e.message && 49129 e.message.match('\\W?'.concat(symbol.name, '\\W')) !== null 49130 ) { 49131 var symbolName = 49132 symbol.type === 'function' ? ''.concat(symbol.name, '()') : symbol.name; 49133 if (typeof IS_MINIFIED !== 'undefined') { 49134 log( 49135 "Did you just try to use p5.js's " 49136 .concat(symbolName, ' ') 49137 .concat( 49138 symbol.type, 49139 "? If so, you may want to move it into your sketch's setup() function.\n\nFor more details, see: " 49140 ) 49141 .concat(FAQ_URL) 49142 ); 49143 } else { 49144 log( 49145 (0, _internationalization.translator)('fes.misusedTopLevel', { 49146 symbolName: symbolName, 49147 symbolType: symbol.type, 49148 link: FAQ_URL 49149 }) 49150 ); 49151 } 49152 return true; 49153 } 49154 }); 49155 }; 49156 49157 // Exposing this primarily for unit testing. 49158 _main.default.prototype._helpForMisusedAtTopLevelCode = helpForMisusedAtTopLevelCode;
49159 49160 if (document.readyState !== 'complete') { 49161 window.addEventListener('error', helpForMisusedAtTopLevelCode, false); 49162 49163 // Our job is only to catch ReferenceErrors that are thrown when 49164 // global (non-instance mode) p5 APIs are used at the top-level 49165 // scope of a file, so we'll unbind our error listener now to make 49166 // sure we don't log false positives later. 49167 window.addEventListener('load', function() { 49168 window.removeEventListener('error', helpForMisusedAtTopLevelCode, false); 49169 }); 49170 } 49171 var _default = _main.default; 49172 exports.default = _default; 49173 }, 49174 { 49175 '../constants': 48, 49176 '../internationalization': 57, 49177 '../main': 59, 49178 './browser_errors': 50 49179 } 49180 ], 49181 52: [ 49182 function(_dereq_, module, exports) { 49183 'use strict'; 49184 Object.defineProperty(exports, '__esModule', { value: true }); 49185 exports.default = void 0; 49186 49187 var _main = _interopRequireDefault(_dereq_('../main')); 49188 var _internationalization = _dereq_('../internationalization'); 49189 function _interopRequireDefault(obj) { 49190 return obj && obj.__esModule ? obj : { default: obj }; 49191 } 49192 /** 49193 * @for p5 49194 * @requires core 49195 * 49196 * This file contains the part of the FES responsible for dealing with 49197 * file load errors 49198 */ if (typeof IS_MINIFIED !== 'undefined') { 49199 _main.default._friendlyFileLoadError = function() {}; 49200 } else { 49201 // mapping used by `_friendlyFileLoadError` 49202 var fileLoadErrorCases = function fileLoadErrorCases(num, filePath) { 49203 var suggestion = (0, _internationalization.translator)( 49204 'fes.fileLoadError.suggestion', 49205 { 49206 filePath: filePath, 49207 link: 'https://github.com/processing/p5.js/wiki/Local-server' 49208 } 49209 ); 49210 49211 switch (num) { 49212 case 0: 49213 return { 49214 message: (0, _internationalization.translator)( 49215 'fes.fileLoadError.image', 49216 { 49217 suggestion: suggestion 49218 } 49219 ), 49220 49221 method: 'loadImage' 49222 }; 49223 49224 case 1: 49225 return { 49226 message: (0, _internationalization.translator)( 49227 'fes.fileLoadError.xml', 49228 { 49229 suggestion: suggestion 49230 } 49231 ), 49232 49233 method: 'loadXML' 49234 }; 49235 49236 case 2: 49237 return { 49238 message: (0, _internationalization.translator)( 49239 'fes.fileLoadError.table', 49240 { 49241 suggestion: suggestion 49242 } 49243 ), 49244 49245 method: 'loadTable' 49246 }; 49247 49248 case 3: 49249 return { 49250 message: (0, _internationalization.translator)( 49251 'fes.fileLoadError.strings', 49252 { 49253 suggestion: suggestion 49254 } 49255 ), 49256 49257 method: 'loadStrings' 49258 }; 49259 49260 case 4: 49261 return { 49262 message: (0, _internationalization.translator)( 49263 'fes.fileLoadError.font', 49264 { 49265 suggestion: suggestion 49266 } 49267 ), 49268 49269 method: 'loadFont' 49270 }; 49271 49272 case 5: 49273 return { 49274 message: (0, _internationalization.translator)( 49275 'fes.fileLoadError.json', 49276 { 49277 suggestion: suggestion 49278 } 49279 ), 49280 49281 method: 'loadJSON' 49282 }; 49283 49284 case 6: 49285 return { 49286 message: (0, _internationalization.translator)( 49287 'fes.fileLoadError.bytes', 49288 { 49289 suggestion: suggestion 49290 } 49291 ), 49292 49293 method: 'loadBytes' 49294 }; 49295 49296 case 7: 49297 return { 49298 message: (0, _internationalization.translator)( 49299 'fes.fileLoadError.large' 49300 ), 49301 method: 'loadX' 49302 }; 49303 49304 case 8: 49305 return { 49306 message: (0, _internationalization.translator)('fes.fileLoadError.gif'), 49307 method: 'loadImage' 49308 }; 49309 } 49310 }; 49311 49312 /**
49313 * This is called internally if there is a error during file loading. 49314 * 49315 * @method _friendlyFileLoadError 49316 * @private 49317 * @param {Number} errorType 49318 * @param {String} filePath 49319 */ 49320 _main.default._friendlyFileLoadError = function(errorType, filePath) { 49321 var _fileLoadErrorCases = fileLoadErrorCases(errorType, filePath), 49322 message = _fileLoadErrorCases.message, 49323 method = _fileLoadErrorCases.method; 49324 _main.default._friendlyError(message, method, 3); 49325 }; 49326 } 49327 var _default = _main.default; 49328 exports.default = _default; 49329 }, 49330 { '../internationalization': 57, '../main': 59 } 49331 ], 49332 53: [ 49333 function(_dereq_, module, exports) { 49334 'use strict'; 49335 Object.defineProperty(exports, '__esModule', { value: true }); 49336 exports.default = void 0; 49337 49338 var _main = _interopRequireDefault(_dereq_('../main')); 49339 function _interopRequireDefault(obj) { 49340 return obj && obj.__esModule ? obj : { default: obj }; 49341 } /** // Borrow from stacktracejs https://github.com/stacktracejs/stacktrace.js with 49342 * @for p5 49343 * @requires core 49344 */ 49345 // minor modifications. The license for the same and the code is included below 49346 // Copyright (c) 2017 Eric Wendelin and other contributors 49347 // Permission is hereby granted, free of charge, to any person obtaining a copy of 49348 // this software and associated documentation files (the "Software"), to deal in 49349 // the Software without restriction, including without limitation the rights to 49350 // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 49351 // of the Software, and to permit persons to whom the Software is furnished to do 49352 // so, subject to the following conditions: 49353 // The above copyright notice and this permission notice shall be included in all 49354 // copies or substantial portions of the Software. 49355 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 49356 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 49357 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 49358 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 49359 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 49360 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 49361 // SOFTWARE. 49362 function ErrorStackParser() { 49363 'use strict'; 49364 49365 var FIREFOX_SAFARI_STACK_REGEXP = /(^|@)\S+:\d+/; 49366 var CHROME_IE_STACK_REGEXP = /^\s*at .*(\S+:\d+|\(native\))/m; 49367 var SAFARI_NATIVE_CODE_REGEXP = /^(eval@)?(\[native code])?$/; 49368 49369 return { 49370 /** 49371 * Given an Error object, extract the most information from it. 49372 * @private 49373 * @param {Error} error object 49374 * @return {Array} of stack frames 49375 */ 49376 parse: function ErrorStackParser$$parse(error) { 49377 if ( 49378 typeof error.stacktrace !== 'undefined' || 49379 typeof error['opera#sourceloc'] !== 'undefined' 49380 ) { 49381 return this.parseOpera(error); 49382 } else if (error.stack && error.stack.match(CHROME_IE_STACK_REGEXP)) { 49383 return this.parseV8OrIE(error); 49384 } else if (error.stack) { 49385 return this.parseFFOrSafari(error); 49386 } else { 49387 // throw new Error('Cannot parse given Error object'); 49388 } 49389 }, 49390 49391 // Separate line and column numbers from a string of the form: (URI:Line:Column) 49392 extractLocation: function ErrorStackParser$$extractLocation(urlLike) { 49393 // Fail-fast but return locations like "(native)" 49394 if (urlLike.indexOf(':') === -1) { 49395 return [urlLike]; 49396 } 49397 49398 var regExp = /(.+?)(?::(\d+))?(?::(\d+))?$/; 49399 var parts = regExp.exec(urlLike.replace(/[()]/g, '')); 49400 return [parts[1], parts[2] || undefined, parts[3] || undefined]; 49401 }, 49402 49403 parseV8OrIE: function ErrorStackParser$$parseV8OrIE(error) { 49404 var filtered = error.stack.split('\n').filter(function(line) { 49405 return !!line.match(CHROME_IE_STACK_REGEXP); 49406 }, this); 49407 49408 return filtered.map(function(line) { 49409 if (line.indexOf('(eval ') > -1) { 49410 // Throw away eval information until we implement stacktrace.js/stackframe#8 49411 line = line 49412 .replace(/eval code/g, 'eval') 49413 .replace(/(\(eval at [^()]*)|(\),.*$)/g, ''); 49414 } 49415 var sanitizedLine = line.replace(/^\s+/, '').replace(/\(eval code/g, '('); 49416 49417 // capture and preseve the parenthesized location "(/foo/my bar.js:12:87)" in 49418 // case it has spaces in it, as the string is split on \s+ later on 49419 var location = sanitizedLine.match(/ (\((.+):(\d+):(\d+)\)$)/); 49420 49421 // remove the parenthesized location from the line, if it was matched 49422 sanitizedLine = location 49423 ? sanitizedLine.replace(location[0], '') 49424 : sanitizedLine; 49425 49426 var tokens = sanitizedLine.split(/\s+/).slice(1); 49427 // if a location was matched, pass it to extractLocation() otherwise pop the last token 49428 var locationParts = this.extractLocation( 49429 location ? location[1] : tokens.pop() 49430 ); 49431 49432 var functionName = tokens.join(' ') || undefined; 49433 var fileName = 49434 ['eval', '<anonymous>'].indexOf(locationParts[0]) > -1 49435 ? undefined 49436 : locationParts[0]; 49437 49438 return { 49439 functionName: functionName, 49440 fileName: fileName, 49441 lineNumber: locationParts[1], 49442 columnNumber: locationParts[2], 49443 source: line 49444 }; 49445 }, this); 49446 }, 49447 49448 parseFFOrSafari: function ErrorStackParser$$parseFFOrSafari(error) { 49449 var filtered = error.stack.split('\n').filter(function(line) { 49450 return !line.match(SAFARI_NATIVE_CODE_REGEXP); 49451 }, this); 49452 49453 return filtered.map(function(line) { 49454 // Throw away eval information until we implement stacktrace.js/stackframe#8 49455 if (line.indexOf(' > eval') > -1) { 49456 line = line.replace( 49457 / line (\d+)(?: > eval line \d+)* > eval:\d+:\d+/g, 49458 ':$1' 49459 ); 49460 } 49461 49462 if (line.indexOf('@') === -1 && line.indexOf(':') === -1) { 49463 // Safari eval frames only have function names and nothing else 49464 return { 49465 functionName: line 49466 }; 49467 } else { 49468 var functionNameRegex = /((.*".+"[^@]*)?[^@]*)(?:@)/; 49469 var matches = line.match(functionNameRegex); 49470 var functionName = matches && matches[1] ? matches[1] : undefined; 49471 var locationParts = this.extractLocation( 49472 line.replace(functionNameRegex, '') 49473 ); 49474 49475 return { 49476 functionName: functionName, 49477 fileName: locationParts[0], 49478 lineNumber: locationParts[1], 49479 columnNumber: locationParts[2], 49480 source: line 49481 }; 49482 } 49483 }, this); 49484 }, 49485 49486 parseOpera: function ErrorStackParser$$parseOpera(e) { 49487 if ( 49488 !e.stacktrace || 49489 (e.message.indexOf('\n') > -1 && 49490 e.message.split('\n').length > e.stacktrace.split('\n').length) 49491 ) { 49492 return this.parseOpera9(e); 49493 } else if (!e.stack) { 49494 return this.parseOpera10(e); 49495 } else { 49496 return this.parseOpera11(e); 49497 } 49498 }, 49499 49500 parseOpera9: function ErrorStackParser$$parseOpera9(e) { 49501 var lineRE = /Line (\d+).*script (?:in )?(\S+)/i; 49502 var lines = e.message.split('\n'); 49503 var result = []; 49504 49505 for (var i = 2, len = lines.length; i < len; i += 2) { 49506 var match = lineRE.exec(lines[i]); 49507 if (match) { 49508 result.push({ 49509 fileName: match[2], 49510 lineNumber: match[1], 49511 source: lines[i] 49512 }); 49513 } 49514 } 49515 49516 return result; 49517 }, 49518 49519 parseOpera10: function ErrorStackParser$$parseOpera10(e) { 49520 var lineRE = /Line (\d+).*script (?:in )?(\S+)(?:: In function (\S+))?$/i; 49521 var lines = e.stacktrace.split('\n'); 49522 var result = []; 49523 49524 for (var i = 0, len = lines.length; i < len; i += 2) { 49525 var match = lineRE.exec(lines[i]); 49526 if (match) { 49527 result.push({ 49528 functionName: match[3] || undefined, 49529 fileName: match[2], 49530 lineNumber: match[1], 49531 source: lines[i] 49532 }); 49533 } 49534 } 49535 49536 return result; 49537 }, 49538 49539 // Opera 10.65+ Error.stack very similar to FF/Safari 49540 parseOpera11: function ErrorStackParser$$parseOpera11(error) { 49541 var filtered = error.stack.split('\n').filter(function(line) { 49542 return ( 49543 !!line.match(FIREFOX_SAFARI_STACK_REGEXP) && 49544 !line.match(/^Error created at/) 49545 ); 49546 }, this); 49547 49548 return filtered.map(function(line) { 49549 var tokens = line.split('@'); 49550 var locationParts = this.extractLocation(tokens.pop()); 49551 var functionCall = tokens.shift() || ''; 49552 var functionName = 49553 functionCall 49554 .replace(/<anonymous function(: (\w+))?>/, '$2') 49555 .replace(/\([^)]*\)/g, '') || undefined; 49556 var argsRaw; 49557 if (functionCall.match(/\(([^)]*)\)/)) { 49558 argsRaw = functionCall.replace(/^[^(]+\(([^)]*)\)$/, '$1'); 49559 } 49560 var args = 49561 argsRaw === undefined || argsRaw === '[arguments not available]' 49562 ? undefined 49563 : argsRaw.split(','); 49564 49565 return { 49566 functionName: functionName, 49567 args: args, 49568 fileName: locationParts[0], 49569 lineNumber: locationParts[1], 49570 columnNumber: locationParts[2], 49571 source: line 49572 }; 49573 }, this); 49574 } 49575 }; 49576 } 49577 49578 // End borrow 49579 49580 // wrapper exposing ErrorStackParser 49581 _main.default._getErrorStackParser = function getErrorStackParser() { 49582 return new ErrorStackParser(); 49583 }; 49584 var _default = _main.default; 49585 exports.default = _default; 49586 }, 49587 { '../main': 59 } 49588 ], 49589 54: [
vendor: 4,501 bytes, lines 49590-49696
49590 function(_dereq_, module, exports) { 49591 'use strict'; 49592 Object.defineProperty(exports, '__esModule', { value: true }); 49593 exports.default = void 0; 49594 49595 var _main = _interopRequireDefault(_dereq_('../main')); 49596 var constants = _interopRequireWildcard(_dereq_('../constants')); 49597 var _internationalization = _dereq_('../internationalization'); 49598 function _getRequireWildcardCache() { 49599 if (typeof WeakMap !== 'function') return null; 49600 var cache = new WeakMap(); 49601 _getRequireWildcardCache = function _getRequireWildcardCache() { 49602 return cache; 49603 }; 49604 return cache; 49605 } 49606 function _interopRequireWildcard(obj) { 49607 if (obj && obj.__esModule) { 49608 return obj; 49609 } 49610 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) { 49611 return { default: obj }; 49612 } 49613 var cache = _getRequireWildcardCache(); 49614 if (cache && cache.has(obj)) { 49615 return cache.get(obj); 49616 } 49617 var newObj = {}; 49618 var hasPropertyDescriptor = 49619 Object.defineProperty && Object.getOwnPropertyDescriptor; 49620 for (var key in obj) { 49621 if (Object.prototype.hasOwnProperty.call(obj, key)) { 49622 var desc = hasPropertyDescriptor 49623 ? Object.getOwnPropertyDescriptor(obj, key) 49624 : null; 49625 if (desc && (desc.get || desc.set)) { 49626 Object.defineProperty(newObj, key, desc); 49627 } else { 49628 newObj[key] = obj[key]; 49629 } 49630 } 49631 } 49632 newObj.default = obj; 49633 if (cache) { 49634 cache.set(obj, newObj); 49635 } 49636 return newObj; 49637 } 49638 function _interopRequireDefault(obj) { 49639 return obj && obj.__esModule ? obj : { default: obj }; 49640 } 49641 function _classCallCheck(instance, Constructor) { 49642 if (!(instance instanceof Constructor)) { 49643 throw new TypeError('Cannot call a class as a function'); 49644 } 49645 } 49646 function _possibleConstructorReturn(self, call) { 49647 if (call && (_typeof(call) === 'object' || typeof call === 'function')) { 49648 return call; 49649 } 49650 return _assertThisInitialized(self); 49651 } 49652 function _assertThisInitialized(self) { 49653 if (self === void 0) { 49654 throw new ReferenceError( 49655 "this hasn't been initialised - super() hasn't been called" 49656 ); 49657 } 49658 return self; 49659 } 49660 function _inherits(subClass, superClass) { 49661 if (typeof superClass !== 'function' && superClass !== null) { 49662 throw new TypeError('Super expression must either be null or a function'); 49663 } 49664 subClass.prototype = Object.create(superClass && superClass.prototype, { 49665 constructor: { value: subClass, writable: true, configurable: true } 49666 }); 49667 if (superClass) _setPrototypeOf(subClass, superClass); 49668 } 49669 function _wrapNativeSuper(Class) { 49670 var _cache = typeof Map === 'function' ? new Map() : undefined; 49671 _wrapNativeSuper = function _wrapNativeSuper(Class) { 49672 if (Class === null || !_isNativeFunction(Class)) return Class; 49673 if (typeof Class !== 'function') { 49674 throw new TypeError('Super expression must either be null or a function'); 49675 } 49676 if (typeof _cache !== 'undefined') { 49677 if (_cache.has(Class)) return _cache.get(Class); 49678 _cache.set(Class, Wrapper); 49679 } 49680 function Wrapper() { 49681 return _construct(Class, arguments, _getPrototypeOf(this).constructor); 49682 } 49683 Wrapper.prototype = Object.create(Class.prototype, { 49684 constructor: { 49685 value: Wrapper, 49686 enumerable: false, 49687 writable: true, 49688 configurable: true 49689 } 49690 }); 49691 return _setPrototypeOf(Wrapper, Class); 49692 }; 49693 return _wrapNativeSuper(Class); 49694 } 49695 function isNativeReflectConstruct() { 49696 if (typeof Reflect === 'undefined' || !Reflect.construct) return false;
49697 if (Reflect.construct.sham) return false; 49698 if (typeof Proxy === 'function') return true; 49699 try { 49700 Date.prototype.toString.call(Reflect.construct(Date, [], function() {})); 49701 return true; 49702 } catch (e) { 49703 return false; 49704 } 49705 } 49706 function _construct(Parent, args, Class) { 49707 if (isNativeReflectConstruct()) { 49708 _construct = Reflect.construct; 49709 } else { 49710 _construct = function _construct(Parent, args, Class) { 49711 var a = [null]; 49712 a.push.apply(a, args); 49713 var Constructor = Function.bind.apply(Parent, a); 49714 var instance = new Constructor(); 49715 if (Class) _setPrototypeOf(instance, Class.prototype); 49716 return instance; 49717 }; 49718 } 49719 return _construct.apply(null, arguments); 49720 } 49721 function _isNativeFunction(fn) { 49722 return Function.toString.call(fn).indexOf('[native code]') !== -1; 49723 } 49724 function _setPrototypeOf(o, p) { 49725 _setPrototypeOf = 49726 Object.setPrototypeOf || 49727 function _setPrototypeOf(o, p) { 49728 o.__proto__ = p; 49729 return o; 49730 }; 49731 return _setPrototypeOf(o, p); 49732 } 49733 function _getPrototypeOf(o) { 49734 _getPrototypeOf = Object.setPrototypeOf 49735 ? Object.getPrototypeOf 49736 : function _getPrototypeOf(o) { 49737 return o.__proto__ || Object.getPrototypeOf(o); 49738 }; 49739 return _getPrototypeOf(o); 49740 } 49741 function _typeof(obj) { 49742 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') { 49743 _typeof = function _typeof(obj) { 49744 return typeof obj; 49745 }; 49746 } else { 49747 _typeof = function _typeof(obj) { 49748 return obj && 49749 typeof Symbol === 'function' && 49750 obj.constructor === Symbol && 49751 obj !== Symbol.prototype 49752 ? 'symbol' 49753 : typeof obj; 49754 }; 49755 } 49756 return _typeof(obj); 49757 } 49758 49759 if (typeof IS_MINIFIED !== 'undefined') { 49760 _main.default._validateParameters = _main.default._clearValidateParamsCache = function() {}; 49761 } else { 49762 // for parameter validation 49763 var dataDoc = _dereq_('../../../docs/parameterData.json'); 49764 var arrDoc = JSON.parse(JSON.stringify(dataDoc)); 49765 49766 var docCache = {}; 49767 var builtinTypes = new Set([ 49768 'null', 49769 'number', 49770 'string', 49771 'boolean', 49772 'constant', 49773 'function', 49774 'any', 49775 'integer' 49776 ]); 49777 49778 var basicTypes = { 49779 number: true, 49780 boolean: true, 49781 string: true, 49782 function: true, 49783 undefined: true 49784 }; 49785 49786 // reverse map of all constants 49787 var constantsReverseMap = {}; 49788 for (var key in constants) { 49789 constantsReverseMap[constants[key]] = key; 49790 } 49791 49792 // mapping names of p5 types to their constructor function 49793 // p5Constructors: 49794 // - Color: f() 49795 // - Graphics: f() 49796 // - Vector: f() 49797 // and so on 49798 var p5Constructors = {}; 49799 49800 // For speedup over many runs. funcSpecificConstructors[func] only has the 49801 // constructors for types which were seen earlier as args of "func" 49802 var funcSpecificConstructors = {}; 49803 window.addEventListener('load', function() { 49804 // Make a list of all p5 classes to be used for argument validation 49805 // This must be done only when everything has loaded otherwise we get 49806 // an empty array 49807 for ( 49808 var _i = 0, _Object$keys = Object.keys(_main.default); 49809 _i < _Object$keys.length; 49810 _i++ 49811 ) { 49812 var _key = _Object$keys[_i]; 49813 // Get a list of all constructors in p5. They are functions whose names 49814 // start with a capital letter 49815 if ( 49816 typeof _main.default[_key] === 'function' && 49817 _key[0] !== _key[0].toLowerCase() 49818 ) { 49819 p5Constructors[_key] = _main.default[_key]; 49820 } 49821 } 49822 }); 49823 49824 var argumentTree = {}; 49825 // The following two functions are responsible for querying and inserting 49826 // into the argument tree. It stores the types of arguments that each 49827 // function has seen so far. It is used to query if a sequence of 49828 // arguments seen in validate parameters was seen before. 49829 // Lets consider that the following segment of code runs repeatedly, perhaps 49830 // in a loop or in draw() 49831 // color(10, 10, 10); 49832 // color(10, 10); 49833 // color('r', 'g', 'b'); 49834 // After the first of run the code segment, the argument tree looks like 49835 // - color 49836 // - number 49837 // - number 49838 // - number 49839 // - seen: true 49840 // - seen: true 49841 // - string 49842 // - string 49843 // - string 49844 // - seen: true 49845 // seen: true signifies that this argument was also seen as the last 49846 // argument in a call. Now in the second run of the sketch, it would traverse 49847 // the existing tree and see seen: true, i.e this sequence was seen 49848 // before and so scoring can be skipped. This also prevents logging multiple 49849 // validation messages for the same thing. 49850 49851 // These two functions would be called repeatedly over and over again, 49852 // so they need to be as optimized for performance as possible 49853 49854 var addType = function addType(value, obj, func) { 49855 var type = _typeof(value); 49856 if (basicTypes[type]) { 49857 if (constantsReverseMap[value]) { 49858 // check if the value is a p5 constant and if it is, we would want the 49859 // value itself to be stored in the tree instead of the type 49860 obj = obj[value] || (obj[value] = {}); 49861 } else { 49862 obj = obj[type] || (obj[type] = {}); 49863 } 49864 } else if (value === null) { 49865 // typeof null -> "object". don't want that 49866 obj = obj['null'] || (obj['null'] = {}); 49867 } else { 49868 // objects which are instances of p5 classes have nameless constructors. 49869 // native objects have a constructor named "Object". This check 49870 // differentiates between the two so that we dont waste time finding the 49871 // p5 class if we just have a native object 49872 if (value.constructor && value.constructor.name) {
49873 obj = obj[value.constructor.name] || (obj[value.constructor.name] = {}); 49874 return obj; 49875 } 49876 49877 // constructors for types defined in p5 do not have a name property. 49878 // e.constructor.name gives "". Code in this segment is a workaround for it 49879 49880 // p5C will only have the name: constructor mapping for types 49881 // which were already seen as args of "func" 49882 var p5C = funcSpecificConstructors[func]; 49883 // p5C would contain much fewer items than p5Constructors. if we find our 49884 // answer in p5C, we don't have to scan through p5Constructors 49885 49886 if (p5C === undefined) { 49887 // if there isn't an entry yet for func 49888 // make an entry of empty object 49889 p5C = funcSpecificConstructors[func] = {}; 49890 } 49891 49892 for (var _key2 in p5C) { 49893 // search on the constructors we have already seen (smaller search space) 49894 if (value instanceof p5C[_key2]) {
49895 obj = obj[_key2] || (obj[_key2] = {}); 49896 return obj; 49897 } 49898 } 49899 49900 for (var _key3 in p5Constructors) { 49901 // if the above search didn't work, search on all p5 constructors 49902 if (value instanceof p5Constructors[_key3]) { 49903 obj = obj[_key3] || (obj[_key3] = {}); 49904 // if found, add to known constructors for this function 49905 p5C[_key3] = p5Constructors[_key3]; 49906 return obj; 49907 } 49908 } 49909 // nothing worked, put the type as is 49910 obj = obj[type] || (obj[type] = {}); 49911 } 49912 49913 return obj; 49914 }; 49915 var buildArgTypeCache = function buildArgTypeCache(func, arr) { 49916 // get the if an argument tree for current function already exists 49917 var obj = argumentTree[func]; 49918 if (obj === undefined) { 49919 // if it doesn't, create an empty tree 49920 obj = argumentTree[func] = {}; 49921 } 49922 49923 for (var i = 0, len = arr.length; i < len; ++i) { 49924 var value = arr[i]; 49925 if (value instanceof Array) { 49926 // an array is passed as an argument, expand it and get the type of 49927 // each of its element. We distinguish the start of an array with 'as' 49928 // or arraystart. This would help distinguish between the arguments 49929 // (number, number, number) and (number, [number, number]) 49930 obj = obj['as'] || (obj['as'] = {}); 49931 for (var j = 0, lenA = value.length; j < lenA; ++j) { 49932 obj = addType(value[j], obj, func); 49933 } 49934 } else { 49935 obj = addType(value, obj, func); 49936 } 49937 } 49938 return obj; 49939 }; 49940 49941 // validateParameters() helper functions: 49942 // lookupParamDoc() for querying data.json 49943 var lookupParamDoc = function lookupParamDoc(func) { 49944 // look for the docs in the `data.json` datastructure 49945 49946 var ichDot = func.lastIndexOf('.'); 49947 var funcName = func.substr(ichDot + 1); 49948 var funcClass = func.substr(0, ichDot) || 'p5'; 49949 49950 var classitems = arrDoc; 49951 var queryResult = classitems[funcClass][funcName]; 49952 49953 // different JSON structure for funct with multi-format 49954 var overloads = []; 49955 if (queryResult.hasOwnProperty('overloads')) { 49956 // add all the overloads 49957 for (var i = 0; i < queryResult.overloads.length; i++) { 49958 overloads.push({ formats: queryResult.overloads[i].params }); 49959 } 49960 } else { 49961 // no overloads, just add the main method definition 49962 overloads.push({ formats: queryResult.params || [] }); 49963 } 49964 49965 // parse the parameter types for each overload 49966 var mapConstants = {}; 49967 var maxParams = 0; 49968 overloads.forEach(function(overload) { 49969 var formats = overload.formats; 49970 49971 // keep a record of the maximum number of arguments 49972 // this method requires. 49973 if (maxParams < formats.length) { 49974 maxParams = formats.length; 49975 } 49976 49977 // calculate the minimum number of arguments 49978 // this overload requires. 49979 var minParams = formats.length; 49980 while (minParams > 0 && formats[minParams - 1].optional) { 49981 minParams--; 49982 } 49983 overload.minParams = minParams; 49984 49985 // loop through each parameter position, and parse its types 49986 formats.forEach(function(format) { 49987 // split this parameter's types 49988 format.types = format.type.split('|').map(function ct(type) { 49989 // array 49990 if (type.substr(type.length - 2, 2) === '[]') { 49991 return { 49992 name: type, 49993 array: ct(type.substr(0, type.length - 2)) 49994 }; 49995 } 49996 49997 var lowerType = type.toLowerCase(); 49998 49999 // contant 50000 if (lowerType === 'constant') { 50001 var constant; 50002 if (mapConstants.hasOwnProperty(format.name)) { 50003 constant = mapConstants[format.name]; 50004 } else { 50005 // parse possible constant values from description 50006 var myRe = /either\s+(?:[A-Z0-9_]+\s*,?\s*(?:or)?\s*)+/g; 50007 var values = {}; 50008 var names = []; 50009 50010 constant = mapConstants[format.name] = { 50011 values: values, 50012 names: names 50013 }; 50014 50015 var myArray = myRe.exec(format.description); 50016 if (func === 'endShape' && format.name === 'mode') { 50017 values[constants.CLOSE] = true; 50018 names.push('CLOSE'); 50019 } else { 50020 var match = myArray[0]; 50021 var reConst = /[A-Z0-9_]+/g; 50022 var matchConst; 50023 while ((matchConst = reConst.exec(match)) !== null) { 50024 var name = matchConst[0]; 50025 if (constants.hasOwnProperty(name)) { 50026 values[constants[name]] = true; 50027 names.push(name); 50028 } 50029 } 50030 } 50031 } 50032 return { 50033 name: type, 50034 builtin: lowerType, 50035 names: constant.names, 50036 values: constant.values 50037 }; 50038 } 50039 50040 // function 50041 if (lowerType.substr(0, 'function'.length) === 'function') { 50042 lowerType = 'function'; 50043 } 50044 // builtin 50045 if (builtinTypes.has(lowerType)) { 50046 return { name: type, builtin: lowerType }; 50047 } 50048 50049 // find type's prototype 50050 var t = window; 50051 var typeParts = type.split('.'); 50052 50053 // special-case 'p5' since it may be non-global 50054 if (typeParts[0] === 'p5') { 50055 t = _main.default; 50056 typeParts.shift(); 50057 } 50058
50059 typeParts.forEach(function(p) { 50060 t = t && t[p]; 50061 }); 50062 if (t) { 50063 return { name: type, prototype: t }; 50064 } 50065 50066 return { name: type, type: lowerType }; 50067 }); 50068 }); 50069 }); 50070 return { 50071 overloads: overloads, 50072 maxParams: maxParams 50073 }; 50074 }; 50075 50076 var isNumber = function isNumber(param) { 50077 switch (_typeof(param)) { 50078 case 'number': 50079 return true; 50080 case 'string': 50081 return !isNaN(param); 50082 default: 50083 return false; 50084 } 50085 }; 50086 50087 var testParamType = function testParamType(param, type) { 50088 var isArray = param instanceof Array; 50089 var matches = true; 50090 if (type.array && isArray) { 50091 for (var i = 0; i < param.length; i++) { 50092 var error = testParamType(param[i], type.array); 50093 if (error) return error / 2; // half error for elements 50094 } 50095 } else if (type.prototype) { 50096 matches = param instanceof type.prototype; 50097 } else if (type.builtin) { 50098 switch (type.builtin) { 50099 case 'number': 50100 matches = isNumber(param); 50101 break; 50102 case 'integer': 50103 matches = isNumber(param) && Number(param) === Math.floor(param); 50104 break; 50105 case 'boolean': 50106 case 'any': 50107 matches = true; 50108 break; 50109 case 'array': 50110 matches = isArray; 50111 break; 50112 case 'string': 50113 matches = /*typeof param === 'number' ||*/ typeof param === 'string'; 50114 break; 50115 case 'constant': 50116 matches = type.values.hasOwnProperty(param); 50117 break; 50118 case 'function': 50119 matches = param instanceof Function; 50120 break; 50121 case 'null': 50122 matches = param === null; 50123 break; 50124 } 50125 } else { 50126 matches = _typeof(param) === type.t; 50127 } 50128 return matches ? 0 : 1; 50129 }; 50130 50131 // testType() for non-object type parameter validation 50132 var testParamTypes = function testParamTypes(param, types) { 50133 var minScore = 9999; 50134 for (var i = 0; minScore > 0 && i < types.length; i++) { 50135 var score = testParamType(param, types[i]); 50136 if (minScore > score) minScore = score; 50137 } 50138 return minScore; 50139 }; 50140 50141 // generate a score (higher is worse) for applying these args to 50142 // this overload. 50143 var scoreOverload = function scoreOverload(args, argCount, overload, minScore) { 50144 var score = 0; 50145 var formats = overload.formats; 50146 var minParams = overload.minParams; 50147 50148 // check for too few/many args 50149 // the score is double number of extra/missing args 50150 if (argCount < minParams) { 50151 score = (minParams - argCount) * 2; 50152 } else if (argCount > formats.length) { 50153 score = (argCount - formats.length) * 2; 50154 } 50155 50156 // loop through the formats, adding up the error score for each arg. 50157 // quit early if the score gets higher than the previous best overload. 50158 for (var p = 0; score <= minScore && p < formats.length; p++) { 50159 var arg = args[p]; 50160 var format = formats[p]; 50161 // '== null' checks for 'null' and typeof 'undefined' 50162 if (arg == null) { 50163 // handle undefined args 50164 if (!format.optional || p < minParams || p < argCount) { 50165 score += 1; 50166 } 50167 } else { 50168 score += testParamTypes(arg, format.types); 50169 } 50170 } 50171 return score; 50172 }; 50173 50174 // gets a list of errors for this overload 50175 var getOverloadErrors = function getOverloadErrors(args, argCount, overload) { 50176 var formats = overload.formats; 50177 var minParams = overload.minParams; 50178 50179 // check for too few/many args 50180 if (argCount < minParams) { 50181 return [ 50182 { 50183 type: 'TOO_FEW_ARGUMENTS', 50184 argCount: argCount, 50185 minParams: minParams 50186 } 50187 ]; 50188 } else if (argCount > formats.length) { 50189 return [ 50190 { 50191 type: 'TOO_MANY_ARGUMENTS', 50192 argCount: argCount, 50193 maxParams: formats.length 50194 } 50195 ]; 50196 } 50197 50198 var errorArray = []; 50199 for (var p = 0; p < formats.length; p++) { 50200 var arg = args[p]; 50201 var format = formats[p]; 50202 // '== null' checks for 'null' and typeof 'undefined' 50203 if (arg == null) { 50204 // handle undefined args 50205 if (!format.optional || p < minParams || p < argCount) { 50206 errorArray.push({ 50207 type: 'EMPTY_VAR', 50208 position: p, 50209 format: format 50210 }); 50211 } 50212 } else if (testParamTypes(arg, format.types) > 0) { 50213 errorArray.push({ 50214 type: 'WRONG_TYPE', 50215 position: p, 50216 format: format, 50217 arg: arg 50218 }); 50219 } 50220 } 50221 50222 return errorArray; 50223 }; 50224 50225 // a custom error type, used by the mocha 50226 // tests when expecting validation errors 50227 _main.default.ValidationError = (function(name) { 50228 var err = /*#__PURE__*/ (function(_Error) { 50229 _inherits(err, _Error); 50230 function err(message, func, type) { 50231 var _this; 50232 _classCallCheck(this, err); 50233 _this = _possibleConstructorReturn(this, _getPrototypeOf(err).call(this)); 50234 _this.message = message; 50235 _this.func = func; 50236 _this.type = type;
50237 if ('captureStackTrace' in Error) 50238 Error.captureStackTrace(_assertThisInitialized(_this), err); 50239 else _this.stack = new Error().stack; 50240 return _this; 50241 } 50242 return err; 50243 })(_wrapNativeSuper(Error)); 50244 50245 err.prototype.name = name; 50246 return err; 50247 })('ValidationError'); 50248 50249 // function for generating console.log() msg 50250 _main.default._friendlyParamError = function(errorObj, func) { 50251 var message; 50252 var translationObj; 50253 50254 function formatType() { 50255 var format = errorObj.format; 50256 return format.types 50257 .map(function(type) { 50258 return type.names ? type.names.join('|') : type.name; 50259 }) 50260 .join('|'); 50261 } 50262 50263 switch (errorObj.type) { 50264 case 'EMPTY_VAR': { 50265 translationObj = { 50266 func: func, 50267 formatType: formatType(), 50268 // It needs to be this way for i18next-extract to work. The comment 50269 // specifies the values that the context can take so that it can 50270 // statically prepare the translation files with them. 50271 /* i18next-extract-mark-context-next-line ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"] */ 50272 position: (0, _internationalization.translator)('fes.positions.p', { 50273 context: (errorObj.position + 1).toString(), 50274 defaultValue: (errorObj.position + 1).toString() 50275 }), 50276 50277 link: '[https://p5js.org/examples/data-variable-scope.html]' 50278 }; 50279 50280 break; 50281 } 50282 case 'WRONG_TYPE': { 50283 var arg = errorObj.arg; 50284 var argType = 50285 arg instanceof Array 50286 ? 'array' 50287 : arg === null ? 'null' : arg.name || _typeof(arg); 50288 50289 translationObj = { 50290 func: func, 50291 formatType: formatType(), 50292 argType: argType, 50293 /* i18next-extract-mark-context-next-line ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"] */ 50294 position: (0, _internationalization.translator)('fes.positions.p', { 50295 context: (errorObj.position + 1).toString(), 50296 defaultValue: (errorObj.position + 1).toString() 50297 }) 50298 }; 50299 50300 break; 50301 } 50302 case 'TOO_FEW_ARGUMENTS': { 50303 translationObj = { 50304 func: func, 50305 minParams: errorObj.minParams, 50306 argCount: errorObj.argCount 50307 }; 50308 50309 break; 50310 } 50311 case 'TOO_MANY_ARGUMENTS': { 50312 translationObj = { 50313 func: func, 50314 maxParams: errorObj.maxParams, 50315 argCount: errorObj.argCount 50316 }; 50317 50318 break; 50319 } 50320 } 50321 50322 if (translationObj) { 50323 try { 50324 // const re = /Function\.validateParameters.*[\r\n].*[\r\n].*\(([^)]*)/; 50325 var myError = new Error(); 50326 var parsed = _main.default._getErrorStackParser().parse(myError); 50327 if ( 50328 parsed[3] && 50329 parsed[3].functionName && 50330 parsed[3].functionName.includes('.') && 50331 _main.default.prototype[parsed[3].functionName.split('.').slice(-1)[0]] 50332 ) { 50333 return; 50334 } 50335 if (_main.default._throwValidationErrors) { 50336 throw new _main.default.ValidationError(message, func, errorObj.type); 50337 } 50338 50339 // try to extract the location from where the function was called 50340 if ( 50341 parsed[3] && 50342 parsed[3].fileName && 50343 parsed[3].lineNumber && 50344 parsed[3].columnNumber 50345 ) { 50346 var location = '' 50347 .concat(parsed[3].fileName, ':') 50348 .concat(parsed[3].lineNumber, ':') 50349 .concat(parsed[3].columnNumber); 50350 50351 translationObj.location = (0, _internationalization.translator)( 50352 'fes.location', 50353 { 50354 location: location, 50355 // for e.g. get "sketch.js" from "https://example.com/abc/sketch.js" 50356 file: parsed[3].fileName.split('/').slice(-1), 50357 line: parsed[3].lineNumber 50358 } 50359 ); 50360 50361 // tell fesErrorMonitor that we have already given a friendly message 50362 // for this line, so it need not to do the same in case of an error 50363 _main.default._fesLogCache[location] = true; 50364 } 50365 } catch (err) { 50366 if (err instanceof _main.default.ValidationError) { 50367 throw err; 50368 } 50369 } 50370 50371 translationObj.context = errorObj.type; 50372 // i18next-extract-mark-context-next-line ["EMPTY_VAR", "TOO_MANY_ARGUMENTS", "TOO_FEW_ARGUMENTS", "WRONG_TYPE"] 50373 message = (0, _internationalization.translator)( 50374 'fes.friendlyParamError.type', 50375 translationObj 50376 ); 50377 50378 _main.default._friendlyError(''.concat(message, '.'), func, 3); 50379 } 50380 }; 50381 50382 // if a function is called with some set of wrong arguments, and then called 50383 // again with the same set of arguments, the messages due to the second call 50384 // will be supressed. If two tests test on the same wrong arguments, the 50385 // second test won't see the validationError. clearing argumentTree solves it 50386 _main.default._clearValidateParamsCache = function clearValidateParamsCache() { 50387 for ( 50388 var _i2 = 0, _Object$keys2 = Object.keys(argumentTree); 50389 _i2 < _Object$keys2.length; 50390 _i2++ 50391 ) { 50392 var _key4 = _Object$keys2[_i2]; 50393 delete argumentTree[_key4]; 50394 } 50395 }; 50396 50397 // allowing access to argumentTree for testing 50398 _main.default._getValidateParamsArgTree = function getValidateParamsArgTree() { 50399 return argumentTree; 50400 }; 50401 50402 /** 50403 * Validates parameters 50404 * param {String} func the name of the function 50405 * param {Array} args user input arguments 50406 * 50407 * example: 50408 * const a; 50409 * ellipse(10,10,a,5); 50410 * console ouput: 50411 * "It looks like ellipse received an empty variable in spot #2." 50412 * 50413 * example: 50414 * ellipse(10,"foo",5,5); 50415 * console output: 50416 * "ellipse was expecting a number for parameter #1, 50417 * received "foo" instead." 50418 */ 50419 _main.default._validateParameters = function validateParameters(func, args) { 50420 if (_main.default.disableFriendlyErrors) { 50421 return;
50421 // skip FES 50422 } 50423 50424 // query / build the argument type tree and check if this sequence 50425 // has already been seen before. 50426 var obj = buildArgTypeCache(func, args); 50427 if (obj.seen) { 50428 return; 50429 } 50430 // mark this sequence as seen 50431 obj.seen = true; 50432 // lookup the docs in the 'data.json' file 50433 var docs = docCache[func] || (docCache[func] = lookupParamDoc(func)); 50434 var overloads = docs.overloads; 50435 50436 var argCount = args.length; 50437 50438 // the following line ignores trailing undefined arguments, commenting 50439 // it to resolve https://github.com/processing/p5.js/issues/4571 50440 // '== null' checks for 'null' and typeof 'undefined' 50441 // while (argCount > 0 && args[argCount - 1] == null) argCount--; 50442 50443 // find the overload with the best score 50444 var minScore = 99999; 50445 var minOverload; 50446 for (var i = 0; i < overloads.length; i++) { 50447 var score = scoreOverload(args, argCount, overloads[i], minScore); 50448 if (score === 0) { 50449 return; // done! 50450 } else if (minScore > score) { 50451 // this score is better that what we have so far... 50452 minScore = score; 50453 minOverload = i; 50454 } 50455 } 50456 50457 // this should _always_ be true here... 50458 if (minScore > 0) { 50459 // get the errors for the best overload 50460 var errorArray = getOverloadErrors(args, argCount, overloads[minOverload]); 50461 50462 // generate err msg 50463 for (var n = 0; n < errorArray.length; n++) { 50464 _main.default._friendlyParamError(errorArray[n], func); 50465 } 50466 } 50467 }; 50468 _main.default.prototype._validateParameters = _main.default.validateParameters; 50469 } 50470 var _default = _main.default; 50471 exports.default = _default; 50472 }, 50473 { 50474 '../../../docs/parameterData.json': 1, 50475 '../constants': 48, 50476 '../internationalization': 57, 50477 '../main': 59 50478 } 50479 ], 50480 55: [ 50481 function(_dereq_, module, exports) { 50482 'use strict'; 50483 function _typeof(obj) { 50484 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') { 50485 _typeof = function _typeof(obj) { 50486 return typeof obj; 50487 }; 50488 } else { 50489 _typeof = function _typeof(obj) { 50490 return obj && 50491 typeof Symbol === 'function' && 50492 obj.constructor === Symbol && 50493 obj !== Symbol.prototype 50494 ? 'symbol' 50495 : typeof obj; 50496 }; 50497 } 50498 return _typeof(obj); 50499 } 50500 Object.defineProperty(exports, '__esModule', { value: true }); 50501 exports.default = void 0; 50502 50503 var constants = _interopRequireWildcard(_dereq_('./constants')); 50504 function _getRequireWildcardCache() { 50505 if (typeof WeakMap !== 'function') return null; 50506 var cache = new WeakMap(); 50507 _getRequireWildcardCache = function _getRequireWildcardCache() { 50508 return cache; 50509 }; 50510 return cache; 50511 } 50512 function _interopRequireWildcard(obj) { 50513 if (obj && obj.__esModule) { 50514 return obj; 50515 } 50516 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) { 50517 return { default: obj }; 50518 } 50519 var cache = _getRequireWildcardCache(); 50520 if (cache && cache.has(obj)) { 50521 return cache.get(obj); 50522 } 50523 var newObj = {}; 50524 var hasPropertyDescriptor = 50525 Object.defineProperty && Object.getOwnPropertyDescriptor; 50526 for (var key in obj) { 50527 if (Object.prototype.hasOwnProperty.call(obj, key)) { 50528 var desc = hasPropertyDescriptor 50529 ? Object.getOwnPropertyDescriptor(obj, key) 50530 : null; 50531 if (desc && (desc.get || desc.set)) { 50532 Object.defineProperty(newObj, key, desc); 50533 } else { 50534 newObj[key] = obj[key]; 50535 } 50536 } 50537 } 50538 newObj.default = obj; 50539 if (cache) { 50540 cache.set(obj, newObj); 50541 } 50542 return newObj; 50543 } 50544 /** 50545 * @requires constants 50546 */ function modeAdjust(a, b, c, d, mode) { 50547 if (mode === constants.CORNER) { 50548 return { x: a, y: b, w: c, h: d }; 50549 } else if (mode === constants.CORNERS) { 50550 return { x: a, y: b, w: c - a, h: d - b }; 50551 } else if (mode === constants.RADIUS) { 50552 return { x: a - c, y: b - d, w: 2 * c, h: 2 * d }; 50553 } else if (mode === constants.CENTER) { 50554 return { x: a - c * 0.5, y: b - d * 0.5, w: c, h: d }; 50555 } 50556 } 50557 var _default = { modeAdjust: modeAdjust }; 50558 exports.default = _default; 50559 }, 50560 { './constants': 48 } 50561 ], 50562 56: [
50563 function(_dereq_, module, exports) { 50564 'use strict'; 50565 var _main = _interopRequireDefault(_dereq_('../core/main')); 50566 var _internationalization = _dereq_('./internationalization'); 50567 function _interopRequireDefault(obj) { 50568 return obj && obj.__esModule ? obj : { default: obj }; 50569 } 50570 50571 /** 50572 * _globalInit 50573 * 50574 * TODO: ??? 50575 * if sketch is on window 50576 * assume "global" mode 50577 * and instantiate p5 automatically 50578 * otherwise do nothing 50579 * 50580 * @private 50581 * @return {Undefined} 50582 */ 50583 var _globalInit = function _globalInit() { 50584 // Could have been any property defined within the p5 constructor. 50585 // If that property is already a part of the global object, 50586 // this code has already run before, likely due to a duplicate import 50587 if (typeof window._setupDone !== 'undefined') { 50588 console.warn( 50589 'p5.js seems to have been imported multiple times. Please remove the duplicate import' 50590 ); 50591 50592 return; 50593 } 50594 50595 if (!window.mocha) { 50596 // If there is a setup or draw function on the window 50597 // then instantiate p5 in "global" mode 50598 if ( 50599 ((window.setup && typeof window.setup === 'function') || 50600 (window.draw && typeof window.draw === 'function')) && 50601 !_main.default.instance 50602 ) { 50603 new _main.default(); 50604 } 50605 } 50606 }; 50607 50608 // make a promise that resolves when the document is ready 50609 var waitForDocumentReady = function waitForDocumentReady() { 50610 return new Promise(function(resolve, reject) { 50611 // if the page is ready, initialize p5 immediately 50612 if (document.readyState === 'complete') { 50613 resolve(); 50614 // if the page is still loading, add an event listener 50615 // and initialize p5 as soon as it finishes loading 50616 } else { 50617 window.addEventListener('load', resolve, false); 50618 } 50619 }); 50620 }; 50621 50622 // only load translations if we're using the full, un-minified library 50623 var waitingForTranslator = 50624 typeof IS_MINIFIED === 'undefined' 50625 ? (0, _internationalization.initialize)() 50626 : Promise.resolve(); 50627 50628 Promise.all([waitForDocumentReady(), waitingForTranslator]).then(_globalInit); 50629 }, 50630 { '../core/main': 59, './internationalization': 57 } 50631 ], 50632 57: [ 50633 function(_dereq_, module, exports) { 50634 'use strict'; 50635 Object.defineProperty(exports, '__esModule', { value: true }); 50636 exports.initialize = exports.translator = void 0; 50637 var _i18next = _interopRequireDefault(_dereq_('i18next')); 50638 var _i18nextBrowserLanguagedetector = _interopRequireDefault( 50639 _dereq_('i18next-browser-languagedetector') 50640 ); 50641 function _interopRequireDefault(obj) { 50642 return obj && obj.__esModule ? obj : { default: obj }; 50643 } 50644 function _classCallCheck(instance, Constructor) { 50645 if (!(instance instanceof Constructor)) { 50646 throw new TypeError('Cannot call a class as a function'); 50647 } 50648 } 50649 function _defineProperties(target, props) { 50650 for (var i = 0; i < props.length; i++) { 50651 var descriptor = props[i]; 50652 descriptor.enumerable = descriptor.enumerable || false; 50653 descriptor.configurable = true; 50654 if ('value' in descriptor) descriptor.writable = true; 50655 Object.defineProperty(target, descriptor.key, descriptor); 50656 } 50657 } 50658 function _createClass(Constructor, protoProps, staticProps) { 50659 if (protoProps) _defineProperties(Constructor.prototype, protoProps); 50660 if (staticProps) _defineProperties(Constructor, staticProps); 50661 return Constructor; 50662 } 50663 50664 var fallbackResources, languages; 50665 if (typeof IS_MINIFIED === 'undefined') { 50666 // internationalization is only for the unminified build 50667 50668 var translationsModule = _dereq_('../../translations'); 50669 fallbackResources = translationsModule.default; 50670 languages = translationsModule.languages; 50671 50672 if (typeof P5_DEV_BUILD !== 'undefined') { 50673 // When the library is built in development mode ( using npm run dev ) 50674 // we want to use the current translation files on the disk, which may have 50675 // been updated but not yet pushed to the CDN. 50676 var completeResources = _dereq_('../../translations/dev'); 50677 for ( 50678 var _i = 0, _Object$keys = Object.keys(completeResources); 50679 _i < _Object$keys.length; 50680 _i++ 50681 ) { 50682 var language = _Object$keys[_i]; 50683 // In es_translation, language is es and namespace is translation 50684 // In es_MX_translation, language is es-MX and namespace is translation 50685 var parts = language.split('_'); 50686 var lng = parts.slice(0, parts.length - 1).join('-'); 50687 var ns = parts[parts.length - 1]; 50688 50689 fallbackResources[lng] = fallbackResources[lng] || {}; 50690 fallbackResources[lng][ns] = completeResources[language]; 50691 } 50692 } 50693 } 50694 50695 /** 50696 * This is our i18next "backend" plugin. It tries to fetch languages 50697 * from a CDN. 50698 */ var FetchResources = /*#__PURE__*/ (function() { 50699 function FetchResources(services, options) { 50700 _classCallCheck(this, FetchResources); 50701 this.init(services, options); 50702 } 50703 50704 // run fetch with a timeout. Automatically rejects on timeout 50705 // default timeout = 2000 ms 50706 _createClass(FetchResources, [ 50707 { 50708 key: 'fetchWithTimeout', 50709 value: function fetchWithTimeout(url, options) { 50710 var timeout = 50711 arguments.length > 2 && arguments[2] !== undefined 50712 ? arguments[2] 50713 : 2000; 50714 return Promise.race([ 50715 fetch(url, options), 50716 new Promise(function(_, reject) { 50717 return setTimeout(function() { 50718 return reject(new Error('timeout')); 50719 }, timeout); 50720 }) 50721 ]); 50722 } 50723 }, 50724 { 50725 key: 'init', 50726 value: function init(services) { 50727 var options = 50728 arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; 50729 this.services = services; 50730 this.options = options; 50731 } 50732 }, 50733 { 50734 key: 'read', 50735 value: function read(language, namespace, callback) { 50736 var loadPath = this.options.loadPath; 50737 50738 if (language === this.options.fallback) { 50739 // if the default language of the user is the same as our inbuilt fallback, 50740 // there's no need to fetch resources from the c
50740dn. This won't actually 50741 // need to run when we use "partialBundledLanguages" in the init 50742 // function. 50743 callback(null, fallbackResources[language][namespace]); 50744 } else if (languages.includes(language)) { 50745 // The user's language is included in the list of languages 50746 // that we so far added translations for. 50747 50748 var url = this.services.interpolator.interpolate(loadPath, { 50749 lng: language, 50750 ns: namespace 50751 }); 50752 50753 this.loadUrl(url, callback); 50754 } else { 50755 // We don't have translations for this language. i18next will use 50756 // the default language instead. 50757 callback('Not found', false); 50758 } 50759 } 50760 }, 50761 { 50762 key: 'loadUrl', 50763 value: function loadUrl(url, callback) { 50764 this.fetchWithTimeout(url) 50765 .then( 50766 function(response) { 50767 var ok = response.ok; 50768 50769 if (!ok) { 50770 // caught in the catch() below 50771 throw new Error('failed loading '.concat(url)); 50772 } 50773 return response.json(); 50774 }, 50775 function() { 50776 // caught in the catch() below 50777 throw new Error('failed loading '.concat(url)); 50778 } 50779 ) 50780 .then(function(data) { 50781 return callback(null, data); 50782 }) 50783 .catch(callback); 50784 } 50785 } 50786 ]); 50787 return FetchResources; 50788 })(); 50789 50790 FetchResources.type = 'backend'; 50791 50792 /** 50793 * This is our translation function. Give it a key and 50794 * it will retreive the appropriate string 50795 * (within supported languages) according to the 50796 * user's browser's language settings. 50797 * @function translator 50798 * @param {String} key a key that corresponds to a message in our translation files 50799 * @param {Object} values values for use in the message under the given `key` 50800 * @returns {String} message (with values inserted) in the user's browser language 50801 * @private 50802 */ 50803 var translator = function translator(key, values) { 50804 console.debug('p5.js translator called before translations were loaded'); 50805 50806 // Certain FES functionality may trigger before translations are downloaded. 50807 // Using "partialBundledLanguages" option during initialization, we can 50808 // still use our fallback language to display messages 50809 _i18next.default.t(key, values); /* i18next-extract-disable-line */ 50810 }; 50811 // (We'll set this to a real value in the init function below!) 50812 50813 /** 50814 * Set up our translation function, with loaded languages 50815 */ exports.translator = translator; 50816 var initialize = function initialize() { 50817 var i18init = _i18next.default 50818 .use(_i18nextBrowserLanguagedetector.default) 50819 .use(FetchResources) 50820 .init({ 50821 fallbackLng: 'en', 50822 nestingPrefix: '$tr(', 50823 nestingSuffix: ')', 50824 defaultNS: 'translation', 50825 returnEmptyString: false, 50826 interpolation: { 50827 escapeValue: false 50828 }, 50829 50830 detection: { 50831 checkWhitelist: false, 50832 50833 // prevent storing or locating language from cookie or localStorage 50834 // more info on https://github.com/processing/p5.js/issues/4862 50835 order: ['querystring', 'navigator', 'htmlTag', 'path', 'subdomain'], 50836 caches: [] 50837 }, 50838 50839 backend: { 50840 fallback: 'en', 50841 loadPath: 50842 'https://cdn.jsdelivr.net/npm/p5/translations/{{lng}}/{{ns}}.json' 50843 }, 50844 50845 partialBundledLanguages: true, 50846 resources: fallbackResources 50847 }) 50848 .then( 50849 function(translateFn) { 50850 exports.translator = translator = translateFn; 50851 }, 50852 function(e) { 50853 return console.debug('Translations failed to load ('.concat(e, ')')); 50854 } 50855 ); 50856
50857 // i18next.init() returns a promise that resolves when the translations 50858 // are loaded. We use this in core/init.js to hold p5 initialization until 50859 // we have the translation files. 50860 return i18init; 50861 }; 50862 exports.initialize = initialize; 50863 }, 50864 { 50865 '../../translations': 118, 50866 '../../translations/dev': undefined, 50867 i18next: 30, 50868 'i18next-browser-languagedetector': 27 50869 } 50870 ], 50871 58: [ 50872 function(_dereq_, module, exports) { 50873 'use strict'; 50874 Object.defineProperty(exports, '__esModule', { value: true }); 50875 exports.default = void 0; 50876 50877 var _main = _interopRequireDefault(_dereq_('./main')); 50878 function _interopRequireDefault(obj) { 50879 return obj && obj.__esModule ? obj : { default: obj }; 50880 } 50881 /** 50882 * @for p5 50883 * @requires core 50884 * These are functions that are part of the Processing API but are not part of 50885 * the p5.js API. In some cases they have a new name, in others, they are 50886 * removed completely. Not all unsupported Processing functions are listed here 50887 * but we try to include ones that a user coming from Processing might likely 50888 * call. 50889 */ _main.default.prototype.pushStyle = function() { 50890 throw new Error('pushStyle() not used, see push()'); 50891 }; 50892 _main.default.prototype.popStyle = function() { 50893 throw new Error('popStyle() not used, see pop()'); 50894 }; 50895 50896 _main.default.prototype.popMatrix = function() { 50897 throw new Error('popMatrix() not used, see pop()'); 50898 }; 50899 50900 _main.default.prototype.pushMatrix = function() { 50901 throw new Error('pushMatrix() not used, see push()'); 50902 }; 50903 var _default = _main.default; 50904 exports.default = _default; 50905 }, 50906 { './main': 59 } 50907 ], 50908 59: [ 50909 function(_dereq_, module, exports) { 50910 'use strict'; 50911 function _typeof(obj) { 50912 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') { 50913 _typeof = function _typeof(obj) { 50914 return typeof obj; 50915 }; 50916 } else { 50917 _typeof = function _typeof(obj) { 50918 return obj && 50919 typeof Symbol === 'function' && 50920 obj.constructor === Symbol && 50921 obj !== Symbol.prototype 50922 ? 'symbol' 50923 : typeof obj; 50924 }; 50925 } 50926 return _typeof(obj); 50927 } 50928 Object.defineProperty(exports, '__esModule', { value: true }); 50929 exports.default = void 0; 50930 50931 _dereq_('./shim'); 50932 50933 var constants = _interopRequireWildcard(_dereq_('./constants')); 50934 function _getRequireWildcardCache() { 50935 if (typeof WeakMap !== 'function') return null; 50936 var cache = new WeakMap(); 50937 _getRequireWildcardCache = function _getRequireWildcardCache() { 50938 return cache; 50939 }; 50940 return cache; 50941 } 50942 function _interopRequireWildcard(obj) { 50943 if (obj && obj.__esModule) { 50944 return obj; 50945 } 50946 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) { 50947 return { default: obj }; 50948 } 50949 var cache = _getRequireWildcardCache(); 50950 if (cache && cache.has(obj)) { 50951 return cache.get(obj); 50952 } 50953 var newObj = {}; 50954 var hasPropertyDescriptor = 50955 Object.defineProperty && Object.getOwnPropertyDescriptor; 50956 for (var key in obj) { 50957 if (Object.prototype.hasOwnProperty.call(obj, key)) { 50958 var desc = hasPropertyDescriptor 50959 ? Object.getOwnPropertyDescriptor(obj, key) 50960 : null; 50961 if (desc && (desc.get || desc.set)) { 50962 Object.defineProperty(newObj, key, desc); 50963 } else { 50964 newObj[key] = obj[key]; 50965 } 50966 } 50967 } 50968 newObj.default = obj; 50969 if (cache) { 50970 cache.set(obj, newObj); 50971 } 50972 return newObj; 50973 } 50974 function _classCallCheck(instance, Constructor) { 50975 if (!(instance instanceof Constructor)) { 50976 throw new TypeError('Cannot call a class as a function'); 50977 } 50978 } 50979 function _defineProperties(target, props) { 50980 for (var i = 0; i < props.length; i++) { 50981 var descriptor = props[i]; 50982 descriptor.enumerable = descriptor.enumerable || false; 50983 descriptor.configurable = true; 50984 if ('value' in descriptor) descriptor.writable = true; 50985 Object.defineProperty(target, descriptor.key, descriptor); 50986 } 50987 } 50988 function _createClass(Constructor, protoProps, staticProps) { 50989 if (protoProps) _defineProperties(Constructor.prototype, protoProps); 50990 if (staticProps) _defineProperties(Constructor, staticProps); 50991 return Constructor; 50992 } 50993 50994 /** 50995 * This is the p5 instance constructor. 50996 * 50997 * A p5 instance holds all the properties and methods related to 50998 * a p5 sketch. It expects an incoming sketch closure and it can also 50999 * take an optional node parameter for attaching the generated p5 canvas 51000 * to a node. The sketch closure takes the newly created p5 instance as 51001 * its sole argument and may optionally set <a href="#/p5/preload">preload()</a>, 51002 * <a href="#/p5/setup">setup()</a>, and/or 51003 * <a href="#/p5/draw">draw()</a> properties on it for running a sketch. 51004 * 51005 * A p5 sketch can run in "global" or "instance" mode: 51006 * "global" - all properties and methods are attached to the window 51007 * "instance" - all properties and methods are bound to this p5 object 51008 * 51009 * @class p5 51010 * @constructor 51011 * @param {function} sketch a closure that can set optional <a href="#/p5/preload">preload()</a>, 51012 * <a href="#/p5/setup">setup()</a>, and/or <a href="#/p5/draw">draw()</a> properties on the 51013 * given p5 instance 51014 * @param {HTMLElement} [node] element to attach canvas to 51015 * @return {p5} a p5 instance 51016 */ var p5 = /*#__PURE__*/ (function() { 51017 function p5(sketch, node, sync) { 51018 var _this = this; 51019 _classCallCheck(this, p5);
51020 ////////////////////////////////////////////// 51021 // PUBLIC p5 PROPERTIES AND METHODS 51022 ////////////////////////////////////////////// 51023 51024 /** 51025 * Called directly before <a href="#/p5/setup">setup()</a>, the <a href="#/p5/preload">preload()</a> function is used to handle 51026 * asynchronous loading of external files in a blocking way. If a preload 51027 * function is defined, <a href="#/p5/setup">setup()</a> will wait until any load calls within have 51028 * finished. Nothing besides load calls (<a href="#/p5/loadImage">loadImage</a>, <a href="#/p5/loadJSON">loadJSON</a>, <a href="#/p5/loadFont">loadFont</a>, 51029 * <a href="#/p5/loadStrings">loadStrings</a>, etc.) should be inside the preload function. If asynchronous 51030 * loading is preferred, the load methods can instead be called in <a href="#/p5/setup">setup()</a> 51031 * or anywhere else with the use of a callback parameter. 51032 * 51033 * By default the text "loading..." will be displayed. To make your own 51034 * loading page, include an HTML element with id "p5_loading" in your 51035 * page. More information <a href="http://bit.ly/2kQ6Nio">here</a>. 51036 * 51037 * @method preload 51038 * @example 51039 * <div><code> 51040 * let img; 51041 * let c; 51042 * function preload() { 51043 * // preload() runs once 51044 * img = loadImage('assets/laDefense.jpg'); 51045 * } 51046 * 51047 * function setup() { 51048 * // setup() waits until preload() is done 51049 * img.loadPixels(); 51050 * // get color of middle pixel 51051 * c = img.get(img.width / 2, img.height / 2); 51052 * } 51053 * 51054 * function draw() { 51055 * background(c); 51056 * image(img, 25, 25, 50, 50); 51057 * } 51058 * </code></div> 51059 * 51060 * @alt 51061 * nothing displayed 51062 * 51063 */ 51064 51065 /** 51066 * The <a href="#/p5/setup">setup()</a> function is called once when the program starts. It's used to 51067 * define initial environment properties such as screen size and background 51068 * color and to load media such as images and fonts as the program starts. 51069 * There can only be one <a href="#/p5/setup">setup()</a> function for each program and it shouldn't 51070 * be called again after its initial execution. 51071 * 51072 * Note: Variables declared within <a href="#/p5/setup">setup()</a> are not accessible within other 51073 * functions, including <a href="#/p5/draw">draw()</a>. 51074 * 51075 * @method setup 51076 * @example 51077 * <div><code> 51078 * let a = 0; 51079 * 51080 * function setup() { 51081 * background(0); 51082 * noStroke(); 51083 * fill(102); 51084 * } 51085 * 51086 * function draw() { 51087 * rect(a++ % width, 10, 2, 80); 51088 * } 51089 * </code></div> 51090 * 51091 * @alt 51092 * nothing displayed 51093 * 51094 */ 51095 51096 /** 51097 * Called directly after <a href="#/p5/setup">setup()</a>, the <a href="#/p5/draw">draw()</a> function continuously executes 51098 * the lines of code contained inside its block until the program is stopped 51099 * 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 51100 * still be executed once before stopping. <a href="#/p5/draw">draw()</a> is called automatically and 51101 * should never be called explicitly. 51102 * 51103 * 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 51104 * <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 51105 * code inside <a href="#/p5/draw">draw()</a> to execute once, and <a href="#/p5/loop">loop()</a> will cause the code 51106 * inside <a href="#/p5/draw">draw()</a> to resume executing continuously. 51107 * 51108 * The number of times <a href="#/p5/draw">draw()</a> executes in each second may be controlled with 51109 * the <a href="#/p5/frameRate">frameRate()</a> function. 51110 * 51111 * There can only be one <a href="#/p5/draw">draw()</a> function for each sketch, and <a href="#/p5/draw">draw()</a> must 51112 * exist if you want the code to run continuously, or to process events such 51113 * as <a href="#/p5/mousePressed">mousePressed()</a>. Sometimes, you might have an empty call to <a href="#/p5/draw">draw()</a> in 51114 * your program, as shown in the above example. 51115 * 51116 * It is important to note that the drawing coordinate system will be reset 51117 * at the beginning of each <a href="#/p5/draw">draw()</a> call. If any transformations are performed 51118 * within <a href="#/p5/draw">draw()</a> (ex: scale, rotate, translate), their effects will be 51119 * undone at the beginning of <a href="#/p5/draw">draw()</a>, so transformations will not accumulate 51120 * over time. On the other hand, styling applied (ex: fill, stroke, etc) will 51121 * remain in effect. 51122 * 51123 * @method draw 51124 * @example 51125 * <div><code> 51126 * let yPos = 0; 51127 * function setup() { 51128 * // setup() runs once 51129 * frameRate(30); 51130 * } 51131 * function draw() { 51132 * // draw() loops forever, until stopped 51133 * background(204); 51134 * yPos = yPos - 1; 51135 * if (yPos < 0) { 51136 * yPos = height; 51137 * } 51138 * line(0, yPos, width, yPos); 51139 * } 51140 * </code></div> 51141 * 51142 * @alt 51143 * nothing displayed 51144 * 51145 */ 51146
51147 ////////////////////////////////////////////// 51148 // PRIVATE p5 PROPERTIES AND METHODS 51149 ////////////////////////////////////////////// 51150 51151 this._accessibleOutputs = { 51152 text: false, 51153 grid: false, 51154 textLabel: false, 51155 gridLabel: false 51156 }; 51157 51158 this._setupDone = false; 51159 // for handling hidpi 51160 this._pixelDensity = Math.ceil(window.devicePixelRatio) || 1; 51161 this._userNode = node; 51162 this._curElement = null; 51163 this._elements = []; 51164 this._glAttributes = null; 51165 this._requestAnimId = 0; 51166 this._preloadCount = 0; 51167 this._isGlobal = false; 51168 this._loop = true; 51169 this._initializeInstanceVariables(); 51170 this._defaultCanvasSize = { 51171 width: 100, 51172 height: 100 51173 }; 51174 51175 this._events = { 51176 // keep track of user-events for unregistering later 51177 mousemove: null, 51178 mousedown: null, 51179 mouseup: null, 51180 dragend: null, 51181 dragover: null, 51182 click: null, 51183 dblclick: null, 51184 mouseover: null, 51185 mouseout: null, 51186 keydown: null, 51187 keyup: null, 51188 keypress: null, 51189 touchstart: null, 51190 touchmove: null, 51191 touchend: null, 51192 resize: null, 51193 blur: null 51194 }; 51195 51196 this._millisStart = -1; 51197 51198 // States used in the custom random generators 51199 this._lcg_random_state = null; 51200 this._gaussian_previous = false; 51201 51202 this._events.wheel = null; 51203 this._loadingScreenId = 'p5_loading'; 51204 51205 // Allows methods to be registered on an instance that 51206 // are instance-specific. 51207 this._registeredMethods = {}; 51208 var methods = Object.getOwnPropertyNames(p5.prototype._registeredMethods); 51209 var _iteratorNormalCompletion = true; 51210 var _didIteratorError = false; 51211 var _iteratorError = undefined; 51212 try { 51213 for ( 51214 var _iterator = methods[Symbol.iterator](), _step; 51215 !(_iteratorNormalCompletion = (_step = _iterator.next()).done); 51216 _iteratorNormalCompletion = true 51217 ) { 51218 var prop = _step.value; 51219 this._registeredMethods[prop] = p5.prototype._registeredMethods[ 51220 prop 51221 ].slice(); 51222 } 51223 } catch (err) { 51224 _didIteratorError = true; 51225 _iteratorError = err; 51226 } finally { 51227 try { 51228 if (!_iteratorNormalCompletion && _iterator.return != null) { 51229 _iterator.return(); 51230 } 51231 } finally { 51232 if (_didIteratorError) { 51233 throw _iteratorError; 51234 } 51235 } 51236 } 51237 51238 if (window.DeviceOrientationEvent) { 51239 this._events.deviceorientation = null; 51240 } 51241 if (window.DeviceMotionEvent && !window._isNodeWebkit) { 51242 this._events.devicemotion = null; 51243 } 51244 51245 this._start = function() { 51246 // Find node if id given 51247 if (_this._userNode) { 51248 if (typeof _this._userNode === 'string') { 51249 _this._userNode = document.getElementById(_this._userNode); 51250 } 51251 } 51252 51253 var context = _this._isGlobal ? window : _this; 51254 if (context.preload) { 51255 // Setup loading screen 51256 // Set loading screen into dom if not present 51257 // Otherwise displays and removes user provided loading screen 51258 var loadingScreen = document.getElementById(_this._loadingScreenId); 51259 if (!loadingScreen) { 51260 loadingScreen = document.createElement('div'); 51261 loadingScreen.innerHTML = 'Loading...'; 51262 loadingScreen.style.position = 'absolute'; 51263 loadingScreen.id = _this._loadingScreenId; 51264 var _node = _this._userNode || document.body; 51265 _node.appendChild(loadingScreen); 51266 } 51267 var _methods = _this._preloadMethods; 51268 for (var method in _methods) { 51269 // default to p5 if no object defined 51270 _methods[method] = _methods[method] || p5; 51271 var obj = _methods[method]; 51272 //it's p5, check if it's global or instance 51273 if (obj === p5.prototype || obj === p5) { 51274 if (_this._isGlobal) { 51275 window[method] = _this._wrapPreload(_this, method); 51276 } 51277 obj = _this; 51278 } 51279 _this._registeredPreloadMethods[method] = obj[method]; 51280 obj[method] = _this._wrapPreload(obj, method); 51281 } 51282 51283 context.preload(); 51284 _this._runIfPreloadsAreDone(); 51285 } else { 51286 _this._setup(); 51287 _this._draw(); 51288 } 51289 }; 51290 51291 this._runIfPreloadsAreDone = function() { 51292 var context = this._isGlobal ? window : this; 51293 if (context._preloadCount === 0) { 51294 var loadingScreen = document.getElementById(context._loadingScreenId); 51295 if (loadingScreen) { 51296 loadingScreen.parentNode.removeChild(loadingScreen); 51297 } 51298 if (!this._setupDone) { 51299 this._lastFrameTime = window.performance.now(); 51300 context._setup(); 51301 context._draw(); 51302 } 51303 } 51304 }; 51305 51306 this._decrementPreload = function() { 51307 var context = this._isGlobal ? window : this; 51308 if (typeof context.preload === 'function') { 51309 context._setProperty('_preloadCount', context._preloadCount - 1); 51310 context._runIfPreloadsAreDone(); 51311 } 51312 }; 51313 51314 this._wrapPreload = function(obj, fnName) { 51315 var _this2 = this; 51316 return function() { 51317 //increment counter 51318 _this2._incrementPreload(); 51319 //call original function 51320 for ( 51321 var _len = arguments.length, args = new Array(_len), _key = 0; 51322 _key < _len; 51323 _key++ 51324 ) { 51325 args[_key] = arguments[_key]; 51326 } 51327 return _this2._registeredPreloadMethods[fnName].apply(obj, args); 51328 }; 51329 }; 51330 51331 this._incrementPreload = function() { 51332 var context = this._isGlobal ? window : this; 51333 context._setProperty('_preloadCount', context._preloadCount + 1); 51334 }; 51335 51336 this._setup = function() { 51337 // Always create a default canvas. 51338 // Later on if the user calls createCanvas, this default one 51339 // will be replaced 51340 _this.createCanvas( 51341 _this._defaultCanvasSize.width, 51342 _this._defaultCanvasSize.height, 51343 'p2d' 51344 ); 51345 51346 // return preload functions to their normal vals if switched by preload 51347 var context = _this._isGlobal ? window : _this; 51348 if (typeof context.preload === 'function') { 51349 for (var f in _this._preloadMethods) { 51350 context[f] = _this._preloadMethods[f][f]; 51351 if (context[f] && _this) { 51352 context[f] = context[f].bind(_this); 51353 } 51354 } 51355 } 51356 51357 // Record the time when sketch starts 51358 _this._millisStart = window.performance.now(); 51359 51360 // Short-circuit on this, in case someone used the library in "global" 51361 // mode earlier 51362 if (typeof context.setup === 'function') { 51363 context.setup(); 51364 } 51365 51366 // unhide any hidden canvases that were created
51367 var canvases = document.getElementsByTagName('canvas'); 51368 var _iteratorNormalCompletion2 = true; 51369 var _didIteratorError2 = false; 51370 var _iteratorError2 = undefined; 51371 try { 51372 for ( 51373 var _iterator2 = canvases[Symbol.iterator](), _step2; 51374 !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); 51375 _iteratorNormalCompletion2 = true 51376 ) { 51377 var k = _step2.value; 51378 if (k.dataset.hidden === 'true') { 51379 k.style.visibility = ''; 51380 delete k.dataset.hidden; 51381 } 51382 } 51383 } catch (err) { 51384 _didIteratorError2 = true; 51385 _iteratorError2 = err; 51386 } finally { 51387 try { 51388 if (!_iteratorNormalCompletion2 && _iterator2.return != null) { 51389 _iterator2.return(); 51390 } 51391 } finally { 51392 if (_didIteratorError2) { 51393 throw _iteratorError2; 51394 } 51395 } 51396 } 51397 51398 _this._lastFrameTime = window.performance.now(); 51399 _this._setupDone = true; 51400 if (_this._accessibleOutputs.grid || _this._accessibleOutputs.text) { 51401 _this._updateAccsOutput(); 51402 } 51403 }; 51404 51405 this._draw = function() { 51406 var now = window.performance.now(); 51407 var time_since_last = now - _this._lastFrameTime; 51408 var target_time_between_frames = 1000 / _this._targetFrameRate; 51409 51410 // only draw if we really need to; don't overextend the browser. 51411 // draw if we're within 5ms of when our next frame should paint 51412 // (this will prevent us from giving up opportunities to draw 51413 // again when it's really about time for us to do so). fixes an 51414 // issue where the frameRate is too low if our refresh loop isn't 51415 // in sync with the browser. note that we have to draw once even 51416 // if looping is off, so we bypass the time delay if that 51417 // is the case. 51418 var epsilon = 5; 51419 if ( 51420 !_this._loop || 51421 time_since_last >= target_time_between_frames - epsilon 51422 ) { 51423 //mandatory update values(matrixs and stack) 51424 _this.redraw(); 51425 _this._frameRate = 1000.0 / (now - _this._lastFrameTime); 51426 _this.deltaTime = now - _this._lastFrameTime; 51427 _this._setProperty('deltaTime', _this.deltaTime); 51428 _this._lastFrameTime = now; 51429 51430 // If the user is actually using mouse module, then update 51431 // coordinates, otherwise skip. We can test this by simply 51432 // checking if any of the mouse functions are available or not. 51433 // NOTE : This reflects only in complete build or modular build. 51434 if (typeof _this._updateMouseCoords !== 'undefined') { 51435 _this._updateMouseCoords(); 51436 51437 //reset delta values so they reset even if there is no mouse event to set them 51438 // for example if the mouse is outside the screen 51439 _this._setProperty('movedX', 0); 51440 _this._setProperty('movedY', 0); 51441 } 51442 } 51443 51444 // get notified the next time the browser gives us 51445 // an opportunity to draw. 51446 if (_this._loop) { 51447 _this._requestAnimId = window.requestAnimationFrame(_this._draw); 51448 } 51449 }; 51450 51451 this._setProperty = function(prop, value) { 51452 _this[prop] = value; 51453 if (_this._isGlobal) { 51454 window[prop] = value; 51455 } 51456 }; 51457 51458 /** 51459 * Removes the entire p5 sketch. This will remove the canvas and any 51460 * elements created by p5.js. It will also stop the draw loop and unbind 51461 * any properties or methods from the window global scope. It will 51462 * leave a variable p5 in case you wanted to create a new p5 sketch. 51463 * If you like, you can set p5 = null to erase it. While all functions and 51464 * variables and objects created by the p5 library will be removed, any 51465 * other global variables created by your code will remain. 51466 * 51467 * @method remove 51468 * @example 51469 * <div class='norender'><code> 51470 * function draw() { 51471 * ellipse(50, 50, 10, 10); 51472 * } 51473 * 51474 * function mousePressed() { 51475 * remove(); // remove whole sketch on mouse press 51476 * } 51477 * </code></div> 51478 * 51479 * @alt 51480 * nothing displayed 51481 * 51482 */ 51483 this.remove = function() { 51484 var loadingScreen = document.getElementById(_this._loadingScreenId); 51485 if (loadingScreen) { 51486 loadingScreen.parentNode.removeChild(loadingScreen); 51487 // Add 1 to preload counter to prevent the sketch ever executing setup() 51488 _this._incrementPreload(); 51489 } 51490 if (_this._curElement) { 51491 // stop draw 51492 _this._loop = false;
51493 if (_this._requestAnimId) { 51494 window.cancelAnimationFrame(_this._requestAnimId); 51495 } 51496 51497 // unregister events sketch-wide 51498 for (var ev in _this._events) { 51499 window.removeEventListener(ev, _this._events[ev]); 51500 } 51501 51502 // remove DOM elements created by p5, and listeners 51503 var _iteratorNormalCompletion3 = true; 51504 var _didIteratorError3 = false; 51505 var _iteratorError3 = undefined; 51506 try { 51507 for ( 51508 var _iterator3 = _this._elements[Symbol.iterator](), _step3; 51509 !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); 51510 _iteratorNormalCompletion3 = true 51511 ) { 51512 var e = _step3.value; 51513 if (e.elt && e.elt.parentNode) { 51514 e.elt.parentNode.removeChild(e.elt); 51515 } 51516 for (var elt_ev in e._events) { 51517 e.elt.removeEventListener(elt_ev, e._events[elt_ev]); 51518 } 51519 } 51520 51521 // call any registered remove functions 51522 } catch (err) { 51523 _didIteratorError3 = true; 51524 _iteratorError3 = err; 51525 } finally { 51526 try { 51527 if (!_iteratorNormalCompletion3 && _iterator3.return != null) { 51528 _iterator3.return(); 51529 } 51530 } finally { 51531 if (_didIteratorError3) { 51532 throw _iteratorError3; 51533 } 51534 } 51535 } 51536 var self = _this; 51537 _this._registeredMethods.remove.forEach(function(f) { 51538 if (typeof f !== 'undefined') { 51539 f.call(self); 51540 } 51541 }); 51542 } 51543 // remove window bound properties and methods 51544 if (_this._isGlobal) { 51545 for (var p in p5.prototype) { 51546 try { 51547 delete window[p]; 51548 } catch (x) { 51549 window[p] = undefined; 51550 } 51551 } 51552 for (var p2 in _this) { 51553 if (_this.hasOwnProperty(p2)) { 51554 try { 51555 delete window[p2]; 51556 } catch (x) { 51557 window[p2] = undefined; 51558 } 51559 } 51560 } 51561 p5.instance = null; 51562 } 51563 }; 51564 51565 // call any registered init functions 51566 this._registeredMethods.init.forEach(function(f) { 51567 if (typeof f !== 'undefined') { 51568 f.call(this); 51569 } 51570 }, this); 51571 // Set up promise preloads 51572 this._setupPromisePreloads(); 51573 51574 var friendlyBindGlobal = this._createFriendlyGlobalFunctionBinder(); 51575 51576 // If the user has created a global setup or draw function, 51577 // assume "global" mode and make everything global (i.e. on the window) 51578 if (!sketch) { 51579 this._isGlobal = true; 51580 p5.instance = this; 51581 // Loop through methods on the prototype and attach them to the window 51582 for (var p in p5.prototype) { 51583 if (typeof p5.prototype[p] === 'function') { 51584 var ev = p.substring(2); 51585 if (!this._events.hasOwnProperty(ev)) { 51586 if (Math.hasOwnProperty(p) && Math[p] === p5.prototype[p]) { 51587 // Multiple p5 methods are just native Math functions. These can be 51588 // called without any binding. 51589 friendlyBindGlobal(p, p5.prototype[p]); 51590 } else { 51591 friendlyBindGlobal(p, p5.prototype[p].bind(this)); 51592 } 51593 } 51594 } else { 51595 friendlyBindGlobal(p, p5.prototype[p]); 51596 } 51597 } 51598 // Attach its properties to the window 51599 for (var p2 in this) { 51600 if (this.hasOwnProperty(p2)) { 51601 friendlyBindGlobal(p2, this[p2]); 51602 } 51603 } 51604 } else { 51605 // Else, the user has passed in a sketch closure that may set
51606 // user-provided 'setup', 'draw', etc. properties on this instance of p5 51607 sketch(this); 51608 51609 // Run a check to see if the user has misspelled 'setup', 'draw', etc 51610 // detects capitalization mistakes only ( Setup, SETUP, MouseClicked, etc) 51611 p5._checkForUserDefinedFunctions(this); 51612 } 51613 51614 // Bind events to window (not using container div bc key events don't work) 51615 51616 for (var e in this._events) { 51617 var f = this['_on'.concat(e)]; 51618 if (f) { 51619 var m = f.bind(this); 51620 window.addEventListener(e, m, { passive: false }); 51621 this._events[e] = m; 51622 } 51623 } 51624 51625 var focusHandler = function focusHandler() { 51626 _this._setProperty('focused', true); 51627 }; 51628 var blurHandler = function blurHandler() { 51629 _this._setProperty('focused', false); 51630 }; 51631 window.addEventListener('focus', focusHandler); 51632 window.addEventListener('blur', blurHandler); 51633 this.registerMethod('remove', function() { 51634 window.removeEventListener('focus', focusHandler); 51635 window.removeEventListener('blur', blurHandler); 51636 }); 51637 51638 if (document.readyState === 'complete') { 51639 this._start(); 51640 } else { 51641 window.addEventListener('load', this._start.bind(this), false); 51642 } 51643 } 51644 _createClass(p5, [ 51645 { 51646 key: '_initializeInstanceVariables', 51647 value: function _initializeInstanceVariables() { 51648 this._styles = []; 51649 51650 this._bezierDetail = 20; 51651 this._curveDetail = 20; 51652 51653 this._colorMode = constants.RGB; 51654 this._colorMaxes = { 51655 rgb: [255, 255, 255, 255], 51656 hsb: [360, 100, 100, 1], 51657 hsl: [360, 100, 100, 1] 51658 }; 51659 51660 this._downKeys = {}; //Holds the key codes of currently pressed keys 51661 } 51662 }, 51663 { 51664 key: 'registerPreloadMethod', 51665 value: function registerPreloadMethod(fnString, obj) { 51666 // obj = obj || p5.prototype; 51667 if (!p5.prototype._preloadMethods.hasOwnProperty(fnString)) { 51668 p5.prototype._preloadMethods[fnString] = obj; 51669 } 51670 } 51671 }, 51672 { 51673 key: 'registerMethod', 51674 value: function registerMethod(name, m) { 51675 var target = this || p5.prototype; 51676 if (!target._registeredMethods.hasOwnProperty(name)) { 51677 target._registeredMethods[name] = []; 51678 } 51679 target._registeredMethods[name].push(m); 51680 } 51681 51682 // create a function which provides a standardized process for binding 51683 // globals; this is implemented as a factory primarily so that there's a 51684 // way to redefine what "global" means for the binding function so it 51685 // can be used in scenarios like unit testing where the window object 51686 // might not exist 51687 }, 51688 { 51689 key: '_createFriendlyGlobalFunctionBinder', 51690 value: function _createFriendlyGlobalFunctionBinder() { 51691 var options = 51692 arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; 51693 var globalObject = options.globalObject || window; 51694 var log = options.log || console.log.bind(console); 51695 var propsToForciblyOverwrite = { 51696 // p5.print actually always overwrites an existing global function, 51697 // albeit one that is very unlikely to be used: 51698 // 51699 // https://developer.mozilla.org/en-US/docs/Web/API/Window/print 51700 print: true 51701 }; 51702 51703 return function(prop, value) { 51704 if ( 51705 !p5.disableFriendlyErrors && 51706 typeof IS_MINIFIED === 'undefined' && 51707 typeof value === 'function' && 51708 !(prop in p5.prototype._preloadMethods) 51709 ) { 51710 try { 51711 // Because p5 has so many common function names, it's likely 51712 // that users may accidentally overwrite global p5 functions with 51713 // their own variables. Let's allow this but log a warning to 51714 // help users who may be doing this unintentionally. 51715 // 51716 // For more information, see: 51717 // 51718 // https://github.com/processing/p5.js/issues/1317 51719 51720 if (prop in globalObject && !(prop in propsToForciblyOverwrite)) { 51721 throw new Error('global "'.concat(prop, '" already exists')); 51722 } 51723 51724 // It's possible that this might throw an error because there 51725 // are a lot of edge-cases in which `Object.defineProperty` might 51726 // not succeed; since this functionality is only intended to 51727 // help beginners anyways, we'll just catch such an exception 51728 // if it occurs, and fall back to legacy behavior. 51729 Object.defineProperty(globalObject, prop, { 51730 configurable: true, 51731 enumerable: true, 51732 get: function get() { 51733 return value; 51734 }, 51735 set: function set(newValue) { 51736 Object.defineProperty(globalObject, prop, { 51737 configurable: true, 51738 enumerable: true, 51739 value: newValue, 51740 writable: true 51741 }); 51742 51743 log( 51744 'You just changed the value of "'.concat( 51745 prop, 51746 '", which was a p5 function. This could cause problems later if you\'re not careful.' 51747 ) 51748 ); 51749 } 51750 }); 51751 } catch (e) { 51752 log( 51753 'p5 had problems creating the global function "'.concat( 51754 prop,
51755 '", possibly because your code is already using that name as a variable. You may want to rename your variable to something else.' 51756 ) 51757 ); 51758 51759 globalObject[prop] = value; 51760 } 51761 } else { 51762 globalObject[prop] = value; 51763 } 51764 }; 51765 } 51766 } 51767 ]); 51768 return p5; 51769 })(); 51770 51771 // This is a pointer to our global mode p5 instance, if we're in 51772 // global mode. 51773 p5.instance = null; 51774 51775 /** 51776 * Allows for the friendly error system (FES) to be turned off when creating a sketch, 51777 * which can give a significant boost to performance when needed. 51778 * See <a href='https://github.com/processing/p5.js/wiki/Optimizing-p5.js-Code-for-Performance#disable-the-friendly-error-system-fes'> 51779 * disabling the friendly error system</a>. 51780 * 51781 * @property {Boolean} disableFriendlyErrors 51782 * @example 51783 * <div class="norender notest"><code> 51784 * p5.disableFriendlyErrors = true; 51785 * 51786 * function setup() { 51787 * createCanvas(100, 50); 51788 * } 51789 * </code></div> 51790 */ 51791 p5.disableFriendlyErrors = false; 51792 51793 // attach constants to p5 prototype 51794 for (var k in constants) { 51795 p5.prototype[k] = constants[k]; 51796 } 51797 51798 // functions that cause preload to wait 51799 // more can be added by using registerPreloadMethod(func) 51800 p5.prototype._preloadMethods = { 51801 loadJSON: p5.prototype, 51802 loadImage: p5.prototype, 51803 loadStrings: p5.prototype, 51804 loadXML: p5.prototype, 51805 loadBytes: p5.prototype, 51806 loadTable: p5.prototype, 51807 loadFont: p5.prototype, 51808 loadModel: p5.prototype, 51809 loadShader: p5.prototype 51810 }; 51811 51812 p5.prototype._registeredMethods = { init: [], pre: [], post: [], remove: [] }; 51813 51814 p5.prototype._registeredPreloadMethods = {}; 51815 var _default = p5; 51816 exports.default = _default; 51817 }, 51818 { './constants': 48, './shim': 70 } 51819 ], 51820 60: [ 51821 function(_dereq_, module, exports) { 51822 'use strict'; 51823 Object.defineProperty(exports, '__esModule', { value: true }); 51824 exports.default = void 0; 51825 51826 var _main = _interopRequireDefault(_dereq_('./main')); 51827 function _interopRequireDefault(obj) { 51828 return obj && obj.__esModule ? obj : { default: obj }; 51829 } 51830 /** 51831 * @module DOM 51832 * @submodule DOM 51833 * @for p5.Element 51834 */ /** 51835 * Base class for all elements added to a sketch, including canvas, 51836 * graphics buffers, and other HTML elements. It is not called directly, but <a href="#/p5.Element">p5.Element</a> 51837 * objects are created by calling <a href="#/p5/createCanvas">createCanvas</a>, <a href="#/p5/createGraphics">createGraphics</a>, 51838 * <a href="#/p5/createDiv">createDiv</a>, <a href="#/p5/createImg">createImg</a>, <a href="#/p5/createInput">createInput</a>, etc. 51839 * 51840 * @class p5.Element 51841 * @constructor 51842 * @param {String} elt DOM node that is wrapped 51843 * @param {p5} [pInst] pointer to p5 instance 51844 */ _main.default.Element = function(elt, pInst) { 51845 /** 51846 * Underlying HTML element. All normal HTML methods can be called on this. 51847 * @example 51848 * <div> 51849 * <code> 51850 * function setup() { 51851 * let c = createCanvas(50, 50); 51852 * c.elt.style.border = '5px solid red'; 51853 * } 51854 * 51855 * function draw() { 51856 * background(220); 51857 * } 51858 * </code> 51859 * </div> 51860 * 51861 * @property elt 51862 * @readOnly 51863 */ 51864 this.elt = elt; 51865 this._pInst = this._pixelsState = pInst; 51866 this._events = {}; 51867 this.width = this.elt.offsetWidth; 51868 this.height = this.elt.offsetHeight; 51869 }; 51870 51871 /** 51872 * 51873 * Attaches the element to the parent specified. A way of setting 51874 * the container for the element. Accepts either a string ID, DOM 51875 * node, or <a href="#/p5.Element">p5.Element</a>. If no arguments given, parent node is returned. 51876 * For more ways to position the canvas, see the 51877 * <a href='https://github.com/processing/p5.js/wiki/Positioning-your-canvas'> 51878 * positioning the canvas</a> wiki page. 51879 * 51880 * @method parent
51881 * @param {String|p5.Element|Object} parent the ID, DOM node, or <a href="#/p5.Element">p5.Element</a> 51882 * of desired parent element 51883 * @chainable 51884 * 51885 * @example 51886 * <div class="norender notest"><code> 51887 * // Add the following comment to html file. 51888 * // <div id="myContainer"></div> 51889 * 51890 * // The js code 51891 * let cnv = createCanvas(100, 100); 51892 * cnv.parent('myContainer'); 51893 * </code></div> 51894 * 51895 * <div class='norender'><code> 51896 * let div0 = createDiv('this is the parent'); 51897 * let div1 = createDiv('this is the child'); 51898 * div1.parent(div0); // use p5.Element 51899 * </code></div> 51900 * 51901 * <div class='norender'><code> 51902 * let div0 = createDiv('this is the parent'); 51903 * div0.id('apples'); 51904 * let div1 = createDiv('this is the child'); 51905 * div1.parent('apples'); // use id 51906 * </code></div> 51907 * 51908 * <div class='norender notest'><code> 51909 * let elt = document.getElementById('myParentDiv'); 51910 * let div1 = createDiv('this is the child'); 51911 * div1.parent(elt); // use element from page 51912 * </code></div> 51913 * 51914 * @alt 51915 * no display. 51916 */ 51917 /** 51918 * @method parent 51919 * @return {p5.Element} 51920 */ 51921 _main.default.Element.prototype.parent = function(p) { 51922 if (typeof p === 'undefined') { 51923 return this.elt.parentNode; 51924 } 51925 51926 if (typeof p === 'string') { 51927 if (p[0] === '#') { 51928 p = p.substring(1); 51929 } 51930 p = document.getElementById(p); 51931 } else if (p instanceof _main.default.Element) { 51932 p = p.elt; 51933 } 51934 p.appendChild(this.elt); 51935 return this; 51936 }; 51937 51938 /** 51939 * 51940 * Sets the ID of the element. If no ID argument is passed in, it instead 51941 * returns the current ID of the element. 51942 * Note that only one element can have a particular id in a page. 51943 * The <a href="#/p5.Element/class">.class()</a> function can be used 51944 * to identify multiple elements with the same class name. 51945 * 51946 * @method id 51947 * @param {String} id ID of the element 51948 * @chainable 51949 * 51950 * @example 51951 * <div class='norender'><code> 51952 * function setup() { 51953 * let cnv = createCanvas(100, 100); 51954 * // Assigns a CSS selector ID to 51955 * // the canvas element. 51956 * cnv.id('mycanvas'); 51957 * } 51958 * </code></div> 51959 * 51960 * @alt 51961 * no display. 51962 */ 51963 /** 51964 * @method id 51965 * @return {String} the id of the element 51966 */ 51967 _main.default.Element.prototype.id = function(id) { 51968 if (typeof id === 'undefined') { 51969 return this.elt.id; 51970 } 51971 51972 this.elt.id = id; 51973 this.width = this.elt.offsetWidth; 51974 this.height = this.elt.offsetHeight; 51975 return this; 51976 }; 51977 51978 /** 51979 * 51980 * Adds given class to the element. If no class argument is passed in, it 51981 * instead returns a string containing the current class(es) of the element. 51982 * 51983 * @method class 51984 * @param {String} class class to add 51985 * @chainable 51986 * 51987 * @example 51988 * <div class='norender'><code> 51989 * function setup() { 51990 * let cnv = createCanvas(100, 100); 51991 * // Assigns a CSS selector class 'small' 51992 * // to the canvas element. 51993 * cnv.class('small'); 51994 * } 51995 * </code></div> 51996 * 51997 * @alt 51998 * no display. 51999 */ 52000 /** 52001 * @method class 52002 * @return {String} the class of the element 52003 */ 52004 _main.default.Element.prototype.class = function(c) { 52005 if (typeof c === 'undefined') { 52006 return this.elt.className; 52007 } 52008 52009 this.elt.className = c; 52010 return this; 52011 }; 52012 52013 /** 52014 * The .<a href="#/p5.Element/mousePressed">mousePressed()</a> function is called 52015 * once after every time a mouse button is pressed over the element. Some mobile 52016 * browsers may also trigger this event on a touch screen, if the user performs 52017 * a quick tap. This can be used to attach element specific event listeners. 52018 * 52019 * @method mousePressed 52020 * @param {Function|Boolean} fxn function to be fired when mouse is 52021 * pressed over the element. 52022 * if `false` is passed instead, the previously 52023 * firing function will no longer fire. 52024 * @chainable 52025 * @example 52026 * <div class='norender'><code> 52027 * let cnv, d, g; 52028 * function setup() { 52029 * cnv = createCanvas(100, 100); 52030 * cnv.mousePressed(changeGray); // attach listener for 52031 * // canvas click only 52032 * d = 10; 52033 * g = 100; 52034 * } 52035 * 52036 * function draw() { 52037 * background(g); 52038 * ellipse(width / 2, height / 2, d, d); 52039 * } 52040 *
52041 * // this function fires with any click anywhere 52042 * function mousePressed() { 52043 * d = d + 10; 52044 * } 52045 * 52046 * // this function fires only when cnv is clicked 52047 * function changeGray() { 52048 * g = random(0, 255); 52049 * } 52050 * </code></div> 52051 * 52052 * @alt 52053 * no display. 52054 */ 52055 _main.default.Element.prototype.mousePressed = function(fxn) { 52056 // Prepend the mouse property setters to the event-listener. 52057 // This is required so that mouseButton is set correctly prior to calling the callback (fxn). 52058 // For details, see https://github.com/processing/p5.js/issues/3087. 52059 var eventPrependedFxn = function eventPrependedFxn(event) { 52060 this._pInst._setProperty('mouseIsPressed', true); 52061 this._pInst._setMouseButton(event); 52062 // Pass along the return-value of the callback: 52063 return fxn.call(this); 52064 }; 52065 // Pass along the event-prepended form of the callback. 52066 _main.default.Element._adjustListener('mousedown', eventPrependedFxn, this); 52067 return this; 52068 }; 52069 52070 /** 52071 * The .<a href="#/p5.Element/doubleClicked">doubleClicked()</a> function is called once after every time a 52072 * mouse button is pressed twice over the element. This can be used to 52073 * attach element and action specific event listeners. 52074 * 52075 * @method doubleClicked 52076 * @param {Function|Boolean} fxn function to be fired when mouse is 52077 * double clicked over the element. 52078 * if `false` is passed instead, the previously 52079 * firing function will no longer fire. 52080 * @return {p5.Element} 52081 * @example 52082 * <div class='norender'><code> 52083 * let cnv, d, g; 52084 * function setup() { 52085 * cnv = createCanvas(100, 100); 52086 * cnv.doubleClicked(changeGray); // attach listener for 52087 * // canvas double click only 52088 * d = 10; 52089 * g = 100; 52090 * } 52091 * 52092 * function draw() { 52093 * background(g); 52094 * ellipse(width / 2, height / 2, d, d); 52095 * } 52096 * 52097 * // this function fires with any double click anywhere 52098 * function doubleClicked() { 52099 * d = d + 10; 52100 * } 52101 * 52102 * // this function fires only when cnv is double clicked 52103 * function changeGray() { 52104 * g = random(0, 255); 52105 * } 52106 * </code></div> 52107 * 52108 * @alt 52109 * no display. 52110 */ 52111 _main.default.Element.prototype.doubleClicked = function(fxn) { 52112 _main.default.Element._adjustListener('dblclick', fxn, this); 52113 return this; 52114 }; 52115 52116 /** 52117 * The <a href="#/p5.Element/mouseWheel">mouseWheel()</a> function is called 52118 * once after every time a mouse wheel is scrolled over the element. This can 52119 * be used to attach element specific event listeners. 52120 * 52121 * The function accepts a callback function as argument which will be executed 52122 * when the `wheel` event is triggered on the element, the callback function is 52123 * passed one argument `event`. The `event.deltaY` property returns negative 52124 * values if the mouse wheel is rotated up or away from the user and positive 52125 * in the other direction. The `event.deltaX` does the same as `event.deltaY` 52126 * except it reads the horizontal wheel scroll of the mouse wheel. 52127 * 52128 * On OS X with "natural" scrolling enabled, the `event.deltaY` values are 52129 * reversed. 52130 * 52131 * @method mouseWheel 52132 * @param {Function|Boolean} fxn function to be fired when mouse is 52133 * scrolled over the element. 52134 * if `false` is passed instead, the previously 52135 * firing function will no longer fire. 52136 * @chainable 52137 * @example 52138 * <div class='norender'><code> 52139 * let cnv, d, g; 52140 * function setup() { 52141 * cnv = createCanvas(100, 100); 52142 * cnv.mouseWheel(changeSize); // attach listener for 52143 * // activity on canvas only 52144 * d = 10; 52145 * g = 100; 52146 * } 52147 * 52148 * function draw() { 52149 * background(g); 52150 * ellipse(width / 2, height / 2, d, d); 52151 * } 52152 * 52153 * // this function fires with mousewheel movement 52154 * // anywhere on screen 52155 * function mouseWheel() { 52156 * g = g + 10; 52157 * } 52158 * 52159 * // this function fires with mousewheel movement 52160 * // over canvas only 52161 * function changeSize(event) { 52162 * if (event.deltaY > 0) { 52163 * d = d + 10; 52164 * } else { 52165 * d = d - 10; 52166 * } 52167 * } 52168 * </code></div> 52169 * 52170 * @alt
52171 * no display. 52172 */ 52173 _main.default.Element.prototype.mouseWheel = function(fxn) { 52174 _main.default.Element._adjustListener('wheel', fxn, this); 52175 return this; 52176 }; 52177 52178 /** 52179 * The <a href="#/p5.Element/mouseReleased">mouseReleased()</a> function is 52180 * called once after every time a mouse button is released over the element. 52181 * Some mobile browsers may also trigger this event on a touch screen, if the 52182 * user performs a quick tap. This can be used to attach element specific event listeners. 52183 * 52184 * @method mouseReleased 52185 * @param {Function|Boolean} fxn function to be fired when mouse is 52186 * released over the element. 52187 * if `false` is passed instead, the previously 52188 * firing function will no longer fire. 52189 * @chainable 52190 * @example 52191 * <div class='norender'><code> 52192 * let cnv, d, g; 52193 * function setup() { 52194 * cnv = createCanvas(100, 100); 52195 * cnv.mouseReleased(changeGray); // attach listener for 52196 * // activity on canvas only 52197 * d = 10; 52198 * g = 100; 52199 * } 52200 * 52201 * function draw() { 52202 * background(g); 52203 * ellipse(width / 2, height / 2, d, d); 52204 * } 52205 * 52206 * // this function fires after the mouse has been 52207 * // released 52208 * function mouseReleased() { 52209 * d = d + 10; 52210 * } 52211 * 52212 * // this function fires after the mouse has been 52213 * // released while on canvas 52214 * function changeGray() { 52215 * g = random(0, 255); 52216 * } 52217 * </code></div> 52218 * 52219 * @alt 52220 * no display. 52221 */ 52222 _main.default.Element.prototype.mouseReleased = function(fxn) { 52223 _main.default.Element._adjustListener('mouseup', fxn, this); 52224 return this; 52225 }; 52226 52227 /** 52228 * The .<a href="#/p5.Element/mouseClicked">mouseClicked()</a> function is 52229 * called once after a mouse button is pressed and released over the element. 52230 * Some mobile browsers may also trigger this event on a touch screen, if the 52231 * user performs a quick tap.This can be used to attach element specific event listeners. 52232 * 52233 * @method mouseClicked 52234 * @param {Function|Boolean} fxn function to be fired when mouse is 52235 * clicked over the element. 52236 * if `false` is passed instead, the previously 52237 * firing function will no longer fire. 52238 * @chainable 52239 * @example 52240 * <div class="norender"> 52241 * <code> 52242 * let cnv, d, g; 52243 * function setup() { 52244 * cnv = createCanvas(100, 100); 52245 * cnv.mouseClicked(changeGray); // attach listener for 52246 * // activity on canvas only 52247 * d = 10; 52248 * g = 100; 52249 * } 52250 * 52251 * function draw() { 52252 * background(g); 52253 * ellipse(width / 2, height / 2, d, d); 52254 * } 52255 * 52256 * // this function fires after the mouse has been 52257 * // clicked anywhere 52258 * function mouseClicked() { 52259 * d = d + 10; 52260 * } 52261 * 52262 * // this function fires after the mouse has been 52263 * // clicked on canvas 52264 * function changeGray() { 52265 * g = random(0, 255); 52266 * } 52267 * </code> 52268 * </div> 52269 * 52270 * @alt 52271 * no display. 52272 */ 52273 _main.default.Element.prototype.mouseClicked = function(fxn) { 52274 _main.default.Element._adjustListener('click', fxn, this); 52275 return this; 52276 }; 52277 52278 /** 52279 * The .<a href="#/p5.Element/mouseMoved">mouseMoved()</a> function is called once every time a 52280 * mouse moves over the element. This can be used to attach an 52281 * element specific event listener. 52282 * 52283 * @method mouseMoved 52284 * @param {Function|Boolean} fxn function to be fired when a mouse moves 52285 * over the element. 52286 * if `false` is passed instead, the previously 52287 * firing function will no longer fire. 52288 * @chainable 52289 * @example 52290 * <div class='norender'><code> 52291 * let cnv; 52292 * let d = 30; 52293 * let g; 52294 * function setup() { 52295 * cnv = createCanvas(100, 100);
52296 * cnv.mouseMoved(changeSize); // attach listener for 52297 * // activity on canvas only 52298 * d = 10; 52299 * g = 100; 52300 * } 52301 * 52302 * function draw() { 52303 * background(g); 52304 * fill(200); 52305 * ellipse(width / 2, height / 2, d, d); 52306 * } 52307 * 52308 * // this function fires when mouse moves anywhere on 52309 * // page 52310 * function mouseMoved() { 52311 * g = g + 5; 52312 * if (g > 255) { 52313 * g = 0; 52314 * } 52315 * } 52316 * 52317 * // this function fires when mouse moves over canvas 52318 * function changeSize() { 52319 * d = d + 2; 52320 * if (d > 100) { 52321 * d = 0; 52322 * } 52323 * } 52324 * </code></div> 52325 * 52326 * @alt 52327 * no display. 52328 */ 52329 _main.default.Element.prototype.mouseMoved = function(fxn) { 52330 _main.default.Element._adjustListener('mousemove', fxn, this); 52331 return this; 52332 }; 52333 52334 /** 52335 * The .<a href="#/p5.Element/mouseOver">mouseOver()</a> function is called once after every time a 52336 * mouse moves onto the element. This can be used to attach an 52337 * element specific event listener. 52338 * 52339 * @method mouseOver 52340 * @param {Function|Boolean} fxn function to be fired when a mouse moves 52341 * onto the element. 52342 * if `false` is passed instead, the previously 52343 * firing function will no longer fire. 52344 * @chainable 52345 * @example 52346 * <div class='norender'><code> 52347 * let cnv; 52348 * let d; 52349 * function setup() { 52350 * cnv = createCanvas(100, 100); 52351 * cnv.mouseOver(changeGray); 52352 * d = 10; 52353 * } 52354 * 52355 * function draw() { 52356 * ellipse(width / 2, height / 2, d, d); 52357 * } 52358 * 52359 * function changeGray() { 52360 * d = d + 10; 52361 * if (d > 100) { 52362 * d = 0; 52363 * } 52364 * } 52365 * </code></div> 52366 * 52367 * @alt 52368 * no display. 52369 */ 52370 _main.default.Element.prototype.mouseOver = function(fxn) { 52371 _main.default.Element._adjustListener('mouseover', fxn, this); 52372 return this; 52373 }; 52374 52375 /** 52376 * The .<a href="#/p5.Element/mouseOut">mouseOut()</a> function is called once after every time a 52377 * mouse moves off the element. This can be used to attach an 52378 * element specific event listener. 52379 * 52380 * @method mouseOut 52381 * @param {Function|Boolean} fxn function to be fired when a mouse 52382 * moves off of an element. 52383 * if `false` is passed instead, the previously 52384 * firing function will no longer fire. 52385 * @chainable 52386 * @example 52387 * <div class='norender'><code> 52388 * let cnv; 52389 * let d; 52390 * function setup() { 52391 * cnv = createCanvas(100, 100); 52392 * cnv.mouseOut(changeGray); 52393 * d = 10; 52394 * } 52395 * 52396 * function draw() { 52397 * ellipse(width / 2, height / 2, d, d); 52398 * } 52399 * 52400 * function changeGray() { 52401 * d = d + 10; 52402 * if (d > 100) { 52403 * d = 0; 52404 * } 52405 * } 52406 * </code></div> 52407 * 52408 * @alt 52409 * no display. 52410 */ 52411 _main.default.Element.prototype.mouseOut = function(fxn) { 52412 _main.default.Element._adjustListener('mouseout', fxn, this); 52413 return this; 52414 }; 52415 52416 /** 52417 * The .<a href="#/p5.Element/touchStarted">touchStarted()</a> function is called once after every time a touch is 52418 * registered. This can be used to attach element specific event listeners. 52419 * 52420 * @method touchStarted 52421 * @param {Function|Boolean} fxn function to be fired when a touch 52422 * starts over the element. 52423 * if `false` is passed instead, the previously 52424 * firing function will no longer fire. 52425 * @chainable 52426 * @example 52427 * <div class='norender'><code> 52428 * let cnv; 52429 * let d; 52430 * let g; 52431 * function setup() { 52432 * cnv = createCanvas(100, 100);
52433 * cnv.touchStarted(changeGray); // attach listener for 52434 * // canvas click only 52435 * d = 10; 52436 * g = 100; 52437 * } 52438 * 52439 * function draw() { 52440 * background(g); 52441 * ellipse(width / 2, height / 2, d, d); 52442 * } 52443 * 52444 * // this function fires with any touch anywhere 52445 * function touchStarted() { 52446 * d = d + 10; 52447 * } 52448 * 52449 * // this function fires only when cnv is clicked 52450 * function changeGray() { 52451 * g = random(0, 255); 52452 * } 52453 * </code></div> 52454 * 52455 * @alt 52456 * no display. 52457 */ 52458 _main.default.Element.prototype.touchStarted = function(fxn) { 52459 _main.default.Element._adjustListener('touchstart', fxn, this); 52460 return this; 52461 }; 52462 52463 /** 52464 * The .<a href="#/p5.Element/touchMoved">touchMoved()</a> function is called once after every time a touch move is 52465 * registered. This can be used to attach element specific event listeners. 52466 * 52467 * @method touchMoved 52468 * @param {Function|Boolean} fxn function to be fired when a touch moves over 52469 * the element. 52470 * if `false` is passed instead, the previously 52471 * firing function will no longer fire. 52472 * @chainable 52473 * @example 52474 * <div class='norender'><code> 52475 * let cnv; 52476 * let g; 52477 * function setup() { 52478 * cnv = createCanvas(100, 100); 52479 * cnv.touchMoved(changeGray); // attach listener for 52480 * // canvas click only 52481 * g = 100; 52482 * } 52483 * 52484 * function draw() { 52485 * background(g); 52486 * } 52487 * 52488 * // this function fires only when cnv is clicked 52489 * function changeGray() { 52490 * g = random(0, 255); 52491 * } 52492 * </code></div> 52493 * 52494 * @alt 52495 * no display. 52496 */ 52497 _main.default.Element.prototype.touchMoved = function(fxn) { 52498 _main.default.Element._adjustListener('touchmove', fxn, this); 52499 return this; 52500 }; 52501 52502 /** 52503 * The .<a href="#/p5.Element/touchEnded">touchEnded()</a> function is called once after every time a touch is 52504 * registered. This can be used to attach element specific event listeners. 52505 * 52506 * @method touchEnded 52507 * @param {Function|Boolean} fxn function to be fired when a touch ends 52508 * over the element. 52509 * if `false` is passed instead, the previously 52510 * firing function will no longer fire. 52511 * @chainable 52512 * @example 52513 * <div class='norender'><code> 52514 * let cnv; 52515 * let d; 52516 * let g; 52517 * function setup() { 52518 * cnv = createCanvas(100, 100); 52519 * cnv.touchEnded(changeGray); // attach listener for 52520 * // canvas click only 52521 * d = 10; 52522 * g = 100; 52523 * } 52524 * 52525 * function draw() { 52526 * background(g); 52527 * ellipse(width / 2, height / 2, d, d); 52528 * } 52529 * 52530 * // this function fires with any touch anywhere 52531 * function touchEnded() { 52532 * d = d + 10; 52533 * } 52534 * 52535 * // this function fires only when cnv is clicked 52536 * function changeGray() { 52537 * g = random(0, 255); 52538 * } 52539 * </code></div> 52540 * 52541 * @alt 52542 * no display. 52543 */ 52544 _main.default.Element.prototype.touchEnded = function(fxn) { 52545 _main.default.Element._adjustListener('touchend', fxn, this); 52546 return this; 52547 }; 52548 52549 /** 52550 * The .<a href="#/p5.Element/dragOver">dragOver()</a> function is called once after every time a 52551 * file is dragged over the element. This can be used to attach an 52552 * element specific event listener. 52553 * 52554 * @method dragOver 52555 * @param {Function|Boolean} fxn function to be fired when a file is 52556 * dragged over the element. 52557 * if `false` is passed instead, the previously 52558 * firing function will no longer fire. 52559 * @chainable 52560 * @example 52561 * <div><code> 52562 * // To test this sketch, simply drag a 52563 * // file over the canvas 52564 * function setup() { 52565 * let c = createCanvas(100, 100); 52566 * background(200); 52567 * textAlign(CENTER); 52568 * text('Drag file', width / 2, height / 2); 52569 * c.dragOver(dragOverCallback); 52570 * } 52571 * 52572 * // This function will be called whenever 52573 * // a file is dragged over the canvas 52574 * function dragOverCallback() { 52575 * background(240); 52576 * text('Dragged over', width / 2, height / 2); 52577 * } 52578 * </code></div> 52579 * @alt 52580 * nothing displayed 52581 */ 52582 _main.default.Element.prototype.dragOver = function(fxn) { 52583 _main.default.Element._adjustListener('dragover', fxn, this); 52584 return this; 52585 }; 52586 52587 /** 52588 * The .dragLeave() function is called once after every time a 52589 * dragged file leaves the element area. This can be used to attach an 52590 * element specific event listener. 52591 * 52592 * @method dragLeave 52593 * @param {Function|Boolean} fxn function to be fired when a file is 52594 * dragged off the element. 52595 * if `false` is passed instead, the previously 52596 * firing function will no longer fire. 52597 * @chainable 52598 * @example 52599 * <div><code> 52600 * // To test this sketch, simply drag a file 52601 * // over and then out of the canvas area 52602 * function setup() { 52603 * let c = createCanvas(100, 100); 52604 * background(200); 52605 * textAlign(CENTER); 52606 * text('Drag file', width / 2, height / 2); 52607 * c.dragLeave(dragLeaveCallback); 52608 * } 52609 * 52610 * // This function will be called whenever 52611 * // a file is dragged out of the canvas 52612 * function dragLeaveCallback() { 52613 * background(240); 52614 * text('Dragged off', width / 2, height / 2); 52615 * } 52616 * </code></div> 52617 * @alt 52618 * nothing displayed 52619 */ 52620 _main.default.Element.prototype.dragLeave = function(fxn) { 52621 _main.default.Element._adjustListener('dragleave', fxn, this); 52622 return this; 52623 }; 52624 52625 // General handler for event attaching and detaching 52626 _main.default.Element._adjustListener = function(ev, fxn, ctx) { 52627 if (fxn === false) { 52628 _main.default.Element._detachListener(ev, ctx); 52629 } else { 52630 _main.default.Element._attachListener(ev, fxn, ctx); 52631 } 52632 return this; 52633 }; 52634 52635 _main.default.Element._attachListener = function(ev, fxn, ctx) { 52636 // detach the old listener if there was one 52637 if (ctx._events[ev]) { 52638 _main.default.Element._detachListener(ev, ctx); 52639 } 52640 var f = fxn.bind(ctx); 52641 ctx.elt.addEventListener(ev, f, false); 52642 ctx._events[ev] = f; 52643 }; 52644 52645 _main.default.Element._detachListener = function(ev, ctx) { 52646 var f = ctx._events[ev]; 52647 ctx.elt.removeEventListener(ev, f, false); 52648 ctx._events[ev] = null; 52649 }; 52650 52651 /** 52652 * Helper fxn for sharing pixel methods 52653 */ 52654 _main.default.Element.prototype._setProperty = function(prop, value) { 52655 this[prop] = value; 52656 }; 52657 var _default = _main.default.Element; 52658 exports.default = _default; 52659 }, 52660 { './main': 59 } 52661 ], 52662 61: [
52663 function(_dereq_, module, exports) { 52664 'use strict'; 52665 function _typeof(obj) { 52666 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') { 52667 _typeof = function _typeof(obj) { 52668 return typeof obj; 52669 }; 52670 } else { 52671 _typeof = function _typeof(obj) { 52672 return obj && 52673 typeof Symbol === 'function' && 52674 obj.constructor === Symbol && 52675 obj !== Symbol.prototype 52676 ? 'symbol' 52677 : typeof obj; 52678 }; 52679 } 52680 return _typeof(obj); 52681 } 52682 Object.defineProperty(exports, '__esModule', { value: true }); 52683 exports.default = void 0; 52684 52685 var _main = _interopRequireDefault(_dereq_('./main')); 52686 var constants = _interopRequireWildcard(_dereq_('./constants')); 52687 function _getRequireWildcardCache() { 52688 if (typeof WeakMap !== 'function') return null; 52689 var cache = new WeakMap(); 52690 _getRequireWildcardCache = function _getRequireWildcardCache() { 52691 return cache; 52692 }; 52693 return cache; 52694 } 52695 function _interopRequireWildcard(obj) { 52696 if (obj && obj.__esModule) { 52697 return obj; 52698 } 52699 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) { 52700 return { default: obj }; 52701 } 52702 var cache = _getRequireWildcardCache(); 52703 if (cache && cache.has(obj)) { 52704 return cache.get(obj); 52705 } 52706 var newObj = {}; 52707 var hasPropertyDescriptor = 52708 Object.defineProperty && Object.getOwnPropertyDescriptor; 52709 for (var key in obj) { 52710 if (Object.prototype.hasOwnProperty.call(obj, key)) { 52711 var desc = hasPropertyDescriptor 52712 ? Object.getOwnPropertyDescriptor(obj, key) 52713 : null; 52714 if (desc && (desc.get || desc.set)) { 52715 Object.defineProperty(newObj, key, desc); 52716 } else { 52717 newObj[key] = obj[key]; 52718 } 52719 } 52720 } 52721 newObj.default = obj; 52722 if (cache) { 52723 cache.set(obj, newObj); 52724 } 52725 return newObj; 52726 } 52727 function _interopRequireDefault(obj) { 52728 return obj && obj.__esModule ? obj : { default: obj }; 52729 } 52730 /** 52731 * @module Rendering 52732 * @submodule Rendering 52733 * @for p5 52734 */ /** 52735 * Thin wrapper around a renderer, to be used for creating a 52736 * graphics buffer object. Use this class if you need 52737 * to draw into an off-screen graphics buffer. The two parameters define the 52738 * width and height in pixels. The fields and methods for this class are 52739 * extensive, but mirror the normal drawing API for p5. 52740 * 52741 * @class p5.Graphics 52742 * @constructor 52743 * @extends p5.Element 52744 * @param {Number} w width 52745 * @param {Number} h height 52746 * @param {Constant} renderer the renderer to use, either P2D or WEBGL 52747 * @param {p5} [pInst] pointer to p5 instance 52748 */ _main.default.Graphics = function(w, h, renderer, pInst) { 52749 var r = renderer || constants.P2D; 52750 52751 this.canvas = document.createElement('canvas'); 52752 var node = pInst._userNode || document.body; 52753 node.appendChild(this.canvas); 52754 52755 _main.default.Element.call(this, this.canvas, pInst); 52756 52757 // bind methods and props of p5 to the new object 52758 for (var p in _main.default.prototype) { 52759 if (!this[p]) { 52760 if (typeof _main.default.prototype[p] === 'function') { 52761 this[p] = _main.default.prototype[p].bind(this); 52762 } else { 52763 this[p] = _main.default.prototype[p]; 52764 } 52765 } 52766 } 52767 52768 _main.default.prototype._initializeInstanceVariables.apply(this); 52769 this.width = w; 52770 this.height = h; 52771 this._pixelDensity = pInst._pixelDensity; 52772 52773 if (r === constants.WEBGL) { 52774 this._renderer = new _main.default.RendererGL(this.canvas, this, false); 52775 } else { 52776 this._renderer = new _main.default.Renderer2D(this.canvas, this, false); 52777 } 52778 pInst._elements.push(this); 52779 52780 Object.defineProperty(this, 'deltaTime', { 52781 get: function get() { 52782 return this._pInst.deltaTime; 52783 } 52784 }); 52785 52786 this._renderer.resize(w, h); 52787 this._renderer._applyDefaults(); 52788 return this; 52789 }; 52790 52791 _main.default.Graphics.prototype = Object.create(_main.default.Element.prototype); 52792 52793 /** 52794 * Resets certain values such as those modified by functions in the Transform category 52795 * and in the Lights category that are not automatically reset 52796 * with graphics buffer objects. Calling this in <a href='#/p5/draw'>draw()</a> will copy the behavior 52797 * of the standard canvas. 52798 * 52799 * @method reset 52800 * @example 52801 * 52802 * <div><code> 52803 * let pg; 52804 * function setup() { 52805 * createCanvas(100, 100); 52806 * background(0); 52807 * pg = createGraphics(50, 100); 52808 * pg.fill(0); 52809 * frameRate(5); 52810 * } 52811 * 52812 * function draw() { 52813 * image(pg, width / 2, 0); 52814 * pg.background(255); 52815 * // p5.Graphics object behave a bit differently in some cases 52816 * // The normal canvas on the left resets the translate 52817 * // with every loop through draw() 52818 * // the graphics object on the right doesn't automatically reset 52819 * // so translate() is additive and it moves down the screen 52820 * rect(0, 0, width / 2, 5); 52821 * pg.rect(0, 0, width / 2, 5); 52822 * translate(0, 5, 0); 52823 * pg.translate(0, 5, 0); 52824 * } 52825 * function mouseClicked() { 52826 * // if you click you will see that 52827 * // reset() resets the translate back to the initial state 52828 * // of the Graphics object 52829 * pg.reset(); 52830 * } 52831 * </code></div> 52832 * 52833 * @alt 52834 * A white line on a black background stays still on the top-left half. 52835 * A black line animates from top to bottom on a white background on the right half. 52836 * When clicked, the black line starts back over at the top. 52837 */ 52838 _main.default.Graphics.prototype.reset = function() { 52839 this._renderer.resetMatrix(); 52840 if (this._renderer.isP3D) { 52841 this._renderer._update(); 52842 } 52843 }; 52844 52845 /** 52846 * Removes a Graphics object from the page and frees any resources 52847 * associated with it. 52848 * 52849 * @method remove 52850 * 52851 * @example 52852 * <div class='norender'><code> 52853 * let bg; 52854 * function setup() { 52855 * bg = createCanvas(100, 100); 52856 * bg.background(0); 52857 * image(bg, 0, 0); 52858 * bg.remove(); 52859 * } 52860 * </code></div> 52861 * 52862 * <div><code> 52863 * let bg; 52864 * function setup() { 52865 * pixelDensity(1); 52866 * createCanvas(100, 100);
52867 * stroke(255); 52868 * fill(0); 52869 * 52870 * // create and draw the background image 52871 * bg = createGraphics(100, 100); 52872 * bg.background(200); 52873 * bg.ellipse(50, 50, 80, 80); 52874 * } 52875 * function draw() { 52876 * let t = millis() / 1000; 52877 * // draw the background 52878 * if (bg) { 52879 * image(bg, frameCount % 100, 0); 52880 * image(bg, frameCount % 100 - 100, 0); 52881 * } 52882 * // draw the foreground 52883 * let p = p5.Vector.fromAngle(t, 35).add(50, 50); 52884 * ellipse(p.x, p.y, 30); 52885 * } 52886 * function mouseClicked() { 52887 * // remove the background 52888 * if (bg) { 52889 * bg.remove(); 52890 * bg = null; 52891 * } 52892 * } 52893 * </code></div> 52894 * 52895 * @alt 52896 * no image 52897 * a multi-colored circle moving back and forth over a scrolling background. 52898 */ 52899 _main.default.Graphics.prototype.remove = function() { 52900 if (this.elt.parentNode) { 52901 this.elt.parentNode.removeChild(this.elt); 52902 } 52903 var idx = this._pInst._elements.indexOf(this); 52904 if (idx !== -1) { 52905 this._pInst._elements.splice(idx, 1); 52906 } 52907 for (var elt_ev in this._events) { 52908 this.elt.removeEventListener(elt_ev, this._events[elt_ev]); 52909 } 52910 }; 52911 var _default = _main.default.Graphics; 52912 exports.default = _default; 52913 }, 52914 { './constants': 48, './main': 59 } 52915 ], 52916 62: [ 52917 function(_dereq_, module, exports) { 52918 'use strict'; 52919 Object.defineProperty(exports, '__esModule', { value: true }); 52920 exports.default = void 0; 52921 52922 var _main = _interopRequireDefault(_dereq_('./main')); 52923 var constants = _interopRequireWildcard(_dereq_('../core/constants')); 52924 function _getRequireWildcardCache() { 52925 if (typeof WeakMap !== 'function') return null; 52926 var cache = new WeakMap(); 52927 _getRequireWildcardCache = function _getRequireWildcardCache() { 52928 return cache; 52929 }; 52930 return cache; 52931 } 52932 function _interopRequireWildcard(obj) { 52933 if (obj && obj.__esModule) { 52934 return obj; 52935 } 52936 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) { 52937 return { default: obj }; 52938 } 52939 var cache = _getRequireWildcardCache(); 52940 if (cache && cache.has(obj)) { 52941 return cache.get(obj); 52942 } 52943 var newObj = {}; 52944 var hasPropertyDescriptor = 52945 Object.defineProperty && Object.getOwnPropertyDescriptor; 52946 for (var key in obj) { 52947 if (Object.prototype.hasOwnProperty.call(obj, key)) { 52948 var desc = hasPropertyDescriptor 52949 ? Object.getOwnPropertyDescriptor(obj, key) 52950 : null; 52951 if (desc && (desc.get || desc.set)) { 52952 Object.defineProperty(newObj, key, desc); 52953 } else { 52954 newObj[key] = obj[key]; 52955 } 52956 } 52957 } 52958 newObj.default = obj; 52959 if (cache) { 52960 cache.set(obj, newObj); 52961 } 52962 return newObj; 52963 } 52964 function _interopRequireDefault(obj) { 52965 return obj && obj.__esModule ? obj : { default: obj }; 52966 } 52967 function _typeof(obj) { 52968 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') { 52969 _typeof = function _typeof(obj) { 52970 return typeof obj; 52971 }; 52972 } else { 52973 _typeof = function _typeof(obj) { 52974 return obj && 52975 typeof Symbol === 'function' && 52976 obj.constructor === Symbol && 52977 obj !== Symbol.prototype 52978 ? 'symbol' 52979 : typeof obj; 52980 }; 52981 } 52982 return _typeof(obj); 52983 } 52984 52985 /** 52986 * Main graphics and rendering context, as well as the base API 52987 * implementation for p5.js "core". To be used as the superclass for
52988 * Renderer2D and Renderer3D classes, respectively. 52989 * 52990 * @class p5.Renderer 52991 * @constructor 52992 * @extends p5.Element 52993 * @param {String} elt DOM node that is wrapped 52994 * @param {p5} [pInst] pointer to p5 instance 52995 * @param {Boolean} [isMainCanvas] whether we're using it as main canvas 52996 */ 52997 _main.default.Renderer = function(elt, pInst, isMainCanvas) { 52998 _main.default.Element.call(this, elt, pInst); 52999 this.canvas = elt; 53000 this._pixelsState = pInst; 53001 if (isMainCanvas) { 53002 this._isMainCanvas = true; 53003 // for pixel method sharing with pimage 53004 this._pInst._setProperty('_curElement', this); 53005 this._pInst._setProperty('canvas', this.canvas); 53006 this._pInst._setProperty('width', this.width); 53007 this._pInst._setProperty('height', this.height); 53008 } else { 53009 // hide if offscreen buffer by default 53010 this.canvas.style.display = 'none'; 53011 this._styles = []; // non-main elt styles stored in p5.Renderer 53012 } 53013 53014 this._textSize = 12; 53015 this._textLeading = 15; 53016 this._textFont = 'sans-serif'; 53017 this._textStyle = constants.NORMAL; 53018 this._textAscent = null; 53019 this._textDescent = null; 53020 this._textAlign = constants.LEFT; 53021 this._textBaseline = constants.BASELINE; 53022 53023 this._rectMode = constants.CORNER; 53024 this._ellipseMode = constants.CENTER; 53025 this._curveTightness = 0; 53026 this._imageMode = constants.CORNER; 53027 53028 this._tint = null; 53029 this._doStroke = true; 53030 this._doFill = true; 53031 this._strokeSet = false; 53032 this._fillSet = false; 53033 }; 53034 53035 _main.default.Renderer.prototype = Object.create(_main.default.Element.prototype); 53036 53037 // the renderer should return a 'style' object that it wishes to 53038 // store on the push stack. 53039 _main.default.Renderer.prototype.push = function() { 53040 return { 53041 properties: { 53042 _doStroke: this._doStroke, 53043 _strokeSet: this._strokeSet, 53044 _doFill: this._doFill, 53045 _fillSet: this._fillSet, 53046 _tint: this._tint, 53047 _imageMode: this._imageMode, 53048 _rectMode: this._rectMode, 53049 _ellipseMode: this._ellipseMode, 53050 _textFont: this._textFont, 53051 _textLeading: this._textLeading, 53052 _textSize: this._textSize, 53053 _textAlign: this._textAlign, 53054 _textBaseline: this._textBaseline, 53055 _textStyle: this._textStyle 53056 } 53057 }; 53058 }; 53059 53060 // a pop() operation is in progress 53061 // the renderer is passed the 'style' object that it returned 53062 // from its push() method. 53063 _main.default.Renderer.prototype.pop = function(style) { 53064 if (style.properties) { 53065 // copy the style properties back into the renderer 53066 Object.assign(this, style.properties); 53067 } 53068 }; 53069 53070 /** 53071 * Resize our canvas element. 53072 */ 53073 _main.default.Renderer.prototype.resize = function(w, h) { 53074 this.width = w; 53075 this.height = h; 53076 this.elt.width = w * this._pInst._pixelDensity; 53077 this.elt.height = h * this._pInst._pixelDensity; 53078 this.elt.style.width = ''.concat(w, 'px'); 53079 this.elt.style.height = ''.concat(h, 'px'); 53080 if (this._isMainCanvas) { 53081 this._pInst._setProperty('width', this.width); 53082 this._pInst._setProperty('height', this.height); 53083 } 53084 }; 53085 53086 _main.default.Renderer.prototype.get = function(x, y, w, h) { 53087 var pixelsState = this._pixelsState; 53088 var pd = pixelsState._pixelDensity; 53089 var canvas = this.canvas; 53090 53091 if (typeof x === 'undefined' && typeof y === 'undefined') { 53092 // get() 53093 x = y = 0; 53094 w = pixelsState.width; 53095 h = pixelsState.height; 53096 } else { 53097 x *= pd; 53098 y *= pd; 53099 53100 if (typeof w === 'undefined' && typeof h === 'undefined') { 53101 // get(x,y) 53102 if (x < 0 || y < 0 || x >= canvas.width || y >= canvas.height) { 53103 return [0, 0, 0, 0]; 53104 } 53105 53106 return this._getPixel(x, y); 53107 } 53108 // get(x,y,w,h) 53109 } 53110 53111 var region = new _main.default.Image(w, h); 53112 region.canvas 53113 .getContext('2d') 53114 .drawImage(canvas, x, y, w * pd, h * pd, 0, 0, w, h); 53115 53116 return region; 53117 }; 53118 53119 _main.default.Renderer.prototype.textLeading = function(l) { 53120 if (typeof l === 'number') { 53121 this._setProperty('_textLeading', l); 53122 return this._pInst; 53123 } 53124 53125 return this._textLeading; 53126 }; 53127 53128 _main.default.Renderer.prototype.textSize = function(s) { 53129 if (typeof s === 'number') { 53130 this._setProperty('_textSize', s); 53131 this._setProperty('_textLeading', s * constants._DEFAULT_LEADMULT); 53132 return this._applyTextProperties(); 53133 } 53134 53135 return this._textSize; 53136 }; 53137 53138 _main.default.Renderer.prototype.textStyle = function(s) { 53139 if (s) { 53140 if ( 53141 s === constants.NORMAL || 53142 s === constants.ITALIC || 53143 s === constants.BOLD || 53144 s === constants.BOLDITALIC 53145 ) { 53146 this._setProperty('_textStyle', s); 53147 } 53148 53149 return this._applyTextProperties(); 53150 } 53151 53152 return this._textStyle; 53153 }; 53154 53155 _main.default.Renderer.prototype.textAscent = function() { 53156 if (this._textAscent === null) { 53157 this._updateTextMetrics(); 53158 } 53159 return this._textAscent; 53160 }; 53161 53162 _main.default.Renderer.prototype.textDescent = function() { 53163 if (this._textDescent === null) { 53164 this._updateTextMetrics(); 53165 } 53166 return this._textDescent; 53167 }; 53168 53169 _main.default.Renderer.prototype.textAlign = function(h, v) { 53170 if (typeof h !== 'undefined') { 53171 this._setProperty('_textAlign', h); 53172 53173 if (typeof v !== 'undefined') { 53174 this._setProperty('_textBaseline', v); 53175 } 53176 53177 return this._applyTextProperties(); 53178 } else { 53179 return { 53180 horizontal: this._textAlign, 53181 vertical: this._textBaseline 53182 }; 53183 } 53184 }; 53185 53186 _main.default.Renderer.prototype.text = function(str, x, y, maxWidth, maxHeight) { 53187 var p = this._pInst; 53188 var cars; 53189 var n; 53190 var ii; 53191 var jj; 53192 var line; 53193 var testLine; 53194 var testWidth; 53195 var words; 53196 var totalHeight; 53197 var shiftedY; 53198 var finalMaxHeight = Number.MAX_VALUE; 53199 53200 if (!(this._doFill || this._doStroke)) { 53201 return; 53202 } 53203 53204 if (typeof str === 'undefined') { 53205 return; 53206 } else if (typeof str !== 'string') { 53207 str = str.toString(); 53208 } 53209 53210 str = str.replace(/(\t)/g, ' '); 53211 cars = str.split('\n'); 53212 53213 if (typeof maxWidth !== 'undefined') { 53214 totalHeight = 0; 53215 for (ii = 0; ii < cars.length; ii++) { 53216 line = ''; 53217 words = cars[ii].split(' '); 53218 for (n = 0; n < words.length; n++) { 53219 testLine = ''.concat(line + words[n], ' '); 53220 testWidth = this.textWidth(testLine); 53221 if (testWidth > maxWidth) { 53222 var currentWord = words[n]; 53223 for (var index = 0; index < currentWord.length; index++) { 53224 testLine = ''.concat(line + currentWord[index]); 53225 testWidth = this.textWidth(testLine); 53226 if (testWidth > maxWidth && line.length > 0) { 53227 line = ''.concat(currentWord[index]); 53228 totalHeight += p.textLeading(); 53229 } else { 53230 line = testLine; 53231 } 53232 } 53233 line = ''.concat(line, ' '); 53234 } else { 53235 line = testLine; 53236 } 53237 } 53238 if (ii < cars.length - 1) { 53239 totalHeight += p.textLeading(); 53240 } 53241 } 53242 53243 if (this._rectMode === constants.CENTER) { 53244 x -= maxWidth / 2; 53245 y -= maxHeight / 2; 53246 } 53247 53248 switch (this._textAlign) { 53249 case constants.CENTER: 53250 x += maxWidth / 2; 53251 break; 53252 case constants.RIGHT: 53253 x += maxWidth; 53254 break; 53255 } 53256 53257 var baselineHacked = false;
53258 if (typeof maxHeight !== 'undefined') { 53259 switch (this._textBaseline) { 53260 case constants.BOTTOM: 53261 shiftedY = y + (maxHeight - totalHeight); 53262 y = Math.max(shiftedY, y); 53263 break; 53264 case constants.CENTER: 53265 shiftedY = y + (maxHeight - totalHeight) / 2; 53266 y = Math.max(shiftedY, y); 53267 break; 53268 case constants.BASELINE: 53269 baselineHacked = true; 53270 this._textBaseline = constants.TOP; 53271 break; 53272 } 53273 53274 // remember the max-allowed y-position for any line (fix to #928) 53275 finalMaxHeight = y + maxHeight - p.textAscent(); 53276 } 53277 53278 for (ii = 0; ii < cars.length; ii++) { 53279 line = ''; 53280 words = cars[ii].split(' '); 53281 for (n = 0; n < words.length; n++) { 53282 testLine = ''.concat(line + words[n], ' '); 53283 testWidth = this.textWidth(testLine); 53284 if (testWidth > maxWidth) { 53285 var _currentWord = words[n]; 53286 for (var _index = 0; _index < _currentWord.length; _index++) { 53287 testLine = ''.concat(line + _currentWord[_index]); 53288 testWidth = this.textWidth(testLine); 53289 if (testWidth > maxWidth && line.length > 0) { 53290 var lastChar = line.slice(-1); 53291 var shouldAddHyphen = lastChar !== '\n' && lastChar !== ' '; 53292 line = ''.concat(line).concat(shouldAddHyphen ? '-' : ''); 53293 53294 this._renderText(p, line, x, y, finalMaxHeight); 53295 y += p.textLeading(); 53296 53297 line = ''.concat(_currentWord[_index]); 53298 } else { 53299 line = testLine; 53300 } 53301 } 53302 line = ''.concat(line, ' '); 53303 } else { 53304 line = testLine; 53305 } 53306 } 53307 53308 this._renderText(p, line, x, y, finalMaxHeight); 53309 y += p.textLeading(); 53310 53311 if (baselineHacked) { 53312 this._textBaseline = constants.BASELINE; 53313 } 53314 } 53315 } else { 53316 // Offset to account for vertically centering multiple lines of text - no 53317 // need to adjust anything for vertical align top or baseline 53318 var offset = 0; 53319 53320 var vAlign = p.textAlign().vertical; 53321 if (vAlign === constants.CENTER) { 53322 offset = (cars.length - 1) * p.textLeading() / 2; 53323 } else if (vAlign === constants.BOTTOM) { 53324 offset = (cars.length - 1) * p.textLeading(); 53325 } 53326 53327 for (jj = 0; jj < cars.length; jj++) { 53328 this._renderText(p, cars[jj], x, y - offset, finalMaxHeight); 53329 y += p.textLeading(); 53330 } 53331 } 53332 53333 return p; 53334 }; 53335 53336 _main.default.Renderer.prototype._applyDefaults = function() { 53337 return this; 53338 }; 53339 53340 /** 53341 * Helper fxn to check font type (system or otf) 53342 */ 53343 _main.default.Renderer.prototype._isOpenType = function() { 53344 var f = 53345 arguments.length > 0 && arguments[0] !== undefined 53346 ? arguments[0] 53347 : this._textFont; 53348 return _typeof(f) === 'object' && f.font && f.font.supported; 53349 }; 53350 53351 _main.default.Renderer.prototype._updateTextMetrics = function() { 53352 if (this._isOpenType()) { 53353 this._setProperty('_textAscent', this._textFont._textAscent()); 53354 this._setProperty('_textDescent', this._textFont._textDescent()); 53355 return this; 53356 } 53357 53358 // Adapted from http://stackoverflow.com/a/25355178 53359 var text = document.createElement('span'); 53360 text.style.fontFamily = this._textFont; 53361 text.style.fontSize = ''.concat(this._textSize, 'px'); 53362 text.innerHTML = 'ABCjgq|'; 53363 53364 var block = document.createElement('div'); 53365 block.style.display = 'inline-block'; 53366 block.style.width = '1px'; 53367 block.style.height = '0px'; 53368 53369 var container = document.createElement('div'); 53370 container.appendChild(text); 53371 container.appendChild(block); 53372 53373 container.style.height = '0px'; 53374 container.style.overflow = 'hidden'; 53375 document.body.appendChild(container); 53376 53377 block.style.verticalAlign = 'baseline'; 53378 var blockOffset = calculateOffset(block); 53379 var textOffset = calculateOffset(text); 53380 var ascent = blockOffset[1] - textOffset[1]; 53381 53382 block.style.verticalAlign = 'bottom'; 53383 blockOffset = calculateOffset(block); 53384 textOffset = calculateOffset(text); 53385 var height = blockOffset[1] - textOffset[1]; 53386 var descent = height - ascent; 53387 53388 document.body.removeChild(container); 53389 53390 this._setProperty('_textAscent', ascent); 53391 this._setProperty('_textDescent', descent); 53392 53393 return this; 53394 }; 53395 53396 /**
53397 * Helper fxn to measure ascent and descent. 53398 * Adapted from http://stackoverflow.com/a/25355178 53399 */ 53400 function calculateOffset(object) { 53401 var currentLeft = 0, 53402 currentTop = 0; 53403 if (object.offsetParent) { 53404 do { 53405 currentLeft += object.offsetLeft; 53406 currentTop += object.offsetTop; 53407 } while ((object = object.offsetParent)); 53408 } else { 53409 currentLeft += object.offsetLeft; 53410 currentTop += object.offsetTop; 53411 } 53412 return [currentLeft, currentTop]; 53413 } 53414 var _default = _main.default.Renderer; 53415 exports.default = _default; 53416 }, 53417 { '../core/constants': 48, './main': 59 } 53418 ], 53419 63: [ 53420 function(_dereq_, module, exports) { 53421 'use strict'; 53422 function _typeof(obj) { 53423 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') { 53424 _typeof = function _typeof(obj) { 53425 return typeof obj; 53426 }; 53427 } else { 53428 _typeof = function _typeof(obj) { 53429 return obj && 53430 typeof Symbol === 'function' && 53431 obj.constructor === Symbol && 53432 obj !== Symbol.prototype 53433 ? 'symbol' 53434 : typeof obj; 53435 }; 53436 } 53437 return _typeof(obj); 53438 } 53439 Object.defineProperty(exports, '__esModule', { value: true }); 53440 exports.default = void 0; 53441 var _main = _interopRequireDefault(_dereq_('./main')); 53442 var constants = _interopRequireWildcard(_dereq_('./constants')); 53443 var _filters = _interopRequireDefault(_dereq_('../image/filters')); 53444 53445 _dereq_('./p5.Renderer'); 53446 function _getRequireWildcardCache() { 53447 if (typeof WeakMap !== 'function') return null; 53448 var cache = new WeakMap(); 53449 _getRequireWildcardCache = function _getRequireWildcardCache() { 53450 return cache; 53451 }; 53452 return cache; 53453 } 53454 function _interopRequireWildcard(obj) { 53455 if (obj && obj.__esModule) { 53456 return obj; 53457 } 53458 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) { 53459 return { default: obj }; 53460 } 53461 var cache = _getRequireWildcardCache(); 53462 if (cache && cache.has(obj)) { 53463 return cache.get(obj); 53464 } 53465 var newObj = {}; 53466 var hasPropertyDescriptor = 53467 Object.defineProperty && Object.getOwnPropertyDescriptor; 53468 for (var key in obj) { 53469 if (Object.prototype.hasOwnProperty.call(obj, key)) { 53470 var desc = hasPropertyDescriptor 53471 ? Object.getOwnPropertyDescriptor(obj, key) 53472 : null; 53473 if (desc && (desc.get || desc.set)) { 53474 Object.defineProperty(newObj, key, desc); 53475 } else { 53476 newObj[key] = obj[key]; 53477 } 53478 } 53479 } 53480 newObj.default = obj; 53481 if (cache) { 53482 cache.set(obj, newObj); 53483 } 53484 return newObj; 53485 } 53486 function _interopRequireDefault(obj) { 53487 return obj && obj.__esModule ? obj : { default: obj }; 53488 } 53489 53490 /** 53491 * p5.Renderer2D 53492 * The 2D graphics canvas renderer class. 53493 * extends p5.Renderer 53494 */ 53495 var styleEmpty = 'rgba(0,0,0,0)'; 53496 // const alphaThreshold = 0.00125; // minimum visible 53497 53498 _main.default.Renderer2D = function(elt, pInst, isMainCanvas) { 53499 _main.default.Renderer.call(this, elt, pInst, isMainCanvas); 53500 this.drawingContext = this.canvas.getContext('2d'); 53501 this._pInst._setProperty('drawingContext', this.drawingContext); 53502 return this; 53503 }; 53504 53505 _main.default.Renderer2D.prototype = Object.create( 53506 _main.default.Renderer.prototype 53507 ); 53508 53509 _main.default.Renderer2D.prototype._applyDefaults = function() { 53510 this._cachedFillStyle = this._cachedStrokeStyle = undefined; 53511 this._cachedBlendMode = constants.BLEND; 53512 this._setFill(constants._DEFAULT_FILL); 53513 this._setStroke(constants._DEFAULT_STROKE); 53514 this.drawingContext.lineCap = constants.ROUND; 53515 this.drawingContext.font = 'normal 12px sans-serif'; 53516 }; 53517 53518 _main.default.Renderer2D.prototype.resize = function(w, h) { 53519 _main.default.Renderer.prototype.resize.call(this, w, h); 53520 this.drawingContext.scale(this._pInst._pixelDensity, this._pInst._pixelDensity); 53521 }; 53522
53523 ////////////////////////////////////////////// 53524 // COLOR | Setting 53525 ////////////////////////////////////////////// 53526 53527 _main.default.Renderer2D.prototype.background = function() { 53528 this.drawingContext.save(); 53529 this.resetMatrix(); 53530 53531 if ( 53532 (arguments.length <= 0 ? undefined : arguments[0]) instanceof 53533 _main.default.Image 53534 ) { 53535 this._pInst.image( 53536 arguments.length <= 0 ? undefined : arguments[0], 53537 0, 53538 0, 53539 this.width, 53540 this.height 53541 ); 53542 } else { 53543 var _this$_pInst; 53544 var curFill = this._getFill(); 53545 // create background rect 53546 var color = (_this$_pInst = this._pInst).color.apply(_this$_pInst, arguments); 53547 53548 //accessible Outputs 53549 if (this._pInst._addAccsOutput()) { 53550 this._pInst._accsBackground(color.levels); 53551 } 53552 53553 var newFill = color.toString(); 53554 this._setFill(newFill); 53555 53556 if (this._isErasing) { 53557 this.blendMode(this._cachedBlendMode); 53558 } 53559 53560 this.drawingContext.fillRect(0, 0, this.width, this.height); 53561 // reset fill 53562 this._setFill(curFill); 53563 53564 if (this._isErasing) { 53565 this._pInst.erase(); 53566 } 53567 } 53568 this.drawingContext.restore(); 53569 }; 53570 53571 _main.default.Renderer2D.prototype.clear = function() { 53572 this.drawingContext.save(); 53573 this.resetMatrix(); 53574 this.drawingContext.clearRect(0, 0, this.width, this.height); 53575 this.drawingContext.restore(); 53576 }; 53577 53578 _main.default.Renderer2D.prototype.fill = function() { 53579 var _this$_pInst2; 53580 var color = (_this$_pInst2 = this._pInst).color.apply(_this$_pInst2, arguments); 53581 this._setFill(color.toString()); 53582 53583 //accessible Outputs 53584 if (this._pInst._addAccsOutput()) { 53585 this._pInst._accsCanvasColors('fill', color.levels); 53586 } 53587 }; 53588 53589 _main.default.Renderer2D.prototype.stroke = function() { 53590 var _this$_pInst3; 53591 var color = (_this$_pInst3 = this._pInst).color.apply(_this$_pInst3, arguments); 53592 this._setStroke(color.toString()); 53593 53594 //accessible Outputs 53595 if (this._pInst._addAccsOutput()) { 53596 this._pInst._accsCanvasColors('stroke', color.levels); 53597 } 53598 }; 53599 53600 _main.default.Renderer2D.prototype.erase = function(opacityFill, opacityStroke) { 53601 if (!this._isErasing) { 53602 // cache the fill style 53603 this._cachedFillStyle = this.drawingContext.fillStyle; 53604 var newFill = this._pInst.color(255, opacityFill).toString(); 53605 this.drawingContext.fillStyle = newFill; 53606 53607 //cache the stroke style 53608 this._cachedStrokeStyle = this.drawingContext.strokeStyle; 53609 var newStroke = this._pInst.color(255, opacityStroke).toString(); 53610 this.drawingContext.strokeStyle = newStroke; 53611 53612 //cache blendMode 53613 var tempBlendMode = this._cachedBlendMode; 53614 this.blendMode(constants.REMOVE); 53615 this._cachedBlendMode = tempBlendMode; 53616 53617 this._isErasing = true; 53618 } 53619 }; 53620 53621 _main.default.Renderer2D.prototype.noErase = function() { 53622 if (this._isErasing) { 53623 this.drawingContext.fillStyle = this._cachedFillStyle; 53624 this.drawingContext.strokeStyle = this._cachedStrokeStyle; 53625 53626 this.blendMode(this._cachedBlendMode); 53627 this._isErasing = false; 53628 } 53629 }; 53630
53631 ////////////////////////////////////////////// 53632 // IMAGE | Loading & Displaying 53633 ////////////////////////////////////////////// 53634 53635 _main.default.Renderer2D.prototype.image = function( 53636 img, 53637 sx, 53638 sy, 53639 sWidth, 53640 sHeight, 53641 dx, 53642 dy, 53643 dWidth, 53644 dHeight 53645 ) { 53646 var cnv; 53647 if (img.gifProperties) { 53648 img._animateGif(this._pInst); 53649 } 53650 53651 try { 53652 if (this._tint) { 53653 if ( 53654 _main.default.MediaElement && 53655 img instanceof _main.default.MediaElement 53656 ) { 53657 img.loadPixels(); 53658 } 53659 if (img.canvas) { 53660 cnv = this._getTintedImageCanvas(img); 53661 } 53662 } 53663 if (!cnv) { 53664 cnv = img.canvas || img.elt; 53665 } 53666 var s = 1; 53667 if (img.width && img.width > 0) { 53668 s = cnv.width / img.width; 53669 } 53670 if (this._isErasing) { 53671 this.blendMode(this._cachedBlendMode); 53672 } 53673 this.drawingContext.drawImage( 53674 cnv, 53675 s * sx, 53676 s * sy, 53677 s * sWidth, 53678 s * sHeight, 53679 dx, 53680 dy, 53681 dWidth, 53682 dHeight 53683 ); 53684 53685 if (this._isErasing) { 53686 this._pInst.erase(); 53687 } 53688 } catch (e) { 53689 if (e.name !== 'NS_ERROR_NOT_AVAILABLE') { 53690 throw e; 53691 } 53692 } 53693 }; 53694 53695 _main.default.Renderer2D.prototype._getTintedImageCanvas = function(img) { 53696 if (!img.canvas) { 53697 return img; 53698 } 53699 var pixels = _filters.default._toPixels(img.canvas); 53700 var tmpCanvas = document.createElement('canvas'); 53701 tmpCanvas.width = img.canvas.width; 53702 tmpCanvas.height = img.canvas.height; 53703 var tmpCtx = tmpCanvas.getContext('2d'); 53704 var id = tmpCtx.createImageData(img.canvas.width, img.canvas.height); 53705 var newPixels = id.data; 53706 for (var i = 0; i < pixels.length; i += 4) { 53707 var r = pixels[i]; 53708 var g = pixels[i + 1]; 53709 var b = pixels[i + 2]; 53710 var a = pixels[i + 3]; 53711 newPixels[i] = r * this._tint[0] / 255; 53712 newPixels[i + 1] = g * this._tint[1] / 255; 53713 newPixels[i + 2] = b * this._tint[2] / 255; 53714 newPixels[i + 3] = a * this._tint[3] / 255; 53715 } 53716 tmpCtx.putImageData(id, 0, 0); 53717 return tmpCanvas; 53718 }; 53719
53720 ////////////////////////////////////////////// 53721 // IMAGE | Pixels 53722 ////////////////////////////////////////////// 53723 53724 _main.default.Renderer2D.prototype.blendMode = function(mode) { 53725 if (mode === constants.SUBTRACT) { 53726 console.warn('blendMode(SUBTRACT) only works in WEBGL mode.'); 53727 } else if ( 53728 mode === constants.BLEND || 53729 mode === constants.REMOVE || 53730 mode === constants.DARKEST || 53731 mode === constants.LIGHTEST || 53732 mode === constants.DIFFERENCE || 53733 mode === constants.MULTIPLY || 53734 mode === constants.EXCLUSION || 53735 mode === constants.SCREEN || 53736 mode === constants.REPLACE || 53737 mode === constants.OVERLAY || 53738 mode === constants.HARD_LIGHT || 53739 mode === constants.SOFT_LIGHT || 53740 mode === constants.DODGE || 53741 mode === constants.BURN || 53742 mode === constants.ADD 53743 ) { 53744 this._cachedBlendMode = mode; 53745 this.drawingContext.globalCompositeOperation = mode; 53746 } else { 53747 throw new Error('Mode '.concat(mode, ' not recognized.')); 53748 } 53749 }; 53750 53751 _main.default.Renderer2D.prototype.blend = function() { 53752 var currBlend = this.drawingContext.globalCompositeOperation; 53753 for ( 53754 var _len = arguments.length, args = new Array(_len), _key = 0; 53755 _key < _len; 53756 _key++ 53757 ) { 53758 args[_key] = arguments[_key]; 53759 } 53760 var blendMode = args[args.length - 1]; 53761 53762 var copyArgs = Array.prototype.slice.call(args, 0, args.length - 1); 53763 53764 this.drawingContext.globalCompositeOperation = blendMode; 53765 53766 _main.default.prototype.copy.apply(this, copyArgs); 53767 53768 this.drawingContext.globalCompositeOperation = currBlend; 53769 }; 53770 53771 // p5.Renderer2D.prototype.get = p5.Renderer.prototype.get; 53772 // .get() is not overridden 53773 53774 // x,y are canvas-relative (pre-scaled by _pixelDensity) 53775 _main.default.Renderer2D.prototype._getPixel = function(x, y) { 53776 var imageData, index; 53777 imageData = this.drawingContext.getImageData(x, y, 1, 1).data; 53778 index = 0; 53779 return [ 53780 imageData[index + 0], 53781 imageData[index + 1], 53782 imageData[index + 2], 53783 imageData[index + 3] 53784 ]; 53785 }; 53786 53787 _main.default.Renderer2D.prototype.loadPixels = function() { 53788 var pixelsState = this._pixelsState; // if called by p5.Image 53789 53790 var pd = pixelsState._pixelDensity; 53791 var w = this.width * pd; 53792 var h = this.height * pd; 53793 var imageData = this.drawingContext.getImageData(0, 0, w, h); 53794 // @todo this should actually set pixels per object, so diff buffers can 53795 // have diff pixel arrays. 53796 pixelsState._setProperty('imageData', imageData); 53797 pixelsState._setProperty('pixels', imageData.data); 53798 }; 53799 53800 _main.default.Renderer2D.prototype.set = function(x, y, imgOrCol) { 53801 // round down to get integer numbers 53802 x = Math.floor(x); 53803 y = Math.floor(y); 53804 var pixelsState = this._pixelsState; 53805 if (imgOrCol instanceof _main.default.Image) { 53806 this.drawingContext.save(); 53807 this.drawingContext.setTransform(1, 0, 0, 1, 0, 0); 53808 this.drawingContext.scale( 53809 pixelsState._pixelDensity, 53810 pixelsState._pixelDensity 53811 ); 53812 53813 this.drawingContext.clearRect(x, y, imgOrCol.width, imgOrCol.height); 53814 this.drawingContext.drawImage(imgOrCol.canvas, x, y); 53815 this.drawingContext.restore(); 53816 } else { 53817 var r = 0, 53818 g = 0, 53819 b = 0, 53820 a = 0; 53821 var idx = 53822 4 * 53823 (y * pixelsState._pixelDensity * (this.width * pixelsState._pixelDensity) + 53824 x * pixelsState._pixelDensity); 53825 if (!pixelsState.imageData) { 53826 pixelsState.loadPixels.call(pixelsState); 53827 } 53828 if (typeof imgOrCol === 'number') { 53829 if (idx < pixelsState.pixels.length) { 53830 r = imgOrCol; 53831 g = imgOrCol; 53832 b = imgOrCol; 53833 a = 255; 53834 //this.updatePixels.call(this); 53835 } 53836 } else if (imgOrCol instanceof Array) { 53837 if (imgOrCol.length < 4) { 53838 throw new Error('pixel array must be of the form [R, G, B, A]'); 53839 } 53840 if (idx < pixelsState.pixels.length) { 53841 r = imgOrCol[0]; 53842 g = imgOrCol[1]; 53843 b = imgOrCol[2]; 53844 a = imgOrCol[3]; 53845 //this.updatePixels.call(this); 53846 } 53847 } else if (imgOrCol instanceof _main.default.Color) { 53848 if (idx < pixelsState.pixels.length) { 53849 r = imgOrCol.levels[0]; 53850 g = imgOrCol.levels[1]; 53851 b = imgOrCol.levels[2]; 53852 a = imgOrCol.levels[3]; 53853 //this.updatePixels.call(this); 53854 } 53855 } 53856 // loop over pixelDensity * pixelDensity 53857 for (var i = 0; i < pixelsState._pixelDensity; i++) { 53858 for (var j = 0; j < pixelsState._pixelDensity; j++) { 53859 // loop over 53860 idx = 53861 4 * 53862 ((y * pixelsState._pixelDensity + j) * 53863 this.width * 53864 pixelsState._pixelDensity + 53865 (x * pixelsState._pixelDensity + i)); 53866 pixelsState.pixels[idx] = r; 53867 pixelsState.pixels[idx + 1] = g; 53868 pixelsState.pixels[idx + 2] = b; 53869 pixelsState.pixels[idx + 3] = a; 53870 } 53871 } 53872 } 53873 }; 53874 53875 _main.default.Renderer2D.prototype.updatePixels = function(x, y, w, h) { 53876 var pixelsState = this._pixelsState; 53877 var pd = pixelsState._pixelDensity; 53878 if (x === undefined && y === undefined && w === undefined && h === undefined) { 53879 x = 0; 53880 y = 0; 53881 w = this.width; 53882 h = this.height; 53883 } 53884 x *= pd; 53885 y *= pd; 53886 w *= pd; 53887 h *= pd; 53888 53889 if (this.gifProperties) { 53890 this.gifProperties.frames[this.gifProperties.displayIndex].image = 53891 pixelsState.imageData; 53892 } 53893 53894 this.drawingContext.putImageData(pixelsState.imageData, x, y, 0, 0, w, h); 53895 }; 53896
53897 ////////////////////////////////////////////// 53898 // SHAPE | 2D Primitives 53899 ////////////////////////////////////////////// 53900 53901 /** 53902 * Generate a cubic Bezier representing an arc on the unit circle of total 53903 * angle `size` radians, beginning `start` radians above the x-axis. Up to 53904 * four of these curves are combined to make a full arc. 53905 * 53906 * See www.joecridge.me/bezier.pdf for an explanation of the method. 53907 */ 53908 _main.default.Renderer2D.prototype._acuteArcToBezier = function _acuteArcToBezier( 53909 start, 53910 size 53911 ) { 53912 // Evaluate constants. 53913 var alpha = size / 2.0, 53914 cos_alpha = Math.cos(alpha), 53915 sin_alpha = Math.sin(alpha), 53916 cot_alpha = 1.0 / Math.tan(alpha), 53917 // This is how far the arc needs to be rotated. 53918 phi = start + alpha, 53919 cos_phi = Math.cos(phi), 53920 sin_phi = Math.sin(phi), 53921 lambda = (4.0 - cos_alpha) / 3.0, 53922 mu = sin_alpha + (cos_alpha - lambda) * cot_alpha; 53923 53924 // Return rotated waypoints. 53925 return { 53926 ax: Math.cos(start).toFixed(7), 53927 ay: Math.sin(start).toFixed(7), 53928 bx: (lambda * cos_phi + mu * sin_phi).toFixed(7), 53929 by: (lambda * sin_phi - mu * cos_phi).toFixed(7), 53930 cx: (lambda * cos_phi - mu * sin_phi).toFixed(7), 53931 cy: (lambda * sin_phi + mu * cos_phi).toFixed(7), 53932 dx: Math.cos(start + size).toFixed(7), 53933 dy: Math.sin(start + size).toFixed(7) 53934 }; 53935 }; 53936 53937 /* 53938 * This function requires that: 53939 * 53940 * 0 <= start < TWO_PI 53941 * 53942 * start <= stop < start + TWO_PI 53943 */ 53944 _main.default.Renderer2D.prototype.arc = function(x, y, w, h, start, stop, mode) { 53945 var ctx = this.drawingContext; 53946 var rx = w / 2.0; 53947 var ry = h / 2.0; 53948 var epsilon = 0.00001; // Smallest visible angle on displays up to 4K. 53949 var arcToDraw = 0; 53950 var curves = []; 53951 53952 x += rx; 53953 y += ry; 53954 53955 // Create curves 53956 while (stop - start >= epsilon) { 53957 arcToDraw = Math.min(stop - start, constants.HALF_PI); 53958 curves.push(this._acuteArcToBezier(start, arcToDraw)); 53959 start += arcToDraw; 53960 } 53961 53962 // Fill curves 53963 if (this._doFill) { 53964 ctx.beginPath(); 53965 curves.forEach(function(curve, index) { 53966 if (index === 0) { 53967 ctx.moveTo(x + curve.ax * rx, y + curve.ay * ry); 53968 } 53969 // prettier-ignore 53970 ctx.bezierCurveTo(x + curve.bx * rx, y + curve.by * ry, 53971 x + curve.cx * rx, y + curve.cy * ry, 53972 x + curve.dx * rx, y + curve.dy * ry); 53973 }); 53974 if (mode === constants.PIE || mode == null) { 53975 ctx.lineTo(x, y); 53976 } 53977 ctx.closePath(); 53978 ctx.fill(); 53979 } 53980 53981 // Stroke curves 53982 if (this._doStroke) { 53983 ctx.beginPath(); 53984 curves.forEach(function(curve, index) { 53985 if (index === 0) { 53986 ctx.moveTo(x + curve.ax * rx, y + curve.ay * ry); 53987 } 53988 // prettier-ignore 53989 ctx.bezierCurveTo(x + curve.bx * rx, y + curve.by * ry, 53990 x + curve.cx * rx, y + curve.cy * ry, 53991 x + curve.dx * rx, y + curve.dy * ry); 53992 }); 53993 if (mode === constants.PIE) { 53994 ctx.lineTo(x, y); 53995 ctx.closePath(); 53996 } else if (mode === constants.CHORD) { 53997 ctx.closePath(); 53998 } 53999 ctx.stroke(); 54000 } 54001 return this; 54002 }; 54003 54004 _main.default.Renderer2D.prototype.ellipse = function(args) { 54005 var ctx = this.drawingContext; 54006 var doFill = this._doFill, 54007 doStroke = this._doStroke; 54008 var x = parseFloat(args[0]), 54009 y = parseFloat(args[1]), 54010 w = parseFloat(args[2]), 54011 h = parseFloat(args[3]); 54012 if (doFill && !doStroke) { 54013 if (this._getFill() === styleEmpty) { 54014 return this; 54015 } 54016 } else if (!doFill && doStroke) { 54017 if (this._getStroke() === styleEmpty) { 54018 return this; 54019 } 54020 } 54021 var kappa = 0.5522847498, 54022 // control point offset horizontal 54023 ox = w / 2 * kappa, 54024 // control point offset vertical 54025 oy = h / 2 * kappa, 54026 // x-end 54027 xe = x + w, 54028 // y-end 54029 ye = y + h, 54030 // x-middle 54031 xm = x + w / 2, 54032 ym = y + h / 2; // y-middle 54033 ctx.beginPath(); 54034 ctx.moveTo(x, ym); 54035 ctx.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); 54036 ctx.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); 54037 ctx.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); 54038 ctx.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); 54039 if (doFill) { 54040 ctx.fill(); 54041 } 54042 if (doStroke) { 54043 ctx.stroke(); 54044 } 54045 }; 54046 54047 _main.default.Renderer2D.prototype.line = function(x1, y1, x2, y2) { 54048 var ctx = this.drawingContext; 54049 if (!this._doStroke) { 54050 return this; 54051 } else if (this._getStroke() === styleEmpty) { 54052 return this; 54053 } 54054 ctx.beginPath(); 54055 ctx.moveTo(x1, y1); 54056 ctx.lineTo(x2, y2); 54057 ctx.stroke(); 54058 return this; 54059 }; 54060 54061 _main.default.Renderer2D.prototype.point = function(x, y) { 54062 var ctx = this.drawingContext; 54063 if (!this._doStroke) { 54064 return this; 54065 } else if (this._getStroke() === styleEmpty) { 54066 return this; 54067 } 54068 var s = this._getStroke(); 54069 var f = this._getFill(); 54070 x = Math.round(x); 54071 y = Math.round(y); 54072 // swapping fill color to stroke and back after for correct point rendering 54073 this._setFill(s); 54074 if (ctx.lineWidth > 1) { 54075 ctx.beginPath(); 54076 ctx.arc(x, y, ctx.lineWidth / 2, 0, constants.TWO_PI, false); 54077 ctx.fill(); 54078 } else { 54079 ctx.fillRect(x, y, 1, 1); 54080 } 54081 this._setFill(f); 54082 }; 54083 54084 _main.default.Renderer2D.prototype.quad = function( 54085 x1, 54086 y1, 54087 x2, 54088 y2, 54089 x3, 54090 y3, 54091 x4, 54092 y4 54093 ) { 54094 var ctx = this.drawingContext; 54095 var doFill = this._doFill, 54096 doStroke = this._doStroke; 54097 if (doFill && !doStroke) { 54098 if (this._getFill() === styleEmpty) { 54099 return this; 54100 } 54101 } else if (!doFill && doStroke) { 54102 if (this._getStroke() === styleEmpty) { 54103 return this; 54104 } 54105 } 54106 ctx.beginPath(); 54107 ctx.moveTo(x1, y1); 54108 ctx.lineTo(x2, y2); 54109 ctx.lineTo(x3, y3); 54110 ctx.lineTo(x4, y4); 54111 ctx.closePath(); 54112 if (doFill) { 54113 ctx.fill(); 54114 } 54115 if (doStroke) { 54116 ctx.stroke(); 54117 } 54118 return this; 54119 }; 54120 54121 _main.default.Renderer2D.prototype.rect = function(args) { 54122 var x = args[0]; 54123 var y = args[1]; 54124 var w = args[2]; 54125 var h = args[3]; 54126 var tl = args[4]; 54127 var tr = args[5]; 54128 var br = args[6]; 54129 var bl = args[7]; 54130 var ctx = this.drawingContext; 54131 var doFill = this._doFill, 54132 doStroke = this._doStroke; 54133 if (doFill && !doStroke) { 54134 if (this._getFill() === styleEmpty) { 54135 return this; 54136 } 54137 } else if (!doFill && doStroke) { 54138 if (this._getStroke() === styleEmpty) { 54139 return this; 54140 } 54141 } 54142 ctx.beginPath(); 54143 54144 if (typeof tl === 'undefined') { 54145 // No rounded corners 54146 ctx.rect(x, y, w, h); 54147 } else { 54148 // At least one rounded corner 54149 // Set defaults when not specified 54150 if (typeof tr === 'undefined') { 54151 tr = tl; 54152 } 54153 if (typeof br === 'undefined') { 54154 br = tr; 54155 } 54156 if (typeof bl === 'undefined') { 54157 bl = br; 54158 } 54159 54160 // corner rounding must always be positive 54161 var absW = Math.abs(w); 54162 var absH = Math.abs(h);
54163 var hw = absW / 2; 54164 var hh = absH / 2; 54165 54166 // Clip radii 54167 if (absW < 2 * tl) { 54168 tl = hw; 54169 } 54170 if (absH < 2 * tl) { 54171 tl = hh; 54172 } 54173 if (absW < 2 * tr) { 54174 tr = hw; 54175 } 54176 if (absH < 2 * tr) { 54177 tr = hh; 54178 } 54179 if (absW < 2 * br) { 54180 br = hw; 54181 } 54182 if (absH < 2 * br) { 54183 br = hh; 54184 } 54185 if (absW < 2 * bl) { 54186 bl = hw; 54187 } 54188 if (absH < 2 * bl) { 54189 bl = hh; 54190 } 54191 54192 // Draw shape 54193 ctx.beginPath(); 54194 ctx.moveTo(x + tl, y); 54195 ctx.arcTo(x + w, y, x + w, y + h, tr); 54196 ctx.arcTo(x + w, y + h, x, y + h, br); 54197 ctx.arcTo(x, y + h, x, y, bl); 54198 ctx.arcTo(x, y, x + w, y, tl); 54199 ctx.closePath(); 54200 } 54201 if (this._doFill) { 54202 ctx.fill(); 54203 } 54204 if (this._doStroke) { 54205 ctx.stroke(); 54206 } 54207 return this; 54208 }; 54209 54210 _main.default.Renderer2D.prototype.triangle = function(args) { 54211 var ctx = this.drawingContext; 54212 var doFill = this._doFill, 54213 doStroke = this._doStroke; 54214 var x1 = args[0], 54215 y1 = args[1]; 54216 var x2 = args[2], 54217 y2 = args[3]; 54218 var x3 = args[4], 54219 y3 = args[5]; 54220 if (doFill && !doStroke) { 54221 if (this._getFill() === styleEmpty) { 54222 return this; 54223 } 54224 } else if (!doFill && doStroke) { 54225 if (this._getStroke() === styleEmpty) { 54226 return this; 54227 } 54228 } 54229 ctx.beginPath(); 54230 ctx.moveTo(x1, y1); 54231 ctx.lineTo(x2, y2); 54232 ctx.lineTo(x3, y3); 54233 ctx.closePath(); 54234 if (doFill) { 54235 ctx.fill(); 54236 } 54237 if (doStroke) { 54238 ctx.stroke(); 54239 } 54240 }; 54241 54242 _main.default.Renderer2D.prototype.endShape = function( 54243 mode, 54244 vertices, 54245 isCurve, 54246 isBezier, 54247 isQuadratic, 54248 isContour, 54249 shapeKind 54250 ) { 54251 if (vertices.length === 0) { 54252 return this; 54253 } 54254 if (!this._doStroke && !this._doFill) { 54255 return this; 54256 } 54257 var closeShape = mode === constants.CLOSE; 54258 var v; 54259 if (closeShape && !isContour) { 54260 vertices.push(vertices[0]); 54261 } 54262 var i, j; 54263 var numVerts = vertices.length; 54264 if (isCurve && (shapeKind === constants.POLYGON || shapeKind === null)) { 54265 if (numVerts > 3) { 54266 var b = [], 54267 s = 1 - this._curveTightness; 54268 this.drawingContext.beginPath(); 54269 this.drawingContext.moveTo(vertices[1][0], vertices[1][1]); 54270 for (i = 1; i + 2 < numVerts; i++) { 54271 v = vertices[i]; 54272 b[0] = [v[0], v[1]]; 54273 b[1] = [ 54274 v[0] + (s * vertices[i + 1][0] - s * vertices[i - 1][0]) / 6, 54275 v[1] + (s * vertices[i + 1][1] - s * vertices[i - 1][1]) / 6 54276 ]; 54277 54278 b[2] = [ 54279 vertices[i + 1][0] + (s * vertices[i][0] - s * vertices[i + 2][0]) / 6, 54280 vertices[i + 1][1] + (s * vertices[i][1] - s * vertices[i + 2][1]) / 6 54281 ]; 54282 54283 b[3] = [vertices[i + 1][0], vertices[i + 1][1]]; 54284 this.drawingContext.bezierCurveTo( 54285 b[1][0], 54286 b[1][1], 54287 b[2][0], 54288 b[2][1], 54289 b[3][0], 54290 b[3][1] 54291 ); 54292 } 54293 if (closeShape) { 54294 this.drawingContext.lineTo(vertices[i + 1][0], vertices[i + 1][1]); 54295 } 54296 this._doFillStrokeClose(closeShape); 54297 } 54298 } else if ( 54299 isBezier && 54300 (shapeKind === constants.POLYGON || shapeKind === null) 54301 ) { 54302 this.drawingContext.beginPath(); 54303 for (i = 0; i < numVerts; i++) { 54304 if (vertices[i].isVert) { 54305 if (vertices[i].moveTo) {
54306 this.drawingContext.moveTo(vertices[i][0], vertices[i][1]); 54307 } else { 54308 this.drawingContext.lineTo(vertices[i][0], vertices[i][1]); 54309 } 54310 } else { 54311 this.drawingContext.bezierCurveTo( 54312 vertices[i][0], 54313 vertices[i][1], 54314 vertices[i][2], 54315 vertices[i][3], 54316 vertices[i][4], 54317 vertices[i][5] 54318 ); 54319 } 54320 } 54321 this._doFillStrokeClose(closeShape); 54322 } else if ( 54323 isQuadratic && 54324 (shapeKind === constants.POLYGON || shapeKind === null) 54325 ) { 54326 this.drawingContext.beginPath(); 54327 for (i = 0; i < numVerts; i++) { 54328 if (vertices[i].isVert) { 54329 if (vertices[i].moveTo) { 54330 this.drawingContext.moveTo(vertices[i][0], vertices[i][1]); 54331 } else { 54332 this.drawingContext.lineTo(vertices[i][0], vertices[i][1]); 54333 } 54334 } else { 54335 this.drawingContext.quadraticCurveTo( 54336 vertices[i][0], 54337 vertices[i][1], 54338 vertices[i][2], 54339 vertices[i][3] 54340 ); 54341 } 54342 } 54343 this._doFillStrokeClose(closeShape); 54344 } else { 54345 if (shapeKind === constants.POINTS) { 54346 for (i = 0; i < numVerts; i++) { 54347 v = vertices[i]; 54348 if (this._doStroke) { 54349 this._pInst.stroke(v[6]); 54350 } 54351 this._pInst.point(v[0], v[1]); 54352 } 54353 } else if (shapeKind === constants.LINES) { 54354 for (i = 0; i + 1 < numVerts; i += 2) { 54355 v = vertices[i]; 54356 if (this._doStroke) { 54357 this._pInst.stroke(vertices[i + 1][6]); 54358 } 54359 this._pInst.line(v[0], v[1], vertices[i + 1][0], vertices[i + 1][1]); 54360 } 54361 } else if (shapeKind === constants.TRIANGLES) { 54362 for (i = 0; i + 2 < numVerts; i += 3) { 54363 v = vertices[i]; 54364 this.drawingContext.beginPath(); 54365 this.drawingContext.moveTo(v[0], v[1]); 54366 this.drawingContext.lineTo(vertices[i + 1][0], vertices[i + 1][1]); 54367 this.drawingContext.lineTo(vertices[i + 2][0], vertices[i + 2][1]); 54368 this.drawingContext.closePath(); 54369 if (this._doFill) { 54370 this._pInst.fill(vertices[i + 2][5]); 54371 this.drawingContext.fill(); 54372 } 54373 if (this._doStroke) { 54374 this._pInst.stroke(vertices[i + 2][6]); 54375 this.drawingContext.stroke(); 54376 } 54377 } 54378 } else if (shapeKind === constants.TRIANGLE_STRIP) { 54379 for (i = 0; i + 1 < numVerts; i++) { 54380 v = vertices[i]; 54381 this.drawingContext.beginPath(); 54382 this.drawingContext.moveTo(vertices[i + 1][0], vertices[i + 1][1]); 54383 this.drawingContext.lineTo(v[0], v[1]); 54384 if (this._doStroke) { 54385 this._pInst.stroke(vertices[i + 1][6]); 54386 } 54387 if (this._doFill) { 54388 this._pInst.fill(vertices[i + 1][5]); 54389 } 54390 if (i + 2 < numVerts) { 54391 this.drawingContext.lineTo(vertices[i + 2][0], vertices[i + 2][1]); 54392 if (this._doStroke) { 54393 this._pInst.stroke(vertices[i + 2][6]); 54394 } 54395 if (this._doFill) { 54396 this._pInst.fill(vertices[i + 2][5]); 54397 } 54398 } 54399 this._doFillStrokeClose(closeShape); 54400 } 54401 } else if (shapeKind === constants.TRIANGLE_FAN) { 54402 if (numVerts > 2) { 54403 // For performance reasons, try to batch as many of the 54404 // fill and stroke calls as possible. 54405 this.drawingContext.beginPath(); 54406 for (i = 2; i < numVerts; i++) { 54407 v = vertices[i];
54408 this.drawingContext.moveTo(vertices[0][0], vertices[0][1]); 54409 this.drawingContext.lineTo(vertices[i - 1][0], vertices[i - 1][1]); 54410 this.drawingContext.lineTo(v[0], v[1]); 54411 this.drawingContext.lineTo(vertices[0][0], vertices[0][1]); 54412 // If the next colour is going to be different, stroke / fill now 54413 if (i < numVerts - 1) { 54414 if ( 54415 (this._doFill && v[5] !== vertices[i + 1][5]) || 54416 (this._doStroke && v[6] !== vertices[i + 1][6]) 54417 ) { 54418 if (this._doFill) { 54419 this._pInst.fill(v[5]); 54420 this.drawingContext.fill(); 54421 this._pInst.fill(vertices[i + 1][5]); 54422 } 54423 if (this._doStroke) { 54424 this._pInst.stroke(v[6]); 54425 this.drawingContext.stroke(); 54426 this._pInst.stroke(vertices[i + 1][6]); 54427 } 54428 this.drawingContext.closePath(); 54429 this.drawingContext.beginPath(); // Begin the next one 54430 } 54431 } 54432 } 54433 this._doFillStrokeClose(closeShape); 54434 } 54435 } else if (shapeKind === constants.QUADS) { 54436 for (i = 0; i + 3 < numVerts; i += 4) { 54437 v = vertices[i]; 54438 this.drawingContext.beginPath(); 54439 this.drawingContext.moveTo(v[0], v[1]); 54440 for (j = 1; j < 4; j++) { 54441 this.drawingContext.lineTo(vertices[i + j][0], vertices[i + j][1]); 54442 } 54443 this.drawingContext.lineTo(v[0], v[1]); 54444 if (this._doFill) { 54445 this._pInst.fill(vertices[i + 3][5]); 54446 } 54447 if (this._doStroke) { 54448 this._pInst.stroke(vertices[i + 3][6]); 54449 } 54450 this._doFillStrokeClose(closeShape); 54451 } 54452 } else if (shapeKind === constants.QUAD_STRIP) { 54453 if (numVerts > 3) { 54454 for (i = 0; i + 1 < numVerts; i += 2) { 54455 v = vertices[i]; 54456 this.drawingContext.beginPath(); 54457 if (i + 3 < numVerts) { 54458 this.drawingContext.moveTo(vertices[i + 2][0], vertices[i + 2][1]); 54459 this.drawingContext.lineTo(v[0], v[1]); 54460 this.drawingContext.lineTo(vertices[i + 1][0], vertices[i + 1][1]); 54461 this.drawingContext.lineTo(vertices[i + 3][0], vertices[i + 3][1]); 54462 if (this._doFill) { 54463 this._pInst.fill(vertices[i + 3][5]); 54464 } 54465 if (this._doStroke) { 54466 this._pInst.stroke(vertices[i + 3][6]); 54467 } 54468 } else { 54469 this.drawingContext.moveTo(v[0], v[1]); 54470 this.drawingContext.lineTo(vertices[i + 1][0], vertices[i + 1][1]); 54471 } 54472 this._doFillStrokeClose(closeShape); 54473 } 54474 } 54475 } else { 54476 this.drawingContext.beginPath(); 54477 this.drawingContext.moveTo(vertices[0][0], vertices[0][1]); 54478 for (i = 1; i < numVerts; i++) { 54479 v = vertices[i]; 54480 if (v.isVert) { 54481 if (v.moveTo) { 54482 this.drawingContext.moveTo(v[0], v[1]); 54483 } else { 54484 this.drawingContext.lineTo(v[0], v[1]); 54485 } 54486 } 54487 } 54488 this._doFillStrokeClose(closeShape); 54489 } 54490 } 54491 isCurve = false; 54492 isBezier = false;
54493 isQuadratic = false; 54494 isContour = false; 54495 if (closeShape) { 54496 vertices.pop(); 54497 } 54498 54499 return this; 54500 }; 54501 ////////////////////////////////////////////// 54502 // SHAPE | Attributes 54503 ////////////////////////////////////////////// 54504 54505 _main.default.Renderer2D.prototype.strokeCap = function(cap) { 54506 if ( 54507 cap === constants.ROUND || 54508 cap === constants.SQUARE || 54509 cap === constants.PROJECT 54510 ) { 54511 this.drawingContext.lineCap = cap; 54512 } 54513 return this; 54514 }; 54515 54516 _main.default.Renderer2D.prototype.strokeJoin = function(join) { 54517 if ( 54518 join === constants.ROUND || 54519 join === constants.BEVEL || 54520 join === constants.MITER 54521 ) { 54522 this.drawingContext.lineJoin = join; 54523 } 54524 return this; 54525 }; 54526 54527 _main.default.Renderer2D.prototype.strokeWeight = function(w) { 54528 if (typeof w === 'undefined' || w === 0) { 54529 // hack because lineWidth 0 doesn't work 54530 this.drawingContext.lineWidth = 0.0001; 54531 } else { 54532 this.drawingContext.lineWidth = w; 54533 } 54534 return this; 54535 }; 54536 54537 _main.default.Renderer2D.prototype._getFill = function() { 54538 if (!this._cachedFillStyle) { 54539 this._cachedFillStyle = this.drawingContext.fillStyle; 54540 } 54541 return this._cachedFillStyle; 54542 }; 54543 54544 _main.default.Renderer2D.prototype._setFill = function(fillStyle) { 54545 if (fillStyle !== this._cachedFillStyle) { 54546 this.drawingContext.fillStyle = fillStyle; 54547 this._cachedFillStyle = fillStyle; 54548 } 54549 }; 54550 54551 _main.default.Renderer2D.prototype._getStroke = function() { 54552 if (!this._cachedStrokeStyle) { 54553 this._cachedStrokeStyle = this.drawingContext.strokeStyle; 54554 } 54555 return this._cachedStrokeStyle; 54556 }; 54557 54558 _main.default.Renderer2D.prototype._setStroke = function(strokeStyle) { 54559 if (strokeStyle !== this._cachedStrokeStyle) { 54560 this.drawingContext.strokeStyle = strokeStyle; 54561 this._cachedStrokeStyle = strokeStyle; 54562 } 54563 }; 54564
54565 ////////////////////////////////////////////// 54566 // SHAPE | Curves 54567 ////////////////////////////////////////////// 54568 _main.default.Renderer2D.prototype.bezier = function( 54569 x1, 54570 y1, 54571 x2, 54572 y2, 54573 x3, 54574 y3, 54575 x4, 54576 y4 54577 ) { 54578 this._pInst.beginShape(); 54579 this._pInst.vertex(x1, y1); 54580 this._pInst.bezierVertex(x2, y2, x3, y3, x4, y4); 54581 this._pInst.endShape(); 54582 return this; 54583 }; 54584 54585 _main.default.Renderer2D.prototype.curve = function( 54586 x1, 54587 y1, 54588 x2, 54589 y2, 54590 x3, 54591 y3, 54592 x4, 54593 y4 54594 ) { 54595 this._pInst.beginShape(); 54596 this._pInst.curveVertex(x1, y1); 54597 this._pInst.curveVertex(x2, y2); 54598 this._pInst.curveVertex(x3, y3); 54599 this._pInst.curveVertex(x4, y4); 54600 this._pInst.endShape(); 54601 return this; 54602 }; 54603
54604 ////////////////////////////////////////////// 54605 // SHAPE | Vertex 54606 ////////////////////////////////////////////// 54607 54608 _main.default.Renderer2D.prototype._doFillStrokeClose = function(closeShape) { 54609 if (closeShape) { 54610 this.drawingContext.closePath(); 54611 } 54612 if (this._doFill) { 54613 this.drawingContext.fill(); 54614 } 54615 if (this._doStroke) { 54616 this.drawingContext.stroke(); 54617 } 54618 }; 54619 54620 ////////////////////////////////////////////// 54621 // TRANSFORM 54622 ////////////////////////////////////////////// 54623 54624 _main.default.Renderer2D.prototype.applyMatrix = function(a, b, c, d, e, f) { 54625 this.drawingContext.transform(a, b, c, d, e, f); 54626 }; 54627 54628 _main.default.Renderer2D.prototype.resetMatrix = function() { 54629 this.drawingContext.setTransform(1, 0, 0, 1, 0, 0); 54630 this.drawingContext.scale(this._pInst._pixelDensity, this._pInst._pixelDensity); 54631 54632 return this; 54633 }; 54634 54635 _main.default.Renderer2D.prototype.rotate = function(rad) { 54636 this.drawingContext.rotate(rad); 54637 }; 54638 54639 _main.default.Renderer2D.prototype.scale = function(x, y) { 54640 this.drawingContext.scale(x, y); 54641 return this; 54642 }; 54643 54644 _main.default.Renderer2D.prototype.translate = function(x, y) { 54645 // support passing a vector as the 1st parameter 54646 if (x instanceof _main.default.Vector) { 54647 y = x.y; 54648 x = x.x; 54649 } 54650 this.drawingContext.translate(x, y); 54651 return this; 54652 }; 54653
54654 ////////////////////////////////////////////// 54655 // TYPOGRAPHY 54656 // 54657 ////////////////////////////////////////////// 54658 54659 _main.default.Renderer2D.prototype.text = function( 54660 str, 54661 x, 54662 y, 54663 maxWidth, 54664 maxHeight 54665 ) { 54666 var baselineHacked; 54667 54668 // baselineHacked: (HACK) 54669 // A temporary fix to conform to Processing's implementation 54670 // of BASELINE vertical alignment in a bounding box 54671 54672 if (typeof maxWidth !== 'undefined') { 54673 if (this.drawingContext.textBaseline === constants.BASELINE) { 54674 baselineHacked = true; 54675 this.drawingContext.textBaseline = constants.TOP; 54676 } 54677 } 54678 54679 var p = _main.default.Renderer.prototype.text.apply(this, arguments); 54680 54681 if (baselineHacked) { 54682 this.drawingContext.textBaseline = constants.BASELINE; 54683 } 54684 54685 return p; 54686 }; 54687 54688 _main.default.Renderer2D.prototype._renderText = function(p, line, x, y, maxY) { 54689 if (y >= maxY) { 54690 return; // don't render lines beyond our maxY position 54691 } 54692 54693 p.push(); // fix to #803 54694 54695 if (!this._isOpenType()) { 54696 // a system/browser font 54697 54698 // no stroke unless specified by user 54699 if (this._doStroke && this._strokeSet) { 54700 this.drawingContext.strokeText(line, x, y); 54701 } 54702 54703 if (this._doFill) { 54704 // if fill hasn't been set by user, use default text fill 54705 if (!this._fillSet) { 54706 this._setFill(constants._DEFAULT_TEXT_FILL); 54707 } 54708 54709 this.drawingContext.fillText(line, x, y); 54710 } 54711 } else { 54712 // an opentype font, let it handle the rendering 54713 54714 this._textFont._renderPath(line, x, y, { renderer: this }); 54715 } 54716 54717 p.pop(); 54718 return p; 54719 }; 54720 54721 _main.default.Renderer2D.prototype.textWidth = function(s) { 54722 if (this._isOpenType()) { 54723 return this._textFont._textWidth(s, this._textSize); 54724 } 54725 54726 return this.drawingContext.measureText(s).width; 54727 }; 54728 54729 _main.default.Renderer2D.prototype._applyTextProperties = function() { 54730 var font; 54731 var p = this._pInst; 54732 54733 this._setProperty('_textAscent', null); 54734 this._setProperty('_textDescent', null); 54735 54736 font = this._textFont; 54737 54738 if (this._isOpenType()) { 54739 font = this._textFont.font.familyName; 54740 this._setProperty('_textStyle', this._textFont.font.styleName); 54741 } 54742 54743 this.drawingContext.font = '' 54744 .concat(this._textStyle || 'normal', ' ') 54745 .concat(this._textSize || 12, 'px ') 54746 .concat(font || 'sans-serif'); 54747 54748 this.drawingContext.textAlign = this._textAlign; 54749 if (this._textBaseline === constants.CENTER) { 54750 this.drawingContext.textBaseline = constants._CTX_MIDDLE; 54751 } else { 54752 this.drawingContext.textBaseline = this._textBaseline; 54753 } 54754 54755 return p; 54756 }; 54757
54758 ////////////////////////////////////////////// 54759 // STRUCTURE 54760 ////////////////////////////////////////////// 54761 54762 // a push() operation is in progress. 54763 // the renderer should return a 'style' object that it wishes to 54764 // store on the push stack. 54765 // derived renderers should call the base class' push() method 54766 // to fetch the base style object. 54767 _main.default.Renderer2D.prototype.push = function() { 54768 this.drawingContext.save(); 54769 54770 // get the base renderer style 54771 return _main.default.Renderer.prototype.push.apply(this); 54772 }; 54773 54774 // a pop() operation is in progress 54775 // the renderer is passed the 'style' object that it returned 54776 // from its push() method. 54777 // derived renderers should pass this object to their base 54778 // class' pop method 54779 _main.default.Renderer2D.prototype.pop = function(style) { 54780 this.drawingContext.restore(); 54781 // Re-cache the fill / stroke state 54782 this._cachedFillStyle = this.drawingContext.fillStyle; 54783 this._cachedStrokeStyle = this.drawingContext.strokeStyle; 54784 54785 _main.default.Renderer.prototype.pop.call(this, style); 54786 }; 54787 var _default = _main.default.Renderer2D; 54788 exports.default = _default; 54789 }, 54790 { '../image/filters': 80, './constants': 48, './main': 59, './p5.Renderer': 62 } 54791 ], 54792 64: [ 54793 function(_dereq_, module, exports) { 54794 'use strict'; 54795 54796 var _main = _interopRequireDefault(_dereq_('./main')); 54797 function _interopRequireDefault(obj) { 54798 return obj && obj.__esModule ? obj : { default: obj }; 54799 } 54800 54801 _main.default.prototype._promisePreloads = [ 54802 /* Example object 54803 { 54804 target: p5.prototype, // The target object to have the method modified 54805 method: 'loadXAsync', // The name of the preload function to wrap 54806 addCallbacks: true, // Whether to automatically handle the p5 callbacks 54807 legacyPreloadSetup: { // Optional object to generate a legacy-style preload 54808 method: 'loadX', // The name of the legacy preload function to generate 54809 createBaseObject: function() { 54810 return {}; 54811 } // An optional function to create the base object for the legacy preload. 54812 } 54813 } 54814 */ 54815 ]; 54816 54817 _main.default.prototype.registerPromisePreload = function(setup) { 54818 _main.default.prototype._promisePreloads.push(setup); 54819 }; 54820 54821 var initialSetupRan = false; 54822 54823 _main.default.prototype._setupPromisePreloads = function() { 54824 var _iteratorNormalCompletion = true; 54825 var _didIteratorError = false; 54826 var _iteratorError = undefined; 54827 try { 54828 for ( 54829 var _iterator = this._promisePreloads[Symbol.iterator](), _step; 54830 !(_iteratorNormalCompletion = (_step = _iterator.next()).done); 54831 _iteratorNormalCompletion = true 54832 ) { 54833 var preloadSetup = _step.value; 54834 var thisValue = this; 54835 var method = preloadSetup.method, 54836 addCallbacks = preloadSetup.addCallbacks, 54837 legacyPreloadSetup = preloadSetup.legacyPreloadSetup; 54838 // Get the target object that the preload gets assigned to by default, 54839 // that is the current object. 54840 var target = preloadSetup.target || this; 54841 var sourceFunction = target[method].bind(target); 54842 // If the target is the p5 prototype, then only set it up on the first run per page 54843 if (target === _main.default.prototype) { 54844 if (initialSetupRan) { 54845 continue; 54846 } 54847 thisValue = null; 54848 sourceFunction = target[method]; 54849 } 54850 54851 // Replace the original method with a wrapped version 54852 target[method] = this._wrapPromisePreload( 54853 thisValue, 54854 sourceFunction, 54855 addCallbacks 54856 ); 54857 54858 // If a legacy preload is required 54859 if (legacyPreloadSetup) { 54860 // What is the name for this legacy preload 54861 var legacyMethod = legacyPreloadSetup.method; 54862 // Wrap the already wrapped Promise-returning method with the legacy setup 54863 target[legacyMethod] = this._legacyPreloadGenerator( 54864 thisValue, 54865 legacyPreloadSetup, 54866 target[method] 54867 ); 54868 } 54869 } 54870 } catch (err) {
54871 _didIteratorError = true; 54872 _iteratorError = err; 54873 } finally { 54874 try { 54875 if (!_iteratorNormalCompletion && _iterator.return != null) { 54876 _iterator.return(); 54877 } 54878 } finally { 54879 if (_didIteratorError) { 54880 throw _iteratorError; 54881 } 54882 } 54883 } 54884 initialSetupRan = true; 54885 }; 54886 54887 _main.default.prototype._wrapPromisePreload = function( 54888 thisValue, 54889 fn, 54890 addCallbacks 54891 ) { 54892 var replacementFunction = function replacementFunction() { 54893 var _this = this; 54894 // Uses the current preload counting mechanism for now. 54895 this._incrementPreload(); 54896 // A variable for the callback function if specified 54897 var callback = null; 54898 // A variable for the errorCallback function if specified 54899 var errorCallback = null; 54900 for ( 54901 var _len = arguments.length, args = new Array(_len), _key = 0; 54902 _key < _len; 54903 _key++ 54904 ) { 54905 args[_key] = arguments[_key]; 54906 } 54907 if (addCallbacks) { 54908 // Loop from the end of the args array, pulling up to two functions off of 54909 // the end and putting them in fns 54910 for (var i = args.length - 1; i >= 0 && !errorCallback; i--) { 54911 if (typeof args[i] !== 'function') { 54912 break; 54913 } 54914 errorCallback = callback; 54915 callback = args.pop(); 54916 } 54917 } 54918 // Call the underlying funciton and pass it to Promise.resolve, 54919 // so that even if it didn't return a promise we can still 54920 // act on the result as if it did. 54921 var promise = Promise.resolve(fn.apply(this, args)); 54922 // Add the optional callbacks 54923 if (callback) { 54924 promise.then(callback); 54925 } 54926 if (errorCallback) { 54927 promise.catch(errorCallback); 54928 } 54929 // Decrement the preload counter only if the promise resolved 54930 promise.then(function() { 54931 return _this._decrementPreload(); 54932 }); 54933 // Return the original promise so that neither callback changes the result. 54934 return promise; 54935 }; 54936 if (thisValue) { 54937 replacementFunction = replacementFunction.bind(thisValue); 54938 } 54939 return replacementFunction; 54940 }; 54941 54942 var objectCreator = function objectCreator() { 54943 return {}; 54944 }; 54945 54946 _main.default.prototype._legacyPreloadGenerator = function( 54947 thisValue, 54948 legacyPreloadSetup, 54949 fn 54950 ) { 54951 // Create a function that will generate an object before the preload is 54952 // launched. For example, if the object should be an array or be an instance 54953 // of a specific class. 54954 var baseValueGenerator = legacyPreloadSetup.createBaseObject || objectCreator; 54955 var returnedFunction = function returnedFunction() { 54956 var _this2 = this; 54957 // Our then clause needs to run before setup, so we also increment the preload counter 54958 this._incrementPreload(); 54959 // Generate the return value based on the generator. 54960 var returnValue = baseValueGenerator.apply(this, arguments); 54961 // Run the original wrapper 54962 fn.apply(this, arguments).then(function(data) { 54963 // Copy each key from the resolved value into returnValue 54964 Object.assign(returnValue, data); 54965 // Decrement the preload counter, to allow setup to continue. 54966 _this2._decrementPreload(); 54967 }); 54968 return returnValue; 54969 }; 54970 if (thisValue) { 54971 returnedFunction = returnedFunction.bind(thisValue); 54972 } 54973 return returnedFunction; 54974 }; 54975 }, 54976 { './main': 59 } 54977 ], 54978 65: [
54979 function(_dereq_, module, exports) { 54980 'use strict'; 54981 Object.defineProperty(exports, '__esModule', { value: true }); 54982 exports.default = void 0; 54983 54984 var _main = _interopRequireDefault(_dereq_('./main')); 54985 var constants = _interopRequireWildcard(_dereq_('./constants')); 54986 _dereq_('./p5.Graphics'); 54987 _dereq_('./p5.Renderer2D'); 54988 _dereq_('../webgl/p5.RendererGL'); 54989 function _getRequireWildcardCache() { 54990 if (typeof WeakMap !== 'function') return null; 54991 var cache = new WeakMap(); 54992 _getRequireWildcardCache = function _getRequireWildcardCache() { 54993 return cache; 54994 }; 54995 return cache; 54996 } 54997 function _interopRequireWildcard(obj) { 54998 if (obj && obj.__esModule) { 54999 return obj; 55000 } 55001 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) { 55002 return { default: obj }; 55003 } 55004 var cache = _getRequireWildcardCache(); 55005 if (cache && cache.has(obj)) { 55006 return cache.get(obj); 55007 } 55008 var newObj = {}; 55009 var hasPropertyDescriptor = 55010 Object.defineProperty && Object.getOwnPropertyDescriptor; 55011 for (var key in obj) { 55012 if (Object.prototype.hasOwnProperty.call(obj, key)) { 55013 var desc = hasPropertyDescriptor 55014 ? Object.getOwnPropertyDescriptor(obj, key) 55015 : null; 55016 if (desc && (desc.get || desc.set)) { 55017 Object.defineProperty(newObj, key, desc); 55018 } else { 55019 newObj[key] = obj[key]; 55020 } 55021 } 55022 } 55023 newObj.default = obj; 55024 if (cache) { 55025 cache.set(obj, newObj); 55026 } 55027 return newObj; 55028 } 55029 function _interopRequireDefault(obj) { 55030 return obj && obj.__esModule ? obj : { default: obj }; 55031 } 55032 function _typeof(obj) { 55033 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') { 55034 _typeof = function _typeof(obj) { 55035 return typeof obj; 55036 }; 55037 } else { 55038 _typeof = function _typeof(obj) { 55039 return obj && 55040 typeof Symbol === 'function' && 55041 obj.constructor === Symbol && 55042 obj !== Symbol.prototype 55043 ? 'symbol' 55044 : typeof obj; 55045 }; 55046 } 55047 return _typeof(obj); 55048 } 55049 var defaultId = 'defaultCanvas0'; // this gets set again in createCanvas 55050 var defaultClass = 'p5Canvas'; 55051 55052 /** 55053 * Creates a canvas element in the document, and sets the dimensions of it 55054 * in pixels. This method should be called only once at the start of setup. 55055 * Calling <a href="#/p5/createCanvas">createCanvas</a> more than once in a 55056 * sketch will result in very unpredictable behavior. If you want more than 55057 * one drawing canvas you could use <a href="#/p5/createGraphics">createGraphics</a> 55058 * (hidden by default but it can be shown). 55059 * 55060 * Important note: in 2D mode (i.e. when `p5.Renderer` is not set) the origin (0,0) 55061 * is positioned at the top left of the screen. In 3D mode (i.e. when `p5.Renderer` 55062 * is set to `WEBGL`), the origin is positioned at the center of the canvas. 55063 * See [this issue](https://github.com/processing/p5.js/issues/1545) for more information. 55064 * 55065 * The system variables width and height are set by the parameters passed to this 55066 * function. If <a href="#/p5/createCanvas">createCanvas()</a> is not used, the 55067 * window will be given a default size of 100x100 pixels. 55068 * 55069 * For more ways to position the canvas, see the 55070 * <a href='https://github.com/processing/p5.js/wiki/Positioning-your-canvas'> 55071 * positioning the canvas</a> wiki page. 55072 * 55073 * @method createCanvas 55074 * @param {Number} w width of the canvas 55075 * @param {Number} h height of the canvas 55076 * @param {Constant} [renderer] either P2D or WEBGL 55077 * @return {p5.Renderer} 55078 * @example 55079 * <div> 55080 * <code> 55081 * function setup() { 55082 * createCanvas(100, 50); 55083 * background(153); 55084 * line(0, 0, width, height); 55085 * } 55086 * </code> 55087 * </div> 55088 * 55089 * @alt 55090 * Black line extending from top-left of canvas to bottom right. 55091 */ 55092 _main.default.prototype.createCanvas = function(w, h, renderer) { 55093 _main.default._validateParameters('createCanvas', arguments); 55094 //optional: renderer, otherwise defaults to p2d 55095 var r = renderer || constants.P2D; 55096 var c; 55097 55098 if (r === constants.WEBGL) { 55099 c = document.getElementById(defaultId); 55100 if (c) { 55101 //if defaultCanvas already exists 55102 c.parentNode.removeChild(c); //replace the existing defaultCanvas 55103 var thisRenderer = this._renderer; 55104 this._elements = this._elements.filter(function(e) { 55105 return e !== thisRenderer; 55106 }); 55107 } 55108 c = document.createElement('canvas'); 55109 c.id = defaultId; 55110 c.classList.add(defaultClass); 55111 } else { 55112 if (!this._defaultGraphicsCreated) { 55113 c = document.createElement('canvas'); 55114 var i = 0; 55115 while (document.getElementById('defaultCanvas'.concat(i))) { 55116 i++; 55117 } 55118 defaultId = 'defaultCanvas'.concat(i); 55119 c.id = defaultId; 55120 c.classList.add(defaultClass); 55121 } else { 55122 // resize the default canvas if new one is created 55123 c = this.canvas; 55124 } 55125 } 55126 55127 // set to invisible if still in setup (to prevent flashing with manipulate) 55128 if (!this._setupDone) { 55129 c.dataset.hidden = true; // tag to show later 55130 c.style.visibility = 'hidden'; 55131 } 55132 55133 if (this._userNode) { 55134 // user input node case 55135 this._userNode.appendChild(c); 55136 } else { 55137 //create main element 55138 if (document.getElementsByTagName('main').length === 0) { 55139 var m = document.createElement('main'); 55140 document.body.appendChild(m); 55141 } 55142 //append canvas to main 55143 document.getElementsByTagName('main')[0].appendChild(c); 55144 } 55145 55146 // Init our graphics renderer 55147 //webgl mode 55148 if (r === constants.WEBGL) { 55149 this._setProperty('_renderer', new _main.default.RendererGL(c, this, true)); 55150 this._elements.push(this._renderer); 55151 } else { 55152 //P2D mode 55153 if (!this._defaultGraphicsCreated) { 55154 this._setProperty('_renderer', new _main.default.Renderer2D(c, this, true)); 55155 this._defaultGraphicsCreated = true; 55156 this._elements.push(this._renderer); 55157 } 55158 } 55159 this._renderer.resize(w, h); 55160 this._renderer._applyDefaults(); 55161 return this._renderer; 55162 }; 55163 55164 /** 55165 * Resizes the canvas to given width and height. The canvas will be cleared 55166 * and draw will be called immediately, allowing the sketch to re-render itself 55167 * in the resized canvas. 55168 * @method resizeCanvas 55169 * @param {Number} w width of the canvas 55170 * @param {Number} h height of the canvas 55171 * @param {Boolean} [noRedraw] don't redraw the canvas immediately 55172 * @example 55173 * <div class="norender"><code> 55174 * function setup() { 55175 * createCanvas(windowWidth, windowHeight); 55176 * } 55177 * 55178 * function draw() { 55179 * background(0, 100, 200); 55180 * } 55181 * 55182 * function windowResized() { 55183 * resizeCanvas(windowWidth, windowHeight); 55184 * } 55185 * </code></div> 55186 * 55187 * @alt 55188 * No image displayed. 55189 */ 55190 _main.default.prototype.resizeCanvas = function(w, h, noRedraw) { 55191 _main.default._validateParameters('resizeCanvas', arguments); 55192 if (this._renderer) { 55193 // save canvas properties 55194 var props = {}; 55195 for (var key in this.drawingContext) { 55196 var val = this.drawingContext[key]; 55197 if (_typeof(val) !== 'object' && typeof val !== 'function') { 55198 props[key] = val; 55199 } 55200 } 55201 this._renderer.resize(w, h); 55202 this.width = w; 55203 this.height = h; 55204 // reset canvas properties 55205 for (var savedKey in props) { 55206 try { 55207 this.drawingContext[savedKey] = props[savedKey]; 55208 } catch (err) { 55209 // ignore read-only property errors 55210 } 55211 } 55212 if (!noRedraw) { 55213 this.redraw(); 55214 } 55215 } 55216 //accessible Outputs 55217 if (this._addAccsOutput()) { 55218 this._updateAccsOutput(); 55219 } 55220 }; 55221 55222 /** 55223 * Removes the default canvas for a p5 sketch that doesn't require a canvas 55224 * @method noCanvas 55225 * @example 55226 * <div> 55227 * <code> 55228 * function setup() { 55229 * noCanvas(); 55230 * } 55231 * </code> 55232 * </div> 55233 * 55234 * @alt 55235 * no image displayed 55236 */ 55237 _main.default.prototype.noCanvas = function() { 55238 if (this.canvas) { 55239 this.canvas.parentNode.removeChild(this.canvas); 55240 } 55241 }; 55242 55243 /** 55244 * Creates and returns a new p5.Renderer object. Use this class if you need 55245 * to draw into an off-screen graphics buffer. The two parameters define the 55246 * width and height in pixels. 55247 * 55248 * @method createGraphics 55249 * @param {Number} w width of the offscreen graphics buffer 55250 * @param {Number} h height of the offscreen graphics buffer 55251 * @param {Constant} [renderer] either P2D or WEBGL 55252 * undefined defaults to p2d 55253 * @return {p5.Graphics} offscreen graphics buffer 55254 * @example 55255 * <div> 55256 * <code> 55257 * let pg; 55258 * function setup() { 55259 * createCanvas(100, 100); 55260 * pg = createGraphics(100, 100); 55261 * } 55262 * 55263 * function draw() { 55264 * background(200); 55265 * pg.background(100); 55266 * pg.noStroke(); 55267 * pg.ellipse(pg.width / 2, pg.height / 2, 50, 50); 55268 * image(pg, 50, 50); 55269 * image(pg, 0, 0, 50, 50); 55270 * } 55271 * </code> 55272 * </div> 55273 * 55274 * @alt 55275 * 4 grey squares alternating light and dark grey. White quarter circle mid-left. 55276 */ 55277 _main.default.prototype.createGraphics = function(w, h, renderer) { 55278 _main.default._validateParameters('createGraphics', arguments); 55279 return new _main.default.Graphics(w, h, renderer, this); 55280 }; 55281 55282 /** 55283 * Blends the pixels in the display window according to the defined mode. 55284 * There is a choice of the following modes to blend the source pixels (A) 55285 * with the ones of pixels already in the display window (B): 55286 * <ul> 55287 * <li><code>BLEND</code> - linear interpolation of colours: C = 55288 * A\*factor + B. <b>This is the default blending mode.</b></li> 55289 * <li><code>ADD</code> - sum of A and B</li> 55290 * <li><code>DARKEST</code> - only the darkest colour succeeds: C = 55291 * min(A\*factor, B).</li> 55292 * <li><code>LIGHTEST</code> - only the lightest colour succeeds: C = 55293 * max(A\*factor, B).</li> 55294 * <li><code>DIFFERENCE</code> - subtract colors from underlying image.</li> 55295 * <li><code>EXCLUSION</code> - similar to <code>DIFFERENCE</code>, but less 55296 * extreme.</li> 55297 * <li><code>MULTIPLY</code> - multiply the colors, result will always be 55298 * darker.</li> 55299 * <li><code>SCREEN</code> - opposite multiply, uses inverse values of the 55300 * colors.</li> 55301 * <li><code>REPLACE</code> - the pixels entirely replace the others and
55302 * don't utilize alpha (transparency) values.</li> 55303 * <li><code>REMOVE</code> - removes pixels from B with the alpha strength of A.</li> 55304 * <li><code>OVERLAY</code> - mix of <code>MULTIPLY</code> and <code>SCREEN 55305 * </code>. Multiplies dark values, and screens light values. <em>(2D)</em></li> 55306 * <li><code>HARD_LIGHT</code> - <code>SCREEN</code> when greater than 50% 55307 * gray, <code>MULTIPLY</code> when lower. <em>(2D)</em></li> 55308 * <li><code>SOFT_LIGHT</code> - mix of <code>DARKEST</code> and 55309 * <code>LIGHTEST</code>. Works like <code>OVERLAY</code>, but not as harsh. <em>(2D)</em> 55310 * </li> 55311 * <li><code>DODGE</code> - lightens light tones and increases contrast, 55312 * ignores darks. <em>(2D)</em></li> 55313 * <li><code>BURN</code> - darker areas are applied, increasing contrast, 55314 * ignores lights. <em>(2D)</em></li> 55315 * <li><code>SUBTRACT</code> - remainder of A and B <em>(3D)</em></li> 55316 * </ul> 55317 * 55318 * <em>(2D)</em> indicates that this blend mode <b>only</b> works in the 2D renderer.<br> 55319 * <em>(3D)</em> indicates that this blend mode <b>only</b> works in the WEBGL renderer. 55320 * 55321 * @method blendMode 55322 * @param {Constant} mode blend mode to set for canvas. 55323 * either BLEND, DARKEST, LIGHTEST, DIFFERENCE, MULTIPLY, 55324 * EXCLUSION, SCREEN, REPLACE, OVERLAY, HARD_LIGHT, 55325 * SOFT_LIGHT, DODGE, BURN, ADD, REMOVE or SUBTRACT 55326 * @example 55327 * <div> 55328 * <code> 55329 * blendMode(LIGHTEST); 55330 * strokeWeight(30); 55331 * stroke(80, 150, 255); 55332 * line(25, 25, 75, 75); 55333 * stroke(255, 50, 50); 55334 * line(75, 25, 25, 75); 55335 * </code> 55336 * </div> 55337 * 55338 * <div> 55339 * <code> 55340 * blendMode(MULTIPLY); 55341 * strokeWeight(30); 55342 * stroke(80, 150, 255); 55343 * line(25, 25, 75, 75); 55344 * stroke(255, 50, 50); 55345 * line(75, 25, 25, 75); 55346 * </code> 55347 * </div> 55348 * 55349 * @alt 55350 * translucent image thick red & blue diagonal rounded lines intersecting center 55351 * Thick red & blue diagonal rounded lines intersecting center. dark at overlap 55352 */ 55353 _main.default.prototype.blendMode = function(mode) { 55354 _main.default._validateParameters('blendMode', arguments); 55355 if (mode === constants.NORMAL) { 55356 // Warning added 3/26/19, can be deleted in future (1.0 release?) 55357 console.warn( 55358 'NORMAL has been deprecated for use in blendMode. defaulting to BLEND instead.' 55359 ); 55360 55361 mode = constants.BLEND; 55362 } 55363 this._renderer.blendMode(mode); 55364 }; 55365 55366 /** 55367 * The p5.js API provides a lot of functionality for creating graphics, but there is 55368 * some native HTML5 Canvas functionality that is not exposed by p5. You can still call 55369 * it directly using the variable `drawingContext`, as in the example shown. This is 55370 * the equivalent of calling `canvas.getContext('2d');` or `canvas.getContext('webgl');`. 55371 * See this 55372 * <a href="https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D"> 55373 * reference for the native canvas API</a> for possible drawing functions you can call. 55374 * 55375 * @property drawingContext 55376 * @example 55377 * <div> 55378 * <code> 55379 * function setup() { 55380 * drawingContext.shadowOffsetX = 5; 55381 * drawingContext.shadowOffsetY = -5; 55382 * drawingContext.shadowBlur = 10; 55383 * drawingContext.shadowColor = 'black'; 55384 * background(200); 55385 * ellipse(width / 2, height / 2, 50, 50); 55386 * } 55387 * </code> 55388 * </div> 55389 * 55390 * @alt 55391 * white ellipse with shadow blur effect around edges 55392 */ var _default = _main.default; 55393 exports.default = _default; 55394 }, 55395 { 55396 '../webgl/p5.RendererGL': 113, 55397 './constants': 48, 55398 './main': 59, 55399 './p5.Graphics': 61, 55400 './p5.Renderer2D': 63 55401 } 55402 ], 55403 66: [
55404 function(_dereq_, module, exports) { 55405 'use strict'; 55406 function _typeof(obj) { 55407 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') { 55408 _typeof = function _typeof(obj) { 55409 return typeof obj; 55410 }; 55411 } else { 55412 _typeof = function _typeof(obj) { 55413 return obj && 55414 typeof Symbol === 'function' && 55415 obj.constructor === Symbol && 55416 obj !== Symbol.prototype 55417 ? 'symbol' 55418 : typeof obj; 55419 }; 55420 } 55421 return _typeof(obj); 55422 } 55423 Object.defineProperty(exports, '__esModule', { value: true }); 55424 exports.default = void 0; 55425 55426 var _main = _interopRequireDefault(_dereq_('../main')); 55427 var constants = _interopRequireWildcard(_dereq_('../constants')); 55428 var _helpers = _interopRequireDefault(_dereq_('../helpers')); 55429 _dereq_('../friendly_errors/fes_core'); 55430 _dereq_('../friendly_errors/file_errors'); 55431 _dereq_('../friendly_errors/validate_params'); 55432 function _getRequireWildcardCache() { 55433 if (typeof WeakMap !== 'function') return null; 55434 var cache = new WeakMap(); 55435 _getRequireWildcardCache = function _getRequireWildcardCache() { 55436 return cache; 55437 }; 55438 return cache; 55439 } 55440 function _interopRequireWildcard(obj) { 55441 if (obj && obj.__esModule) { 55442 return obj; 55443 } 55444 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) { 55445 return { default: obj }; 55446 } 55447 var cache = _getRequireWildcardCache(); 55448 if (cache && cache.has(obj)) { 55449 return cache.get(obj); 55450 } 55451 var newObj = {}; 55452 var hasPropertyDescriptor = 55453 Object.defineProperty && Object.getOwnPropertyDescriptor; 55454 for (var key in obj) { 55455 if (Object.prototype.hasOwnProperty.call(obj, key)) { 55456 var desc = hasPropertyDescriptor 55457 ? Object.getOwnPropertyDescriptor(obj, key) 55458 : null; 55459 if (desc && (desc.get || desc.set)) { 55460 Object.defineProperty(newObj, key, desc); 55461 } else { 55462 newObj[key] = obj[key]; 55463 } 55464 } 55465 } 55466 newObj.default = obj; 55467 if (cache) { 55468 cache.set(obj, newObj); 55469 } 55470 return newObj; 55471 } 55472 function _interopRequireDefault(obj) { 55473 return obj && obj.__esModule ? obj : { default: obj }; 55474 } 55475 /** 55476 * @module Shape 55477 * @submodule 2D Primitives 55478 * @for p5 55479 * @requires core 55480 * @requires constants 55481 */ /** 55482 * This function does 3 things: 55483 * 55484 * 1. Bounds the desired start/stop angles for an arc (in radians) so that: 55485 * 55486 * 0 <= start < TWO_PI ; start <= stop < start + TWO_PI 55487 * 55488 * This means that the arc rendering functions don't have to be concerned 55489 * with what happens if stop is smaller than start, or if the arc 'goes 55490 * round more than once', etc.: they can just start at start and increase 55491 * until stop and the correct arc will be drawn. 55492 * 55493 * 2. Optionally adjusts the angles within each quadrant to counter the naive 55494 * scaling of the underlying ellipse up from the unit circle. Without 55495 * this, the angles become arbitrary when width != height: 45 degrees 55496 * might be drawn at 5 degrees on a 'wide' ellipse, or at 85 degrees on 55497 * a 'tall' ellipse. 55498 * 55499 * 3. Flags up when start and stop correspond to the same place on the 55500 * underlying ellipse. This is useful if you want to do something special 55501 * there (like rendering a whole ellipse instead). 55502 */ _main.default.prototype._normalizeArcAngles = function( 55503 start, 55504 stop, 55505 width, 55506 height, 55507 correctForScaling 55508 ) { 55509 var epsilon = 0.00001; // Smallest visible angle on displays up to 4K. 55510 var separation; 55511 55512 // The order of the steps is important here: each one builds upon the 55513 // adjustments made in the steps that precede it. 55514 55515 // Constrain both start and stop to [0,TWO_PI). 55516 start = start - constants.TWO_PI * Math.floor(start / constants.TWO_PI); 55517 stop = stop - constants.TWO_PI * Math.floor(stop / constants.TWO_PI); 55518 55519 // Get the angular separation between the requested start and stop points. 55520 // 55521 // Technically this separation only matches what gets drawn if 55522 // correctForScaling is enabled. We could add a more complicated calculation 55523 // for when the scaling is uncorrected (in which case the drawn points could 55524 // end up pushed together or pulled apart quite dramatically relative to what 55525 // was requested), but it would make things more opaque for little practical 55526 // benefit. 55527 // 55528 // (If you do disable correctForScaling and find that correspondToSamePoint 55529 // is set too aggressively, the easiest thing to do is probably to just make 55530 // epsilon smaller...) 55531 separation = Math.min( 55532 Math.abs(start - stop), 55533 constants.TWO_PI - Math.abs(start - stop) 55534 ); 55535 55536 // Optionally adjust the angles to counter linear scaling. 55537 if (correctForScaling) { 55538 if (start <= constants.HALF_PI) { 55539 start = Math.atan(width / height * Math.tan(start)); 55540 } else if (start > constants.HALF_PI && start <= 3 * constants.HALF_PI) { 55541 start = Math.atan(width / height * Math.tan(start)) + constants.PI; 55542 } else { 55543 start = Math.atan(width / height * Math.tan(start)) + constants.TWO_PI; 55544 } 55545 if (stop <= constants.HALF_PI) { 55546 stop = Math.atan(width / height * Math.tan(stop)); 55547 } else if (stop > constants.HALF_PI && stop <= 3 * constants.HALF_PI) { 55548 stop = Math.atan(width / height * Math.tan(stop)) + constants.PI; 55549 } else { 55550 stop = Math.atan(width / height * Math.tan(stop)) + constants.TWO_PI; 55551 } 55552 } 55553 55554 // Ensure that start <= stop < start + TWO_PI. 55555 if (start > stop) { 55556 stop += constants.TWO_PI; 55557 } 55558 55559 return { 55560 start: start, 55561 stop: stop, 55562 correspondToSamePoint: separation < epsilon 55563 }; 55564 }; 55565 55566 /** 55567 * Draw an arc to the screen. If called with only x, y, w, h, start and stop, 55568 * the arc will be drawn and filled as an open pie segment. If a mode parameter 55569 * is provided, the arc will be filled like an open semi-circle (OPEN), a closed 55570 * semi-circle (CHORD), or as a closed pie segment (PIE). The origin may be changed 55571 * with the <a href="#/p5/ellipseMode">ellipseMode()</a> function. 55572 * 55573 * The arc is always drawn clockwise from wherever start falls to wherever stop 55574 * falls on the ellipse.Adding or subtracting TWO_PI to either angle does not 55575 * change where they fall. If both start and stop fall at the same place, a full 55576 * ellipse will be drawn. Be aware that the y-axis increases in the downward 55577 * direction, therefore angles are measured clockwise from the positive 55578 * x-direction ("3 o'clock"). 55579 * 55580 * @method arc 55581 * @param {Number} x x-coordinate of the arc's ellipse 55582 * @param {Number} y y-coordinate of the arc's ellipse 55583 * @param {Number} w width of the arc's ellipse by default 55584 * @param {Number} h height of the arc's ellipse by default 55585 * @param {Number} start angle to start the arc, specified in radians 55586 * @param {Number} stop angle to stop the arc, specified in radians 55587 * @param {Constant} [mode] optional parameter to determine the way of drawing 55588 * the arc. either CHORD, PIE or OPEN 55589 * @param {Number} [detail] optional parameter for WebGL mode only. This is to 55590 * specify the number of vertices that makes up the 55591 * perimeter of the arc. Default value is 25. 55592 * @chainable 55593 * 55594 * @example 55595 * <div> 55596 * <code> 55597 * arc(50, 55, 50, 50, 0, HALF_PI); 55598 * noFill(); 55599 * arc(50, 55, 60, 60, HALF_PI, PI); 55600 * arc(50, 55, 70, 70, PI, PI + QUARTER_PI); 55601 * arc(50, 55, 80, 80, PI + QUARTER_PI, TWO_PI); 55602 * </code> 55603 * </div> 55604 * 55605 * <div> 55606 * <code> 55607 * arc(50, 50, 80, 80, 0, PI + QUARTER_PI); 55608 * </code> 55609 * </div> 55610 * 55611 * <div> 55612 * <code> 55613 * arc(50, 50, 80, 80, 0, PI + QUARTER_PI, OPEN); 55614 * </code> 55615 * </div> 55616 * 55617 * <div> 55618 * <code> 55619 * arc(50, 50, 80, 80, 0, PI + QUARTER_PI, CHORD); 55620 * </code> 55621 * </div> 55622 * 55623 * <div> 55624 * <code> 55625 * arc(50, 50, 80, 80, 0, PI + QUARTER_PI, PIE); 55626 * </code> 55627 * </div> 55628 * 55629 * @alt 55630 *shattered outline of an ellipse with a quarter of a white circle bottom-right. 55631 *white ellipse with top right quarter missing. 55632 *white ellipse with black outline with top right missing. 55633 *white ellipse with top right missing with black outline around shape. 55634 *white ellipse with top right quarter missing with black outline around the shape. 55635 */ 55636 _main.default.prototype.arc = function(x, y, w, h, start, stop, mode, detail) { 55637 _main.default._validateParameters('arc', arguments); 55638 55639 // if the current stroke and fill settings wouldn't result in something 55640 // visible, exit immediately 55641 if (!this._renderer._doStroke && !this._renderer._doFill) { 55642 return this; 55643 } 55644 55645 if (start === stop) { 55646 return this; 55647 } 55648 55649 start = this._toRadians(start); 55650 stop = this._toRadians(stop); 55651 55652 // p5 supports negative width and heights for ellipses 55653 w = Math.abs(w); 55654 h = Math.abs(h); 55655 55656 var vals = _helpers.default.modeAdjust(x, y, w, h, this._renderer._ellipseMode); 55657 var angles = this._normalizeArcAngles(start, stop, vals.w, vals.h, true); 55658 55659 if (angles.correspondToSamePoint) { 55660 // If the arc starts and ends at (near enough) the same place, we choose to 55661 // draw an ellipse instead. This is preferable to faking an ellipse (by 55662 // making stop ever-so-slightly less than start + TWO_PI) because the ends 55663 // join up to each other rather than at a vertex at the centre (leaving 55664 // an unwanted spike in the stroke/fill). 55665 this._renderer.ellipse([vals.x, vals.y, vals.w, vals.h, detail]); 55666 } else { 55667 this._renderer.arc( 55668 vals.x, 55669 vals.y, 55670 vals.w, 55671 vals.h, 55672 angles.start, // [0, TWO_PI) 55673 angles.stop, // [start, start + TWO_PI) 55674 mode, 55675 detail 55676 ); 55677 55678 //accessible Outputs 55679 if (this._accessibleOutputs.grid || this._accessibleOutputs.text) { 55680 this._accsOutput('arc', [ 55681 vals.x, 55682 vals.y, 55683 vals.w, 55684 vals.h, 55685 angles.start, 55686 angles.stop, 55687 mode 55688 ]); 55689 } 55690 } 55691 55692 return this; 55693 }; 55694 55695 /** 55696 * Draws an ellipse (oval) to the screen. By default, the first two parameters 55697 * set the location of the center of the ellipse, and the third and fourth 55698 * parameters set the shape's width and height. If no height is specified, the 55699 * value of width is used for both the width and height. If a negative height or 55700 * width is specified, the absolute value is taken. 55701 * 55702 * An ellipse with equal width and height is a circle.The origin may be changed 55703 * with the <a href="#/p5/ellipseMode">ellipseMode()</a> function. 55704 * 55705 * @method ellipse 55706 * @param {Number} x x-coordinate of the center of ellipse. 55707 * @param {Number} y y-coordinate of the center of ellipse. 55708 * @param {Number} w width of the ellipse. 55709 * @param {Number} [h] height of the ellipse. 55710 * @chainable 55711 * @example 55712 * <div> 55713 * <code> 55714 * ellipse(56, 46, 55, 55); 55715 * </code> 55716 * </div> 55717 * 55718 * @alt 55719 *white ellipse with black outline in middle-right of canvas that is 55x55 55720 */ 55721 55722 /** 55723 * @method ellipse 55724 * @param {Number} x 55725 * @param {Number} y 55726 * @param {Number} w 55727 * @param {Number} h 55728 * @param {Integer} detail number of radial sectors to draw (for WebGL mode) 55729 */ 55730 _main.default.prototype.ellipse = function(x, y, w, h, detailX) { 55731 _main.default._validateParameters('ellipse', arguments); 55732 return this._renderEllipse.apply(this, arguments); 55733 }; 55734 55735 /** 55736 * Draws a circle to the screen. A circle is a simple closed shape. It is the set 55737 * of all points in a plane that are at a given distance from a given point, 55738 * the centre. This function is a special case of the ellipse() function, where 55739 * the width and height of the ellipse are the same. Height and width of the 55740 * ellipse correspond to the diameter of the circle. By default, the first two 55741 * parameters set the location of the centre of the circle, the third sets the 55742 * diameter of the circle. 55743 * 55744 * @method circle 55745 * @param {Number} x x-coordinate of the centre of the circle. 55746 * @param {Number} y y-coordinate of the centre of the circle. 55747 * @param {Number} d diameter of the circle. 55748 * @chainable 55749 * @example 55750 * <div> 55751 * <code> 55752 * // Draw a circle at location (30, 30) with a diameter of 20. 55753 * circle(30, 30, 20); 55754 * </code> 55755 * </div> 55756 * 55757 * @alt 55758 * white circle with black outline in mid of canvas that is 55x55. 55759 */ 55760 _main.default.prototype.circle = function() { 55761 _main.default._validateParameters('circle', arguments); 55762 var args = Array.prototype.slice.call(arguments, 0, 2); 55763 args.push(arguments[2]); 55764 args.push(arguments[2]); 55765 return this._renderEllipse.apply(this, args); 55766 }; 55767 55768 // internal method for drawing ellipses (without parameter validation) 55769 _main.default.prototype._renderEllipse = function(x, y, w, h, detailX) { 55770 // if the current stroke and fill settings wouldn't result in something 55771 // visible, exit immediately 55772 if (!this._renderer._doStroke && !this._renderer._doFill) { 55773 return this; 55774 } 55775 55776 // p5 supports negative width and heights for rects 55777 if (w < 0) { 55778 w = Math.abs(w); 55779 } 55780 55781 if (typeof h === 'undefined') { 55782 // Duplicate 3rd argument if only 3 given. 55783 h = w; 55784 } else if (h < 0) { 55785 h
55785= Math.abs(h); 55786 } 55787 55788 var vals = _helpers.default.modeAdjust(x, y, w, h, this._renderer._ellipseMode); 55789 this._renderer.ellipse([vals.x, vals.y, vals.w, vals.h, detailX]); 55790 55791 //accessible Outputs 55792 if (this._accessibleOutputs.grid || this._accessibleOutputs.text) { 55793 this._accsOutput('ellipse', [vals.x, vals.y, vals.w, vals.h]); 55794 } 55795 55796 return this; 55797 }; 55798 55799 /** 55800 * Draws a line (a direct path between two points) to the screen. If called with 55801 * only 4 parameters, it will draw a line in 2D with a default width of 1 pixel. 55802 * This width can be modified by using the <a href="#/p5/strokeWeight"> 55803 * strokeWeight()</a> function. A line cannot be filled, therefore the <a 55804 * href="#/p5/fill">fill()</a> function will not affect the color of a line. So to 55805 * color a line, use the <a href="#/p5/stroke">stroke()</a> function. 55806 * 55807 * @method line 55808 * @param {Number} x1 the x-coordinate of the first point 55809 * @param {Number} y1 the y-coordinate of the first point 55810 * @param {Number} x2 the x-coordinate of the second point 55811 * @param {Number} y2 the y-coordinate of the second point 55812 * @chainable 55813 * @example 55814 * <div> 55815 * <code> 55816 * line(30, 20, 85, 75); 55817 * </code> 55818 * </div> 55819 * 55820 * <div> 55821 * <code> 55822 * line(30, 20, 85, 20); 55823 * stroke(126); 55824 * line(85, 20, 85, 75); 55825 * stroke(255); 55826 * line(85, 75, 30, 75); 55827 * </code> 55828 * </div> 55829 * 55830 * @alt 55831 * An example showing a line 78 pixels long running from mid-top to bottom-right of canvas. 55832 * An example showing 3 lines of various stroke sizes. Form top, bottom and right sides of a square. 55833 */ 55834 55835 /** 55836 * @method line 55837 * @param {Number} x1 55838 * @param {Number} y1 55839 * @param {Number} z1 the z-coordinate of the first point 55840 * @param {Number} x2 55841 * @param {Number} y2 55842 * @param {Number} z2 the z-coordinate of the second point 55843 * @chainable 55844 */ 55845 _main.default.prototype.line = function() { 55846 for ( 55847 var _len = arguments.length, args = new Array(_len), _key = 0; 55848 _key < _len; 55849 _key++ 55850 ) { 55851 args[_key] = arguments[_key]; 55852 } 55853 _main.default._validateParameters('line', args); 55854 55855 if (this._renderer._doStroke) { 55856 var _this$_renderer; 55857 (_this$_renderer = this._renderer).line.apply(_this$_renderer, args); 55858 } 55859 55860 //accessible Outputs 55861 if (this._accessibleOutputs.grid || this._accessibleOutputs.text) { 55862 this._accsOutput('line', args); 55863 } 55864 55865 return this; 55866 }; 55867 55868 /** 55869 * Draws a point, a coordinate in space at the dimension of one pixel. 55870 * The first parameter is the horizontal value for the point, the second 55871 * param is the vertical value for the point. The color of the point is 55872 * changed with the <a href="#/p5/stroke">stroke()</a> function. The size of the point 55873 * can be changed with the <a href="#/p5/strokeWeight">
55873strokeWeight()</a> function. 55874 * 55875 * @method point 55876 * @param {Number} x the x-coordinate 55877 * @param {Number} y the y-coordinate 55878 * @param {Number} [z] the z-coordinate (for WebGL mode) 55879 * @chainable 55880 * @example 55881 * <div> 55882 * <code> 55883 * point(30, 20); 55884 * point(85, 20); 55885 * point(85, 75); 55886 * point(30, 75); 55887 * </code> 55888 * </div> 55889 * 55890 * <div> 55891 * <code> 55892 * point(30, 20); 55893 * point(85, 20); 55894 * stroke('purple'); // Change the color 55895 * strokeWeight(10); // Make the points 10 pixels in size 55896 * point(85, 75); 55897 * point(30, 75); 55898 * </code> 55899 * </div> 55900 * 55901 * <div> 55902 * <code> 55903 * let a = createVector(10, 10); 55904 * point(a); 55905 * let b = createVector(10, 20); 55906 * point(b); 55907 * point(createVector(20, 10)); 55908 * point(createVector(20, 20)); 55909 * </code> 55910 * </div> 55911 * 55912 * @alt 55913 * 4 points centered in the middle-right of the canvas. 55914 * 2 large points and 2 large purple points centered in the middle-right of the canvas. 55915 * Vertices of a square of length 10 pixels towards the top-left of the canvas. 55916 */ 55917 55918 /** 55919 * @method point 55920 * @param {p5.Vector} coordinate_vector the coordinate vector 55921 * @chainable 55922 */ 55923 _main.default.prototype.point = function() { 55924 for ( 55925 var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; 55926 _key2 < _len2; 55927 _key2++ 55928 ) { 55929 args[_key2] = arguments[_key2]; 55930 } 55931 _main.default._validateParameters('point', args); 55932 55933 if (this._renderer._doStroke) { 55934 if (args.length === 1 && args[0] instanceof _main.default.Vector) { 55935 this._renderer.point.call(this._renderer, args[0].x, args[0].y, args[0].z); 55936 } else { 55937 var _this$_renderer2; 55938 (_this$_renderer2 = this._renderer).point.apply(_this$_renderer2, args); 55939 //accessible Outputs 55940 if (this._accessibleOutputs.grid || this._accessibleOutputs.text) { 55941 this._accsOutput('point', args); 55942 } 55943 } 55944 } 55945 55946 return this; 55947 }; 55948 55949 /** 55950 * Draws a quad on the canvas. A quad is a quadrilateral, a four sided polygon. It is 55951 * similar to a rectangle, but the angles between its edges are not 55952 * constrained to ninety degrees. The first pair of parameters (x1,y1) 55953 * sets the first vertex and the subsequent pairs should proceed 55954 * clockwise or counter-clockwise around the defined shape. 55955 * z-arguments only work when quad() is used in WEBGL mode. 55956 * 55957 * @method quad 55958 * @param {Number} x1 the x-coordinate of the first point 55959 * @param {Number} y1 the y-coordinate of the first point 55960 * @param {Number} x2 the x-coordinate of the second point 55961 * @param {Number} y2 the y-coordinate of the second point 55962 * @param {Number} x3 the x-coordinate of the third point 55963 * @param {Number} y3 the y-coordinate of the third point 55964 * @param {Number} x4 the x-coordinate of the fourth point 55965 * @param {Number} y4 the y-coordinate of the fourth point 55966 * @chainable 55967 * @example 55968 * <div> 55969 * <code> 55970 * quad(38, 31, 86, 20, 69, 63, 30, 76); 55971 * </code> 55972 * </div> 55973 * 55974 * @alt 55975 *irregular white quadrilateral shape with black outline mid-right of canvas. 55976 */ 55977 /** 55978 * @method quad 55979 * @param {Number} x1 55980 * @param {Number} y1 55981 * @param {Number} z1 the z-coordinate of the first point 55982 * @param {Number} x2 55983 * @param {Number} y2 55984 * @param {Number} z2 the z-coordinate of the second point 55985 * @param {Number} x3 55986 * @param {Number} y3 55987 * @param {Number} z3 the z-coordinate of the third point 55988 * @param {Number} x4 55989 * @param {Number} y4 55990 * @param {Number} z4 the z-coordinate of the fourth point 55991 * @chainable 55992 */ 55993 _main.default.prototype.quad = function() { 55994 for ( 55995 var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; 55996 _key3 < _len3; 55997 _key3++ 55998 ) { 55999 args[_key3] = arguments[_key3]; 56000 } 56001 _main.default._validateParameters('quad', args); 56002 56003 if (this._renderer._doStroke || this._renderer._doFill) { 56004 if (this._renderer.isP3D && args.length !== 12) { 56005 // if 3D and we weren't passed 12 args, assume Z is 0 56006 // prettier-ignore 56007 this._renderer.quad.call( 56008 this._renderer, 56009 args[0], args[1], 0, 56010 args[2], args[3], 0, 56011 args[4], args[5], 0, 56012 args[6], args[7], 0); 56013 } else { 56014 var _this$_renderer3; 56015 (_this$_renderer3 = this._renderer).quad.apply(_this$_renderer3, args); 56016 //accessibile outputs 56017 if (this._accessibleOutputs.grid || this._accessibleOutputs.text) { 56018 this._accsOutput('quadrilateral', args); 56019 } 56020 } 56021 } 56022 56023 return this; 56024 }; 56025 56026 /** 56027 * Draws a rectangle on the canvas. A rectangle is a four-sided closed shape with 56028 * every angle at ninety degrees. By default, the first two parameters set 56029 * the location of the upper-left corner, the third sets the width, and the 56030 * fourth sets the height. The way these parameters are interpreted, may be 56031 * changed with the <a href="#/p5/rectMode">rectMode()</a> function. 56032 * 56033 * The fifth, sixth, seventh and eighth parameters, if specified, 56034 * determine corner radius for the top-left, top-right, lower-right and 56035 * lower-left corners, respectively. An omitted corner radius parameter is set 56036 * to the value of the previously specified radius value in the parameter list. 56037 * 56038 * @method rect 56039 * @param {Number} x x-coordinate of the rectangle. 56040 * @param {Number} y y-coordinate of the rectangle. 56041 * @param {Number} w width of the rectangle. 56042 * @param {Number} [h] height of the rectangle. 56043 * @param {Number} [tl] optional radius of top-left corner. 56044 * @param {Number} [tr] optional radius of top-right corner. 56045 * @param {Number} [br] optional radius of bottom-right corner. 56046 * @param {Number} [bl] optional radius of bottom-left corner. 56047 * @chainable 56048 * @example 56049 * <div> 56050 * <code> 56051 * // Draw a rectangle at location (30, 20) with a width and height of 55. 56052 * rect(30, 20, 55, 55); 56053 * </code> 56054 * </div> 56055 * 56056 * <div> 56057 * <code> 56058 * // Draw a rectangle with rounded corners, each having a radius of 20. 56059 * rect(30, 20, 55, 55, 20); 56060 * </code> 56061 * </div> 56062 * 56063 * <div> 56064 * <code> 56065 * // Draw a rectangle with rounded corners having the following radii: 56066 * // top-left = 20, top-right = 15, bottom-right = 10, bottom-left = 5. 56067 * rect(30, 20, 55, 55, 20, 15, 10, 5); 56068 * </code> 56069 * </div> 56070 * 56071 * @alt 56072 * 55x55 white rect with black outline in mid-right of canvas. 56073 * 55x55 white rect with black outline and rounded edges in mid-right of canvas. 56074 * 55x55 white rect with black outline and rounded edges of different radii. 56075 */ 56076 56077 /** 56078 * @method rect 56079 * @param {Number} x 56080 * @param {Number} y 56081 * @param {Number} w 56082 * @param {Number} h 56083 * @param {Integer} [detailX] number of segments in the x-direction (for WebGL mode) 56084 * @param {Integer} [detailY] number of segments in the y-direction (for WebGL mode) 56085 * @chainable 56086 */ 56087 _main.default.prototype.rect = function() { 56088 _main.default._validateParameters('rect', arguments); 56089 return this._renderRect.apply(this, arguments); 56090 }; 56091 56092 /**
56093 * Draws a square to the screen. A square is a four-sided shape with every angle 56094 * at ninety degrees, and equal side size. This function is a special case of the 56095 * rect() function, where the width and height are the same, and the parameter 56096 * is called "s" for side size. By default, the first two parameters set the 56097 * location of the upper-left corner, the third sets the side size of the square. 56098 * The way these parameters are interpreted, may be changed with the <a 56099 * href="#/p5/rectMode">rectMode()</a> function. 56100 * 56101 * The fourth, fifth, sixth and seventh parameters, if specified, 56102 * determine corner radius for the top-left, top-right, lower-right and 56103 * lower-left corners, respectively. An omitted corner radius parameter is set 56104 * to the value of the previously specified radius value in the parameter list. 56105 * 56106 * @method square 56107 * @param {Number} x x-coordinate of the square. 56108 * @param {Number} y y-coordinate of the square. 56109 * @param {Number} s side size of the square. 56110 * @param {Number} [tl] optional radius of top-left corner. 56111 * @param {Number} [tr] optional radius of top-right corner. 56112 * @param {Number} [br] optional radius of bottom-right corner. 56113 * @param {Number} [bl] optional radius of bottom-left corner. 56114 * @chainable 56115 * @example 56116 * <div> 56117 * <code> 56118 * // Draw a square at location (30, 20) with a side size of 55. 56119 * square(30, 20, 55); 56120 * </code> 56121 * </div> 56122 * 56123 * <div> 56124 * <code> 56125 * // Draw a square with rounded corners, each having a radius of 20. 56126 * square(30, 20, 55, 20); 56127 * </code> 56128 * </div> 56129 * 56130 * <div> 56131 * <code> 56132 * // Draw a square with rounded corners having the following radii: 56133 * // top-left = 20, top-right = 15, bottom-right = 10, bottom-left = 5. 56134 * square(30, 20, 55, 20, 15, 10, 5); 56135 * </code> 56136 * </div> 56137 * 56138 * @alt 56139 * 55x55 white square with black outline in mid-right of canvas. 56140 * 55x55 white square with black outline and rounded edges in mid-right of canvas. 56141 * 55x55 white square with black outline and rounded edges of different radii. 56142 */ 56143 _main.default.prototype.square = function(x, y, s, tl, tr, br, bl) { 56144 _main.default._validateParameters('square', arguments); 56145 // duplicate width for height in case of square 56146 return this._renderRect.call(this, x, y, s, s, tl, tr, br, bl); 56147 }; 56148 56149 // internal method to have renderer draw a rectangle 56150 _main.default.prototype._renderRect = function() { 56151 if (this._renderer._doStroke || this._renderer._doFill) { 56152 // duplicate width for height in case only 3 arguments is provided 56153 if (arguments.length === 3) { 56154 arguments[3] = arguments[2]; 56155 } 56156 var vals = _helpers.default.modeAdjust( 56157 arguments[0], 56158 arguments[1], 56159 arguments[2], 56160 arguments[3], 56161 this._renderer._rectMode 56162 ); 56163 56164 var args = [vals.x, vals.y, vals.w, vals.h]; 56165 // append the additional arguments (either cornder radii, or 56166 // segment details) to the argument list 56167 for (var i = 4; i < arguments.length; i++) { 56168 args[i] = arguments[i]; 56169 } 56170 this._renderer.rect(args); 56171 56172 //accessible outputs 56173 if (this._accessibleOutputs.grid || this._accessibleOutputs.text) { 56174 this._accsOutput('rectangle', [vals.x, vals.y, vals.w, vals.h]); 56175 } 56176 } 56177 56178 return this; 56179 }; 56180 56181 /** 56182 * Draws a triangle to the canvas. A triangle is a plane created by connecting 56183 * three points. The first two arguments specify the first point, the middle two 56184 * arguments specify the second point, and the last two arguments specify the 56185 * third point. 56186 * 56187 * @method triangle 56188 * @param {Number} x1 x-coordinate of the first point 56189 * @param {Number} y1 y-coordinate of the first point 56190 * @param {Number} x2 x-coordinate of the second point 56191 * @param {Number} y2 y-coordinate of the second point 56192 * @param {Number} x3 x-coordinate of the third point 56193 * @param {Number} y3 y-coordinate of the third point 56194 * @chainable 56195 * @example 56196 * <div> 56197 * <code> 56198 * triangle(30, 75, 58, 20, 86, 75); 56199 * </code> 56200 * </div> 56201 * 56202 *@alt 56203 * white triangle with black outline in mid-right of canvas. 56204 */ 56205 _main.default.prototype.triangle = function() { 56206 for ( 56207 var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; 56208 _key4 < _len4; 56209 _key4++ 56210 ) {
56211 args[_key4] = arguments[_key4]; 56212 } 56213 _main.default._validateParameters('triangle', args); 56214 56215 if (this._renderer._doStroke || this._renderer._doFill) { 56216 this._renderer.triangle(args); 56217 } 56218 56219 //accessible outputs 56220 if (this._accessibleOutputs.grid || this._accessibleOutputs.text) { 56221 this._accsOutput('triangle', args); 56222 } 56223 56224 return this; 56225 }; 56226 var _default = _main.default; 56227 exports.default = _default; 56228 }, 56229 { 56230 '../constants': 48, 56231 '../friendly_errors/fes_core': 51, 56232 '../friendly_errors/file_errors': 52, 56233 '../friendly_errors/validate_params': 54, 56234 '../helpers': 55, 56235 '../main': 59 56236 } 56237 ], 56238 67: [ 56239 function(_dereq_, module, exports) { 56240 'use strict'; 56241 function _typeof(obj) { 56242 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') { 56243 _typeof = function _typeof(obj) { 56244 return typeof obj; 56245 }; 56246 } else { 56247 _typeof = function _typeof(obj) { 56248 return obj && 56249 typeof Symbol === 'function' && 56250 obj.constructor === Symbol && 56251 obj !== Symbol.prototype 56252 ? 'symbol' 56253 : typeof obj; 56254 }; 56255 } 56256 return _typeof(obj); 56257 } 56258 Object.defineProperty(exports, '__esModule', { value: true }); 56259 exports.default = void 0; 56260 56261 var _main = _interopRequireDefault(_dereq_('../main')); 56262 var constants = _interopRequireWildcard(_dereq_('../constants')); 56263 function _getRequireWildcardCache() { 56264 if (typeof WeakMap !== 'function') return null; 56265 var cache = new WeakMap(); 56266 _getRequireWildcardCache = function _getRequireWildcardCache() { 56267 return cache; 56268 }; 56269 return cache; 56270 } 56271 function _interopRequireWildcard(obj) { 56272 if (obj && obj.__esModule) { 56273 return obj; 56274 } 56275 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) { 56276 return { default: obj }; 56277 } 56278 var cache = _getRequireWildcardCache(); 56279 if (cache && cache.has(obj)) { 56280 return cache.get(obj); 56281 } 56282 var newObj = {}; 56283 var hasPropertyDescriptor = 56284 Object.defineProperty && Object.getOwnPropertyDescriptor; 56285 for (var key in obj) { 56286 if (Object.prototype.hasOwnProperty.call(obj, key)) { 56287 var desc = hasPropertyDescriptor 56288 ? Object.getOwnPropertyDescriptor(obj, key) 56289 : null; 56290 if (desc && (desc.get || desc.set)) { 56291 Object.defineProperty(newObj, key, desc); 56292 } else { 56293 newObj[key] = obj[key]; 56294 } 56295 } 56296 } 56297 newObj.default = obj; 56298 if (cache) { 56299 cache.set(obj, newObj); 56300 } 56301 return newObj; 56302 } 56303 function _interopRequireDefault(obj) { 56304 return obj && obj.__esModule ? obj : { default: obj }; 56305 } 56306 /** 56307 * @module Shape 56308 * @submodule Attributes 56309 * @for p5 56310 * @requires core 56311 * @requires constants 56312 */ /** 56313 * Modifies the location from which ellipses are drawn by changing the way in 56314 * which parameters given to <a href="#/p5/ellipse">ellipse()</a>, 56315 * <a href="#/p5/circle">circle()</a> and <a href="#/p5/arc">arc()</a> are interpreted. 56316 * 56317 * The default mode is CENTER, in which the first two parameters are interpreted 56318 * as the shape's center point's x and y coordinates respectively, while the third 56319 * and fourth parameters are its width and height. 56320 * 56321 * ellipseMode(RADIUS) also uses the first two parameters as the shape's center 56322 * point's x and y coordinates, but uses the third and fourth parameters to 56323 * specify half of the shapes's width and height. 56324 * 56325 * ellipseMode(CORNER) interprets the first two parameters as the upper-left 56326 * corner of the shape, while the third and fourth parameters are its width 56327 * and height. 56328 * 56329 * ellipseMode(CORNERS) interprets the first two parameters as the location of 56330 * one corner of the ellipse's bounding box, and the third and fourth parameters 56331 * as the location of the opposite corner. 56332 * 56333 * The parameter to this method must be written in ALL CAPS because they are 56334 * predefined as constants in ALL CAPS and Javascript is a case-sensitive language. 56335 * 56336 * @method ellipseMode 56337 * @param {Constant} mode either CENTER, RADIUS, CORNER, or CORNERS 56338 * @chainable 56339 * @example 56340 * <div> 56341 * <code> 56342 * // Example showing RADIUS and CENTER ellipsemode with 2 overlaying ellipses 56343 * ellipseMode(RADIUS); 56344 * fill(255); 56345 * ellipse(50, 50, 30, 30); // Outer white ellipse 56346 * ellipseMode(CENTER); 56347 * fill(100); 56348 * ellipse(50, 50, 30, 30); // Inner gray ellipse 56349 * </code> 56350 * </div> 56351 * 56352 * <div> 56353 * <code> 56354 * // Example showing CORNER and CORNERS ellipseMode with 2 overlaying ellipses 56355 * ellipseMode(CORNER); 56356 * fill(255); 56357 * ellipse(25, 25, 50, 50); // Outer white ellipse 56358 * ellipseMode(CORNERS); 56359 * fill(100); 56360 * ellipse(25, 25, 50, 50); // Inner gray ellipse 56361 * </code> 56362 * </div> 56363 * 56364 * @alt 56365 * 60x60 white ellipse and 30x30 grey ellipse with black outlines at center. 56366 * 60x60 white ellipse and 30x30 grey ellipse top-right with black outlines. 56367 */ _main.default.prototype.ellipseMode = function(m) { 56368 _main.default._validateParameters('ellipseMode', arguments); 56369 if ( 56370 m === constants.CORNER || 56371 m === constants.CORNERS || 56372 m === constants.RADIUS || 56373 m === constants.CENTER 56374 ) { 56375 this._renderer._ellipseMode = m; 56376 } 56377 return this; 56378 }; 56379 56380 /** 56381 * Draws all geometry with jagged (aliased) edges. Note that <a href="#/p5/smooth">smooth()</a> is 56382 * active by default in 2D mode, so it is necessary to call <a href="#/p5/noSmooth">noSmooth()</a> to disable 56383 * smoothing of geometry, images, and fonts. In 3D mode, <a href="#/p5/noSmooth">noSmooth()</a> is enabled 56384 * by default, so it is necessary to call <a href="#/p5/smooth">smooth()</a> if you would like 56385 * smooth (antialiased) edges on your geometry. 56386 * 56387 * @method noSmooth 56388 * @chainable 56389 * @example 56390 * <div> 56391 * <code> 56392 * background(0); 56393 * noStroke(); 56394 * smooth(); 56395 * ellipse(30, 48, 36, 36); 56396 * noSmooth(); 56397 * ellipse(70, 48, 36, 36); 56398 * </code> 56399 * </div> 56400 * 56401 * @alt 56402 * 2 pixelated 36x36 white ellipses to left & right of center, black background 56403 */ 56404 _main.default.prototype.noSmooth = function() { 56405 this.setAttributes('antialias', false); 56406 if (!this._renderer.isP3D) { 56407 if ('imageSmoothingEnabled' in this.drawingContext) {
56408 this.drawingContext.imageSmoothingEnabled = false; 56409 } 56410 } 56411 return this; 56412 }; 56413 56414 /** 56415 * Modifies the location from which rectangles are drawn by changing the way 56416 * in which parameters given to <a href="#/p5/rect">rect()</a> are interpreted. 56417 * 56418 * The default mode is CORNER, which interprets the first two parameters as the 56419 * upper-left corner of the shape, while the third and fourth parameters are its 56420 * width and height. 56421 * 56422 * rectMode(CORNERS) interprets the first two parameters as the location of 56423 * one of the corners, and the third and fourth parameters as the location of 56424 * the diagonally opposite corner. Note, the rectangle is drawn between the 56425 * coordinates, so it is not neccesary that the first corner be the upper left 56426 * corner. 56427 * 56428 * rectMode(CENTER) interprets the first two parameters as the shape's center 56429 * point, while the third and fourth parameters are its width and height. 56430 * 56431 * rectMode(RADIUS) also uses the first two parameters as the shape's center 56432 * point, but uses the third and fourth parameters to specify half of the shape's 56433 * width and height respectively. 56434 * 56435 * The parameter to this method must be written in ALL CAPS because they are 56436 * predefined as constants in ALL CAPS and Javascript is a case-sensitive language. 56437 * 56438 * @method rectMode 56439 * @param {Constant} mode either CORNER, CORNERS, CENTER, or RADIUS 56440 * @chainable 56441 * @example 56442 * <div> 56443 * <code> 56444 * rectMode(CORNER); 56445 * fill(255); 56446 * rect(25, 25, 50, 50); // Draw white rectangle using CORNER mode 56447 * 56448 * rectMode(CORNERS); 56449 * fill(100); 56450 * rect(25, 25, 50, 50); // Draw gray rectangle using CORNERS mode 56451 * </code> 56452 * </div> 56453 * 56454 * <div> 56455 * <code> 56456 * rectMode(RADIUS); 56457 * fill(255); 56458 * rect(50, 50, 30, 30); // Draw white rectangle using RADIUS mode 56459 * 56460 * rectMode(CENTER); 56461 * fill(100); 56462 * rect(50, 50, 30, 30); // Draw gray rectangle using CENTER mode 56463 * </code> 56464 * </div> 56465 * 56466 * @alt 56467 * 50x50 white rect at center and 25x25 grey rect in the top left of the other. 56468 * 50x50 white rect at center and 25x25 grey rect in the center of the other. 56469 */ 56470 _main.default.prototype.rectMode = function(m) { 56471 _main.default._validateParameters('rectMode', arguments); 56472 if ( 56473 m === constants.CORNER || 56474 m === constants.CORNERS || 56475 m === constants.RADIUS || 56476 m === constants.CENTER 56477 ) { 56478 this._renderer._rectMode = m; 56479 } 56480 return this; 56481 }; 56482 56483 /** 56484 * Draws all geometry with smooth (anti-aliased) edges. <a href="#/p5/smooth">smooth()</a> will also 56485 * improve image quality of resized images. Note that <a href="#/p5/smooth">smooth()</a> is active by 56486 * default in 2D mode; <a href="#/p5/noSmooth">noSmooth()</a> can be used to disable smoothing of geometry, 56487 * images, and fonts. In 3D mode, <a href="#/p5/noSmooth">noSmooth()</a> is enabled 56488 * by default, so it is necessary to call <a href="#/p5/smooth">smooth()</a> if you would like 56489 * smooth (antialiased) edges on your geometry. 56490 * 56491 * @method smooth 56492 * @chainable 56493 * @example 56494 * <div> 56495 * <code> 56496 * background(0); 56497 * noStroke(); 56498 * smooth(); 56499 * ellipse(30, 48, 36, 36); 56500 * noSmooth(); 56501 * ellipse(70, 48, 36, 36); 56502 * </code> 56503 * </div> 56504 * 56505 * @alt 56506 * 2 pixelated 36x36 white ellipses one left one right of center. On black. 56507 */ 56508 _main.default.prototype.smooth = function() { 56509 this.setAttributes('antialias', true); 56510 if (!this._renderer.isP3D) { 56511 if ('imageSmoothingEnabled' in this.drawingContext) {
56512 this.drawingContext.imageSmoothingEnabled = true; 56513 } 56514 } 56515 return this; 56516 }; 56517 56518 /** 56519 * Sets the style for rendering line endings. These ends are either rounded, 56520 * squared or extended, each of which specified with the corresponding 56521 * parameters: ROUND, SQUARE and PROJECT. The default cap is ROUND. 56522 * 56523 * The parameter to this method must be written in ALL CAPS because they are 56524 * predefined as constants in ALL CAPS and Javascript is a case-sensitive language. 56525 * 56526 * @method strokeCap 56527 * @param {Constant} cap either ROUND, SQUARE or PROJECT 56528 * @chainable 56529 * @example 56530 * <div> 56531 * <code> 56532 * // Example of different strokeCaps 56533 * strokeWeight(12.0); 56534 * strokeCap(ROUND); 56535 * line(20, 30, 80, 30); 56536 * strokeCap(SQUARE); 56537 * line(20, 50, 80, 50); 56538 * strokeCap(PROJECT); 56539 * line(20, 70, 80, 70); 56540 * </code> 56541 * </div> 56542 * 56543 * @alt 56544 * 3 lines. Top line: rounded ends, mid: squared, bottom:longer squared ends. 56545 */ 56546 _main.default.prototype.strokeCap = function(cap) { 56547 _main.default._validateParameters('strokeCap', arguments); 56548 if ( 56549 cap === constants.ROUND || 56550 cap === constants.SQUARE || 56551 cap === constants.PROJECT 56552 ) { 56553 this._renderer.strokeCap(cap); 56554 } 56555 return this; 56556 }; 56557 56558 /** 56559 * Sets the style of the joints which connect line segments. These joints 56560 * are either mitered, beveled or rounded and specified with the 56561 * corresponding parameters MITER, BEVEL and ROUND. The default joint is 56562 * MITER. 56563 * 56564 * The parameter to this method must be written in ALL CAPS because they are 56565 * predefined as constants in ALL CAPS and Javascript is a case-sensitive language. 56566 * 56567 * @method strokeJoin 56568 * @param {Constant} join either MITER, BEVEL, ROUND 56569 * @chainable 56570 * @example 56571 * <div> 56572 * <code> 56573 * // Example of MITER type of joints 56574 * noFill(); 56575 * strokeWeight(10.0); 56576 * strokeJoin(MITER); 56577 * beginShape(); 56578 * vertex(35, 20); 56579 * vertex(65, 50); 56580 * vertex(35, 80); 56581 * endShape(); 56582 * </code> 56583 * </div> 56584 * 56585 * <div> 56586 * <code> 56587 * // Example of BEVEL type of joints 56588 * noFill(); 56589 * strokeWeight(10.0); 56590 * strokeJoin(BEVEL); 56591 * beginShape(); 56592 * vertex(35, 20); 56593 * vertex(65, 50); 56594 * vertex(35, 80); 56595 * endShape(); 56596 * </code> 56597 * </div> 56598 * 56599 * <div> 56600 * <code> 56601 * // Example of ROUND type of joints 56602 * noFill(); 56603 * strokeWeight(10.0); 56604 * strokeJoin(ROUND); 56605 * beginShape(); 56606 * vertex(35, 20); 56607 * vertex(65, 50); 56608 * vertex(35, 80); 56609 * endShape(); 56610 * </code> 56611 * </div> 56612 * 56613 * @alt 56614 * Right-facing arrowhead shape with pointed tip in center of canvas. 56615 * Right-facing arrowhead shape with flat tip in center of canvas. 56616 * Right-facing arrowhead shape with rounded tip in center of canvas. 56617 */ 56618 _main.default.prototype.strokeJoin = function(join) { 56619 _main.default._validateParameters('strokeJoin', arguments); 56620 if ( 56621 join === constants.ROUND || 56622 join === constants.BEVEL || 56623 join === constants.MITER 56624 ) { 56625 this._renderer.strokeJoin(join); 56626 } 56627 return this; 56628 }; 56629 56630 /** 56631 * Sets the width of the stroke used for lines, points and the border around 56632 * shapes. All widths are set in units of pixels. 56633 * 56634 * @method strokeWeight 56635 * @param {Number} weight the weight of the stroke (in pixels) 56636 * @chainable 56637 * @example 56638 * <div> 56639 * <code> 56640 * // Example of different stroke weights 56641 * strokeWeight(1); // Default 56642 * line(20, 20, 80, 20); 56643 * strokeWeight(4); // Thicker 56644 * line(20, 40, 80, 40); 56645 * strokeWeight(10); // Beastly 56646 * line(20, 70, 80, 70); 56647 * </code> 56648 * </div> 56649 * 56650 * @alt 56651 * 3 horizontal black lines. Top line: thin, mid: medium, bottom:thick. 56652 */ 56653 _main.default.prototype.strokeWeight = function(w) { 56654 _main.default._validateParameters('strokeWeight', arguments); 56655 this._renderer.strokeWeight(w); 56656 return this; 56657 }; 56658 var _default = _main.default; 56659 exports.default = _default; 56660 }, 56661 { '../constants': 48, '../main': 59 } 56662 ], 56663 68: [
56664 function(_dereq_, module, exports) { 56665 'use strict'; 56666 Object.defineProperty(exports, '__esModule', { value: true }); 56667 exports.default = void 0; 56668 56669 var _main = _interopRequireDefault(_dereq_('../main')); 56670 _dereq_('../friendly_errors/fes_core'); 56671 _dereq_('../friendly_errors/file_errors'); 56672 _dereq_('../friendly_errors/validate_params'); 56673 function _interopRequireDefault(obj) { 56674 return obj && obj.__esModule ? obj : { default: obj }; 56675 } 56676 /** 56677 * @module Shape 56678 * @submodule Curves 56679 * @for p5 56680 * @requires core 56681 */ /** 56682 * Draws a cubic Bezier curve on the screen. These curves are defined by a 56683 * series of anchor and control points. The first two parameters specify 56684 * the first anchor point and the last two parameters specify the other 56685 * anchor point, which become the first and last points on the curve. The 56686 * middle parameters specify the two control points which define the shape 56687 * of the curve. Approximately speaking, control points "pull" the curve 56688 * towards them. 56689 * 56690 * Bezier curves were developed by French automotive engineer Pierre Bezier, 56691 * and are commonly used in computer graphics to define gently sloping curves. 56692 * See also <a href="#/p5/curve">curve()</a>. 56693 * 56694 * @method bezier 56695 * @param {Number} x1 x-coordinate for the first anchor point 56696 * @param {Number} y1 y-coordinate for the first anchor point 56697 * @param {Number} x2 x-coordinate for the first control point 56698 * @param {Number} y2 y-coordinate for the first control point 56699 * @param {Number} x3 x-coordinate for the second control point 56700 * @param {Number} y3 y-coordinate for the second control point 56701 * @param {Number} x4 x-coordinate for the second anchor point 56702 * @param {Number} y4 y-coordinate for the second anchor point 56703 * @chainable 56704 * @example 56705 * <div> 56706 * <code> 56707 * noFill(); 56708 * stroke(255, 102, 0); 56709 * line(85, 20, 10, 10); 56710 * line(90, 90, 15, 80); 56711 * stroke(0, 0, 0); 56712 * bezier(85, 20, 10, 10, 90, 90, 15, 80); 56713 * </code> 56714 * </div> 56715 * 56716 * <div> 56717 * <code> 56718 * background(0, 0, 0); 56719 * noFill(); 56720 * stroke(255); 56721 * bezier(250, 250, 0, 100, 100, 0, 100, 0, 0, 0, 100, 0); 56722 * </code> 56723 * </div> 56724 * 56725 * @alt 56726 * stretched black s-shape in center with orange lines extending from end points. 56727 * a white colored curve on black background from the upper-right corner to the lower right corner. 56728 */ /** 56729 * @method bezier 56730 * @param {Number} x1 56731 * @param {Number} y1 56732 * @param {Number} z1 z-coordinate for the first anchor point 56733 * @param {Number} x2 56734 * @param {Number} y2 56735 * @param {Number} z2 z-coordinate for the first control point 56736 * @param {Number} x3 56737 * @param {Number} y3 56738 * @param {Number} z3 z-coordinate for the second control point 56739 * @param {Number} x4 56740 * @param {Number} y4 56741 * @param {Number} z4 z-coordinate for the second anchor point 56742 * @chainable 56743 */ _main.default.prototype.bezier = function() { 56744 var _this$_renderer; 56745 for ( 56746 var _len = arguments.length, args = new Array(_len), _key = 0; 56747 _key < _len; 56748 _key++ 56749 ) { 56750 args[_key] = arguments[_key]; 56751 } 56752 _main.default._validateParameters('bezier', args); 56753 56754 // if the current stroke and fill settings wouldn't result in something 56755 // visible, exit immediately 56756 if (!this._renderer._doStroke && !this._renderer._doFill) { 56757 return this; 56758 } 56759 56760 (_this$_renderer = this._renderer).bezier.apply(_this$_renderer, args); 56761 56762 return this; 56763 }; 56764 56765 /** 56766 * Sets the resolution at which Bezier's curve is displayed. The default value is 20. 56767 * 56768 * Note, This function is only useful when using the WEBGL renderer 56769 * as the default canvas renderer does not use this information. 56770 * 56771 * @method bezierDetail 56772 * @param {Number} detail resolution of the curves 56773 * @chainable 56774 * @example 56775 * <div modernizr='webgl'> 56776 * <code> 56777 * function setup() { 56778 * createCanvas(100, 100, WEBGL); 56779 * noFill(); 56780 * bezierDetail(5); 56781 * } 56782 * 56783 * function draw() { 56784 * background(200); 56785 * // prettier-ignore 56786 * bezier(-40, -40, 0, 56787 * 90, -40, 0, 56788 * -90, 40, 0, 56789 * 40, 40, 0); 56790 * } 56791 * </code> 56792 * </div> 56793 * 56794 * @alt 56795 * stretched black s-shape with a low level of bezier detail 56796 */ 56797 _main.default.prototype.bezierDetail = function(d) { 56798 _main.default._validateParameters('bezierDetail', arguments); 56799 this._bezierDetail = d; 56800 return this; 56801 }; 56802 56803 /** 56804 * Given the x or y co-ordinate values of control and anchor points of a bezier 56805 * curve, it evaluates the x or y coordinate of the bezier at position t. The 56806 * parameters a and d are the x or y coordinates of first and last points on the 56807 * curve while b and c are of the control points.The final parameter t is the 56808 * position of the resultant point which is given between 0 and 1. 56809 * This can be done once with the x coordinates and a second time 56810 * with the y coordinates to get the location of a bezier curve at t. 56811 * 56812 * @method bezierPoint 56813 * @param {Number} a coordinate of first point on the curve 56814 * @param {Number} b coordinate of first control point 56815 * @param {Number} c coordinate of second control point 56816 * @param {Number} d coordinate of second point on the curve 56817 * @param {Number} t value between 0 and 1 56818 * @return {Number} the value of the Bezier at position t 56819 * @example 56820 * <div> 56821 * <code> 56822 * noFill(); 56823 * let x1 = 85, 56824 x2 = 10, 56825 x3 = 90, 56826 x4 = 15; 56827 * let y1 = 20, 56828 y2 = 10, 56829 y3 = 90, 56830 y4 = 80; 56831 * bezier(x1, y1, x2, y2, x3, y3, x4, y4); 56832 * fill(255); 56833 * let steps = 10; 56834 * for (let i = 0; i <= steps; i++) { 56835 * let t = i / steps; 56836 * let x = bezierPoint(x1, x2, x3, x4, t); 56837 * let y = bezierPoint(y1, y2, y3, y4, t); 56838 * circle(x, y, 5); 56839 * } 56840 * </code> 56841 * </div> 56842 * 56843 * @alt 56844 * 10 points plotted on a given bezier at equal distances. 56845 */ 56846 _main.default.prototype.bezierPoint = function(a, b, c, d, t) { 56847 _main.default._validateParameters('bezierPoint', arguments); 56848 56849 var adjustedT = 1 - t; 56850 return ( 56851 Math.pow(adjustedT, 3) * a + 56852 3 * Math.pow(adjustedT, 2) * t * b + 56853 3 * adjustedT * Math.pow(t, 2) * c + 56854 Math.pow(t, 3) * d 56855 ); 56856 }; 56857 56858 /** 56859 * Evaluates the tangent to the Bezier at position t for points a, b, c, d. 56860 * The parameters a and d are the first and last points 56861 * on the curve, and b and c are the control points. 56862 * The final parameter t varies between 0 and 1. 56863 * 56864 * @method bezierTangent 56865 * @param {Number} a coordinate of first point on the curve 56866 * @param {Number} b coordinate of first control point 56867 * @param {Number} c coordinate of second control point 56868 * @param {Number} d coordinate of second point on the curve 56869 * @param {Number} t value between 0 and 1 56870 * @return {Number} the tangent at position t 56871 * @example 56872 * <div> 56873 * <code> 56874 * noFill(); 56875 * bezier(85, 20, 10, 10, 90, 90, 15, 80); 56876 * let steps = 6; 56877 * fill(255); 56878 * for (let i = 0; i <= steps; i++) { 56879 * let t = i / steps; 56880 * // Get the location of the point 56881 * let x = bezierPoint(85, 10, 90, 15, t); 56882 * let y = bezierPoint(20, 10, 90, 80, t); 56883 * // Get the tangent points 56884 * let tx = bezierTangent(85, 10, 90, 15, t); 56885 * let ty = bezierTangent(20, 10, 90, 80, t); 56886 * // Calculate an angle from the tangent points 56887 * let a = atan2(ty, tx); 56888 * a += PI; 56889 * stroke(255, 102, 0); 56890 * line(x, y, cos(a) * 30 + x, sin(a) * 30 + y); 56891 * // The following line of code makes a line 56892 * // inverse of the above line 56893 * //line(x, y, cos(a)*-30 + x, sin(a)*-30 + y); 56894 * stroke(0); 56895 * ellipse(x, y, 5, 5); 56896 * } 56897 * </code> 56898 * </div> 56899 * 56900 * <div> 56901 * <code> 56902 * noFill(); 56903 * bezier(85, 20, 10, 10, 90, 90, 15, 80); 56904 * stroke(255, 102, 0); 56905 * let steps = 16; 56906 * for (let i = 0; i <= steps; i++) { 56907 * let t = i / steps; 56908 * let x = bezierPoint(85, 10, 90, 15, t); 56909 * let y = bezierPoint(20, 10, 90, 80, t); 56910 * let tx = bezierTangent(85, 10, 90, 15, t); 56911 * let ty = bezierTangent(20, 10, 90, 80, t); 56912 * let a = atan2(ty, tx); 56913 * a -= HALF_PI; 56914 * line(x, y, cos(a) * 8 + x, sin(a) * 8 + y); 56915 * } 56916 * </code> 56917 * </div> 56918 * 56919 * @alt 56920 * s-shaped line with 6 short orange lines showing the tangents at those points. 56921 * s-shaped line with 6 short orange lines showing lines coming out the underside of the bezier. 56922 */ 56923 _main.default.prototype.bezierTangent = function(a, b, c, d, t) { 56924 _main.default._validateParameters('bezierTangent', arguments); 56925 56926 var adjustedT = 1 - t; 56927 return ( 56928 3 * d * Math.pow(t, 2) - 56929 3 * c * Math.pow(t, 2) + 56930 6 * c * adjustedT * t - 56931 6 * b * adjustedT * t + 56932 3 * b * Math.pow(adjustedT, 2) - 56933 3 * a * Math.pow(adjustedT, 2) 56934 ); 56935 }; 56936 56937 /** 56938 * Draws a curved line on the screen between two points, given as the 56939 * middle four parameters. The first two parameters are a control point, as 56940 * if the curve came from this point even though it's not drawn. The last 56941 * two parameters similarly describe the other control point. <br /><br /> 56942 * Longer curves can be created by putting a series of <a href="#/p5/curve">curve()</a> functions
56943 * together or using <a href="#/p5/curveVertex">curveVertex()</a>. An additional function called 56944 * <a href="#/p5/curveTightness">curveTightness()</a> provides control for the visual quality of the curve. 56945 * The <a href="#/p5/curve">curve()</a> function is an implementation of Catmull-Rom splines. 56946 * 56947 * @method curve 56948 * @param {Number} x1 x-coordinate for the beginning control point 56949 * @param {Number} y1 y-coordinate for the beginning control point 56950 * @param {Number} x2 x-coordinate for the first point 56951 * @param {Number} y2 y-coordinate for the first point 56952 * @param {Number} x3 x-coordinate for the second point 56953 * @param {Number} y3 y-coordinate for the second point 56954 * @param {Number} x4 x-coordinate for the ending control point 56955 * @param {Number} y4 y-coordinate for the ending control point 56956 * @chainable 56957 * @example 56958 * <div> 56959 * <code> 56960 * noFill(); 56961 * stroke(255, 102, 0); 56962 * curve(5, 26, 5, 26, 73, 24, 73, 61); 56963 * stroke(0); 56964 * curve(5, 26, 73, 24, 73, 61, 15, 65); 56965 * stroke(255, 102, 0); 56966 * curve(73, 24, 73, 61, 15, 65, 15, 65); 56967 * </code> 56968 * </div> 56969 * 56970 * <div> 56971 * <code> 56972 * // Define the curve points as JavaScript objects 56973 * let p1 = { x: 5, y: 26 }; 56974 * let p2 = { x: 73, y: 24 }; 56975 * let p3 = { x: 73, y: 61 }; 56976 * let p4 = { x: 15, y: 65 }; 56977 * noFill(); 56978 * stroke(255, 102, 0); 56979 * curve(p1.x, p1.y, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y); 56980 * stroke(0); 56981 * curve(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y); 56982 * stroke(255, 102, 0); 56983 * curve(p2.x, p2.y, p3.x, p3.y, p4.x, p4.y, p4.x, p4.y); 56984 * </code> 56985 * </div> 56986 * 56987 * <div> 56988 * <code> 56989 * noFill(); 56990 * stroke(255, 102, 0); 56991 * curve(5, 26, 0, 5, 26, 0, 73, 24, 0, 73, 61, 0); 56992 * stroke(0); 56993 * curve(5, 26, 0, 73, 24, 0, 73, 61, 0, 15, 65, 0); 56994 * stroke(255, 102, 0); 56995 * curve(73, 24, 0, 73, 61, 0, 15, 65, 0, 15, 65, 0); 56996 * </code> 56997 * </div> 56998 * 56999 * @alt 57000 * horseshoe shape with orange ends facing left and black curved center. 57001 * horseshoe shape with orange ends facing left and black curved center. 57002 * curving black and orange lines. 57003 */ 57004 57005 /** 57006 * @method curve 57007 * @param {Number} x1 57008 * @param {Number} y1 57009 * @param {Number} z1 z-coordinate for the beginning control point 57010 * @param {Number} x2 57011 * @param {Number} y2 57012 * @param {Number} z2 z-coordinate for the first point 57013 * @param {Number} x3 57014 * @param {Number} y3 57015 * @param {Number} z3 z-coordinate for the second point 57016 * @param {Number} x4 57017 * @param {Number} y4 57018 * @param {Number} z4 z-coordinate for the ending control point 57019 * @chainable 57020 */ 57021 _main.default.prototype.curve = function() { 57022 for ( 57023 var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; 57024 _key2 < _len2; 57025 _key2++ 57026 ) { 57027 args[_key2] = arguments[_key2]; 57028 } 57029 _main.default._validateParameters('curve', args); 57030 57031 if (this._renderer._doStroke) { 57032 var _this$_renderer2; 57033 (_this$_renderer2 = this._renderer).curve.apply(_this$_renderer2, args); 57034 } 57035 57036 return this; 57037 }; 57038 57039 /** 57040 * Sets the resolution at which curves display. The default value is 20 while 57041 * the minimum value is 3. 57042 * 57043 * This function is only useful when using the WEBGL renderer 57044 * as the default canvas renderer does not use this 57045 * information. 57046 * 57047 * @method curveDetail 57048 * @param {Number} resolution resolution of the curves 57049 * @chainable 57050 * @example 57051 * <div modernizr='webgl'> 57052 * <code> 57053 * function setup() { 57054 * createCanvas(100, 100, WEBGL); 57055 * 57056 * curveDetail(5); 57057 * } 57058 * function draw() { 57059 * background(200); 57060 * 57061 * curve(250, 600, 0, -30, 40, 0, 30, 30, 0, -250, 600, 0); 57062 * } 57063 * </code> 57064 * </div> 57065 * 57066 * @alt 57067 * white arch shape with a low level of curve detail. 57068 */ 57069 _main.default.prototype.curveDetail = function(d) { 57070 _main.default._validateParameters('curveDetail', arguments); 57071 if (d < 3) { 57072 this._curveDetail = 3; 57073 } else { 57074 this._curveDetail = d; 57075 } 57076 return this; 57077 }; 57078 57079 /** 57080 * Modifies the quality of forms created with <a href="#/p5/curve">curve()</a> 57081 * and <a href="#/p5/curveVertex">curveVertex()</a>.The parameter tightness 57082 * determines how the curve fits to the vertex points. The value 0.0 is the 57083 * default value for tightness (this value defines the curves to be Catmull-Rom 57084 * splines) and the value 1.0 connects all the points with straight lines. 57085 * Values within the range -5.0 and 5.0 will deform the curves but will leave 57086 * them recognizable and as values increase in magnitude, they will continue to deform. 57087 * 57088 * @method curveTightness 57089 * @param {Number} amount amount of deformation from the original vertices 57090 * @chainable 57091 * @example 57092 * <div> 57093 * <code> 57094 * // Move the mouse left and right to see the curve change 57095 * function setup() { 57096 * createCanvas(100, 100); 57097 * noFill(); 57098 * } 57099 * 57100 * function draw() { 57101 * background(204); 57102 * let t = map(mouseX, 0, width, -5, 5); 57103 * curveTightness(t); 57104 * beginShape(); 57105 * curveVertex(10, 26); 57106 * curveVertex(10, 26); 57107 * curveVertex(83, 24); 57108 * curveVertex(83, 61); 57109 * curveVertex(25, 65); 57110 * curveVertex(25, 65); 57111 * endShape(); 57112 * } 57113 * </code> 57114 * </div> 57115 * 57116 * @alt 57117 * Line shaped like right-facing arrow,points move with mouse-x and warp shape. 57118 */ 57119 _main.default.prototype.curveTightness = function(t) { 57120 _main.default._validateParameters('curveTightness', arguments); 57121 this._renderer._curveTightness = t; 57122 return this; 57123 }; 57124 57125 /** 57126 * Evaluates the curve at position t for points a, b, c, d. 57127 * The parameter t varies between 0 and 1, a and d are control points 57128 * of the curve, and b and c are the start and end points of the curve. 57129 * This can be done once with the x coordinates and a second time 57130 * with the y coordinates to get the location of a curve at t. 57131 * 57132 * @method curvePoint 57133 * @param {Number} a coordinate of first control point of the curve 57134 * @param {Number} b coordinate of first point 57135 * @param {Number} c coordinate of second point 57136 * @param {Number} d coordinate of second control point 57137 * @param {Number} t value between 0 and 1 57138 * @return {Number} bezier value at position t 57139 * @example 57140 * <div> 57141 * <code> 57142 * noFill(); 57143 * curve(5, 26, 5, 26, 73, 24, 73, 61); 57144 * curve(5, 26, 73, 24, 73, 61, 15, 65); 57145 * fill(255); 57146 * ellipseMode(CENTER); 57147 * let steps = 6; 57148 * for (let i = 0; i <= steps; i++) { 57149 * let t = i / steps; 57150 * let x = curvePoint(5, 5, 73, 73, t); 57151 * let y = curvePoint(26, 26, 24, 61, t); 57152 * ellipse(x, y, 5, 5); 57153 * x = curvePoint(5, 73, 73, 15, t); 57154 * y = curvePoint(26, 24, 61, 65, t); 57155 * ellipse(x, y, 5, 5); 57156 * } 57157 * </code> 57158 * </div> 57159 * 57160 *line hooking down to right-bottom with 13 5x5 white ellipse points 57161 */ 57162 _main.default.prototype.curvePoint = function(a, b, c, d, t) { 57163 _main.default._validateParameters('curvePoint', arguments); 57164 57165 var t3 = t * t * t, 57166 t2 = t * t, 57167 f1 = -0.5 * t3 + t2 - 0.5 * t, 57168 f2 = 1.5 * t3 - 2.5 * t2 + 1.0, 57169 f3 = -1.5 * t3 + 2.0 * t2 + 0.5 * t, 57170 f4 = 0.5 * t3 - 0.5 * t2; 57171 return a * f1 + b * f2 + c * f3 + d * f4; 57172 }; 57173 57174 /** 57175 * Evaluates the tangent to the curve at position t for points a, b, c, d. 57176 * The parameter t varies between 0 and 1, a and d are points on the curve, 57177 * and b and c are the control points. 57178 * 57179 * @method curveTangent 57180 * @param {Number} a coordinate of first control point 57181 * @param {Number} b coordinate of first point on the curve 57182 * @param {Number} c coordinate of second point on the curve 57183 * @param {Number} d coordinate of second conrol point 57184 * @param {Number} t value between 0 and 1 57185 * @return {Number} the tangent at position t 57186 * @example 57187 * <div> 57188 * <code> 57189 * noFill(); 57190 * curve(5, 26, 73, 24, 73, 61, 15, 65); 57191 * let steps = 6; 57192 * for (let i = 0; i <= steps; i++) { 57193 * let t = i / steps; 57194 * let x = curvePoint(5, 73, 73, 15, t); 57195 * let y = curvePoint(26, 24, 61, 65, t); 57196 * //ellipse(x, y, 5, 5); 57197 * let tx = curveTangent(5, 73, 73, 15, t); 57198 * let ty = curveTangent(26, 24, 61, 65, t); 57199 * let a = atan2(ty, tx); 57200 * a -= PI / 2.0; 57201 * line(x, y, cos(a) * 8 + x, sin(a) * 8 + y); 57202 * } 57203 * </code> 57204 * </div> 57205 * 57206 * @alt 57207 * right curving line mid-right of canvas with 7 short lines radiating from it. 57208 */ 57209 _main.default.prototype.curveTangent = function(a, b, c, d, t) { 57210 _main.default._validateParameters('curveTangent', arguments); 57211 57212 var t2 = t * t, 57213 f1 = -3 * t2 / 2 + 2 * t - 0.5, 57214 f2 = 9 * t2 / 2 - 5 * t, 57215 f3 = -9 * t2 / 2 + 4 * t + 0.5, 57216 f4 = 3 * t2 / 2 - t; 57217 return a * f1 + b * f2 + c * f3 + d * f4; 57218 }; 57219 var _default = _main.default; 57220 exports.default = _default; 57221 }, 57222 { 57223 '../friendly_errors/fes_core': 51, 57224 '../friendly_errors/file_errors': 52, 57225 '../friendly_errors/validate_params': 54, 57226 '../main': 59 57227 } 57228 ], 57229 69: [
57230 function(_dereq_, module, exports) { 57231 'use strict'; 57232 function _typeof(obj) { 57233 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') { 57234 _typeof = function _typeof(obj) { 57235 return typeof obj; 57236 }; 57237 } else { 57238 _typeof = function _typeof(obj) { 57239 return obj && 57240 typeof Symbol === 'function' && 57241 obj.constructor === Symbol && 57242 obj !== Symbol.prototype 57243 ? 'symbol' 57244 : typeof obj; 57245 }; 57246 } 57247 return _typeof(obj); 57248 } 57249 Object.defineProperty(exports, '__esModule', { value: true }); 57250 exports.default = void 0; 57251 57252 var _main = _interopRequireDefault(_dereq_('../main')); 57253 var constants = _interopRequireWildcard(_dereq_('../constants')); 57254 function _getRequireWildcardCache() { 57255 if (typeof WeakMap !== 'function') return null; 57256 var cache = new WeakMap(); 57257 _getRequireWildcardCache = function _getRequireWildcardCache() { 57258 return cache; 57259 }; 57260 return cache; 57261 } 57262 function _interopRequireWildcard(obj) { 57263 if (obj && obj.__esModule) { 57264 return obj; 57265 } 57266 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) { 57267 return { default: obj }; 57268 } 57269 var cache = _getRequireWildcardCache(); 57270 if (cache && cache.has(obj)) { 57271 return cache.get(obj); 57272 } 57273 var newObj = {}; 57274 var hasPropertyDescriptor = 57275 Object.defineProperty && Object.getOwnPropertyDescriptor; 57276 for (var key in obj) { 57277 if (Object.prototype.hasOwnProperty.call(obj, key)) { 57278 var desc = hasPropertyDescriptor 57279 ? Object.getOwnPropertyDescriptor(obj, key) 57280 : null; 57281 if (desc && (desc.get || desc.set)) { 57282 Object.defineProperty(newObj, key, desc); 57283 } else { 57284 newObj[key] = obj[key]; 57285 } 57286 } 57287 } 57288 newObj.default = obj; 57289 if (cache) { 57290 cache.set(obj, newObj); 57291 } 57292 return newObj; 57293 } 57294 function _interopRequireDefault(obj) { 57295 return obj && obj.__esModule ? obj : { default: obj }; 57296 } 57297 /** 57298 * @module Shape 57299 * @submodule Vertex 57300 * @for p5 57301 * @requires core 57302 * @requires constants 57303 */ var shapeKind = null; 57304 var vertices = []; 57305 var contourVertices = []; 57306 var isBezier = false;
57307 var isCurve = false; 57308 var isQuadratic = false; 57309 var isContour = false; 57310 var isFirstContour = true; 57311 57312 /** 57313 * Use the <a href="#/p5/beginContour">beginContour()</a> and 57314 * <a href="#/p5/endContour">endContour()</a> functions to create negative shapes 57315 * within shapes such as the center of the letter 'O'. <a href="#/p5/beginContour">beginContour()</a> 57316 * begins recording vertices for the shape and <a href="#/p5/endContour">endContour()</a> stops recording. 57317 * The vertices that define a negative shape must "wind" in the opposite direction 57318 * from the exterior shape. First draw vertices for the exterior clockwise order, then for internal shapes, draw vertices 57319 * shape in counter-clockwise. 57320 * 57321 * These functions can only be used within a <a href="#/p5/beginShape">beginShape()</a>/<a href="#/p5/endShape">endShape()</a> pair and 57322 * 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 57323 * within a <a href="#/p5/beginContour">beginContour()</a>/<a href="#/p5/endContour">endContour()</a> pair. It is also not possible to use 57324 * other shapes, such as <a href="#/p5/ellipse">ellipse()</a> or <a href="#/p5/rect">rect()</a> within. 57325 * 57326 * @method beginContour 57327 * @chainable 57328 * @example 57329 * <div> 57330 * <code> 57331 * translate(50, 50); 57332 * stroke(255, 0, 0); 57333 * beginShape(); 57334 * // Exterior part of shape, clockwise winding 57335 * vertex(-40, -40); 57336 * vertex(40, -40); 57337 * vertex(40, 40); 57338 * vertex(-40, 40); 57339 * // Interior part of shape, counter-clockwise winding 57340 * beginContour(); 57341 * vertex(-20, -20); 57342 * vertex(-20, 20); 57343 * vertex(20, 20); 57344 * vertex(20, -20); 57345 * endContour(); 57346 * endShape(CLOSE); 57347 * </code> 57348 * </div> 57349 * 57350 * @alt 57351 * white rect and smaller grey rect with red outlines in center of canvas. 57352 */ 57353 _main.default.prototype.beginContour = function() { 57354 contourVertices = []; 57355 isContour = true; 57356 return this; 57357 }; 57358 57359 /** 57360 * Using the <a href="#/p5/beginShape">beginShape()</a> and <a href="#/p5/endShape">endShape()</a> functions allow creating more 57361 * complex forms. <a href="#/p5/beginShape">beginShape()</a> begins recording vertices for a shape and 57362 * <a href="#/p5/endShape">endShape()</a> stops recording. The value of the kind parameter tells it which 57363 * types of shapes to create from the provided vertices. With no mode 57364 * specified, the shape can be any irregular polygon. 57365 * 57366 * The parameters available for <a href="#/p5/beginShape">beginShape()</a> are POINTS, LINES, TRIANGLES, 57367 * TRIANGLE_FAN, TRIANGLE_STRIP, QUADS, QUAD_STRIP, and TESS (WebGL only). After calling the 57368 * <a href="#/p5/beginShape">beginShape()</a> function, a series of <a href="#/p5/vertex">vertex()</a> commands must follow. To stop 57369 * drawing the shape, call <a href="#/p5/endShape">endShape()</a>. Each shape will be outlined with the 57370 * current stroke color and filled with the fill color. 57371 * 57372 * 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 57373 * within <a href="#/p5/beginShape">beginShape()</a>. It is also not possible to use other shapes, such as 57374 * <a href="#/p5/ellipse">ellipse()</a> or <a href="#/p5/rect">rect()</a> within <a href="#/p5/beginShape">beginShape()</a>. 57375 * 57376 * @method beginShape 57377 * @param {Constant} [kind] either POINTS, LINES, TRIANGLES, TRIANGLE_FAN 57378 * TRIANGLE_STRIP, QUADS, QUAD_STRIP or TESS 57379 * @chainable 57380 * @example 57381 * <div> 57382 * <code> 57383 * beginShape(); 57384 * vertex(30, 20); 57385 * vertex(85, 20);
57386 * vertex(85, 75); 57387 * vertex(30, 75); 57388 * endShape(CLOSE); 57389 * </code> 57390 * </div> 57391 * 57392 * <div> 57393 * <code> 57394 * beginShape(POINTS); 57395 * vertex(30, 20); 57396 * vertex(85, 20); 57397 * vertex(85, 75); 57398 * vertex(30, 75); 57399 * endShape(); 57400 * </code> 57401 * </div> 57402 * 57403 * <div> 57404 * <code> 57405 * beginShape(LINES); 57406 * vertex(30, 20); 57407 * vertex(85, 20); 57408 * vertex(85, 75); 57409 * vertex(30, 75); 57410 * endShape(); 57411 * </code> 57412 * </div> 57413 * 57414 * <div> 57415 * <code> 57416 * noFill(); 57417 * beginShape(); 57418 * vertex(30, 20); 57419 * vertex(85, 20); 57420 * vertex(85, 75); 57421 * vertex(30, 75); 57422 * endShape(); 57423 * </code> 57424 * </div> 57425 * 57426 * <div> 57427 * <code> 57428 * noFill(); 57429 * beginShape(); 57430 * vertex(30, 20); 57431 * vertex(85, 20); 57432 * vertex(85, 75); 57433 * vertex(30, 75); 57434 * endShape(CLOSE); 57435 * </code> 57436 * </div> 57437 * 57438 * <div> 57439 * <code> 57440 * beginShape(TRIANGLES); 57441 * vertex(30, 75); 57442 * vertex(40, 20); 57443 * vertex(50, 75); 57444 * vertex(60, 20); 57445 * vertex(70, 75); 57446 * vertex(80, 20); 57447 * endShape(); 57448 * </code> 57449 * </div> 57450 * 57451 * <div> 57452 * <code> 57453 * beginShape(TRIANGLE_STRIP); 57454 * vertex(30, 75); 57455 * vertex(40, 20); 57456 * vertex(50, 75); 57457 * vertex(60, 20); 57458 * vertex(70, 75); 57459 * vertex(80, 20); 57460 * vertex(90, 75); 57461 * endShape(); 57462 * </code> 57463 * </div> 57464 * 57465 * <div> 57466 * <code> 57467 * beginShape(TRIANGLE_FAN); 57468 * vertex(57.5, 50); 57469 * vertex(57.5, 15); 57470 * vertex(92, 50); 57471 * vertex(57.5, 85); 57472 * vertex(22, 50); 57473 * vertex(57.5, 15); 57474 * endShape(); 57475 * </code> 57476 * </div> 57477 * 57478 * <div> 57479 * <code> 57480 * beginShape(QUADS); 57481 * vertex(30, 20); 57482 * vertex(30, 75); 57483 * vertex(50, 75); 57484 * vertex(50, 20); 57485 * vertex(65, 20); 57486 * vertex(65, 75); 57487 * vertex(85, 75); 57488 * vertex(85, 20); 57489 * endShape(); 57490 * </code> 57491 * </div> 57492 * 57493 * <div> 57494 * <code> 57495 * beginShape(QUAD_STRIP); 57496 * vertex(30, 20); 57497 * vertex(30, 75); 57498 * vertex(50, 20); 57499 * vertex(50, 75); 57500 * vertex(65, 20); 57501 * vertex(65, 75); 57502 * vertex(85, 20); 57503 * vertex(85, 75); 57504 * endShape(); 57505 * </code> 57506 * </div> 57507 * 57508 * <div> 57509 * <code> 57510 * beginShape(); 57511 * vertex(20, 20); 57512 * vertex(40, 20); 57513 * vertex(40, 40); 57514 * vertex(60, 40); 57515 * vertex(60, 60); 57516 * vertex(20, 60); 57517 * endShape(CLOSE); 57518 * </code> 57519 * </div> 57520 * 57521 * @alt 57522 * white square-shape with black outline in middle-right of canvas. 57523 * 4 black points in a square shape in middle-right of canvas. 57524 * 2 horizontal black lines. In the top-right and bottom-right of canvas. 57525 * 3 line shape with horizontal on top, vertical in middle and horizontal bottom. 57526 * square line shape in middle-right of canvas. 57527 * 2 white triangle shapes mid-right canvas. left one pointing up and right down. 57528 * 5 horizontal interlocking and alternating white triangles in mid-right canvas. 57529 * 4 interlocking white triangles in 45 degree rotated square-shape. 57530 * 2 white rectangle shapes in mid-right canvas. Both 20x55. 57531 * 3 side-by-side white rectangles center rect is smaller in mid-right canvas.
57532 * Thick white l-shape with black outline mid-top-left of canvas. 57533 */ 57534 _main.default.prototype.beginShape = function(kind) { 57535 _main.default._validateParameters('beginShape', arguments); 57536 if (this._renderer.isP3D) { 57537 var _this$_renderer; 57538 (_this$_renderer = this._renderer).beginShape.apply( 57539 _this$_renderer, 57540 arguments 57541 ); 57542 } else { 57543 if ( 57544 kind === constants.POINTS || 57545 kind === constants.LINES || 57546 kind === constants.TRIANGLES || 57547 kind === constants.TRIANGLE_FAN || 57548 kind === constants.TRIANGLE_STRIP || 57549 kind === constants.QUADS || 57550 kind === constants.QUAD_STRIP 57551 ) { 57552 shapeKind = kind; 57553 } else { 57554 shapeKind = null; 57555 } 57556 57557 vertices = []; 57558 contourVertices = []; 57559 } 57560 return this; 57561 }; 57562 57563 /** 57564 * Specifies vertex coordinates for Bezier curves. Each call to 57565 * bezierVertex() defines the position of two control points and 57566 * one anchor point of a Bezier curve, adding a new segment to a 57567 * line or shape. For WebGL mode bezierVertex() can be used in 2D 57568 * as well as 3D mode. 2D mode expects 6 parameters, while 3D mode 57569 * expects 9 parameters (including z coordinates). 57570 * 57571 * The first time bezierVertex() is used within a <a href="#/p5/beginShape">beginShape()</a> 57572 * call, it must be prefaced with a call to <a href="#/p5/vertex">vertex()</a> to set the first anchor 57573 * point. This function must be used between <a href="#/p5/beginShape">beginShape()</a> and <a href="#/p5/endShape">endShape()</a> 57574 * and only when there is no MODE or POINTS parameter specified to 57575 * <a href="#/p5/beginShape">beginShape()</a>. 57576 * 57577 * @method bezierVertex 57578 * @param {Number} x2 x-coordinate for the first control point 57579 * @param {Number} y2 y-coordinate for the first control point 57580 * @param {Number} x3 x-coordinate for the second control point 57581 * @param {Number} y3 y-coordinate for the second control point 57582 * @param {Number} x4 x-coordinate for the anchor point 57583 * @param {Number} y4 y-coordinate for the anchor point 57584 * @chainable 57585 * 57586 * @example 57587 * <div> 57588 * <code> 57589 * noFill(); 57590 * beginShape(); 57591 * vertex(30, 20); 57592 * bezierVertex(80, 0, 80, 75, 30, 75); 57593 * endShape(); 57594 * </code> 57595 * </div> 57596 * 57597 * <div> 57598 * <code> 57599 * beginShape(); 57600 * vertex(30, 20); 57601 * bezierVertex(80, 0, 80, 75, 30, 75); 57602 * bezierVertex(50, 80, 60, 25, 30, 20); 57603 * endShape(); 57604 * </code> 57605 * </div> 57606 * 57607 * <div> 57608 * <code> 57609 * function setup() { 57610 * createCanvas(100, 100, WEBGL); 57611 * setAttributes('antialias', true); 57612 * } 57613 * function draw() { 57614 * orbitControl(); 57615 * background(50); 57616 * strokeWeight(4); 57617 * stroke(255); 57618 * point(-25, 30); 57619 * point(25, 30); 57620 * point(25, -30); 57621 * point(-25, -30); 57622 * 57623 * strokeWeight(1); 57624 * noFill(); 57625 * 57626 * beginShape(); 57627 * vertex(-25, 30); 57628 * bezierVertex(25, 30, 25, -30, -25, -30); 57629 * endShape(); 57630 * 57631 * beginShape(); 57632 * vertex(-25, 30, 20); 57633 * bezierVertex(25, 30, 20, 25, -30, 20, -25, -30, 20); 57634 * endShape(); 57635 * } 57636 * </code> 57637 * </div> 57638 * 57639 * @alt 57640 * crescent-shaped line in middle of canvas. Points facing left. 57641 * white crescent shape in middle of canvas. Points facing left. 57642 * crescent shape in middle of canvas with another crescent shape on positive z-axis. 57643 */ 57644 57645 /** 57646 * @method bezierVertex 57647 * @param {Number} x2 57648 * @param {Number} y2 57649 * @param {Number} z2 z-coordinate for the first control point (for WebGL mode) 57650 * @param {Number} x3 57651 * @param {Number} y3 57652 * @param {Number} z3 z-coordinate for the second control point (for WebGL mode) 57653 * @param {Number} x4 57654 * @param {Number} y4 57655 * @param {Number}
57655 z4 z-coordinate for the anchor point (for WebGL mode) 57656 * @chainable 57657 */ 57658 _main.default.prototype.bezierVertex = function() { 57659 for ( 57660 var _len = arguments.length, args = new Array(_len), _key = 0; 57661 _key < _len; 57662 _key++ 57663 ) { 57664 args[_key] = arguments[_key]; 57665 } 57666 _main.default._validateParameters('bezierVertex', args); 57667 if (this._renderer.isP3D) { 57668 var _this$_renderer2; 57669 (_this$_renderer2 = this._renderer).bezierVertex.apply( 57670 _this$_renderer2, 57671 args 57672 ); 57673 } else { 57674 if (vertices.length === 0) { 57675 _main.default._friendlyError( 57676 'vertex() must be used once before calling bezierVertex()', 57677 'bezierVertex' 57678 ); 57679 } else { 57680 isBezier = true; 57681 var vert = []; 57682 for (var i = 0; i < args.length; i++) { 57683 vert[i] = args[i]; 57684 } 57685 vert.isVert = false; 57686 if (isContour) { 57687 contourVertices.push(vert); 57688 } else { 57689 vertices.push(vert); 57690 } 57691 } 57692 } 57693 return this; 57694 }; 57695 57696 /** 57697 * Specifies vertex coordinates for curves. This function may only 57698 * be used between <a href="#/p5/beginShape">beginShape()</a> and <a href="#/p5/endShape">endShape()</a> and only when there 57699 * is no MODE parameter specified to <a href="#/p5/beginShape">beginShape()</a>. 57700 * For WebGL mode curveVertex() can be used in 2D as well as 3D mode. 57701 * 2D mode expects 2 parameters, while 3D mode expects 3 parameters. 57702 * 57703 * The first and last points in a series of curveVertex() lines will be used to 57704 * guide the beginning and end of a the curve. A minimum of four 57705 * points is required to draw a tiny curve between the second and 57706 * third points. Adding a fifth point with curveVertex() will draw 57707 * the curve between the second, third, and fourth points. The 57708 * curveVertex() function is an implementation of Catmull-Rom 57709 * splines. 57710 * 57711 * @method curveVertex 57712 * @param {Number} x x-coordinate of the vertex 57713 * @param {Number} y y-coordinate of the vertex 57714 * @chainable 57715 * @example 57716 * <div> 57717 * <code> 57718 * strokeWeight(5); 57719 * point(84, 91); 57720 * point(68, 19); 57721 * point(21, 17); 57722 * point(32, 91); 57723 * strokeWeight(1); 57724 * 57725 * noFill(); 57726 * beginShape(); 57727 * curveVertex(84, 91); 57728 * curveVertex(84, 91); 57729 * curveVertex(68, 19); 57730 * curveVertex(21, 17); 57731 * curveVertex(32, 91); 57732 * curveVertex(32, 91); 57733 * endShape(); 57734 * </code> 57735 * </div> 57736 * 57737 * @alt 57738 * Upside-down u-shape line, mid canvas. left point extends beyond canvas view. 57739 */ 57740 57741 /** 57742 * @method curveVertex 57743 * @param {Number} x 57744 * @param {Number} y 57745 * @param {Number} [z] z-coordinate of the vertex (for WebGL mode) 57746 * @chainable 57747 * @example 57748 * <div> 57749 * <code> 57750 * function setup() { 57751 * createCanvas(100, 100, WEBGL); 57752 * setAttributes('antialias', true); 57753 * } 57754 * function draw() { 57755 * orbitControl(); 57756 * background(50); 57757 * strokeWeight(4); 57758 * stroke(255); 57759 * 57760 * point(-25, 25); 57761 * point(-25, 25); 57762 * point(-25, -25); 57763 * point(25, -25); 57764 * point(25, 25); 57765 * point(25, 25); 57766 * 57767 * strokeWeight(1); 57768 * noFill(); 57769 * 57770 * beginShape(); 57771 * curveVertex(-25, 25); 57772 * curveVertex(-25, 25); 57773 * curveVertex(-25, -25); 57774 * curveVertex(25, -25); 57775 * curveVertex(25, 25); 57776 * curveVertex(25, 25); 57777 * endShape(); 57778 * 57779 * beginShape(); 57780 * curveVertex(-25, 25, 20); 57781 * curveVertex(-25, 25, 20); 57782 * curveVertex(-25, -25, 20); 57783 * curveVertex(25, -25, 20); 57784 * curveVertex(25, 25, 20); 57785 * curveVertex(25, 25, 20); 57786 * endShape(); 57787 * } 57788 * </code> 57789 * </div> 57790 * 57791 * @alt 57792 * Upside-down u-shape line, mid canvas with the same shape in positive z-axis. 57793 */ 57794 _main.default.prototype.curveVertex = function() { 57795 for ( 57796 var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; 57797 _key2 < _len2; 57798 _key2++ 57799 ) { 57800 args[_key2] = arguments[_key2]; 57801 } 57802 _main.default._validateParameters('curveVertex', args
57802); 57803 if (this._renderer.isP3D) { 57804 var _this$_renderer3; 57805 (_this$_renderer3 = this._renderer).curveVertex.apply(_this$_renderer3, args); 57806 } else { 57807 isCurve = true; 57808 this.vertex(args[0], args[1]); 57809 } 57810 return this; 57811 }; 57812 57813 /** 57814 * Use the <a href="#/p5/beginContour">beginContour()</a> and <a href="#/p5/endContour">endContour()</a> functions to create negative 57815 * shapes within shapes such as the center of the letter 'O'. <a href="#/p5/beginContour">beginContour()</a> 57816 * begins recording vertices for the shape and <a href="#/p5/endContour">endContour()</a> stops recording. 57817 * The vertices that define a negative shape must "wind" in the opposite 57818 * direction from the exterior shape. First draw vertices for the exterior 57819 * clockwise order, then for internal shapes, draw vertices 57820 * shape in counter-clockwise. 57821 * 57822 * These functions can only be used within a <a href="#/p5/beginShape">beginShape()</a>/<a href="#/p5/endShape">endShape()</a> pair and 57823 * 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 57824 * within a <a href="#/p5/beginContour">beginContour()</a>/<a href="#/p5/endContour">endContour()</a> pair. It is also not possible to use 57825 * other shapes, such as <a href="#/p5/ellipse">ellipse()</a> or <a href="#/p5/rect">rect()</a> within. 57826 * 57827 * @method endContour 57828 * @chainable 57829 * @example 57830 * <div> 57831 * <code> 57832 * translate(50, 50); 57833 * stroke(255, 0, 0); 57834 * beginShape(); 57835 * // Exterior part of shape, clockwise winding 57836 * vertex(-40, -40); 57837 * vertex(40, -40); 57838 * vertex(40, 40); 57839 * vertex(-40, 40); 57840 * // Interior part of shape, counter-clockwise winding 57841 * beginContour(); 57842 * vertex(-20, -20); 57843 * vertex(-20, 20); 57844 * vertex(20, 20); 57845 * vertex(20, -20); 57846 * endContour(); 57847 * endShape(CLOSE); 57848 * </code> 57849 * </div> 57850 * 57851 * @alt 57852 * white rect and smaller grey rect with red outlines in center of canvas. 57853 */ 57854 _main.default.prototype.endContour = function() { 57855 var vert = contourVertices[0].slice(); // copy all data 57856 vert.isVert = contourVertices[0].isVert; 57857 vert.moveTo = false; 57858 contourVertices.push(vert); 57859 57860 // prevent stray lines with multiple contours 57861 if (isFirstContour) { 57862 vertices.push(vertices[0]); 57863 isFirstContour = false; 57864 } 57865 57866 for (var i = 0; i < contourVertices.length; i++) { 57867 vertices.push(contourVertices[i]); 57868 } 57869 return this; 57870 }; 57871 57872 /** 57873 * The <a href="#/p5/endShape">endShape()</a> function is the companion to <a href="#/p5/beginShape">beginShape()</a> and may only be 57874 * called after <a href="#/p5/beginShape">beginShape()</a>. When <a href="#/p5/endshape">endShape()</a> is called, all of image data 57875 * defined since the previous call to <a href="#/p5/beginShape">beginShape()</a> is written into the image 57876 * buffer. The constant CLOSE as the value for the MODE parameter to close 57877 * the shape (to connect the beginning and the end). 57878 * 57879 * @method endShape 57880 * @param {Constant} [mode] use CLOSE to close the shape 57881 * @chainable 57882 * @example 57883 * <div> 57884 * <code> 57885 * noFill(); 57886 * 57887 * beginShape(); 57888 * vertex(20, 20); 57889 * vertex(45, 20); 57890 * vertex(45, 80); 57891 * endShape(CLOSE); 57892 * 57893 * beginShape(); 57894 * vertex(50, 20); 57895 * vertex(75, 20); 57896 * vertex(75, 80); 57897 * endShape(); 57898 * </code> 57899 * </div> 57900 * 57901 * @alt 57902 * Triangle line shape with smallest interior angle on bottom and upside-
57902down L. 57903 */ 57904 _main.default.prototype.endShape = function(mode) { 57905 _main.default._validateParameters('endShape', arguments); 57906 if (this._renderer.isP3D) { 57907 this._renderer.endShape( 57908 mode, 57909 isCurve, 57910 isBezier, 57911 isQuadratic, 57912 isContour, 57913 shapeKind 57914 ); 57915 } else { 57916 if (vertices.length === 0) { 57917 return this; 57918 } 57919 if (!this._renderer._doStroke && !this._renderer._doFill) { 57920 return this; 57921 } 57922 57923 var closeShape = mode === constants.CLOSE; 57924 57925 // if the shape is closed, the first element is also the last element 57926 if (closeShape && !isContour) { 57927 vertices.push(vertices[0]); 57928 } 57929 57930 this._renderer.endShape( 57931 mode, 57932 vertices, 57933 isCurve, 57934 isBezier, 57935 isQuadratic, 57936 isContour, 57937 shapeKind 57938 ); 57939 57940 // Reset some settings 57941 isCurve = false; 57942 isBezier = false;
57943 isQuadratic = false; 57944 isContour = false; 57945 isFirstContour = true; 57946 57947 // If the shape is closed, the first element was added as last element. 57948 // We must remove it again to prevent the list of vertices from growing 57949 // over successive calls to endShape(CLOSE) 57950 if (closeShape) { 57951 vertices.pop(); 57952 } 57953 } 57954 return this; 57955 }; 57956 57957 /** 57958 * Specifies vertex coordinates for quadratic Bezier curves. Each call to 57959 * quadraticVertex() defines the position of one control points and one 57960 * anchor point of a Bezier curve, adding a new segment to a line or shape. 57961 * The first time quadraticVertex() is used within a <a href="#/p5/beginShape">beginShape()</a> call, it 57962 * must be prefaced with a call to <a href="#/p5/vertex">vertex()</a> to set the first anchor point. 57963 * For WebGL mode quadraticVertex() can be used in 2D as well as 3D mode. 57964 * 2D mode expects 4 parameters, while 3D mode expects 6 parameters 57965 * (including z coordinates). 57966 * 57967 * This function must be used between <a href="#/p5/beginShape">beginShape()</a> and <a href="#/p5/endShape">endShape()</a> 57968 * and only when there is no MODE or POINTS parameter specified to 57969 * <a href="#/p5/beginShape">beginShape()</a>. 57970 * 57971 * @method quadraticVertex 57972 * @param {Number} cx x-coordinate for the control point 57973 * @param {Number} cy y-coordinate for the control point 57974 * @param {Number} x3 x-coordinate for the anchor point 57975 * @param {Number} y3 y-coordinate for the anchor point 57976 * @chainable 57977 * 57978 * @example 57979 * <div> 57980 * <code> 57981 * strokeWeight(5); 57982 * point(20, 20); 57983 * point(80, 20); 57984 * point(50, 50); 57985 * 57986 * noFill(); 57987 * strokeWeight(1); 57988 * beginShape(); 57989 * vertex(20, 20); 57990 * quadraticVertex(80, 20, 50, 50); 57991 * endShape(); 57992 * </code> 57993 * </div> 57994 * 57995 * <div> 57996 * <code> 57997 * strokeWeight(5); 57998 * point(20, 20); 57999 * point(80, 20); 58000 * point(50, 50); 58001 * 58002 * point(20, 80); 58003 * point(80, 80); 58004 * point(80, 60); 58005 * 58006 * noFill(); 58007 * strokeWeight(1); 58008 * beginShape(); 58009 * vertex(20, 20); 58010 * quadraticVertex(80, 20, 50, 50); 58011 * quadraticVertex(20, 80, 80, 80); 58012 * vertex(80, 60); 58013 * endShape(); 58014 * </code> 58015 * </div> 58016 * 58017 * @alt 58018 * arched-shaped black line with 4 pixel thick stroke weight. 58019 * backwards s-shaped black line with 4 pixel thick stroke weight. 58020 */ 58021 58022 /** 58023 * @method quadraticVertex 58024 * @param {Number} cx 58025 * @param {Number} cy 58026 * @param {Number} cz z-coordinate for the control point (for WebGL mode) 58027 * @param {Number} x3 58028 * @param {Number} y3 58029 * @param {Number} z3 z-coordinate for the anchor point (for WebGL mode) 58030 * @chainable 58031 * 58032 * @example 58033 * <div> 58034 * <code> 58035 * function setup() { 58036 * createCanvas(100, 100, WEBGL); 58037 * setAttributes('antialias', true); 58038 * } 58039 * function draw() { 58040 * orbitControl(); 58041 * background(50); 58042 * strokeWeight(4); 58043 * stroke(255); 58044 * 58045 * point(-35, -35); 58046 * point(35, -35); 58047 * point(0, 0); 58048 * point(-35, 35); 58049 * point(35, 35); 58050 * point(35, 10); 58051 * 58052 * strokeWeight(1); 58053 * noFill(); 58054 * 58055 * beginShape(); 58056 * vertex(-35, -35); 58057 * quadraticVertex(35, -35, 0, 0); 58058 * quadraticVertex(-35, 35, 35, 35); 58059 * vertex(35, 10); 58060 * endShape(); 58061 * 58062 * beginShape(); 58063 * vertex(-35, -35, 20); 58064 * quadraticVertex(35, -35, 20, 0, 0, 20); 58065 * quadraticVertex(-35, 35, 20, 35, 35, 20); 58066 * vertex(35, 10, 20); 58067 * endShape(); 58068 * } 58069 * </code> 58070 * </div> 58071 * 58072 * @alt 58073 * backwards s-shaped black line with the same s-shaped line in postive z-axis. 58074 */ 58075 _main.default.prototype.quadraticVertex = function() { 58076 for ( 58077 var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; 58078 _key3 < _len3; 58079 _key3++ 58080 ) { 58081 args[_key3] = arguments[_key3]; 58082 } 58083 _main.default._validateParameters('quadraticVertex', args
58083); 58084 if (this._renderer.isP3D) { 58085 var _this$_renderer4; 58086 (_this$_renderer4 = this._renderer).quadraticVertex.apply( 58087 _this$_renderer4, 58088 args 58089 ); 58090 } else { 58091 //if we're drawing a contour, put the points into an 58092 // array for inside drawing 58093 if (this._contourInited) { 58094 var pt = {}; 58095 pt.x = args[0]; 58096 pt.y = args[1]; 58097 pt.x3 = args[2]; 58098 pt.y3 = args[3]; 58099 pt.type = constants.QUADRATIC; 58100 this._contourVertices.push(pt); 58101 58102 return this; 58103 } 58104 if (vertices.length > 0) { 58105 isQuadratic = true; 58106 var vert = []; 58107 for (var i = 0; i < args.length; i++) { 58108 vert[i] = args[i]; 58109 } 58110 vert.isVert = false; 58111 if (isContour) { 58112 contourVertices.push(vert); 58113 } else { 58114 vertices.push(vert); 58115 } 58116 } else { 58117 _main.default._friendlyError( 58118 'vertex() must be used once before calling quadraticVertex()', 58119 'quadraticVertex' 58120 ); 58121 } 58122 } 58123 return this; 58124 }; 58125 58126 /** 58127 * All shapes are constructed by connecting a series of vertices. <a href="#/p5/vertex">vertex()</a> 58128 * is used to specify the vertex coordinates for points, lines, triangles, 58129 * quads, and polygons. It is used exclusively within the <a href="#/p5/beginShape">beginShape()</a> and 58130 * <a href="#/p5/endShape">endShape()</a> functions. 58131 * 58132 * @method vertex 58133 * @param {Number} x x-coordinate of the vertex 58134 * @param {Number} y y-coordinate of the vertex 58135 * @chainable 58136 * @example 58137 * <div> 58138 * <code> 58139 * strokeWeight(3); 58140 * beginShape(POINTS); 58141 * vertex(30, 20); 58142 * vertex(85, 20); 58143 * vertex(85, 75); 58144 * vertex(30, 75); 58145 * endShape(); 58146 * </code> 58147 * </div> 58148 * 58149 * <div> 58150 * <code> 58151 * createCanvas(100, 100, WEBGL); 58152 * background(240, 240, 240); 58153 * fill(237, 34, 93); 58154 * noStroke(); 58155 * beginShape(); 58156 * vertex(0, 35); 58157 * vertex(35, 0); 58158 * vertex(0, -35); 58159 * vertex(-35, 0); 58160 * endShape(); 58161 * </code> 58162 * </div> 58163 * 58164 * <div> 58165 * <code> 58166 * createCanvas(100, 100, WEBGL); 58167 * background(240, 240, 240); 58168 * fill(237, 34, 93); 58169 * noStroke(); 58170 * beginShape(); 58171 * vertex(-10, 10); 58172 * vertex(0, 35); 58173 * vertex(10, 10); 58174 * vertex(35, 0); 58175 * vertex(10, -8); 58176 * vertex(0, -35); 58177 * vertex(-10, -8); 58178 * vertex(-35, 0); 58179 * endShape(); 58180 * </code> 58181 * </div> 58182 * 58183 * <div> 58184 * <code> 58185 * strokeWeight(3); 58186 * stroke(237, 34, 93); 58187 * beginShape(LINES); 58188 * vertex(10, 35); 58189 * vertex(90, 35); 58190 * vertex(10, 65); 58191 * vertex(90, 65); 58192 * vertex(35, 10); 58193 * vertex(35, 90); 58194 * vertex(65, 10); 58195 * vertex(65, 90); 58196 * endShape(); 58197 * </code> 58198 * </div> 58199 * 58200 * <div> 58201 * <code> 58202 * // Click to change the number of sides. 58203 * // In WebGL mode, custom shapes will only 58204 * // display hollow fill sections when 58205 * // all calls to vertex() use the same z-value. 58206 * 58207 * let sides = 3; 58208 * let angle, px, py; 58209 * 58210 * function setup() { 58211 * createCanvas(100, 100, WEBGL); 58212 * setAttributes('antialias', true); 58213 * fill(237, 34, 93); 58214 * strokeWeight(3); 58215 * } 58216 * 58217 * function draw() { 58218 * background(200); 58219 * rotateX(frameCount * 0.01); 58220 * rotateZ(frameCount * 0.01); 58221 * ngon(sides, 0, 0, 80); 58222 * } 58223 * 58224 * function mouseClicked() { 58225 * if (sides > 6) { 58226 * sides = 3; 58227 * } else { 58228 * sides++; 58229 * } 58230 * } 58231 * 58232 * function ngon(n, x, y, d) { 58233 * beginShape(TESS); 58234 * for (let i = 0; i < n + 1; i++) { 58235 * angle = TWO_PI / n * i; 58236 * px = x + sin(angle) * d / 2; 58237 * py = y - cos(angle) * d / 2; 58238 * vertex(px, py, 0); 58239 * } 58240 * for (let i = 0; i < n + 1; i++) { 58241 * angle = TWO_PI / n * i; 58242 * px = x + sin(angle) * d / 4; 58243 * py = y - cos(angle) * d / 4; 58244 * vertex(px, py, 0); 58245 * } 58246 * endShape(); 58247 * } 58248 * </code> 58249 * </div> 58250 * @alt 58251 * 4 black points in a square shape in middle-right of canvas. 58252 * 4 points making a diamond shape. 58253 * 8 points making a star. 58254 * 8 points making 4 lines. 58255 * A rotating 3D shape with a hollow section in the middle. 58256 */ 58257 /** 58258 * @method vertex 58259 * @param {Number} x 58260 * @param {Number} y 58261 * @param {Number} z z-coordinate of the vertex 58262 * @param {Number} [u] the vertex's texture u-coordinate 58263 * @param {Number} [v] the vertex's texture v-coordinate 58264 * @chainable 58265 */ 58266 _main.default.prototype.vertex = function(x, y, moveTo, u, v) { 58267 if (this._renderer.isP3D) { 58268 var _this$_renderer5; 58269 (_this$_renderer5 = this._renderer).vertex.apply(_this$_renderer5, arguments); 58270 } else { 58271 var vert = []; 58272 vert.isVert = true; 58273 vert[0] = x; 58274 vert[1] = y; 58275 vert[2] = 0; 58276 vert[3] = 0; 58277 vert[4] = 0; 58278 vert[5] = this._renderer._getFill(); 58279 vert[6] = this._renderer._getStroke(); 58280 58281 if (moveTo) { 58282 vert.moveTo = moveTo; 58283 } 58284 if (isContour) { 58285 if (contourVertices.length === 0) { 58286 vert.moveTo = true; 58287 } 58288 contourVertices.push(vert); 58289 } else { 58290 vertices.push(vert); 58291 } 58292 } 58293 return this; 58294 }; 58295 var _default = _main.default; 58296 exports.default = _default; 58297 }, 58298 { '../constants': 48, '../main': 59 } 58299 ], 58300 70: [
58301 function(_dereq_, module, exports) { 58302 'use strict'; 58303 function _typeof(obj) { 58304 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') { 58305 _typeof = function _typeof(obj) { 58306 return typeof obj; 58307 }; 58308 } else { 58309 _typeof = function _typeof(obj) { 58310 return obj && 58311 typeof Symbol === 'function' && 58312 obj.constructor === Symbol && 58313 obj !== Symbol.prototype 58314 ? 'symbol' 58315 : typeof obj; 58316 }; 58317 } 58318 return _typeof(obj); 58319 } // requestAnim shim layer by Paul Irish 58320 // http://paulirish.com/2011/requestanimationframe-for-smart-animating/ 58321 // http://my.opera.com/emoller/blog/2011/12/20/ 58322 // requestanimationframe-for-smart-er-animating 58323 // requestAnimationFrame polyfill by Erik Möller 58324 // fixes from Paul Irish and Tino Zijdel 58325 window.requestAnimationFrame = (function() { 58326 return ( 58327 window.requestAnimationFrame || 58328 window.webkitRequestAnimationFrame || 58329 window.mozRequestAnimationFrame || 58330 window.oRequestAnimationFrame || 58331 window.msRequestAnimationFrame || 58332 function(callback, element) { 58333 // should '60' here be framerate? 58334 window.setTimeout(callback, 1000 / 60); 58335 } 58336 ); 58337 })(); 58338 58339 /** 58340 * shim for Uint8ClampedArray.slice 58341 * (allows arrayCopy to work with pixels[]) 58342 * with thanks to http://halfpapstudios.com/blog/tag/html5-canvas/ 58343 * Enumerable set to false to protect for...in from 58344 * Uint8ClampedArray.prototype pollution. 58345 */ 58346 (function() { 58347 if ( 58348 typeof Uint8ClampedArray !== 'undefined' && 58349 !Uint8ClampedArray.prototype.slice 58350 ) { 58351 Object.defineProperty(Uint8ClampedArray.prototype, 'slice', { 58352 value: Array.prototype.slice, 58353 writable: true, 58354 configurable: true, 58355 enumerable: false 58356 }); 58357 } 58358 })(); 58359 58360 /** 58361 * this is implementation of Object.assign() which is unavailable in 58362 * IE11 and (non-Chrome) Android browsers. 58363 * The assign() method is used to copy the values of all enumerable 58364 * own properties from one or more source objects to a target object. 58365 * It will return the target object. 58366 * Modified from https://github.com/ljharb/object.assign 58367 */ 58368 (function() { 58369 if (!Object.assign) { 58370 var keys = Object.keys; 58371 var defineProperty = Object.defineProperty; 58372 var canBeObject = function canBeObject(obj) { 58373 return typeof obj !== 'undefined' && obj !== null; 58374 }; 58375 var hasSymbols = 58376 typeof Symbol === 'function' && _typeof(Symbol()) === 'symbol'; 58377 var propIsEnumerable = Object.prototype.propertyIsEnumerable; 58378 var isEnumerableOn = function isEnumerableOn(obj) { 58379 return function isEnumerable(prop) { 58380 return propIsEnumerable.call(obj, prop); 58381 }; 58382 }; 58383 58384 // per ES6 spec, this function has to have a length of 2 58385 var assignShim = function assign(target, source1) { 58386 if (!canBeObject(target)) { 58387 throw new TypeError('target must be an object'); 58388 } 58389 var objTarget = Object(target); 58390 var s, source, i, props; 58391 for (s = 1; s < arguments.length; ++s) { 58392 source = Object(arguments[s]); 58393 props = keys(source); 58394 if (hasSymbols && Object.getOwnPropertySymbols) { 58395 props.push.apply( 58396 props, 58397 Object.getOwnPropertySymbols(source).filter(isEnumerableOn(source)) 58398 ); 58399 } 58400 for (i = 0; i < props.length; ++i) { 58401 objTarget[props[i]] = source[props[i]]; 58402 } 58403 } 58404 return objTarget; 58405 }; 58406 58407 defineProperty(Object, 'assign', { 58408 value: assignShim, 58409 configurable: true, 58410 enumerable: false, 58411 writable: true 58412 }); 58413 } 58414 })(); 58415 }, 58416 {} 58417 ], 58418 71: [
58419 function(_dereq_, module, exports) { 58420 'use strict'; 58421 Object.defineProperty(exports, '__esModule', { value: true }); 58422 exports.default = void 0; 58423 58424 var _main = _interopRequireDefault(_dereq_('./main')); 58425 function _interopRequireDefault(obj) { 58426 return obj && obj.__esModule ? obj : { default: obj }; 58427 } 58428 /** 58429 * @module Structure 58430 * @submodule Structure 58431 * @for p5 58432 * @requires core 58433 */ /** 58434 * Stops p5.js from continuously executing the code within <a href="#/p5/draw">draw()</a>. 58435 * If <a href="#/p5/loop">loop()</a> is called, the code in <a href="#/p5/draw">draw()</a> 58436 * begins to run continuously again. If using <a href="#/p5/noLoop">noLoop()</a> 58437 * in <a href="#/p5/setup">setup()</a>, it should be the last line inside the block. 58438 * 58439 * When <a href="#/p5/noLoop">noLoop()</a> is used, it's not possible to manipulate 58440 * or access the screen inside event handling functions such as 58441 * <a href="#/p5/mousePressed">mousePressed()</a> or 58442 * <a href="#/p5/keyPressed">keyPressed()</a>. Instead, use those functions to 58443 * call <a href="#/p5/redraw">redraw()</a> or <a href="#/p5/loop">loop()</a>, 58444 * which will run <a href="#/p5/draw">draw()</a>, which can update the screen 58445 * properly. This means that when <a href="#/p5/noLoop">noLoop()</a> has been 58446 * called, no drawing can happen, and functions like <a href="#/p5/saveFrame">saveFrame()</a> 58447 * or <a href="#/p5/loadPixels">loadPixels()</a> may not be used. 58448 * 58449 * Note that if the sketch is resized, <a href="#/p5/redraw">redraw()</a> will 58450 * be called to update the sketch, even after <a href="#/p5/noLoop">noLoop()</a> 58451 * has been specified. Otherwise, the sketch would enter an odd state until 58452 * <a href="#/p5/loop">loop()</a> was called. 58453 * 58454 * Use <a href="#/p5/isLooping">isLooping()</a> to check current state of loop(). 58455 * 58456 * @method noLoop 58457 * @example 58458 * <div> 58459 * <code> 58460 * function setup() { 58461 * createCanvas(100, 100); 58462 * background(200); 58463 * noLoop(); 58464 * } 58465 58466 * function draw() { 58467 * line(10, 10, 90, 90); 58468 * } 58469 * </code> 58470 * </div> 58471 * 58472 * <div> 58473 * <code> 58474 * let x = 0; 58475 * function setup() { 58476 * createCanvas(100, 100); 58477 * } 58478 * 58479 * function draw() { 58480 * background(204); 58481 * x = x + 0.1; 58482 * if (x > width) { 58483 * x = 0; 58484 * } 58485 * line(x, 0, x, height); 58486 * } 58487 * 58488 * function mousePressed() { 58489 * noLoop(); 58490 * } 58491 * 58492 * function mouseReleased() { 58493 * loop(); 58494 * } 58495 * </code> 58496 * </div> 58497 * 58498 * @alt 58499 * 113 pixel long line extending from top-left to bottom right of canvas. 58500 * horizontal line moves slowly from left. Loops but stops on mouse press. 58501 */ _main.default.prototype.noLoop = function() { 58502 this._loop = false;
58503 }; 58504 58505 /** 58506 * By default, p5.js loops through draw() continuously, executing the code within 58507 * it. However, the <a href="#/p5/draw">draw()</a> loop may be stopped by calling 58508 * <a href="#/p5/noLoop">noLoop()</a>. In that case, the <a href="#/p5/draw">draw()</a> 58509 * loop can be resumed with loop(). 58510 * 58511 * Avoid calling loop() from inside setup(). 58512 * 58513 * Use <a href="#/p5/isLooping">isLooping()</a> to check current state of loop(). 58514 * 58515 * @method loop 58516 * @example 58517 * <div> 58518 * <code> 58519 * let x = 0; 58520 * function setup() { 58521 * createCanvas(100, 100); 58522 * noLoop(); 58523 * } 58524 * 58525 * function draw() { 58526 * background(204); 58527 * x = x + 0.1; 58528 * if (x > width) { 58529 * x = 0; 58530 * } 58531 * line(x, 0, x, height); 58532 * } 58533 * 58534 * function mousePressed() { 58535 * loop(); 58536 * } 58537 * 58538 * function mouseReleased() { 58539 * noLoop(); 58540 * } 58541 * </code> 58542 * </div> 58543 * 58544 * @alt 58545 * horizontal line moves slowly from left. Loops but stops on mouse press. 58546 */ 58547 _main.default.prototype.loop = function() { 58548 if (!this._loop) { 58549 this._loop = true; 58550 if (this._setupDone) { 58551 this._draw(); 58552 } 58553 } 58554 }; 58555 58556 /** 58557 * By default, p5.js loops through <a href="#/p5/draw">draw()</a> continuously, 58558 * executing the code within it. If the sketch is stopped with 58559 * <a href="#/p5/noLoop">noLoop()</a> or resumed with <a href="#/p5/loop">loop()</a>, 58560 * isLooping() returns the current state for use within custom event handlers. 58561 * 58562 * @method isLooping 58563 * @example 58564 * <div> 58565 * <code> 58566 * let checkbox, button, colBG, colFill; 58567 * 58568 * function setup() { 58569 * createCanvas(100, 100); 58570 * 58571 * button = createButton('Colorize if loop()'); 58572 * button.position(0, 120); 58573 * button.mousePressed(changeBG); 58574 * 58575 * checkbox = createCheckbox('loop()', true); 58576 * checkbox.changed(checkLoop); 58577 * 58578 * colBG = color(0); 58579 * colFill = color(255); 58580 * } 58581 * 58582 * function changeBG() { 58583 * if (isLooping()) { 58584 * colBG = color(random(255), random(255), random(255)); 58585 * colFill = color(random(255), random(255), random(255)); 58586 * } 58587 * } 58588 * 58589 * function checkLoop() { 58590 * if (this.checked()) { 58591 * loop(); 58592 * } else { 58593 * noLoop(); 58594 * } 58595 * } 58596 * 58597 * function draw() { 58598 * background(colBG); 58599 * fill(colFill); 58600 * ellipse(frameCount % width, height / 2, 50); 58601 * } 58602 * </code> 58603 * </div> 58604 * 58605 * @alt 58606 * Ellipse moves slowly from left. Checkbox toggles loop()/noLoop(). 58607 * Button colorizes sketch if isLooping(). 58608 * 58609 */ 58610 _main.default.prototype.isLooping = function() { 58611 return this._loop; 58612 }; 58613 58614 /** 58615 * The <a href="#/p5/push">push()</a> function saves the current drawing style 58616 * settings and transformations, while <a href="#/p5/pop">pop()</a> restores these 58617 * settings. Note that these functions are always used together. They allow you to 58618 * change the style and transformation settings and later return to what you had. 58619 * When a new state is started with <a href="#/p5/push">push()</a>, it builds on 58620 * the current style and transform information. The <a href="#/p5/push">push()</a> 58621 * and <a href="#/p5/pop">pop()</a> functions can be embedded to provide more 58622 * control. (See the second example for a demonstration.) 58623 * 58624 * <a href="#/p5/push">push()</a> stores information related to the current transformation state 58625 * and style settings controlled by the following functions: 58626 * <a href="#/p5/fill">fill()</a>, 58627 * <a href="#/p5/noFill">noFill()</a>, 58628 * <a href="#/p5/noStroke">noStroke()</a>, 58629 * <a href="#/p5/stroke">stroke()</a>, 58630 * <a href="#/p5/tint">tint()</a>, 58631 * <a href="#/p5/noTint">noTint()</a>, 58632 * <a href="#/p5/strokeWeight">
58632strokeWeight()</a>, 58633 * <a href="#/p5/strokeCap">strokeCap()</a>, 58634 * <a href="#/p5/strokeJoin">strokeJoin()</a>, 58635 * <a href="#/p5/imageMode">imageMode()</a>, 58636 * <a href="#/p5/rectMode">rectMode()</a>, 58637 * <a href="#/p5/ellipseMode">ellipseMode()</a>, 58638 * <a href="#/p5/colorMode">colorMode()</a>, 58639 * <a href="#/p5/textAlign">textAlign()</a>, 58640 * <a href="#/p5/textFont">textFont()</a>, 58641 * <a href="#/p5/textSize">textSize()</a>, 58642 * <a href="#/p5/textLeading">textLeading()</a>, 58643 * <a href="#/p5/applyMatrix">applyMatrix()</a>, 58644 * <a href="#/p5/resetMatrix">resetMatrix()</a>, 58645 * <a href="#/p5/rotate">rotate()</a>, 58646 * <a href="#/p5/scale">scale()</a>, 58647 * <a href="#/p5/shearX">shearX()</a>, 58648 * <a href="#/p5/shearY">shearY()</a>, 58649 * <a href="#/p5/translate">translate()</a>, 58650 * <a href="#/p5/noiseSeed">noiseSeed()</a>. 58651 * 58652 * In WEBGL mode additional style settings are stored. These are controlled by the 58653 * following functions: <a href="#/p5/setCamera">setCamera()</a>, 58654 * <a href="#/p5/ambientLight">ambientLight()</a>, 58655 * <a href="#/p5/directionalLight">directionalLight()</a>, 58656 * <a href="#/p5/pointLight">pointLight()</a>, <a href="#/p5/texture">texture()</a>, 58657 * <a href="#/p5/specularMaterial">specularMaterial()</a>, 58658 * <a href="#/p5/shininess">shininess()</a>, 58659 * <a href="#/p5/normalMaterial">normalMaterial()</a> 58660 * and <a href="#/p5/shader">shader()</a>. 58661 * 58662 * @method push 58663 * @example 58664 * <div> 58665 * <code> 58666 * ellipse(0, 50, 33, 33); // Left circle 58667 * 58668 * push(); // Start a new drawing state 58669 * strokeWeight(10); 58670 * fill(204, 153, 0); 58671 * translate(50, 0); 58672 * ellipse(0, 50, 33, 33); // Middle circle 58673 * pop(); // Restore original state 58674 * 58675 * ellipse(100, 50, 33, 33); // Right circle 58676 * </code> 58677 * </div> 58678 * 58679 * <div> 58680 * <code> 58681 * ellipse(0, 50, 33, 33); // Left circle 58682 * 58683 * push(); // Start a new drawing state 58684 * strokeWeight(10); 58685 * fill(204, 153, 0); 58686 * ellipse(33, 50, 33, 33); // Left-middle circle 58687 * 58688 * push(); // Start another new drawing state 58689 * stroke(0, 102, 153); 58690 * ellipse(66, 50, 33, 33); // Right-middle circle 58691 * pop(); // Restore previous state 58692 * 58693 * pop(); // Restore original state 58694 * 58695 * ellipse(100, 50, 33, 33); // Right circle 58696 * </code> 58697 * </div> 58698 * 58699 * @alt 58700 * Gold ellipse + thick black outline @center 2 white ellipses on left and right. 58701 * 2 Gold ellipses left black right blue stroke. 2 white ellipses on left+right. 58702 */ 58703 _main.default.prototype.push = function() { 58704 this._styles.push({ 58705 props: { 58706 _colorMode: this._colorMode 58707 }, 58708 58709 renderer: this._renderer.push() 58710 }); 58711 }; 58712 58713 /** 58714 * The <a href="#/p5/push">push()</a> function saves the current drawing style 58715 * settings and transformations, while <a href="#/p5/pop">pop()</a> restores 58716 * these settings. Note that these functions are always used together. They allow 58717 * you to change the style and transformation settings and later return to what 58718 * you had. When a new state is started with <a href="#/p5/push">push()</a>, it 58719 * builds on the current style and transform information. The <a href="#/p5/push">push()</a> 58720 * and <a href="#/p5/pop">pop()</a> functions can be embedded to provide more 58721 * control. (See the second example for a demonstration.) 58722 * 58723 * <a href="#/p5/push">push()</a> stores information related to the current transformation state 58724 * and style settings controlled by the following functions: 58725 * <a href="#/p5/fill">fill()</a>, 58726 * <a href="#/p5/noFill">noFill()</a>, 58727 * <a href="#/p5/noStroke">noStroke()</a>, 58728 * <a href="#/p5/stroke">stroke()</a>, 58729 * <a href="#/p5/tint">tint()</a>, 58730 * <a href="#/p5/noTint">noTint()</a>, 58731 * <a href="#/p5/strokeWeight">
58731strokeWeight()</a>, 58732 * <a href="#/p5/strokeCap">strokeCap()</a>, 58733 * <a href="#/p5/strokeJoin">strokeJoin()</a>, 58734 * <a href="#/p5/imageMode">imageMode()</a>, 58735 * <a href="#/p5/rectMode">rectMode()</a>, 58736 * <a href="#/p5/ellipseMode">ellipseMode()</a>, 58737 * <a href="#/p5/colorMode">colorMode()</a>, 58738 * <a href="#/p5/textAlign">textAlign()</a>, 58739 * <a href="#/p5/textFont">textFont()</a>, 58740 * <a href="#/p5/textSize">textSize()</a>, 58741 * <a href="#/p5/textLeading">textLeading()</a>, 58742 * <a href="#/p5/applyMatrix">applyMatrix()</a>, 58743 * <a href="#/p5/resetMatrix">resetMatrix()</a>, 58744 * <a href="#/p5/rotate">rotate()</a>, 58745 * <a href="#/p5/scale">scale()</a>, 58746 * <a href="#/p5/shearX">shearX()</a>, 58747 * <a href="#/p5/shearY">shearY()</a>, 58748 * <a href="#/p5/translate">translate()</a>, 58749 * <a href="#/p5/noiseSeed">noiseSeed()</a>. 58750 * 58751 * In WEBGL mode additional style settings are stored. These are controlled by 58752 * the following functions: 58753 * <a href="#/p5/setCamera">setCamera()</a>, 58754 * <a href="#/p5/ambientLight">ambientLight()</a>, 58755 * <a href="#/p5/directionalLight">directionalLight()</a>, 58756 * <a href="#/p5/pointLight">pointLight()</a>, 58757 * <a href="#/p5/texture">texture()</a>, 58758 * <a href="#/p5/specularMaterial">specularMaterial()</a>, 58759 * <a href="#/p5/shininess">shininess()</a>, 58760 * <a href="#/p5/normalMaterial">normalMaterial()</a> and 58761 * <a href="#/p5/shader">shader()</a>. 58762 * 58763 * @method pop 58764 * @example 58765 * <div> 58766 * <code> 58767 * ellipse(0, 50, 33, 33); // Left circle 58768 * 58769 * push(); // Start a new drawing state 58770 * translate(50, 0); 58771 * strokeWeight(10); 58772 * fill(204, 153, 0); 58773 * ellipse(0, 50, 33, 33); // Middle circle 58774 * pop(); // Restore original state 58775 * 58776 * ellipse(100, 50, 33, 33); // Right circle 58777 * </code> 58778 * </div> 58779 * 58780 * <div> 58781 * <code> 58782 * ellipse(0, 50, 33, 33); // Left circle 58783 * 58784 * push(); // Start a new drawing state 58785 * strokeWeight(10); 58786 * fill(204, 153, 0); 58787 * ellipse(33, 50, 33, 33); // Left-middle circle 58788 * 58789 * push(); // Start another new drawing state 58790 * stroke(0, 102, 153); 58791 * ellipse(66, 50, 33, 33); // Right-middle circle 58792 * pop(); // Restore previous state 58793 * 58794 * pop(); // Restore original state 58795 * 58796 * ellipse(100, 50, 33, 33); // Right circle 58797 * </code> 58798 * </div> 58799 * 58800 * @alt 58801 * Gold ellipse + thick black outline @center 2 white ellipses on left and right. 58802 * 2 Gold ellipses left black right blue stroke. 2 white ellipses on left+right. 58803 */ 58804 _main.default.prototype.pop = function() { 58805 var style = this._styles.pop(); 58806 if (style) { 58807 this._renderer.pop(style.renderer); 58808 Object.assign(this, style.props); 58809 } else { 58810 console.warn('pop() was called without matching push()'); 58811 } 58812 }; 58813 58814 /** 58815 * Executes the code within <a href="#/p5/draw">draw()</a> one time. This 58816 * function allows the program to update the display window only when necessary, 58817 * for example when an event registered by <a href="#/p5/mousePressed">mousePressed()</a> 58818 * or <a href="#/p5/keyPressed">keyPressed()</a> occurs. 58819 * 58820 * In structuring a program, it only makes sense to call <a href="#/p5/redraw">redraw()</a> 58821 * within events such as <a href="#/p5/mousePressed">mousePressed()</a>. This 58822 * is because <a href="#/p5/redraw">redraw()</a> does not run 58823 * <a href="#/p5/draw">draw()</a> immediately (it only sets a flag that indicates 58824 * an update is needed). 58825 * 58826 * The <a href="#/p5/redraw">redraw()</a> function does not work properly when
58827 * called inside <a href="#/p5/draw">draw()</a>.To enable/disable animations, 58828 * use <a href="#/p5/loop">loop()</a> and <a href="#/p5/noLoop">noLoop()</a>. 58829 * 58830 * In addition you can set the number of redraws per method call. Just 58831 * add an integer as single parameter for the number of redraws. 58832 * 58833 * @method redraw 58834 * @param {Integer} [n] Redraw for n-times. The default value is 1. 58835 * @example 58836 * <div><code> 58837 * let x = 0; 58838 * 58839 * function setup() { 58840 * createCanvas(100, 100); 58841 * noLoop(); 58842 * } 58843 * 58844 * function draw() { 58845 * background(204); 58846 * line(x, 0, x, height); 58847 * } 58848 * 58849 * function mousePressed() { 58850 * x += 1; 58851 * redraw(); 58852 * } 58853 * </code> 58854 * </div> 58855 * 58856 * <div class='norender'> 58857 * <code> 58858 * let x = 0; 58859 * 58860 * function setup() { 58861 * createCanvas(100, 100); 58862 * noLoop(); 58863 * } 58864 * 58865 * function draw() { 58866 * background(204); 58867 * x += 1; 58868 * line(x, 0, x, height); 58869 * } 58870 * 58871 * function mousePressed() { 58872 * redraw(5); 58873 * } 58874 * </code> 58875 * </div> 58876 * 58877 * @alt 58878 * black line on far left of canvas 58879 * black line on far left of canvas 58880 */ 58881 _main.default.prototype.redraw = function(n) { 58882 if (this._inUserDraw || !this._setupDone) { 58883 return; 58884 } 58885 58886 var numberOfRedraws = parseInt(n); 58887 if (isNaN(numberOfRedraws) || numberOfRedraws < 1) { 58888 numberOfRedraws = 1; 58889 } 58890 58891 var context = this._isGlobal ? window : this; 58892 if (typeof context.draw === 'function') { 58893 if (typeof context.setup === 'undefined') { 58894 context.scale(context._pixelDensity, context._pixelDensity); 58895 } 58896 var callMethod = function callMethod(f) { 58897 f.call(context); 58898 }; 58899 for (var idxRedraw = 0; idxRedraw < numberOfRedraws; idxRedraw++) { 58900 context.resetMatrix(); 58901 if (this._accessibleOutputs.grid || this._accessibleOutputs.text) { 58902 this._updateAccsOutput(); 58903 } 58904 if (context._renderer.isP3D) { 58905 context._renderer._update(); 58906 } 58907 context._setProperty('frameCount', context.frameCount + 1); 58908 context._registeredMethods.pre.forEach(callMethod); 58909 this._inUserDraw = true; 58910 try { 58911 context.draw(); 58912 } finally { 58913 this._inUserDraw = false; 58914 } 58915 context._registeredMethods.post.forEach(callMethod); 58916 } 58917 } 58918 }; 58919 58920 /** 58921 * The `p5()` constructor enables you to activate "instance mode" instead of normal 58922 * "global mode". This is an advanced topic. A short description and example is 58923 * included below. Please see 58924 * <a target="blank" href="https://www.youtube.com/watch?v=Su792jEauZg&feature=youtu.be"> 58925 * Dan Shiffman's Coding Train video tutorial</a> or this 58926 * <a target="blank" href="https://github.com/processing/p5.js/wiki/p5.js-overview#instantiation--namespace">tutorial page</a> 58927 * for more info. 58928 * 58929 * By default, all p5.js functions are in the global namespace (i.e. bound to the window 58930 * object), meaning you can call them simply `ellipse()`, `fill()`, etc. However, this 58931 * might be inconvenient if you are mixing with other JS libraries (synchronously or 58932 * asynchronously) or writing long programs of your own. p5.js currently supports a 58933 * way around this problem called "instance mode". In instance mode, all p5 functions 58934 * are bound up in a single variable instead of polluting your global namespace. 58935 * 58936 * Optionally, you can specify a default container for the canvas and any other elements 58937 * to append to with a second argument. You can give the ID of an element in your html, 58938 * or an html node itself. 58939 * 58940 * Note that creating instances like this also allows you to have more than one p5 sketch on 58941 * a single web page, as they will each be wrapped up with their own set up variables. Of 58942 * course, you could also use iframes to have multiple sketches in global mode. 58943 * 58944 * @method p5 58945 * @param {Object} sketch a function containing a p5.js sketch 58946 * @param {String|Object} node ID or pointer to HTML DOM node to contain sketch in 58947 * @example 58948 * <div class='norender'><code> 58949 * const s = p => { 58950 * let x = 100; 58951 * let y = 100; 58952 * 58953 * p.setup = function() { 58954 * p.createCanvas(700, 410); 58955 * }; 58956 * 58957 * p.draw = function() { 58958 * p.background(0); 58959 * p.fill(255); 58960 * p.rect(x, y, 50, 50); 58961 * }; 58962 * }; 58963 * 58964 * new p5(s); // invoke p5 58965 * </code></div> 58966 * 58967 * @alt 58968 * white rectangle on black background 58969 */ var _default = _main.default; 58970 exports.default = _default; 58971 }, 58972 { './main': 59 } 58973 ], 58974 72: [
58975 function(_dereq_, module, exports) { 58976 'use strict'; 58977 Object.defineProperty(exports, '__esModule', { value: true }); 58978 exports.default = void 0; 58979 58980 var _main = _interopRequireDefault(_dereq_('./main')); 58981 function _interopRequireDefault(obj) { 58982 return obj && obj.__esModule ? obj : { default: obj }; 58983 } 58984 /** 58985 * @module Transform 58986 * @submodule Transform 58987 * @for p5 58988 * @requires core 58989 * @requires constants 58990 */ /** 58991 * Multiplies the current matrix by the one specified through the parameters. 58992 * This is a powerful operation that can perform the equivalent of translate, 58993 * scale, shear and rotate all at once. You can learn more about transformation 58994 * matrices on <a href="https://en.wikipedia.org/wiki/Transformation_matrix"> 58995 * Wikipedia</a>. 58996 * 58997 * The naming of the arguments here follows the naming of the <a href= 58998 * "https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-transform"> 58999 * WHATWG specification</a> and corresponds to a 59000 * transformation matrix of the 59001 * form: 59002 * 59003 * > <img style="max-width: 150px" src="assets/transformation-matrix.png" 59004 * alt="The transformation matrix used when applyMatrix is called"/> 59005 *
59006 * @method applyMatrix 59007 * @param {Number} a numbers which define the 2x3 matrix to be multiplied 59008 * @param {Number} b numbers which define the 2x3 matrix to be multiplied 59009 * @param {Number} c numbers which define the 2x3 matrix to be multiplied 59010 * @param {Number} d numbers which define the 2x3 matrix to be multiplied 59011 * @param {Number} e numbers which define the 2x3 matrix to be multiplied 59012 * @param {Number} f numbers which define the 2x3 matrix to be multiplied 59013 * @chainable 59014 * @example 59015 * <div> 59016 * <code> 59017 * function setup() { 59018 * frameRate(10); 59019 * rectMode(CENTER); 59020 * } 59021 * 59022 * function draw() { 59023 * let step = frameCount % 20; 59024 * background(200); 59025 * // Equivalent to translate(x, y); 59026 * applyMatrix(1, 0, 0, 1, 40 + step, 50); 59027 * rect(0, 0, 50, 50); 59028 * } 59029 * </code> 59030 * </div> 59031 * 59032 * <div> 59033 * <code> 59034 * function setup() { 59035 * frameRate(10); 59036 * rectMode(CENTER); 59037 * } 59038 * 59039 * function draw() { 59040 * let step = frameCount % 20; 59041 * background(200); 59042 * translate(50, 50); 59043 * // Equivalent to scale(x, y); 59044 * applyMatrix(1 / step, 0, 0, 1 / step, 0, 0); 59045 * rect(0, 0, 50, 50); 59046 * } 59047 * </code> 59048 * </div> 59049 * 59050 * <div> 59051 * <code> 59052 * function setup() { 59053 * frameRate(10); 59054 * rectMode(CENTER); 59055 * } 59056 * 59057 * function draw() { 59058 * let step = frameCount % 20; 59059 * let angle = map(step, 0, 20, 0, TWO_PI); 59060 * let cos_a = cos(angle); 59061 * let sin_a = sin(angle); 59062 * background(200); 59063 * translate(50, 50); 59064 * // Equivalent to rotate(angle); 59065 * applyMatrix(cos_a, sin_a, -sin_a, cos_a, 0, 0); 59066 * rect(0, 0, 50, 50); 59067 * } 59068 * </code> 59069 * </div> 59070 * 59071 * <div> 59072 * <code> 59073 * function setup() { 59074 * frameRate(10); 59075 * rectMode(CENTER); 59076 * } 59077 * 59078 * function draw() { 59079 * let step = frameCount % 20; 59080 * let angle = map(step, 0, 20, -PI / 4, PI / 4); 59081 * background(200); 59082 * translate(50, 50); 59083 * // equivalent to shearX(angle); 59084 * let shear_factor = 1 / tan(PI / 2 - angle); 59085 * applyMatrix(1, 0, shear_factor, 1, 0, 0); 59086 * rect(0, 0, 50, 50); 59087 * } 59088 * </code> 59089 * </div> 59090 * 59091 * <div modernizr='webgl'> 59092 * <code> 59093 * function setup() { 59094 * createCanvas(100, 100, WEBGL); 59095 * noFill(); 59096 * } 59097 * 59098 * function draw() { 59099 * background(200); 59100 * rotateY(PI / 6); 59101 * stroke(153); 59102 * box(35); 59103 * let rad = millis() / 1000; 59104 * // Set rotation angles 59105 * let ct = cos(rad); 59106 * let st = sin(rad); 59107 * // Matrix for rotation around the Y axis 59108 * // prettier-ignore 59109 * applyMatrix( ct, 0.0, st, 0.0, 59110 * 0.0, 1.0, 0.0, 0.0, 59111 * -st, 0.0, ct, 0.0, 59112 * 0.0, 0.0, 0.0, 1.0); 59113 * stroke(255); 59114 * box(50); 59115 * } 59116 * </code> 59117 * </div> 59118 * 59119 * @alt 59120 * A rectangle translating to the right 59121 * A rectangle shrinking to the center 59122 * A rectangle rotating clockwise about the center 59123 * A rectangle shearing 59124 */ _main.default.prototype.applyMatrix = function(a, b, c, d, e, f) { 59125 var _this$_renderer; 59126 (_this$_renderer = this._renderer).applyMatrix.apply( 59127 _this$_renderer, 59128 arguments 59129 ); 59130 return this; 59131 }; 59132 59133 /** 59134 * Replaces the current matrix with the identity matrix. 59135 * 59136 * @method resetMatrix 59137 * @chainable 59138 * @example 59139 * <div> 59140 * <code> 59141 * translate(50, 50); 59142 * applyMatrix(0.5, 0.5, -0.5, 0.5, 0, 0); 59143 * rect(0, 0, 20, 20); 59144 * // Note that the translate is also reset. 59145 * resetMatrix(); 59146 * rect(0, 0, 20, 20); 59147 * </code> 59148 * </div> 59149 * 59150 * @alt 59151 * A rotated retangle in the center with another at the top left corner 59152 */ 59153 _main.default.prototype.resetMatrix = function() { 59154 this._renderer.resetMatrix(); 59155 return this; 59156 }; 59157 59158 /** 59159 * Rotates a shape by the amount specified by the angle parameter. This 59160 * function accounts for <a href="#/p5/angleMode">angleMode</a>, so angles 59161 * can be entered in either RADIANS or DEGREES.
59162 * 59163 * Objects are always rotated around their relative position to the 59164 * origin and positive numbers rotate objects in a clockwise direction. 59165 * Transformations apply to everything that happens after and subsequent 59166 * calls to the function accumulates the effect. For example, calling 59167 * rotate(HALF_PI) and then rotate(HALF_PI) is the same as rotate(PI). 59168 * All tranformations are reset when <a href="#/p5/draw">draw()</a> begins again. 59169 * 59170 * Technically, <a href="#/p5/rotate">rotate()</a> multiplies the current transformation matrix 59171 * by a rotation matrix. This function can be further controlled by 59172 * the <a href="#/p5/push">push()</a> and <a href="#/p5/pop">pop()</a>. 59173 * 59174 * @method rotate 59175 * @param {Number} angle the angle of rotation, specified in radians 59176 * or degrees, depending on current angleMode 59177 * @param {p5.Vector|Number[]} [axis] (in 3d) the axis to rotate around 59178 * @chainable 59179 * @example 59180 * <div> 59181 * <code> 59182 * translate(width / 2, height / 2); 59183 * rotate(PI / 3.0); 59184 * rect(-26, -26, 52, 52); 59185 * </code> 59186 * </div> 59187 * 59188 * @alt 59189 * white 52x52 rect with black outline at center rotated counter 45 degrees 59190 */ 59191 _main.default.prototype.rotate = function(angle, axis) { 59192 _main.default._validateParameters('rotate', arguments); 59193 this._renderer.rotate(this._toRadians(angle), axis); 59194 return this; 59195 }; 59196 59197 /** 59198 * Rotates a shape around X axis by the amount specified in angle parameter. 59199 * The angles can be entered in either RADIANS or DEGREES. 59200 * 59201 * Objects are always rotated around their relative position to the 59202 * origin and positive numbers rotate objects in a clockwise direction. 59203 * All tranformations are reset when <a href="#/p5/draw">draw()</a> begins again. 59204 * 59205 * @method rotateX 59206 * @param {Number} angle the angle of rotation, specified in radians 59207 * or degrees, depending on current angleMode 59208 * @chainable 59209 * @example 59210 * <div modernizr='webgl'> 59211 * <code> 59212 * function setup() { 59213 * createCanvas(100, 100, WEBGL); 59214 * } 59215 * function draw() { 59216 * background(255); 59217 * rotateX(millis() / 1000); 59218 * box(); 59219 * } 59220 * </code> 59221 * </div> 59222 * 59223 * @alt 59224 * 3d box rotating around the x axis. 59225 */ 59226 _main.default.prototype.rotateX = function(angle) { 59227 this._assert3d('rotateX'); 59228 _main.default._validateParameters('rotateX', arguments); 59229 this._renderer.rotateX(this._toRadians(angle)); 59230 return this; 59231 }; 59232 59233 /** 59234 * Rotates a shape around Y axis by the amount specified in angle parameter. 59235 * The angles can be entered in either RADIANS or DEGREES. 59236 * 59237 * Objects are always rotated around their relative position to the 59238 * origin and positive numbers rotate objects in a clockwise direction. 59239 * All tranformations are reset when <a href="#/p5/draw">draw()</a> begins again. 59240 * 59241 * @method rotateY 59242 * @param {Number} angle the angle of rotation, specified in radians 59243 * or degrees, depending on current angleMode 59244 * @chainable 59245 * @example 59246 * <div modernizr='webgl'> 59247 * <code> 59248 * function setup() { 59249 * createCanvas(100, 100, WEBGL); 59250 * } 59251 * function draw() { 59252 * background(255); 59253 * rotateY(millis() / 1000); 59254 * box(); 59255 * } 59256 * </code> 59257 * </div> 59258 * 59259 * @alt 59260 * 3d box rotating around the y axis. 59261 */ 59262 _main.default.prototype.rotateY = function(angle) { 59263 this._assert3d('rotateY'); 59264 _main.default._validateParameters('rotateY', arguments); 59265 this._renderer.rotateY(this._toRadians(angle)); 59266 return this; 59267 }; 59268 59269 /** 59270 * Rotates a shape around Z axis by the amount specified in angle parameter. 59271 * The angles can be entered in either RADIANS or DEGREES.
59272 * 59273 * This method works in WEBGL mode only. 59274 * 59275 * Objects are always rotated around their relative position to the 59276 * origin and positive numbers rotate objects in a clockwise direction. 59277 * All tranformations are reset when <a href="#/p5/draw">draw()</a> begins again. 59278 * 59279 * @method rotateZ 59280 * @param {Number} angle the angle of rotation, specified in radians 59281 * or degrees, depending on current angleMode 59282 * @chainable 59283 * @example 59284 * <div modernizr='webgl'> 59285 * <code> 59286 * function setup() { 59287 * createCanvas(100, 100, WEBGL); 59288 * } 59289 * function draw() { 59290 * background(255); 59291 * rotateZ(millis() / 1000); 59292 * box(); 59293 * } 59294 * </code> 59295 * </div> 59296 * 59297 * @alt 59298 * 3d box rotating around the z axis. 59299 */ 59300 _main.default.prototype.rotateZ = function(angle) { 59301 this._assert3d('rotateZ'); 59302 _main.default._validateParameters('rotateZ', arguments); 59303 this._renderer.rotateZ(this._toRadians(angle)); 59304 return this; 59305 }; 59306 59307 /** 59308 * Increases or decreases the size of a shape by expanding or contracting 59309 * vertices. Objects always scale from their relative origin to the 59310 * coordinate system. Scale values are specified as decimal percentages. 59311 * For example, the function call scale(2.0) increases the dimension of a 59312 * shape by 200%. 59313 * 59314 * Transformations apply to everything that happens after and subsequent 59315 * calls to the function multiply the effect. For example, calling scale(2.0) 59316 * and then scale(1.5) is the same as scale(3.0). If <a href="#/p5/scale">scale()</a> is called 59317 * within <a href="#/p5/draw">draw()</a>, the transformation is reset when the loop begins again. 59318 * 59319 * Using this function with the z parameter is only available in WEBGL mode. 59320 * This function can be further controlled with <a href="#/p5/push">push()</a> and <a href="#/p5/pop">pop()</a>. 59321 * 59322 * @method scale 59323 * @param {Number|p5.Vector|Number[]} s 59324 * percent to scale the object, or percentage to 59325 * scale the object in the x-axis if multiple arguments 59326 * are given 59327 * @param {Number} [y] percent to scale the object in the y-axis 59328 * @param {Number} [z] percent to scale the object in the z-axis (webgl only) 59329 * @chainable 59330 * @example 59331 * <div> 59332 * <code> 59333 * rect(30, 20, 50, 50); 59334 * scale(0.5); 59335 * rect(30, 20, 50, 50); 59336 * </code> 59337 * </div> 59338 * 59339 * <div> 59340 * <code> 59341 * rect(30, 20, 50, 50); 59342 * scale(0.5, 1.3); 59343 * rect(30, 20, 50, 50); 59344 * </code> 59345 * </div> 59346 * 59347 * @alt 59348 * white 52x52 rect with black outline at center rotated counter 45 degrees 59349 * 2 white rects with black outline- 1 50x50 at center. other 25x65 bottom left 59350 */ 59351 /** 59352 * @method scale 59353 * @param {p5.Vector|Number[]} scales per-axis percents to scale the object 59354 * @chainable 59355 */ 59356 _main.default.prototype.scale = function(x, y, z) { 59357 _main.default._validateParameters('scale', arguments); 59358 // Only check for Vector argument type if Vector is available 59359 if (x instanceof _main.default.Vector) { 59360 var v = x; 59361 x = v.x; 59362 y = v.y; 59363 z = v.z; 59364 } else if (x instanceof Array) { 59365 var rg = x; 59366 x = rg[0]; 59367 y = rg[1]; 59368 z = rg[2] || 1; 59369 } 59370 if (isNaN(y)) { 59371 y = z = x; 59372 } else if (isNaN(z)) { 59373 z = 1; 59374 } 59375 59376 this._renderer.scale.call(this._renderer, x, y, z); 59377 59378 return this; 59379 }; 59380 59381 /** 59382 * Shears a shape around the x-axis by the amount specified by the angle 59383 * parameter. Angles should be specified in the current angleMode. 59384 * Objects are always sheared around their relative position to the origin 59385 * and positive numbers shear objects in a clockwise direction. 59386 * 59387 * Transformations apply to everything that happens after and subsequent 59388 * calls to the function accumulates the effect. For example, calling 59389 * shearX(PI/2) and then shearX(PI/2) is the same as shearX(PI). 59390 * If <a href="#/p5/shearX">shearX()</a> is called within the <a href="#/p5/draw">draw()</a>, 59391 * the transformation is reset when the loop begins again. 59392 *
59393 * Technically, <a href="#/p5/shearX">shearX()</a> multiplies the current 59394 * transformation matrix by a rotation matrix. This function can be further 59395 * controlled by the <a href="#/p5/push">push()</a> and <a href="#/p5/pop">pop()</a> functions. 59396 * 59397 * @method shearX 59398 * @param {Number} angle angle of shear specified in radians or degrees, 59399 * depending on current angleMode 59400 * @chainable 59401 * @example 59402 * <div> 59403 * <code> 59404 * translate(width / 4, height / 4); 59405 * shearX(PI / 4.0); 59406 * rect(0, 0, 30, 30); 59407 * </code> 59408 * </div> 59409 * 59410 * @alt 59411 * white irregular quadrilateral with black outline at top middle. 59412 */ 59413 _main.default.prototype.shearX = function(angle) { 59414 _main.default._validateParameters('shearX', arguments); 59415 var rad = this._toRadians(angle); 59416 this._renderer.applyMatrix(1, 0, Math.tan(rad), 1, 0, 0); 59417 return this; 59418 }; 59419 59420 /** 59421 * Shears a shape around the y-axis the amount specified by the angle 59422 * parameter. Angles should be specified in the current angleMode. Objects 59423 * are always sheared around their relative position to the origin and 59424 * positive numbers shear objects in a clockwise direction. 59425 * 59426 * Transformations apply to everything that happens after and subsequent 59427 * calls to the function accumulates the effect. For example, calling 59428 * shearY(PI/2) and then shearY(PI/2) is the same as shearY(PI). If 59429 * <a href="#/p5/shearY">shearY()</a> is called within the <a href="#/p5/draw">draw()</a>, the transformation is reset when 59430 * the loop begins again. 59431 * 59432 * Technically, <a href="#/p5/shearY">shearY()</a> multiplies the current transformation matrix by a 59433 * rotation matrix. This function can be further controlled by the 59434 * <a href="#/p5/push">push()</a> and <a href="#/p5/pop">pop()</a> functions. 59435 * 59436 * @method shearY 59437 * @param {Number} angle angle of shear specified in radians or degrees, 59438 * depending on current angleMode 59439 * @chainable 59440 * @example 59441 * <div> 59442 * <code> 59443 * translate(width / 4, height / 4); 59444 * shearY(PI / 4.0); 59445 * rect(0, 0, 30, 30); 59446 * </code> 59447 * </div> 59448 * 59449 * @alt 59450 * white irregular quadrilateral with black outline at middle bottom. 59451 */ 59452 _main.default.prototype.shearY = function(angle) { 59453 _main.default._validateParameters('shearY', arguments); 59454 var rad = this._toRadians(angle); 59455 this._renderer.applyMatrix(1, Math.tan(rad), 0, 1, 0, 0); 59456 return this; 59457 }; 59458 59459 /** 59460 * Specifies an amount to displace objects within the display window. 59461 * The x parameter specifies left/right translation, the y parameter 59462 * specifies up/down translation. 59463 * 59464 * Transformations are cumulative and apply to everything that happens after 59465 * and subsequent calls to the function accumulates the effect. For example, 59466 * calling translate(50, 0) and then translate(20, 0) is the same as 59467 * translate(70, 0). If <a href="#/p5/translate">translate()</a> is called within <a href="#/p5/draw">draw()</a>, the 59468 * transformation is reset when the loop begins again. This function can be 59469 * further controlled by using <a href="#/p5/push">push()</a> and <a href="#/p5/pop">pop()</a>. 59470 * 59471 * @method translate 59472 * @param {Number} x left/right translation 59473 * @param {Number} y up/down translation 59474 * @param {Number} [z] forward/backward translation (webgl only) 59475 * @chainable 59476 * @example 59477 * <div> 59478 * <code> 59479 * translate(30, 20); 59480 * rect(0, 0, 55, 55); 59481 * </code> 59482 * </div> 59483 * 59484 * <div> 59485 * <code> 59486 * rect(0, 0, 55, 55); // Draw rect at original 0,0 59487 * translate(30, 20); 59488 * rect(0, 0, 55, 55); // Draw rect at new 0,0 59489 * translate(14, 14); 59490 * rect(0, 0, 55, 55); // Draw rect at new 0,0 59491 * </code> 59492 * </div> 59493 * 59494 59495 * <div> 59496 * <code> 59497 * function draw() { 59498 * background(200); 59499 * rectMode(CENTER); 59500 * translate(width / 2, height / 2); 59501 * translate(p5.Vector.fromAngle(millis() / 1000, 40)); 59502 * rect(0, 0, 20, 20); 59503 * } 59504 * </code> 59505 * </div> 59506 * 59507 * @alt 59508 * white 55x55 rect with black outline at center right. 59509 * 3 white 55x55 rects with black outlines at top-l, center-r and bottom-r.
59510 * a 20x20 white rect moving in a circle around the canvas 59511 */ 59512 /** 59513 * @method translate 59514 * @param {p5.Vector} vector the vector to translate by 59515 * @chainable 59516 */ 59517 _main.default.prototype.translate = function(x, y, z) { 59518 _main.default._validateParameters('translate', arguments); 59519 if (this._renderer.isP3D) { 59520 this._renderer.translate(x, y, z); 59521 } else { 59522 this._renderer.translate(x, y); 59523 } 59524 return this; 59525 }; 59526 var _default = _main.default; 59527 exports.default = _default; 59528 }, 59529 { './main': 59 } 59530 ], 59531 73: [ 59532 function(_dereq_, module, exports) { 59533 'use strict'; 59534 59535 var _main = _interopRequireDefault(_dereq_('../core/main')); 59536 function _interopRequireDefault(obj) { 59537 return obj && obj.__esModule ? obj : { default: obj }; 59538 } 59539 function _toConsumableArray(arr) { 59540 return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); 59541 } 59542 function _nonIterableSpread() { 59543 throw new TypeError('Invalid attempt to spread non-iterable instance'); 59544 } 59545 function _iterableToArray(iter) { 59546 if ( 59547 Symbol.iterator in Object(iter) || 59548 Object.prototype.toString.call(iter) === '[object Arguments]' 59549 ) 59550 return Array.from(iter); 59551 } 59552 function _arrayWithoutHoles(arr) { 59553 if (Array.isArray(arr)) { 59554 for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { 59555 arr2[i] = arr[i]; 59556 } 59557 return arr2; 59558 } 59559 } 59560 function _typeof(obj) { 59561 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') { 59562 _typeof = function _typeof(obj) { 59563 return typeof obj; 59564 }; 59565 } else { 59566 _typeof = function _typeof(obj) { 59567 return obj && 59568 typeof Symbol === 'function' && 59569 obj.constructor === Symbol && 59570 obj !== Symbol.prototype 59571 ? 'symbol' 59572 : typeof obj; 59573 }; 59574 } 59575 return _typeof(obj); 59576 } 59577 /** 59578 * 59579 * Stores a value in local storage under the key name. 59580 * Local storage is saved in the browser and persists 59581 * between browsing sessions and page reloads. 59582 * The key can be the name of the variable but doesn't 59583 * have to be. To retrieve stored items 59584 * see <a href="#/p5/getItem">getItem</a>. 59585 * 59586 * Sensitive data such as passwords or personal information 59587 * should not be stored in local storage. 59588 * 59589 * @method storeItem 59590 * @for p5 59591 * @param {String} key 59592 * @param {String|Number|Object|Boolean|p5.Color|p5.Vector} value 59593 * 59594 * @example 59595 * <div><code> 59596 * // Type to change the letter in the 59597 * // center of the canvas. 59598 * // If you reload the page, it will 59599 * // still display the last key you entered 59600 * 59601 * let myText; 59602 * 59603 * function setup() { 59604 * createCanvas(100, 100); 59605 * myText = getItem('myText'); 59606 * if (myText === null) { 59607 * myText = ''; 59608 * } 59609 * } 59610 * 59611 * function draw() { 59612 * textSize(40); 59613 * background(255); 59614 * text(myText, width / 2, height / 2); 59615 * } 59616 * 59617 * function keyPressed() { 59618 * myText = key; 59619 * storeItem('myText', myText); 59620 * } 59621 * </code></div> 59622 * 59623 * @alt 59624 * When you type the key name is displayed as black text on white background. 59625 * If you reload the page, the last letter typed is still displaying. 59626 */ 59627 _main.default.prototype.storeItem = function(key, value) { 59628 if (typeof key !== 'string') { 59629 console.log( 59630 'The argument that you passed to storeItem() - '.concat( 59631 key, 59632 ' is not a string.' 59633 ) 59634 ); 59635 }
59636 if (key.endsWith('p5TypeID')) { 59637 console.log( 59638 'The argument that you passed to storeItem() - '.concat( 59639 key, 59640 " must not end with 'p5TypeID'." 59641 ) 59642 ); 59643 } 59644 59645 if (typeof value === 'undefined') { 59646 console.log('You cannot store undefined variables using storeItem().'); 59647 } 59648 var type = _typeof(value); 59649 switch (type) { 59650 case 'number': 59651 case 'boolean': 59652 value = value.toString(); 59653 break; 59654 case 'object': 59655 if (value instanceof _main.default.Color) { 59656 type = 'p5.Color'; 59657 } else if (value instanceof _main.default.Vector) { 59658 type = 'p5.Vector'; 59659 var coord = [value.x, value.y, value.z]; 59660 value = coord; 59661 } 59662 value = JSON.stringify(value); 59663 break; 59664 case 'string': 59665 default: 59666 break; 59667 } 59668 59669 localStorage.setItem(key, value); 59670 var typeKey = ''.concat(key, 'p5TypeID'); 59671 localStorage.setItem(typeKey, type); 59672 }; 59673 59674 /** 59675 * 59676 * Returns the value of an item that was stored in local storage 59677 * using storeItem() 59678 * 59679 * @method getItem 59680 * @for p5 59681 * @param {String} key name that you wish to use to store in local storage 59682 * @return {Number|Object|String|Boolean|p5.Color|p5.Vector} Value of stored item 59683 * 59684 * @example 59685 * <div><code> 59686 * // Click the mouse to change 59687 * // the color of the background 59688 * // Once you have changed the color 59689 * // it will stay changed even when you 59690 * // reload the page. 59691 * 59692 * let myColor; 59693 * 59694 * function setup() { 59695 * createCanvas(100, 100); 59696 * myColor = getItem('myColor'); 59697 * } 59698 * 59699 * function draw() { 59700 * if (myColor !== null) { 59701 * background(myColor); 59702 * } 59703 * } 59704 * 59705 * function mousePressed() { 59706 * myColor = color(random(255), random(255), random(255)); 59707 * storeItem('myColor', myColor); 59708 * } 59709 * </code></div> 59710 * 59711 * @alt 59712 * If you click, the canvas changes to a random color. 59713 * If you reload the page, the canvas is still the color it 59714 * was when the page was previously loaded. 59715 */ 59716 _main.default.prototype.getItem = function(key) { 59717 var value = localStorage.getItem(key); 59718 var type = localStorage.getItem(''.concat(key, 'p5TypeID')); 59719 if (typeof type === 'undefined') { 59720 console.log( 59721 'Unable to determine type of item stored under '.concat( 59722 key, 59723 'in local storage. Did you save the item with something other than setItem()?' 59724 ) 59725 ); 59726 } else if (value !== null) { 59727 switch (type) { 59728 case 'number': 59729 value = parseFloat(value); 59730 break; 59731 case 'boolean': 59732 value = value === 'true'; 59733 break; 59734 case 'object': 59735 value = JSON.parse(value); 59736 break; 59737 case 'p5.Color': 59738 value = JSON.parse(value); 59739 value = this.color.apply(this, _toConsumableArray(value.levels)); 59740 break; 59741 case 'p5.Vector': 59742 value = JSON.parse(value); 59743 value = this.createVector.apply(this, _toConsumableArray(value)); 59744 break; 59745 case 'string': 59746 default: 59747 break; 59748 } 59749 } 59750 return value; 59751 }; 59752 59753 /** 59754 * 59755 * Clears all local storage items set with storeItem() 59756 * for the current domain. 59757 * 59758 * @method clearStorage 59759 * @for p5 59760 * 59761 * @example 59762 * <div class="norender"> 59763 * <code> 59764 * function setup() { 59765 * let myNum = 10; 59766 * let myBool = false;
59767 * storeItem('myNum', myNum); 59768 * storeItem('myBool', myBool); 59769 * print(getItem('myNum')); // logs 10 to the console 59770 * print(getItem('myBool')); // logs false to the console 59771 * clearStorage(); 59772 * print(getItem('myNum')); // logs null to the console 59773 * print(getItem('myBool')); // logs null to the console 59774 * } 59775 * </code></div> 59776 */ 59777 _main.default.prototype.clearStorage = function() { 59778 localStorage.clear(); 59779 }; 59780 59781 /** 59782 * 59783 * Removes an item that was stored with storeItem() 59784 * 59785 * @method removeItem 59786 * @param {String} key 59787 * @for p5 59788 * 59789 * @example 59790 * <div class="norender"> 59791 * <code> 59792 * function setup() { 59793 * let myVar = 10; 59794 * storeItem('myVar', myVar); 59795 * print(getItem('myVar')); // logs 10 to the console 59796 * removeItem('myVar'); 59797 * print(getItem('myVar')); // logs null to the console 59798 * } 59799 * </code></div> 59800 */ 59801 _main.default.prototype.removeItem = function(key) { 59802 if (typeof key !== 'string') { 59803 console.log( 59804 'The argument that you passed to removeItem() - '.concat( 59805 key, 59806 ' is not a string.' 59807 ) 59808 ); 59809 } 59810 localStorage.removeItem(key); 59811 localStorage.removeItem(''.concat(key, 'p5TypeID')); 59812 }; 59813 }, 59814 { '../core/main': 59 } 59815 ], 59816 74: [ 59817 function(_dereq_, module, exports) { 59818 'use strict'; 59819 Object.defineProperty(exports, '__esModule', { value: true }); 59820 exports.default = void 0; 59821 59822 var _main = _interopRequireDefault(_dereq_('../core/main')); 59823 function _interopRequireDefault(obj) { 59824 return obj && obj.__esModule ? obj : { default: obj }; 59825 } 59826 /** 59827 * @module Data 59828 * @submodule Dictionary 59829 * @for p5.TypedDict 59830 * @requires core 59831 * 59832 * This module defines the p5 methods for the p5 Dictionary classes. 59833 * The classes StringDict and NumberDict are for storing and working 59834 * with key-value pairs. 59835 */ /** 59836 * 59837 * Creates a new instance of p5.StringDict using the key-value pair 59838 * or the object you provide. 59839 * 59840 * @method createStringDict 59841 * @for p5 59842 * @param {String} key 59843 * @param {String} value 59844 * @return {p5.StringDict} 59845 * 59846 * @example 59847 * <div class="norender"> 59848 * <code> 59849 * function setup() { 59850 * let myDictionary = createStringDict('p5', 'js'); 59851 * print(myDictionary.hasKey('p5')); // logs true to console 59852 * 59853 * let anotherDictionary = createStringDict({ happy: 'coding' }); 59854 * print(anotherDictionary.hasKey('happy')); // logs true to console 59855 * } 59856 * </code></div> 59857 */ /** 59858 * @method createStringDict 59859 * @param {Object} object object 59860 * @return {p5.StringDict} 59861 */ _main.default.prototype.createStringDict = function(key, value) { 59862 _main.default._validateParameters('createStringDict', arguments); 59863 return new _main.default.StringDict(key, value); 59864 }; 59865 /** 59866 * 59867 * Creates a new instance of <a href="#/p5.NumberDict">p5.NumberDict</a> using the key-value pair 59868 * or object you provide. 59869 * 59870 * @method createNumberDict 59871 * @for p5 59872 * @param {Number} key 59873 * @param {Number} value 59874 * @return {p5.NumberDict} 59875 * 59876 * @example 59877 * <div class="norender"> 59878 * <code> 59879 * function setup() { 59880 * let myDictionary = createNumberDict(100, 42); 59881 * print(myDictionary.hasKey(100)); // logs true to console 59882 * 59883 * let anotherDictionary = createNumberDict({ 200: 84 }); 59884 * print(anotherDictionary.hasKey(200)); // logs true to console 59885 * } 59886 * </code></div> 59887 */ 59888 /** 59889 * @method createNumberDict 59890 * @param {Object} object object 59891 * @return {p5.NumberDict} 59892 */ 59893 59894 _main.default.prototype.createNumberDict = function(key, value) { 59895 _main.default._validateParameters('createNumberDict', arguments); 59896 return new _main.default.NumberDict(key, value); 59897 }; 59898 59899 /** 59900 * 59901 * Base class for all p5.Dictionary types. Specifically 59902 * typed Dictionary classes inherit from this class. 59903 * 59904 * @class p5.TypedDict 59905 * @constructor 59906 */ 59907 59908 _main.default.TypedDict = function(key, value) { 59909 if (key instanceof Object) { 59910 this.data = key; 59911 } else { 59912 this.data = {}; 59913 this.data[key] = value; 59914 } 59915 return this; 59916 }; 59917 59918 /** 59919 * Returns the number of key-value pairs currently stored in the Dictionary. 59920 * 59921 * @method size 59922 * @return {Integer} the number of key-value pairs in the Dictionary 59923 * 59924 * @example 59925 * <div class="norender"> 59926 * <code> 59927 * function setup() { 59928 * let myDictionary = createNumberDict(1, 10); 59929 * myDictionary.create(2, 20); 59930 * myDictionary.create(3, 30); 59931 * print(myDictionary.size()); // logs 3 to the console 59932 * } 59933 * </code></div> 59934 */ 59935 _main.default.TypedDict.prototype.size = function() { 59936 return Object.keys(this.data).length; 59937 }; 59938 59939 /** 59940 * Returns true if the given key exists in the Dictionary, 59941 * otherwise returns false. 59942 * 59943 * @method hasKey 59944 * @param {Number|String} key that you want to look up 59945 * @return {Boolean} whether that key exists in Dictionary 59946 * 59947 * @example 59948 * <div class="norender"> 59949 * <code> 59950 * function setup() { 59951 * let myDictionary = createStringDict('p5', 'js'); 59952 * print(myDictionary.hasKey('p5')); // logs true to console 59953 * } 59954 * </code></div> 59955 */ 59956 59957 _main.default.TypedDict.prototype.hasKey = function(key) { 59958 return this.data.hasOwnProperty(key); 59959 }; 59960 59961 /** 59962 * Returns the value stored at the given key. 59963 * 59964 * @method get 59965 * @param {Number|String} the key you want to access 59966 * @return {Number|String} the value stored at that key 59967 * 59968 * @example 59969 * <div class="norender"> 59970 * <code> 59971 * function setup() { 59972 * let myDictionary = createStringDict('p5', 'js'); 59973 * let myValue = myDictionary.get('p5'); 59974 * print(myValue === 'js'); // logs true to console 59975 * } 59976 * </code></div> 59977 */ 59978 59979 _main.default.TypedDict.prototype.get = function(key) { 59980 if (this.data.hasOwnProperty(key)) { 59981 return this.data[key]; 59982 } else { 59983 console.log(''.concat(key, ' does not exist in this Dictionary')); 59984 } 59985 }; 59986 59987 /** 59988 * Updates the value associated with the given key in case it already exists 59989 * in the Dictionary. Otherwise a new key-value pair is added. 59990 * 59991 * @method set 59992 * @param {Number|String} key 59993 * @param {Number|String} value 59994 * 59995 * @example 59996 * <div class="norender"> 59997 * <code> 59998 * function setup() { 59999 * let myDictionary = createStringDict('p5', 'js'); 60000 * myDictionary.set('p5', 'JS'); 60001 * myDictionary.print(); // logs "key: p5 - value: JS" to console 60002 * } 60003 * </code></div> 60004 */ 60005 60006 _main.default.TypedDict.prototype.set = function(key, value) {
60007 if (this._validate(value)) { 60008 this.data[key] = value; 60009 } else { 60010 console.log('Those values dont work for this dictionary type.'); 60011 } 60012 }; 60013 60014 /** 60015 * private helper function to handle the user passing in objects 60016 * during construction or calls to create() 60017 */ 60018 60019 _main.default.TypedDict.prototype._addObj = function(obj) { 60020 for (var key in obj) { 60021 this.set(key, obj[key]); 60022 } 60023 }; 60024 60025 /** 60026 * Creates a new key-value pair in the Dictionary. 60027 * 60028 * @method create 60029 * @param {Number|String} key 60030 * @param {Number|String} value 60031 * 60032 * @example 60033 * <div class="norender"> 60034 * <code> 60035 * function setup() { 60036 * let myDictionary = createStringDict('p5', 'js'); 60037 * myDictionary.create('happy', 'coding'); 60038 * myDictionary.print(); 60039 * // above logs "key: p5 - value: js, key: happy - value: coding" to console 60040 * } 60041 * </code></div> 60042 */ 60043 /** 60044 * @method create 60045 * @param {Object} obj key/value pair 60046 */ 60047 60048 _main.default.TypedDict.prototype.create = function(key, value) { 60049 if (key instanceof Object && typeof value === 'undefined') { 60050 this._addObj(key); 60051 } else if (typeof key !== 'undefined') { 60052 this.set(key, value); 60053 } else { 60054 console.log( 60055 'In order to create a new Dictionary entry you must pass ' + 60056 'an object or a key, value pair' 60057 ); 60058 } 60059 }; 60060 60061 /** 60062 * Removes all previously stored key-value pairs from the Dictionary. 60063 * 60064 * @method clear 60065 * @example 60066 * <div class="norender"> 60067 * <code> 60068 * function setup() { 60069 * let myDictionary = createStringDict('p5', 'js'); 60070 * print(myDictionary.hasKey('p5')); // prints 'true' 60071 * myDictionary.clear(); 60072 * print(myDictionary.hasKey('p5')); // prints 'false' 60073 * } 60074 * </code> 60075 * </div> 60076 */ 60077 60078 _main.default.TypedDict.prototype.clear = function() { 60079 this.data = {}; 60080 }; 60081 60082 /** 60083 * Removes the key-value pair stored at the given key from the Dictionary. 60084 * 60085 * @method remove 60086 * @param {Number|String} key for the pair to remove 60087 * 60088 * @example 60089 * <div class="norender"> 60090 * <code> 60091 * function setup() { 60092 * let myDictionary = createStringDict('p5', 'js'); 60093 * myDictionary.create('happy', 'coding'); 60094 * myDictionary.print(); 60095 * // above logs "key: p5 - value: js, key: happy - value: coding" to console 60096 * myDictionary.remove('p5'); 60097 * myDictionary.print(); 60098 * // above logs "key: happy value: coding" to console 60099 * } 60100 * </code></div> 60101 */ 60102 60103 _main.default.TypedDict.prototype.remove = function(key) { 60104 if (this.data.hasOwnProperty(key)) { 60105 delete this.data[key]; 60106 } else { 60107 throw new Error(''.concat(key, ' does not exist in this Dictionary')); 60108 } 60109 }; 60110 60111 /** 60112 * Logs the set of items currently stored in the Dictionary to the console. 60113 * 60114 * @method print 60115 * 60116 * @example 60117 * <div class="norender"> 60118 * <code> 60119 * function setup() { 60120 * let myDictionary = createStringDict('p5', 'js'); 60121 * myDictionary.create('happy', 'coding'); 60122 * myDictionary.print(); 60123 * // above logs "key: p5 - value: js, key: happy - value: coding" to console 60124 * } 60125 * </code> 60126 * </div> 60127 */ 60128 60129 _main.default.TypedDict.prototype.print = function() { 60130 for (var item in this.data) { 60131 console.log('key:'.concat(item, ' value:').concat(this.data[item])); 60132 } 60133 }; 60134 60135 /** 60136 * Converts the Dictionary into a CSV file for local download. 60137 * 60138 * @method saveTable 60139 * @example 60140 * <div> 60141 * <code> 60142 * function setup() { 60143 * createCanvas(100, 100); 60144 * background(200); 60145 * text('click here to save', 10, 10, 70, 80); 60146 * } 60147 * 60148 * function mousePressed() { 60149 * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) { 60150 * createStringDict({ 60151 * john: 1940, 60152 * paul: 1942, 60153 * george: 1943, 60154 * ringo: 1940 60155 * }).saveTable('beatles'); 60156 * } 60157 * } 60158 * </code> 60159 * </div> 60160 */ 60161 60162 _main.default.TypedDict.prototype.saveTable = function(filename) { 60163 var output = ''; 60164 60165 for (var key in this.data) { 60166 output += ''.concat(key, ',').concat(this.data[key], '\n'); 60167 } 60168 60169 var blob = new Blob([output], { type: 'text/csv' }); 60170 _main.default.prototype.downloadFile(blob, filename || 'mycsv', 'csv'); 60171 }; 60172 60173 /** 60174 * Converts the Dictionary into a JSON file for local download. 60175 * 60176 * @method saveJSON 60177 * @example 60178 * <div> 60179 * <code> 60180 * function setup() { 60181 * createCanvas(100, 100); 60182 * background(200); 60183 * text('click here to save', 10, 10, 70, 80); 60184 * } 60185 * 60186 * function mousePressed() { 60187 * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) { 60188 * createStringDict({ 60189 * john: 1940, 60190 * paul: 1942, 60191 * george: 1943, 60192 * ringo: 1940 60193 * }).saveJSON('beatles'); 60194 * } 60195 * } 60196 * </code> 60197 * </div> 60198 */ 60199 60200 _main.default.TypedDict.prototype.saveJSON = function(filename, opt) { 60201 _main.default.prototype.saveJSON(this.data, filename, opt); 60202 }; 60203 60204 /** 60205 * private helper function to ensure that the user passed in valid 60206 * values for the Dictionary type 60207 */ 60208 60209 _main.default.TypedDict.prototype._validate = function(value) { 60210 return true; 60211 }; 60212 60213 /** 60214 * 60215 * A simple Dictionary class for Strings. 60216 * 60217 * @class p5.StringDict 60218 * @extends p5.TypedDict 60219 */ 60220 60221 _main.default.StringDict = function() { 60222 for ( 60223 var _len = arguments.length, args = new Array(_len), _key = 0; 60224 _key < _len; 60225 _key++ 60226 ) { 60227 args[_key] = arguments[_key]; 60228 } 60229 _main.default.TypedDict.apply(this, args); 60230 }; 60231 60232 _main.default.StringDict.prototype = Object.create( 60233 _main.default.TypedDict.prototype 60234 ); 60235 60236 _main.default.StringDict.prototype._validate = function(value) { 60237 return typeof value === 'string'; 60238 }; 60239 60240 /** 60241 * 60242 * A simple Dictionary class for Numbers. 60243 * 60244 * @class p5.NumberDict 60245 * @constructor 60246 * @extends p5.TypedDict 60247 */ 60248 60249 _main.default.NumberDict = function() { 60250 for ( 60251 var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; 60252 _key2 < _len2; 60253 _key2++ 60254 ) { 60255 args[_key2] = arguments[_key2]; 60256 } 60257 _main.default.TypedDict.apply(this, args); 60258 }; 60259 60260 _main.default.NumberDict.prototype = Object.create( 60261 _main.default.TypedDict.prototype 60262 ); 60263 60264 /** 60265 * private helper function to ensure that the user passed in valid 60266 * values for the Dictionary type 60267 */ 60268 60269 _main.default.NumberDict.prototype._validate = function(value) { 60270 return typeof value === 'number'; 60271 }; 60272 60273 /** 60274 * Add the given number to the value currently stored at the given key. 60275 * The sum then replaces the value previously stored in the Dictionary. 60276 * 60277 * @method add 60278 * @param {Number} Key for the value you wish to add to 60279 * @param {Number} Number to add to the value 60280 * @example 60281 * <div class='norender'> 60282 * <code> 60283 * function setup() { 60284 * let myDictionary = createNumberDict(2, 5); 60285 * myDictionary.add(2, 2); 60286 * print(myDictionary.get(2)); // logs 7 to console. 60287 * } 60288 * </code></div> 60289 * 60290 */ 60291 60292 _main.default.NumberDict.prototype.add = function(key, amount) { 60293 if (this.data.hasOwnProperty(key)) { 60294 this.data[key] += amount; 60295 } else { 60296 console.log('The key - '.concat(key, ' does not exist in this dictionary.')); 60297 } 60298 }; 60299 60300 /** 60301 * Subtract the given number from the value currently stored at the given key. 60302 * The difference then replaces the value previously stored in the Dictionary. 60303 * 60304 * @method sub 60305 * @param {Number}
60305 Key for the value you wish to subtract from 60306 * @param {Number} Number to subtract from the value 60307 * @example 60308 * <div class='norender'> 60309 * <code> 60310 * function setup() { 60311 * let myDictionary = createNumberDict(2, 5); 60312 * myDictionary.sub(2, 2); 60313 * print(myDictionary.get(2)); // logs 3 to console. 60314 * } 60315 * </code></div> 60316 * 60317 */ 60318 60319 _main.default.NumberDict.prototype.sub = function(key, amount) { 60320 this.add(key, -amount); 60321 }; 60322 60323 /** 60324 * Multiply the given number with the value currently stored at the given key. 60325 * The product then replaces the value previously stored in the Dictionary. 60326 * 60327 * @method mult 60328 * @param {Number} Key for value you wish to multiply 60329 * @param {Number} Amount to multiply the value by 60330 * @example 60331 * <div class='norender'> 60332 * <code> 60333 * function setup() { 60334 * let myDictionary = createNumberDict(2, 4); 60335 * myDictionary.mult(2, 2); 60336 * print(myDictionary.get(2)); // logs 8 to console. 60337 * } 60338 * </code></div> 60339 * 60340 */ 60341 60342 _main.default.NumberDict.prototype.mult = function(key, amount) { 60343 if (this.data.hasOwnProperty(key)) { 60344 this.data[key] *= amount; 60345 } else { 60346 console.log('The key - '.concat(key, ' does not exist in this dictionary.')); 60347 } 60348 }; 60349 60350 /** 60351 * Divide the given number with the value currently stored at the given key. 60352 * The quotient then replaces the value previously stored in the Dictionary. 60353 * 60354 * @method div 60355 * @param {Number} Key for value you wish to divide 60356 * @param {Number} Amount to divide the value by 60357 * @example 60358 * <div class='norender'> 60359 * <code> 60360 * function setup() { 60361 * let myDictionary = createNumberDict(2, 8); 60362 * myDictionary.div(2, 2); 60363 * print(myDictionary.get(2)); // logs 4 to console. 60364 * } 60365 * </code></div> 60366 * 60367 */ 60368 60369 _main.default.NumberDict.prototype.div = function(key, amount) { 60370 if (this.data.hasOwnProperty(key)) { 60371 this.data[key] /= amount; 60372 } else { 60373 console.log('The key - '.concat(key, ' does not exist in this dictionary.')); 60374 } 60375 }; 60376 60377 /** 60378 * private helper function for finding lowest or highest value 60379 * the argument 'flip' is used to flip the comparison arrow 60380 * from 'less than' to 'greater than' 60381 */ 60382 60383 _main.default.NumberDict.prototype._valueTest = function(flip) { 60384 if (Object.keys(this.data).length === 0) { 60385 throw new Error( 60386 'Unable to search for a minimum or maximum value on an empty NumberDict' 60387 ); 60388 } else if (Object.keys(this.data).length === 1) { 60389 return this.data[Object.keys(this.data)[0]]; 60390 } else { 60391 var result = this.data[Object.keys(this.data)[0]]; 60392 for (var key in this.data) { 60393 if (this.data[key] * flip < result * flip) { 60394 result = this.data[key]; 60395 } 60396 } 60397 return result; 60398 } 60399 }; 60400 60401 /** 60402 * Return the lowest number currently stored in the Dictionary. 60403 * 60404 * @method minValue 60405 * @return {Number} 60406 * @example 60407 * <div class='norender'> 60408 * <code> 60409 * function setup() { 60410 * let myDictionary = createNumberDict({ 2: -10, 4: 0.65, 1.2: 3 }); 60411 * let lowestValue = myDictionary.minValue(); // value is -10 60412 * print(lowestValue); 60413 * } 60414 * </code></div> 60415 */ 60416 60417 _main.default.NumberDict.prototype.minValue = function() { 60418 return this._valueTest(1); 60419 }; 60420 60421 /** 60422 * Return the highest number currently stored in the Dictionary. 60423 * 60424 * @method maxValue 60425 * @return {Number} 60426 * @example 60427 * <div class='norender'> 60428 * <code> 60429 * function setup() { 60430 * let myDictionary = createNumberDict({ 2: -10, 4: 0.65, 1.2: 3 }); 60431 * let highestValue = myDictionary.maxValue(); // value is 3 60432 * print(highestValue); 60433 * } 60434 * </code></div> 60435 */ 60436 60437 _main.default.NumberDict.prototype.maxValue = function() { 60438 return this._valueTest(-1); 60439 }; 60440 60441 /** 60442 * private helper function for finding lowest or highest key 60443 * the argument 'flip' is used to flip the comparison arrow 60444 * from 'less than' to 'greater than' 60445 */ 60446 60447 _main.default.NumberDict.prototype._keyTest = function(flip) { 60448 if (Object.keys(this.data).length === 0) { 60449 throw new Error('Unable to use minValue on an empty NumberDict'); 60450 } else if (Object.keys(this.data).length === 1) { 60451 return Object.keys(this.data)[0]; 60452 } else { 60453 var result = Object.keys(this.data)[0]; 60454 for (var i = 1; i < Object.keys(this.data).length; i++) { 60455 if (Object.keys(this.data)[i] * flip < result * flip) { 60456 result = Object.keys(this.data)[i]; 60457 } 60458 } 60459 return result; 60460 } 60461 }; 60462 60463 /** 60464 * Return the lowest key currently used in the Dictionary. 60465 * 60466 * @method minKey 60467 * @return {Number} 60468 * @example 60469 * <div class='norender'> 60470 * <code> 60471 * function setup() { 60472 * let myDictionary = createNumberDict({ 2: 4, 4: 6, 1.2: 3 }); 60473 * let lowestKey = myDictionary.minKey(); // value is 1.2 60474 * print(lowestKey); 60475 * } 60476 * </code></div> 60477 */ 60478 60479 _main.default.NumberDict.prototype.minKey = function() { 60480 return this._keyTest(1); 60481 }; 60482 60483 /** 60484 * Return the highest key currently used in the Dictionary. 60485 * 60486 * @method maxKey 60487 * @return {Number} 60488 * @example 60489 * <div class='norender'> 60490 * <code> 60491 * function setup() { 60492 * let myDictionary = createNumberDict({ 2: 4, 4: 6, 1.2: 3 }); 60493 * let highestKey = myDictionary.maxKey(); // value is 4 60494 * print(highestKey); 60495 * } 60496 * </code></div> 60497 */ 60498 60499 _main.default.NumberDict.prototype.maxKey = function() { 60500 return this._keyTest(-1); 60501 }; 60502 var _default = _main.default.TypedDict; 60503 exports.default = _default; 60504 }, 60505 { '../core/main': 59 } 60506 ], 60507 75: [
60508 function(_dereq_, module, exports) { 60509 'use strict'; 60510 Object.defineProperty(exports, '__esModule', { value: true }); 60511 exports.default = void 0; 60512 60513 var _main = _interopRequireDefault(_dereq_('../core/main')); 60514 function _interopRequireDefault(obj) { 60515 return obj && obj.__esModule ? obj : { default: obj }; 60516 } 60517 function _typeof(obj) { 60518 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') { 60519 _typeof = function _typeof(obj) { 60520 return typeof obj; 60521 }; 60522 } else { 60523 _typeof = function _typeof(obj) { 60524 return obj && 60525 typeof Symbol === 'function' && 60526 obj.constructor === Symbol && 60527 obj !== Symbol.prototype 60528 ? 'symbol' 60529 : typeof obj; 60530 }; 60531 } 60532 return _typeof(obj); 60533 } 60534 60535 /** 60536 * Searches the page for the first element that matches the given CSS selector string (can be an 60537 * ID, class, tag name or a combination) and returns it as a <a href="#/p5.Element">p5.Element</a>. 60538 * The DOM node itself can be accessed with .elt. 60539 * Returns null if none found. You can also specify a container to search within. 60540 * 60541 * @method select 60542 * @param {String} selectors CSS selector string of element to search for 60543 * @param {String|p5.Element|HTMLElement} [container] CSS selector string, <a href="#/p5.Element">p5.Element</a>, or 60544 * HTML element to search within 60545 * @return {p5.Element|null} <a href="#/p5.Element">p5.Element</a> containing node found 60546 * @example 60547 * <div><code> 60548 * function setup() { 60549 * createCanvas(50, 50); 60550 * background(30); 60551 * // move canvas down and right 60552 * select('canvas').position(10, 30); 60553 * } 60554 * </code></div> 60555 * 60556 * <div class="norender"><code> 60557 * // select using ID 60558 * let a = select('#container'); 60559 * let b = select('#beep', '#container'); 60560 * let c; 60561 * if (a) { 60562 * // select using class 60563 * c = select('.boop', a); 60564 * } 60565 * // select using CSS selector string 60566 * let d = select('#container #bleep'); 60567 * let e = select('#container p'); 60568 * [a, b, c, d, e]; // unused 60569 * </code></div> 60570 */ 60571 _main.default.prototype.select = function(e, p) { 60572 _main.default._validateParameters('select', arguments); 60573 var container = this._getContainer(p); 60574 var res = container.querySelector(e); 60575 if (res) { 60576 return this._wrapElement(res); 60577 } else { 60578 return null; 60579 } 60580 }; 60581 60582 /** 60583 * Searches the page for elements that match the given CSS selector string (can be an ID a class, 60584 * tag name or a combination) and returns them as <a href="#/p5.Element">p5.Element</a>s in 60585 * an array. 60586 * The DOM node itself can be accessed with .elt. 60587 * Returns an empty array if none found. 60588 * You can also specify a container to search within. 60589 * 60590 * @method selectAll 60591 * @param {String} selectors CSS selector string of elements to search for 60592 * @param {String|p5.Element|HTMLElement} [container] CSS selector string, <a href="#/p5.Element">p5.Element</a> 60593 * , or HTML element to search within 60594 * @return {p5.Element[]} Array of <a href="#/p5.Element">p5.Element</a>s containing nodes found 60595 * @example 60596 * <div class='norender'><code> 60597 * function setup() { 60598 * createButton('btn'); 60599 * createButton('2nd btn'); 60600 * createButton('3rd btn'); 60601 * let buttons = selectAll('button'); 60602 * 60603 * for (let i = 0; i < buttons.length; i++) { 60604 * buttons[i].size(100, 100); 60605 * } 60606 * } 60607 * </code></div> 60608 * <div class='norender'><code> 60609 * // these are all valid calls to selectAll() 60610 * let a = selectAll('.beep'); 60611 * a = selectAll('div'); 60612 * a = selectAll('button', '#container'); 60613 * 60614 * let b = createDiv(); 60615 * b.id('container'); 60616 * let c = select('#container'); 60617 * a = selectAll('p', c); 60618 * a = selectAll('#container p'); 60619 * 60620 * let d = document.getElementById('container'); 60621 * a = selectAll('.boop', d); 60622 * a = selectAll('#container .boop'); 60623 * console.log(a); 60624 * </code></div> 60625 */ 60626 _main.default.prototype.selectAll = function(e, p) { 60627 _main.default._validateParameters('selectAll', arguments); 60628 var arr = []; 60629 var container = this._getContainer(p); 60630 var res = container.querySelectorAll(e); 60631 if (res) { 60632 for (var j = 0; j < res.length; j++) { 60633 var obj = this._wrapElement(res[j]); 60634 arr.push(obj); 60635 } 60636 } 60637 return arr; 60638 }; 60639 60640 /** 60641 * Helper function for select and selectAll 60642 */ 60643 _main.default.prototype._getContainer = function(p) { 60644 var container = document; 60645 if (typeof p === 'string') { 60646 container = document.querySelector(p) || document; 60647 } else if (p instanceof _main.default.Element) { 60648 container = p.elt; 60649 } else if (p instanceof HTMLElement) { 60650 container = p; 60651 } 60652 return container; 60653 }; 60654 60655 /** 60656 * Helper function for getElement and getElements. 60657 */ 60658 _main.default.prototype._wrapElement = function(elt) { 60659 var children = Array.prototype.slice.call(elt.children); 60660 if (elt.tagName === 'INPUT' && elt.type === 'checkbox') { 60661 var converted = new _main.default.Element(elt, this); 60662 converted.checked = function() { 60663 if (arguments.length === 0) { 60664 return this.elt.checked; 60665 } else if (arguments[0]) { 60666 this.elt.checked = true; 60667 } else { 60668 this.elt.checked = false;
60669 } 60670 return this; 60671 }; 60672 return converted; 60673 } else if (elt.tagName === 'VIDEO' || elt.tagName === 'AUDIO') { 60674 return new _main.default.MediaElement(elt, this); 60675 } else if (elt.tagName === 'SELECT') { 60676 return this.createSelect(new _main.default.Element(elt, this)); 60677 } else if ( 60678 children.length > 0 && 60679 children.every(function(c) { 60680 return c.tagName === 'INPUT' || c.tagName === 'LABEL'; 60681 }) 60682 ) { 60683 return this.createRadio(new _main.default.Element(elt, this)); 60684 } else { 60685 return new _main.default.Element(elt, this); 60686 } 60687 }; 60688 60689 /** 60690 * Removes all elements created by p5, except any canvas / graphics 60691 * elements created by <a href="#/p5/createCanvas">createCanvas</a> or <a href="#/p5/createGraphics">createGraphics</a>. 60692 * Event handlers are removed, and element is removed from the DOM. 60693 * @method removeElements 60694 * @example 60695 * <div class='norender'><code> 60696 * function setup() { 60697 * createCanvas(100, 100); 60698 * createDiv('this is some text'); 60699 * createP('this is a paragraph'); 60700 * } 60701 * function mousePressed() { 60702 * removeElements(); // this will remove the div and p, not canvas 60703 * } 60704 * </code></div> 60705 */ 60706 _main.default.prototype.removeElements = function(e) { 60707 _main.default._validateParameters('removeElements', arguments); 60708 // el.remove splices from this._elements, so don't mix iteration with it 60709 var isNotCanvasElement = function isNotCanvasElement(el) { 60710 return !(el.elt instanceof HTMLCanvasElement); 60711 }; 60712 var removeableElements = this._elements.filter(isNotCanvasElement); 60713 removeableElements.map(function(el) { 60714 return el.remove(); 60715 }); 60716 }; 60717 60718 /** 60719 * The .<a href="#/p5.Element/changed">changed()</a> function is called when the value of an 60720 * element changes. 60721 * This can be used to attach an element specific event listener. 60722 * 60723 * @method changed 60724 * @param {Function|Boolean} fxn function to be fired when the value of 60725 * an element changes. 60726 * if `false` is passed instead, the previously 60727 * firing function will no longer fire. 60728 * @chainable 60729 * @example 60730 * <div><code> 60731 * let sel; 60732 * 60733 * function setup() { 60734 * textAlign(CENTER); 60735 * background(200); 60736 * sel = createSelect(); 60737 * sel.position(10, 10); 60738 * sel.option('pear'); 60739 * sel.option('kiwi'); 60740 * sel.option('grape'); 60741 * sel.changed(mySelectEvent); 60742 * } 60743 * 60744 * function mySelectEvent() { 60745 * let item = sel.value(); 60746 * background(200); 60747 * text("it's a " + item + '!', 50, 50); 60748 * } 60749 * </code></div> 60750 * 60751 * <div><code> 60752 * let checkbox; 60753 * let cnv; 60754 * 60755 * function setup() { 60756 * checkbox = createCheckbox(' fill'); 60757 * checkbox.changed(changeFill); 60758 * cnv = createCanvas(100, 100); 60759 * cnv.position(0, 30); 60760 * noFill(); 60761 * } 60762 * 60763 * function draw() { 60764 * background(200); 60765 * ellipse(50, 50, 50, 50); 60766 * } 60767 * 60768 * function changeFill() { 60769 * if (checkbox.checked()) { 60770 * fill(0); 60771 * } else { 60772 * noFill(); 60773 * } 60774 * } 60775 * </code></div> 60776 * 60777 * @alt 60778 * dropdown: pear, kiwi, grape. When selected text "its a" + selection shown.
60779 */ 60780 _main.default.Element.prototype.changed = function(fxn) { 60781 _main.default.Element._adjustListener('change', fxn, this); 60782 return this; 60783 }; 60784 60785 /** 60786 * The .<a href="#/p5.Element/input">input()</a> function is called when any user input is 60787 * detected with an element. The input event is often used 60788 * to detect keystrokes in a input element, or changes on a 60789 * slider element. This can be used to attach an element specific 60790 * event listener. 60791 * 60792 * @method input 60793 * @param {Function|Boolean} fxn function to be fired when any user input is 60794 * detected within the element. 60795 * if `false` is passed instead, the previously 60796 * firing function will no longer fire. 60797 * @chainable 60798 * @example 60799 * <div class='norender'><code> 60800 * // Open your console to see the output 60801 * function setup() { 60802 * let inp = createInput(''); 60803 * inp.input(myInputEvent); 60804 * } 60805 * 60806 * function myInputEvent() { 60807 * console.log('you are typing: ', this.value()); 60808 * } 60809 * </code></div> 60810 * 60811 * @alt 60812 * no display. 60813 */ 60814 _main.default.Element.prototype.input = function(fxn) { 60815 _main.default.Element._adjustListener('input', fxn, this); 60816 return this; 60817 }; 60818 60819 /** 60820 * Helpers for create methods. 60821 */ 60822 function addElement(elt, pInst, media) { 60823 var node = pInst._userNode ? pInst._userNode : document.body; 60824 node.appendChild(elt); 60825 var c = media 60826 ? new _main.default.MediaElement(elt, pInst) 60827 : new _main.default.Element(elt, pInst); 60828 pInst._elements.push(c); 60829 return c; 60830 } 60831 60832 /** 60833 * Creates a `<div></div>` element in the DOM with given inner HTML. 60834 * 60835 * @method createDiv 60836 * @param {String} [html] inner HTML for element created 60837 * @return {p5.Element} pointer to <a href="#/p5.Element">p5.Element</a> holding created node 60838 * @example 60839 * <div class='norender'><code> 60840 * createDiv('this is some text'); 60841 * </code></div> 60842 */ 60843 _main.default.prototype.createDiv = function() { 60844 var html = 60845 arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; 60846 var elt = document.createElement('div'); 60847 elt.innerHTML = html; 60848 return addElement(elt, this); 60849 }; 60850 60851 /** 60852 * Creates a `<p></p>` element in the DOM with given inner HTML. Used 60853 * for paragraph length text. 60854 * 60855 * @method createP 60856 * @param {String} [html] inner HTML for element created 60857 * @return {p5.Element} pointer to <a href="#/p5.Element">p5.Element</a> holding created node 60858 * @example 60859 * <div class='norender'><code> 60860 * createP('this is some text'); 60861 * </code></div> 60862 */ 60863 _main.default.prototype.createP = function() { 60864 var html = 60865 arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; 60866 var elt = document.createElement('p'); 60867 elt.innerHTML = html; 60868 return addElement(elt, this); 60869 }; 60870 60871 /** 60872 * Creates a `<span></span>` element in the DOM with given inner HTML. 60873 * 60874 * @method createSpan 60875 * @param {String} [html] inner HTML for element created 60876 * @return {p5.Element} pointer to <a href="#/p5.Element">p5.Element</a> holding created node 60877 * @example 60878 * <div class='norender'><code> 60879 * createSpan('this is some text'); 60880 * </code></div> 60881 */ 60882 _main.default.prototype.createSpan = function() { 60883 var html = 60884 arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; 60885 var elt = document.createElement('span'); 60886 elt.innerHTML = html; 60887 return addElement(elt, this); 60888 }; 60889 60890 /** 60891 * Creates an `<img>` element in the DOM with given src and 60892 * alternate text. 60893 * 60894 * @method createImg 60895 * @param {String} src src path or url for image 60896 * @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. 60897 * @return {p5.Element} pointer to <a href="#/p5.Element">p5.Element</a> holding created node 60898 * @example 60899 * <div class='norender'><code> 60900 * createImg( 60901 * 'https://p5js.org/assets/img/asterisk-01.png', 60902 * 'the p5 magenta asterisk' 60903 * ); 60904 * </code></div> 60905 */ 60906 /** 60907 * @method createImg 60908 * @param {String} src 60909 * @param {String} alt 60910 * @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 60911 * @param {Function} [successCallback] callback to be called once image data is loaded with the <a href="#/p5.Element">p5.Element</a> as argument 60912 * @return {p5.Element} pointer to <a href="#/p5.Element">p5.Element</a> holding created node 60913 */ 60914 _main.default.prototype.createImg = function() { 60915 _main.default._validateParameters('createImg', arguments); 60916 var elt = document.createElement('img'); 60917 var args = arguments; 60918 var self; 60919 if (args.length > 1 && typeof args[1] === 'string') { 60920 elt.alt = args[1]; 60921 } 60922 if (args.length > 2 && typeof args[2] === 'string') { 60923 elt.crossOrigin = args[2]; 60924 } 60925 elt.src = args[0]; 60926 self = addElement(elt, this); 60927 elt.addEventListener('load', function() { 60928 self.width = elt.offsetWidth || elt.width; 60929 self.height = elt.offsetHeight || elt.height; 60930 var last = args[args.length - 1]; 60931 if (typeof last === 'function') last(self); 60932 }); 60933 return self; 60934 }; 60935 60936 /** 60937 * Creates an `<a></a>` element in the DOM for including a hyperlink. 60938 * 60939 * @method createA 60940 * @param {String} href url of page to link to 60941 * @param {String} html inner html of link element to display 60942 * @param {String} [target] target where new link should open, 60943 * could be _blank, _self, _parent, _top. 60944 * @return {p5.Element} pointer to <a href="#/p5.Element">p5.Element</a> holding created node 60945 * @example 60946 * <div class='norender'><code> 60947 * createA('http://p5js.org/', 'this is a link'); 60948 * </code></div> 60949 */ 60950 _main.default.prototype.createA = function(href, html, target) { 60951 _main.default._validateParameters('createA', arguments); 60952 var elt = document.createElement('a'); 60953 elt.href = href; 60954 elt.innerHTML = html; 60955 if (target) elt.target = target; 60956 return addElement(elt, this); 60957 }; 60958 60959 /** INPUT **/ 60960 60961 /** 60962 * Creates a slider `<input></input>` element in the DOM. 60963 * Use .size() to set the display length of the slider. 60964 * 60965 * @method createSlider 60966 * @param {Number} min minimum value of the slider 60967 * @param {Number} max maximum value of the slider 60968 * @param {Number} [value] default value of the slider 60969 * @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) 60970 * @return {p5.Element} pointer to <a href="#/p5.Element">p5.Element</a> holding created node 60971 * @example 60972 * <div><code> 60973 * let slider; 60974 * function setup() { 60975 * slider = createSlider(0, 255, 100); 60976 * slider.position(10, 10); 60977 * slider.style('width', '80px'); 60978 * } 60979 * 60980 * function draw() { 60981 * let val = slider.value(); 60982 * background(val); 60983 * } 60984 * </code></div> 60985 * 60986 * <div><code> 60987 * let slider; 60988 * function setup() { 60989 * colorMode(HSB); 60990 * slider = createSlider(0, 360, 60, 40); 60991 * slider.position(10, 10); 60992 * slider.style('width', '80px'); 60993 * } 60994 * 60995 * function draw() { 60996 * let val = slider.value();
60997 * background(val, 100, 100, 1); 60998 * } 60999 * </code></div> 61000 */ 61001 _main.default.prototype.createSlider = function(min, max, value, step) { 61002 _main.default._validateParameters('createSlider', arguments); 61003 var elt = document.createElement('input'); 61004 elt.type = 'range'; 61005 elt.min = min; 61006 elt.max = max; 61007 if (step === 0) { 61008 elt.step = 0.000000000000000001; // smallest valid step 61009 } else if (step) { 61010 elt.step = step; 61011 } 61012 if (typeof value === 'number') elt.value = value; 61013 return addElement(elt, this); 61014 }; 61015 61016 /** 61017 * Creates a `<button></button>` element in the DOM. 61018 * Use .size() to set the display size of the button. 61019 * Use .mousePressed() to specify behavior on press. 61020 * 61021 * @method createButton 61022 * @param {String} label label displayed on the button 61023 * @param {String} [value] value of the button 61024 * @return {p5.Element} pointer to <a href="#/p5.Element">p5.Element</a> holding created node 61025 * @example 61026 * <div class='norender'><code> 61027 * let button; 61028 * function setup() { 61029 * createCanvas(100, 100); 61030 * background(0); 61031 * button = createButton('click me'); 61032 * button.position(19, 19); 61033 * button.mousePressed(changeBG); 61034 * } 61035 * 61036 * function changeBG() { 61037 * let val = random(255); 61038 * background(val); 61039 * } 61040 * </code></div> 61041 */ 61042 _main.default.prototype.createButton = function(label, value) { 61043 _main.default._validateParameters('createButton', arguments); 61044 var elt = document.createElement('button'); 61045 elt.innerHTML = label; 61046 if (value) elt.value = value; 61047 return addElement(elt, this); 61048 }; 61049 61050 /** 61051 * Creates a checkbox `<input></input>` element in the DOM. 61052 * Calling .checked() on a checkbox returns if it is checked or not 61053 * 61054 * @method createCheckbox 61055 * @param {String} [label] label displayed after checkbox 61056 * @param {boolean} [value] value of the checkbox; checked is true, unchecked is false 61057 * @return {p5.Element} pointer to <a href="#/p5.Element">p5.Element</a> holding created node 61058 * @example 61059 * <div class='norender'><code> 61060 * let checkbox; 61061 * 61062 * function setup() { 61063 * checkbox = createCheckbox('label', false); 61064 * checkbox.changed(myCheckedEvent); 61065 * } 61066 * 61067 * function myCheckedEvent() { 61068 * if (this.checked()) { 61069 * console.log('Checking!'); 61070 * } else { 61071 * console.log('Unchecking!'); 61072 * } 61073 * } 61074 * </code></div> 61075 */ 61076 _main.default.prototype.createCheckbox = function() { 61077 _main.default._validateParameters('createCheckbox', arguments); 61078 var elt = document.createElement('div'); 61079 var checkbox = document.createElement('input'); 61080 checkbox.type = 'checkbox'; 61081 elt.appendChild(checkbox); 61082 //checkbox must be wrapped in p5.Element before label so that label appears after 61083 var self = addElement(elt, this); 61084 self.checked = function() { 61085 var cb = self.elt.getElementsByTagName('input')[0]; 61086 if (cb) { 61087 if (arguments.length === 0) { 61088 return cb.checked; 61089 } else if (arguments[0]) { 61090 cb.checked = true; 61091 } else { 61092 cb.checked = false; 61093 } 61094 } 61095 return self; 61096 }; 61097 this.value = function(val) { 61098 self.value = val; 61099 return this; 61100 }; 61101 if (arguments[0]) { 61102 var ran = Math.random() 61103 .toString(36) 61104 .slice(2); 61105 var label = document.createElement('label'); 61106 checkbox.setAttribute('id', ran); 61107 label.htmlFor = ran; 61108 self.value(arguments[0]); 61109 label.appendChild(document.createTextNode(arguments[0])); 61110 elt.appendChild(label); 61111 } 61112 if (arguments[1]) { 61113 checkbox.checked = true; 61114 } 61115 return self; 61116 }; 61117 61118 /** 61119 * Creates a dropdown menu `<select></select>` element in the DOM. 61120 * It also helps to assign select-box methods to <a href="#/p5.Element">p5.Element</a> when selecting existing select box. 61121 * - `.option(name, [value])` can be used to set options for the select after it is created. 61122 * - `.value()` will return the currently selected option. 61123 * - `.selected()` will return current dropdown element which is an instance of <a href="#/p5.Element">p5.Element</a> 61124 * - `.selected(value)` can be used to make given option selected by default when the page first loads. 61125 * - `.disable()` marks whole of dropdown element as disabled. 61126 * - `.disable(value)` marks given option as disabled 61127 * 61128 * @method createSelect 61129 * @param {boolean} [multiple] true if dropdown should support multiple selections 61130 * @return {p5.Element} 61131 * @example 61132 * <div><code> 61133 * let sel; 61134 * 61135 * function setup() { 61136 * textAlign(CENTER); 61137 * background(200); 61138 * sel = createSelect(); 61139 * sel.position(10, 10); 61140 * sel.option('pear'); 61141 * sel.option('kiwi'); 61142 * sel.option('grape'); 61143 * sel.selected('kiwi'); 61144 * sel.changed(mySelectEvent); 61145 * } 61146 * 61147 * function mySelectEvent() { 61148 * let item = sel.value(); 61149 * background(200); 61150 * text('It is a ' + item + '!', 50, 50); 61151 * } 61152 * </code></div> 61153 * 61154 * <div><code> 61155 * let sel; 61156 * 61157 * function setup() { 61158 * textAlign(CENTER); 61159 * background(200); 61160 * sel = createSelect(); 61161 * sel.position(10, 10); 61162 * sel.option('oil'); 61163 * sel.option('milk'); 61164 * sel.option('bread'); 61165 * sel.disable('milk'); 61166 * } 61167 * </code></div> 61168 */ 61169 /** 61170 * @method createSelect 61171 * @param {Object} existing DOM select element 61172 * @return {p5.Element} 61173 */ 61174 61175 _main.default.prototype.createSelect = function() { 61176 _main.default._validateParameters('createSelect', arguments); 61177 var self; 61178 var arg = arguments[0]; 61179 if ( 61180 arg instanceof _main.default.Element && 61181 arg.elt instanceof HTMLSelectElement 61182 ) { 61183 // If given argument is p5.Element of select type 61184 self = arg; 61185 this.elt = arg.elt; 61186 } else if (arg instanceof HTMLSelectElement) { 61187 self = addElement(arg, this); 61188 this.elt = arg; 61189 } else { 61190 var elt = document.createElement('select'); 61191 if (arg && typeof arg === 'boolean') { 61192 elt.setAttribute('multiple', 'true'); 61193 } 61194 self = addElement(elt, this); 61195 this.elt = elt; 61196 } 61197 self.option = function(name, value) { 61198 var index; 61199
61200 // if no name is passed, return 61201 if (name === undefined) { 61202 return; 61203 } 61204 //see if there is already an option with this name 61205 for (var i = 0; i < this.elt.length; i += 1) { 61206 if (this.elt[i].innerHTML === name) { 61207 index = i; 61208 break; 61209 } 61210 } 61211 //if there is an option with this name we will modify it 61212 if (index !== undefined) { 61213 //if the user passed in false then delete that option 61214 if (value === false) { 61215 this.elt.remove(index); 61216 } else { 61217 // Update the option at index with the value 61218 this.elt[index].value = value; 61219 } 61220 } else { 61221 //if it doesn't exist create it 61222 var opt = document.createElement('option'); 61223 opt.innerHTML = name; 61224 opt.value = value === undefined ? name : value; 61225 this.elt.appendChild(opt); 61226 this._pInst._elements.push(opt); 61227 } 61228 }; 61229 61230 self.selected = function(value) { 61231 // Update selected status of option 61232 if (value !== undefined) { 61233 for (var i = 0; i < this.elt.length; i += 1) { 61234 if (this.elt[i].value.toString() === value.toString()) { 61235 this.elt.selectedIndex = i; 61236 } 61237 } 61238 return this; 61239 } else { 61240 if (this.elt.getAttribute('multiple')) { 61241 var arr = []; 61242 var _iteratorNormalCompletion = true; 61243 var _didIteratorError = false; 61244 var _iteratorError = undefined; 61245 try { 61246 for ( 61247 var _iterator = this.elt.selectedOptions[Symbol.iterator](), _step; 61248 !(_iteratorNormalCompletion = (_step = _iterator.next()).done); 61249 _iteratorNormalCompletion = true 61250 ) { 61251 var selectedOption = _step.value; 61252 arr.push(selectedOption.value); 61253 } 61254 } catch (err) { 61255 _didIteratorError = true; 61256 _iteratorError = err; 61257 } finally { 61258 try { 61259 if (!_iteratorNormalCompletion && _iterator.return != null) { 61260 _iterator.return(); 61261 } 61262 } finally { 61263 if (_didIteratorError) { 61264 throw _iteratorError; 61265 } 61266 } 61267 } 61268 return arr; 61269 } else { 61270 return this.elt.value; 61271 } 61272 } 61273 }; 61274 61275 self.disable = function(value) { 61276 if (typeof value === 'string') { 61277 for (var i = 0; i < this.elt.length; i++) { 61278 if (this.elt[i].value.toString() === value) { 61279 this.elt[i].disabled = true; 61280 this.elt[i].selected = false; 61281 } 61282 } 61283 } else { 61284 this.elt.disabled = true; 61285 } 61286 return this; 61287 }; 61288 61289 return self; 61290 }; 61291 61292 /** 61293 * Creates a radio button element in the DOM.It also helps existing radio buttons 61294 * assign methods of <a href="#/p5.Element/">p5.Element</a>. 61295 * - `.option(value, [label])` can be used to create a new option for the 61296 * element. If an option with a value already exists, it will be returned. 61297 * Optionally, a label can be provided as second argument for the option. 61298 * - `.remove(value)` can be used to remove an option for the element. 61299 * - `.value()` method will return the currently selected value. 61300 * - `.selected()` method will return the currently selected input element. 61301 * - `.selected(value)` method will select the option and return it. 61302 * - `.disable(Boolean)` method will enable/disable the whole radio button element. 61303 * 61304 * @method createRadio 61305 * @param {Object} containerElement An container HTML Element either a div 61306 * or span inside which all existing radio inputs will be considered as options. 61307 * @param {string} [name] A name parameter for each Input Element. 61308 * @return {p5.Element} pointer to <a href="#/p5.Element">p5.Element</a> holding created node 61309 * @example 61310 * <div><code> 61311 * let radio; 61312 * 61313 * function setup() { 61314 * radio = createRadio(); 61315 * radio.option('black'); 61316 * radio.option('white'); 61317 * radio.option('gray'); 61318 * radio.style('width', '60px'); 61319 * textAlign(CENTER); 61320 * fill(255, 0, 0); 61321 * } 61322 * 61323 * function draw() {
61324 * let val = radio.value(); 61325 * background(val); 61326 * text(val, width / 2, height / 2); 61327 * } 61328 * </code></div> 61329 * <div><code> 61330 * let radio; 61331 * 61332 * function setup() { 61333 * radio = createRadio(); 61334 * radio.option(1, 'apple'); 61335 * radio.option(2, 'bread'); 61336 * radio.option(3, 'juice'); 61337 * radio.style('width', '30px'); 61338 * textAlign(CENTER); 61339 * } 61340 * 61341 * function draw() { 61342 * background(200); 61343 * let val = radio.value(); 61344 * if (val) { 61345 * text('item cost is $' + val, width / 2, height / 2); 61346 * } 61347 * } 61348 * </code></div> 61349 */ 61350 /** 61351 * @method createRadio 61352 * @param {String} name 61353 * @return {p5.Element} pointer to <a href="#/p5.Element">p5.Element</a> holding created node 61354 */ 61355 /** 61356 * @method createRadio 61357 * @return {p5.Element} pointer to <a href="#/p5.Element">p5.Element</a> holding created node 61358 */ 61359 _main.default.prototype.createRadio = function() { 61360 // Creates a div, adds each option as an individual input inside it. 61361 // If already given with a containerEl, will search for all input[radio] 61362 // it, create a p5.Element out of it, add options to it and return the p5.Element. 61363 61364 var radioElement; 61365 var name; 61366 var arg0 = arguments[0]; 61367 // If existing radio Element is provided as argument 0 61368 if (arg0 instanceof HTMLDivElement || arg0 instanceof HTMLSpanElement) { 61369 radioElement = arg0; 61370 if (typeof arguments[1] === 'string') name = arguments[1]; 61371 } else { 61372 if (typeof arg0 === 'string') name = arg0; 61373 radioElement = document.createElement('div'); 61374 } 61375 this.elt = radioElement; 61376 var self = addElement(radioElement, this); 61377 self._name = name || 'radioOption'; 61378 61379 // setup member functions 61380 var isRadioInput = function isRadioInput(el) { 61381 return el instanceof HTMLInputElement && el.type === 'radio'; 61382 }; 61383 var isNextLabel = function isNextLabel(el) { 61384 return el.nextElementSibling instanceof HTMLLabelElement; 61385 }; 61386 61387 self._getOptionsArray = function() { 61388 return Array.from(this.elt.children).filter(isRadioInput); 61389 }; 61390 61391 self.option = function(value, label) { 61392 // return an option with this value, create if not exists. 61393 var optionEl; 61394 var _iteratorNormalCompletion2 = true; 61395 var _didIteratorError2 = false;
61396 var _iteratorError2 = undefined; 61397 try { 61398 for ( 61399 var _iterator2 = self._getOptionsArray()[Symbol.iterator](), _step2; 61400 !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); 61401 _iteratorNormalCompletion2 = true 61402 ) { 61403 var option = _step2.value; 61404 if (option.value === value) { 61405 optionEl = option; 61406 break; 61407 } 61408 } 61409 61410 // Create a new option, add it to radioElement and return it. 61411 } catch (err) { 61412 _didIteratorError2 = true; 61413 _iteratorError2 = err; 61414 } finally { 61415 try { 61416 if (!_iteratorNormalCompletion2 && _iterator2.return != null) { 61417 _iterator2.return(); 61418 } 61419 } finally { 61420 if (_didIteratorError2) { 61421 throw _iteratorError2; 61422 } 61423 } 61424 } 61425 if (optionEl === undefined) { 61426 optionEl = document.createElement('input'); 61427 optionEl.setAttribute('type', 'radio'); 61428 optionEl.setAttribute('value', value); 61429 this.elt.appendChild(optionEl); 61430 } 61431 61432 // Check if label element exists, else create it 61433 var labelElement; 61434 if (!isNextLabel(optionEl)) { 61435 labelElement = document.createElement('label'); 61436 optionEl.insertAdjacentElement('afterend', labelElement); 61437 } else { 61438 labelElement = optionEl.nextElementSibling; 61439 } 61440 61441 labelElement.innerHTML = label === undefined ? value : label; 61442 optionEl.setAttribute('name', self._name); 61443 return optionEl; 61444 }; 61445 61446 self.remove = function(value) { 61447 var _iteratorNormalCompletion3 = true; 61448 var _didIteratorError3 = false; 61449 var _iteratorError3 = undefined; 61450 try { 61451 for ( 61452 var _iterator3 = self._getOptionsArray()[Symbol.iterator](), _step3; 61453 !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); 61454 _iteratorNormalCompletion3 = true 61455 ) { 61456 var optionEl = _step3.value; 61457 if (optionEl.value === value) { 61458 if (isNextLabel(optionEl)) optionEl.nextElementSibling.remove(); 61459 optionEl.remove(); 61460 return; 61461 } 61462 } 61463 } catch (err) { 61464 _didIteratorError3 = true; 61465 _iteratorError3 = err; 61466 } finally { 61467 try { 61468 if (!_iteratorNormalCompletion3 && _iterator3.return != null) { 61469 _iterator3.return(); 61470 } 61471 } finally { 61472 if (_didIteratorError3) { 61473 throw _iteratorError3; 61474 } 61475 } 61476 } 61477 }; 61478 61479 self.value = function() { 61480 var result = ''; 61481 var _iteratorNormalCompletion4 = true; 61482 var _didIteratorError4 = false; 61483 var _iteratorError4 = undefined; 61484 try { 61485 for ( 61486 var _iterator4 = self._getOptionsArray()[Symbol.iterator](), _step4; 61487 !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); 61488 _iteratorNormalCompletion4 = true 61489 ) { 61490 var option = _step4.value; 61491 if (option.checked) { 61492 result = option.value; 61493 break; 61494 } 61495 } 61496 } catch (err) { 61497 _didIteratorError4 = true; 61498 _iteratorError4 = err; 61499 } finally { 61500 try { 61501 if (!_iteratorNormalCompletion4 && _iterator4.return != null) { 61502 _iterator4.return(); 61503 } 61504 } finally { 61505 if (_didIteratorError4) { 61506 throw _iteratorError4; 61507 } 61508 } 61509 } 61510 return result; 61511 }; 61512 61513 self.selected = function(value) { 61514 var result = null; 61515 if (value === undefined) { 61516 var _iteratorNormalCompletion5 = true;
61517 var _didIteratorError5 = false; 61518 var _iteratorError5 = undefined; 61519 try { 61520 for ( 61521 var _iterator5 = self._getOptionsArray()[Symbol.iterator](), _step5; 61522 !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); 61523 _iteratorNormalCompletion5 = true 61524 ) { 61525 var option = _step5.value; 61526 if (option.checked) { 61527 result = option; 61528 break; 61529 } 61530 } 61531 } catch (err) { 61532 _didIteratorError5 = true; 61533 _iteratorError5 = err; 61534 } finally { 61535 try { 61536 if (!_iteratorNormalCompletion5 && _iterator5.return != null) { 61537 _iterator5.return(); 61538 } 61539 } finally { 61540 if (_didIteratorError5) { 61541 throw _iteratorError5; 61542 } 61543 } 61544 } 61545 } else { 61546 var _iteratorNormalCompletion6 = true; 61547 var _didIteratorError6 = false; 61548 var _iteratorError6 = undefined; 61549 try { 61550 for ( 61551 var _iterator6 = self._getOptionsArray()[Symbol.iterator](), _step6; 61552 !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done); 61553 _iteratorNormalCompletion6 = true 61554 ) { 61555 var _option = _step6.value; 61556 if (_option.value === value) { 61557 _option.setAttribute('checked', true); 61558 result = _option; 61559 } 61560 } 61561 } catch (err) { 61562 _didIteratorError6 = true; 61563 _iteratorError6 = err; 61564 } finally { 61565 try { 61566 if (!_iteratorNormalCompletion6 && _iterator6.return != null) { 61567 _iterator6.return(); 61568 } 61569 } finally { 61570 if (_didIteratorError6) { 61571 throw _iteratorError6; 61572 } 61573 } 61574 } 61575 } 61576 return result; 61577 }; 61578 61579 self.disable = function() { 61580 var shouldDisable = 61581 arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; 61582 var _iteratorNormalCompletion7 = true; 61583 var _didIteratorError7 = false; 61584 var _iteratorError7 = undefined; 61585 try { 61586 for ( 61587 var _iterator7 = self._getOptionsArray()[Symbol.iterator](), _step7; 61588 !(_iteratorNormalCompletion7 = (_step7 = _iterator7.next()).done); 61589 _iteratorNormalCompletion7 = true 61590 ) { 61591 var radioInput = _step7.value; 61592 radioInput.setAttribute('disabled', shouldDisable); 61593 } 61594 } catch (err) { 61595 _didIteratorError7 = true; 61596 _iteratorError7 = err; 61597 } finally { 61598 try { 61599 if (!_iteratorNormalCompletion7 && _iterator7.return != null) { 61600 _iterator7.return(); 61601 } 61602 } finally { 61603 if (_didIteratorError7) { 61604 throw _iteratorError7; 61605 } 61606 } 61607 } 61608 }; 61609 61610 return self; 61611 }; 61612 61613 /** 61614 * Creates a colorPicker element in the DOM for color input. 61615 * The .value() method will return a hex string (#rrggbb) of the color. 61616 * The .color() method will return a p5.Color object with the current chosen color. 61617 * 61618 * @method createColorPicker 61619 * @param {String|p5.Color} [value] default color of element 61620 * @return {p5.Element} pointer to <a href="#/p5.Element">p5.Element</a> holding created node 61621 * @example 61622 * <div><code> 61623 * let colorPicker; 61624 * function setup() { 61625 * createCanvas(100, 100); 61626 * colorPicker = createColorPicker('#ed225d'); 61627 * colorPicker.position(0, height + 5); 61628 * } 61629 * 61630 * function draw() { 61631 * background(colorPicker.color()); 61632 * } 61633 * </code></div> 61634 * <div><code> 61635 * let inp1, inp2; 61636 * function setup() { 61637 * createCanvas(100, 100); 61638 * background('grey'); 61639 * inp1 = createColorPicker('#ff0000'); 61640 * inp1.position(0, height + 5); 61641 * inp1.input(setShade1); 61642 * inp2 = createColorPicker(color('yellow')); 61643 * inp2.position(0, height + 30); 61644 * inp2.input(setShade2); 61645 * setMidShade(); 61646 * } 61647 * 61648 * function setMidShade() { 61649 * // Finding a shade between the two 61650 * let commonShade = lerpColor(inp1.color(), inp2.color(), 0.5); 61651 * fill(commonShade); 61652 * rect(20, 20, 60, 60); 61653 * } 61654 * 61655 * function setShade1() { 61656 * setMidShade();
61657 * console.log('You are choosing shade 1 to be : ', this.value()); 61658 * } 61659 * function setShade2() { 61660 * setMidShade(); 61661 * console.log('You are choosing shade 2 to be : ', this.value()); 61662 * } 61663 * </code></div> 61664 */ 61665 _main.default.prototype.createColorPicker = function(value) { 61666 _main.default._validateParameters('createColorPicker', arguments); 61667 var elt = document.createElement('input'); 61668 var self; 61669 elt.type = 'color'; 61670 if (value) { 61671 if (value instanceof _main.default.Color) { 61672 elt.value = value.toString('#rrggbb'); 61673 } else { 61674 _main.default.prototype._colorMode = 'rgb'; 61675 _main.default.prototype._colorMaxes = { 61676 rgb: [255, 255, 255, 255], 61677 hsb: [360, 100, 100, 1], 61678 hsl: [360, 100, 100, 1] 61679 }; 61680 61681 elt.value = _main.default.prototype.color(value).toString('#rrggbb'); 61682 } 61683 } else { 61684 elt.value = '#000000'; 61685 } 61686 self = addElement(elt, this); 61687 // Method to return a p5.Color object for the given color. 61688 self.color = function() { 61689 if (value) { 61690 if (value.mode) { 61691 _main.default.prototype._colorMode = value.mode; 61692 } 61693 if (value.maxes) { 61694 _main.default.prototype._colorMaxes = value.maxes; 61695 } 61696 } 61697 return _main.default.prototype.color(this.elt.value); 61698 }; 61699 return self; 61700 }; 61701 61702 /** 61703 * Creates an `<input></input>` element in the DOM for text input. 61704 * Use .<a href="#/p5.Element/size">size()</a> to set the display length of the box. 61705 * 61706 * @method createInput 61707 * @param {String} value default value of the input box 61708 * @param {String} [type] type of text, ie text, password etc. Defaults to text. 61709 * Needs a value to be specified first. 61710 * @return {p5.Element} pointer to <a href="#/p5.Element">p5.Element</a> holding created node 61711 * @example 61712 * <div class='norender'><code> 61713 * function setup() { 61714 * let inp = createInput(''); 61715 * inp.input(myInputEvent); 61716 * } 61717 * 61718 * function myInputEvent() { 61719 * console.log('you are typing: ', this.value()); 61720 * } 61721 * </code></div> 61722 */ 61723 /** 61724 * @method createInput 61725 * @param {String} [value] 61726 * @return {p5.Element} 61727 */ 61728 _main.default.prototype.createInput = function() { 61729 var value = 61730 arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; 61731 var type = 61732 arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'text'; 61733 _main.default._validateParameters('createInput', arguments); 61734 var elt = document.createElement('input'); 61735 elt.setAttribute('value', value); 61736 elt.setAttribute('type', type); 61737 return addElement(elt, this); 61738 }; 61739 61740 /** 61741 * Creates an `<input></input>` element in the DOM of type 'file'. 61742 * This allows users to select local files for use in a sketch. 61743 * 61744 * @method createFileInput 61745 * @param {Function} callback callback function for when a file is loaded 61746 * @param {Boolean} [multiple] optional, to allow multiple files to be selected 61747 * @return {p5.Element} pointer to <a href="#/p5.Element">p5.Element</a> holding created DOM element 61748 * @example 61749 * <div><code> 61750 * let input; 61751 * let img; 61752 * 61753 * function setup() { 61754 * input = createFileInput(handleFile); 61755 * input.position(0, 0); 61756 * } 61757 * 61758 * function draw() { 61759 * background(255); 61760 * if (img) { 61761 * image(img, 0, 0, width, height); 61762 * } 61763 * } 61764 * 61765 * function handleFile(file) { 61766 * print(file); 61767 * if (file.type === 'image') { 61768 * img = createImg(file.data, ''); 61769 * img.hide(); 61770 * } else { 61771 * img = null; 61772 * } 61773 * } 61774 * </code></div> 61775 */ 61776 _main.default.prototype.createFileInput = function(callback) { 61777 var multiple = 61778 arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
61779 _main.default._validateParameters('createFileInput', arguments); 61780 61781 var handleFileSelect = function handleFileSelect(event) { 61782 var _iteratorNormalCompletion8 = true; 61783 var _didIteratorError8 = false; 61784 var _iteratorError8 = undefined; 61785 try { 61786 for ( 61787 var _iterator8 = event.target.files[Symbol.iterator](), _step8; 61788 !(_iteratorNormalCompletion8 = (_step8 = _iterator8.next()).done); 61789 _iteratorNormalCompletion8 = true 61790 ) { 61791 var file = _step8.value; 61792 _main.default.File._load(file, callback); 61793 } 61794 } catch (err) { 61795 _didIteratorError8 = true; 61796 _iteratorError8 = err; 61797 } finally { 61798 try { 61799 if (!_iteratorNormalCompletion8 && _iterator8.return != null) { 61800 _iterator8.return(); 61801 } 61802 } finally { 61803 if (_didIteratorError8) { 61804 throw _iteratorError8; 61805 } 61806 } 61807 } 61808 }; 61809 61810 // If File API's are not supported, throw Error 61811 if (!(window.File && window.FileReader && window.FileList && window.Blob)) { 61812 console.log( 61813 'The File APIs are not fully supported in this browser. Cannot create element.' 61814 ); 61815 61816 return; 61817 } 61818 61819 var fileInput = document.createElement('input'); 61820 fileInput.setAttribute('type', 'file'); 61821 if (multiple) fileInput.setAttribute('multiple', true); 61822 fileInput.addEventListener('change', handleFileSelect, false); 61823 return addElement(fileInput, this); 61824 }; 61825 61826 /** VIDEO STUFF **/ 61827 61828 // Helps perform similar tasks for media element methods. 61829 function createMedia(pInst, type, src, callback) { 61830 var elt = document.createElement(type); 61831 61832 // Create source elements from given sources 61833 src = src || ''; 61834 if (typeof src === 'string') { 61835 src = [src]; 61836 } 61837 var _iteratorNormalCompletion9 = true; 61838 var _didIteratorError9 = false; 61839 var _iteratorError9 = undefined; 61840 try { 61841 for ( 61842 var _iterator9 = src[Symbol.iterator](), _step9; 61843 !(_iteratorNormalCompletion9 = (_step9 = _iterator9.next()).done); 61844 _iteratorNormalCompletion9 = true 61845 ) { 61846 var mediaSource = _step9.value; 61847 var sourceEl = document.createElement('source'); 61848 sourceEl.setAttribute('src', mediaSource); 61849 elt.appendChild(sourceEl); 61850 } 61851 61852 // If callback is provided, attach to element 61853 } catch (err) { 61854 _didIteratorError9 = true; 61855 _iteratorError9 = err; 61856 } finally { 61857 try { 61858 if (!_iteratorNormalCompletion9 && _iterator9.return != null) { 61859 _iterator9.return(); 61860 } 61861 } finally { 61862 if (_didIteratorError9) { 61863 throw _iteratorError9; 61864 } 61865 } 61866 } 61867 if (typeof callback === 'function') { 61868 var callbackHandler = function callbackHandler() { 61869 callback(); 61870 elt.removeEventListener('canplaythrough', callbackHandler); 61871 }; 61872 elt.addEventListener('canplaythrough', callbackHandler); 61873 } 61874 61875 var mediaEl = addElement(elt, pInst, true); 61876 mediaEl.loadedmetadata = false; 61877 61878 // set width and height onload metadata 61879 elt.addEventListener('loadedmetadata', function() { 61880 mediaEl.width = elt.videoWidth; 61881 mediaEl.height = elt.videoHeight; 61882 61883 // set elt width and height if not set 61884 if (mediaEl.elt.width === 0) mediaEl.elt.width = elt.videoWidth; 61885 if (mediaEl.elt.height === 0) mediaEl.elt.height = elt.videoHeight; 61886 if (mediaEl.presetPlaybackRate) { 61887 mediaEl.elt.playbackRate = mediaEl.presetPlaybackRate; 61888 delete mediaEl.presetPlaybackRate; 61889 } 61890 mediaEl.loadedmetadata = true; 61891 }); 61892 61893 return mediaEl; 61894 } 61895 61896 /** 61897 * Creates an HTML5 `<video>` element in the DOM for simple playback 61898 * of audio/video. Shown by default, can be hidden with .<a href="#/p5.Element/hide">hide()</a> 61899 * and drawn into canvas using <a href="#/p5/image">image()</a>. The first parameter
61900 * can be either a single string path to a video file, or an array of string 61901 * paths to different formats of the same video. This is useful for ensuring 61902 * that your video can play across different browsers, as each supports 61903 * different formats. See <a href='https://developer.mozilla.org/en-US/docs/Web/HTML/Supported_media_formats'>this 61904 * page</a> for further information about supported formats. 61905 * 61906 * @method createVideo 61907 * @param {String|String[]} src path to a video file, or array of paths for 61908 * supporting different browsers 61909 * @param {Function} [callback] callback function to be called upon 61910 * 'canplaythrough' event fire, that is, when the 61911 * browser can play the media, and estimates that 61912 * enough data has been loaded to play the media 61913 * up to its end without having to stop for 61914 * further buffering of content 61915 * @return {p5.MediaElement} pointer to video <a href="#/p5.Element">p5.Element</a> 61916 * @example 61917 * <div><code> 61918 * let vid; 61919 * function setup() { 61920 * noCanvas(); 61921 * 61922 * vid = createVideo( 61923 * ['assets/small.mp4', 'assets/small.ogv', 'assets/small.webm'], 61924 * vidLoad 61925 * ); 61926 * 61927 * vid.size(100, 100); 61928 * } 61929 * 61930 * // This function is called when the video loads 61931 * function vidLoad() { 61932 * vid.loop(); 61933 * vid.volume(0); 61934 * } 61935 * </code></div> 61936 */ 61937 _main.default.prototype.createVideo = function(src, callback) { 61938 _main.default._validateParameters('createVideo', arguments); 61939 return createMedia(this, 'video', src, callback); 61940 }; 61941 61942 /** AUDIO STUFF **/ 61943 61944 /** 61945 * Creates a hidden HTML5 `<audio>` element in the DOM for simple audio 61946 * playback. The first parameter can be either a single string path to a 61947 * audio file, or an array of string paths to different formats of the same 61948 * audio. This is useful for ensuring that your audio can play across 61949 * different browsers, as each supports different formats. 61950 * See <a href='https://developer.mozilla.org/en-US/docs/Web/HTML/Supported_media_formats'>this 61951 * page for further information about supported formats</a>. 61952 * 61953 * @method createAudio 61954 * @param {String|String[]} [src] path to an audio file, or array of paths 61955 * for supporting different browsers 61956 * @param {Function} [callback] callback function to be called upon 61957 * 'canplaythrough' event fire, that is, when the 61958 * browser can play the media, and estimates that 61959 * enough data has been loaded to play the media 61960 * up to its end without having to stop for 61961 * further buffering of content 61962 * @return {p5.MediaElement} pointer to audio <a href="#/p5.Element">p5.Element</a> 61963 * @example 61964 * <div><code> 61965 * let ele; 61966 * function setup() { 61967 * ele = createAudio('assets/beat.mp3'); 61968 * 61969 * // here we set the element to autoplay 61970 * // The element will play as soon 61971 * // as it is able to do so. 61972 * ele.autoplay(true); 61973 * } 61974 * </code></div> 61975 */ 61976 _main.default.prototype.createAudio = function(src, callback) { 61977 _main.default._validateParameters('createAudio', arguments); 61978 return createMedia(this, 'audio', src, callback); 61979 }; 61980 61981 /** CAMERA STUFF **/ 61982 61983 /** 61984 * @property {String} VIDEO 61985 * @final 61986 * @category Constants 61987 */ 61988 _main.default.prototype.VIDEO = 'video'; 61989 /** 61990 * @property {String} AUDIO 61991 * @final 61992 * @category Constants 61993 */ 61994 _main.default.prototype.AUDIO = 'audio'; 61995 61996 // from: https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia 61997 // Older browsers might not implement mediaDevices at all, so we set an empty object first 61998 if (navigator.mediaDevices === undefined) { 61999 navigator.mediaDevices = {}; 62000 } 62001 62002 // Some browsers partially implement mediaDevices. We can't just assign an object 62003 // with getUserMedia as it would overwrite existing properties. 62004 // Here, we will just add the getUserMedia property if it's missing. 62005 if (navigator.mediaDevices.getUserMedia === undefined) { 62006 navigator.mediaDevices.getUserMedia = function(constraints) { 62007 // First get ahold of the legacy getUserMedia, if present 62008 var getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia; 62009 62010 // Some browsers just don't implement it - return a rejected promise with an error 62011 // to keep a consistent interface 62012 if (!getUserMedia) { 62013 return Promise.reject( 62014 new Error('getUserMedia is not implemented in this browser') 62015 ); 62016 } 62017 62018 // Otherwise, wrap the call to the old navigator.getUserMedia with a Promise 62019 return new Promise(function(resolve, reject) { 62020 getUserMedia.call(navigator, constraints, resolve, reject); 62021 }); 62022 }; 62023 } 62024 62025 /** 62026 * Creates a new HTML5 `<video>` element that contains the audio/video feed 62027 * from a webcam. The element is separate from the canvas and is displayed by 62028 * default. The element can be hidden using .<a href="#/p5.Element/hide">hide()</a>. 62029 * The feed can be drawn onto the canvas using <a href="#/p5/image">image()</a>. 62030 * The loadedmetadata property can be used to detect when the element has fully 62031 * loaded (see second example). 62032 * 62033 * More specific properties of the feed can be passing in a Constraints object. 62034 * See the <a href='http://w3c.github.io/mediacapture-main/getusermedia.html#media-track-constraints'> 62035 * W3C spec</a> for possible properties. Note that not all of these are supported 62036 * by all browsers. 62037 * 62038 * <em>Security note</em>: A new browser security specification requires that 62039 * getUserMedia, which is behind <a href="#/p5/createCapture">createCapture()</a>, 62040 * only works when you're running the code locally, or on HTTPS. Learn more 62041 * <a href='http://stackoverflow.com/questions/34197653/getusermedia-in-chrome-47-without-using-https'>here</a> 62042 * and <a href='https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia'>here</a>. 62043 * 62044 * @method createCapture 62045 * @param {String|Constant|Object} type type of capture, either VIDEO or 62046 * AUDIO if none specified, default both, 62047 * or a Constraints object 62048 * @param {Function} [callback] function to be called once 62049 * stream has loaded 62050 * @return {p5.Element} capture video <a href="#/p5.Element">p5.Element</a> 62051 * @example 62052 * <div class='norender notest'> 62053 * <code> 62054 * let capture; 62055 * 62056 * function setup() { 62057 * createCanvas(480, 480); 62058 * capture = createCapture(VIDEO); 62059 * capture.hide(); 62060 * } 62061 * 62062 * function draw() { 62063 * image(capture, 0, 0, width, width * capture.height / capture.width); 62064 * filter(INVERT); 62065 * } 62066 * </code> 62067 * </div> 62068 * 62069 * <div class='norender notest'> 62070 * <code> 62071 * function setup() { 62072 * createCanvas(480, 120); 62073 * let constraints = { 62074 * video: { 62075 * mandatory: { 62076 * minWidth: 1280, 62077 * minHeight: 720 62078 * }, 62079 * optional: [{ maxFrameRate: 10 }] 62080 * }, 62081 * audio: true 62082 * }; 62083 * createCapture(constraints, function(stream) { 62084 * console.log(stream); 62085 * }); 62086 * } 62087 * </code> 62088 * </div> 62089 * <div class='norender notest'> 62090 * <code> 62091 * let capture; 62092 * 62093 * function setup() { 62094 * createCanvas(640, 480); 62095 * capture = createCapture(VIDEO); 62096 * } 62097 * function draw() { 62098 * background(0); 62099 * if (capture.loadedmetadata) { 62100 * let c = capture.get(0, 0, 100, 100); 62101 * image(c, 0, 0); 62102 * } 62103 * } 62104 * </code> 62105 * </div> 62106 */ 62107 _main.default.prototype.createCapture = function() { 62108 _main.default._validateParameters('createCapture', arguments); 62109 62110 // return if getUserMedia is not supported by browser 62111 if (!(navigator.mediaDevices && navigator.mediaDevices.getUserMedia)) { 62112 throw new DOMException('getUserMedia not supported in this browser'); 62113 } 62114 62115 var useVideo = true; 62116 var useAudio = true; 62117 var constraints; 62118 var callback; 62119 var _iteratorNormalCompletion10 = true; 62120 var _didIteratorError10 = false;
62121 var _iteratorError10 = undefined; 62122 try { 62123 for ( 62124 var _iterator10 = arguments[Symbol.iterator](), _step10; 62125 !(_iteratorNormalCompletion10 = (_step10 = _iterator10.next()).done); 62126 _iteratorNormalCompletion10 = true 62127 ) { 62128 var arg = _step10.value; 62129 if (arg === _main.default.prototype.VIDEO) useAudio = false; 62130 else if (arg === _main.default.prototype.AUDIO) useVideo = false; 62131 else if (_typeof(arg) === 'object') constraints = arg; 62132 else if (typeof arg === 'function') callback = arg; 62133 } 62134 } catch (err) { 62135 _didIteratorError10 = true; 62136 _iteratorError10 = err; 62137 } finally { 62138 try { 62139 if (!_iteratorNormalCompletion10 && _iterator10.return != null) { 62140 _iterator10.return(); 62141 } 62142 } finally { 62143 if (_didIteratorError10) { 62144 throw _iteratorError10; 62145 } 62146 } 62147 } 62148 if (!constraints) constraints = { video: useVideo, audio: useAudio }; 62149 62150 var domElement = document.createElement('video'); 62151 // required to work in iOS 11 & up: 62152 domElement.setAttribute('playsinline', ''); 62153 62154 navigator.mediaDevices.getUserMedia(constraints).then(function(stream) { 62155 try { 62156 if ('srcObject' in domElement) { 62157 domElement.srcObject = stream; 62158 } else { 62159 domElement.src = window.URL.createObjectURL(stream); 62160 } 62161 } catch (err) { 62162 domElement.src = stream; 62163 } 62164 }, console.log); 62165 62166 var videoEl = addElement(domElement, this, true); 62167 videoEl.loadedmetadata = false; 62168 // set width and height onload metadata 62169 domElement.addEventListener('loadedmetadata', function() { 62170 domElement.play(); 62171 if (domElement.width) { 62172 videoEl.width = domElement.width; 62173 videoEl.height = domElement.height; 62174 } else { 62175 videoEl.width = videoEl.elt.width = domElement.videoWidth; 62176 videoEl.height = videoEl.elt.height = domElement.videoHeight; 62177 } 62178 videoEl.loadedmetadata = true; 62179 62180 if (callback) callback(domElement.srcObject); 62181 }); 62182 return videoEl; 62183 }; 62184 62185 /** 62186 * Creates element with given tag in the DOM with given content. 62187 * 62188 * @method createElement 62189 * @param {String} tag tag for the new element 62190 * @param {String} [content] html content to be inserted into the element 62191 * @return {p5.Element} pointer to <a href="#/p5.Element">p5.Element</a> holding created node 62192 * @example 62193 * <div class='norender'><code> 62194 * createElement('h2', 'im an h2 p5.element!'); 62195 * </code></div> 62196 */ 62197 _main.default.prototype.createElement = function(tag, content) { 62198 _main.default._validateParameters('createElement', arguments); 62199 var elt = document.createElement(tag); 62200 if (typeof content !== 'undefined') { 62201 elt.innerHTML = content; 62202 } 62203 return addElement(elt, this); 62204 }; 62205 62206 // ============================================================================= 62207 // p5.Element additions 62208 // ============================================================================= 62209 /** 62210 * 62211 * Adds specified class to the element. 62212 * 62213 * @for p5.Element 62214 * @method addClass 62215 * @param {String} class name of class to add 62216 * @chainable 62217 * @example 62218 * <div class='norender'><code> 62219 * let div = createDiv('div'); 62220 * div.addClass('myClass'); 62221 * </code></div> 62222 */ 62223 _main.default.Element.prototype.addClass = function(c) { 62224 if (this.elt.className) { 62225 if (!this.hasClass(c)) { 62226 this.elt.className = this.elt.className + ' ' + c; 62227 } 62228 } else { 62229 this.elt.className = c; 62230 } 62231 return this; 62232 }; 62233 62234 /** 62235 * 62236 * Removes specified class from the element. 62237 * 62238 * @method removeClass 62239 * @param {String} class name of class to remove 62240 * @chainable 62241 * @example 62242 * <div class='norender'><code> 62243 * // In this example, a class is set when the div is created 62244 * // and removed when mouse is pressed. This could link up 62245 * // with a CSS style rule to toggle style properties. 62246 * 62247 * let div; 62248 * 62249 * function setup() { 62250 * div = createDiv('div'); 62251 * div.addClass('myClass'); 62252 * } 62253 * 62254 * function mousePressed() { 62255 * div.removeClass('myClass'); 62256 * } 62257 * </code></div> 62258 */ 62259 _main.default.Element.prototype.removeClass = function(c) { 62260 // Note: Removing a class that does not exist does NOT throw an error in classList.remove method 62261 this.elt.classList.remove(c); 62262 return this; 62263 }; 62264 62265 /** 62266 * 62267 * Checks if specified class already set to element 62268 * 62269 * @method hasClass 62270 * @returns {boolean} a boolean value if element has specified class 62271 * @param c {String} class name of class to check 62272 * @example 62273 * <div class='norender'><code> 62274 * let div; 62275 * 62276 * function setup() { 62277 * div = createDiv('div'); 62278 * div.addClass('show'); 62279 * } 62280 * 62281 * function mousePressed() { 62282 * if (div.hasClass('show')) { 62283 * div.addClass('show'); 62284 * } else { 62285 * div.removeClass('show'); 62286 * } 62287 * } 62288 * </code></div> 62289 */ 62290 _main.default.Element.prototype.hasClass = function(c) { 62291 return this.elt.classList.contains(c); 62292 }; 62293 62294 /** 62295 * 62296 * Toggles element class 62297 * 62298 * @method toggleClass 62299 * @param c {String} class name to toggle 62300 * @chainable 62301 * @example 62302 * <div class='norender'><code> 62303 * let div; 62304 * 62305 * function setup() { 62306 * div = createDiv('div'); 62307 * div.addClass('show'); 62308 * } 62309 * 62310 * function mousePressed() { 62311 * div.toggleClass('show'); 62312 * } 62313 * </code></div> 62314 */ 62315 _main.default.Element.prototype.toggleClass = function(c) {
62316 // classList also has a toggle() method, but we cannot use that yet as support is unclear. 62317 // See https://github.com/processing/p5.js/issues/3631 62318 // this.elt.classList.toggle(c); 62319 if (this.elt.classList.contains(c)) { 62320 this.elt.classList.remove(c); 62321 } else { 62322 this.elt.classList.add(c); 62323 } 62324 return this; 62325 }; 62326 62327 /** 62328 * 62329 * Attaches the element as a child to the parent specified. 62330 * Accepts either a string ID, DOM node, or <a href="#/p5.Element">p5.Element</a>. 62331 * If no argument is specified, an array of children DOM nodes is returned. 62332 * 62333 * @method child 62334 * @returns {Node[]} an array of child nodes 62335 * @example 62336 * <div class='norender'><code> 62337 * let div0 = createDiv('this is the parent'); 62338 * let div1 = createDiv('this is the child'); 62339 * div0.child(div1); // use p5.Element 62340 * </code></div> 62341 * <div class='norender'><code> 62342 * let div0 = createDiv('this is the parent'); 62343 * let div1 = createDiv('this is the child'); 62344 * div1.id('apples'); 62345 * div0.child('apples'); // use id 62346 * </code></div> 62347 * <div class='norender notest'><code> 62348 * // this example assumes there is a div already on the page 62349 * // with id "myChildDiv" 62350 * let div0 = createDiv('this is the parent'); 62351 * let elt = document.getElementById('myChildDiv'); 62352 * div0.child(elt); // use element from page 62353 * </code></div> 62354 */ 62355 /** 62356 * @method child 62357 * @param {String|p5.Element} [child] the ID, DOM node, or <a href="#/p5.Element">p5.Element</a> 62358 * to add to the current element 62359 * @chainable 62360 */ 62361 _main.default.Element.prototype.child = function(childNode) { 62362 if (typeof childNode === 'undefined') { 62363 return this.elt.childNodes; 62364 } 62365 if (typeof childNode === 'string') { 62366 if (childNode[0] === '#') { 62367 childNode = childNode.substring(1); 62368 } 62369 childNode = document.getElementById(childNode); 62370 } else if (childNode instanceof _main.default.Element) { 62371 childNode = childNode.elt; 62372 } 62373 62374 if (childNode instanceof HTMLElement) { 62375 this.elt.appendChild(childNode); 62376 } 62377 return this; 62378 }; 62379 62380 /** 62381 * Centers a p5 Element either vertically, horizontally, 62382 * or both, relative to its parent or according to 62383 * the body if the Element has no parent. If no argument is passed 62384 * the Element is aligned both vertically and horizontally. 62385 * 62386 * @method center 62387 * @param {String} [align] passing 'vertical', 'horizontal' aligns element accordingly 62388 * @chainable 62389 * 62390 * @example 62391 * <div><code> 62392 * function setup() { 62393 * let div = createDiv('').size(10, 10); 62394 * div.style('background-color', 'orange'); 62395 * div.center(); 62396 * } 62397 * </code></div> 62398 */ 62399 _main.default.Element.prototype.center = function(align) { 62400 var style = this.elt.style.display; 62401 var hidden = this.elt.style.display === 'none'; 62402 var parentHidden = this.parent().style.display === 'none'; 62403 var pos = { x: this.elt.offsetLeft, y: this.elt.offsetTop }; 62404 62405 if (hidden) this.show(); 62406 if (parentHidden) this.parent().show(); 62407 this.elt.style.display = 'block'; 62408 62409 this.position(0, 0); 62410 var wOffset = Math.abs(this.parent().offsetWidth - this.elt.offsetWidth); 62411 var hOffset = Math.abs(this.parent().offsetHeight - this.elt.offsetHeight); 62412 62413 if (align === 'both' || align === undefined) { 62414 this.position( 62415 wOffset / 2 + this.parent().offsetLeft, 62416 hOffset / 2 + this.parent().offsetTop 62417 ); 62418 } else if (align === 'horizontal') { 62419 this.position(wOffset / 2 + this.parent().offsetLeft, pos.y); 62420 } else if (align === 'vertical') { 62421 this.position(pos.x, hOffset / 2 + this.parent().offsetTop); 62422 } 62423 62424 this.style('display', style); 62425 if (hidden) this.hide(); 62426 if (parentHidden) this.parent().hide(); 62427 62428 return this; 62429 }; 62430 62431 /** 62432 * 62433 * If an argument is given, sets the inner HTML of the element, 62434 * replacing any existing html. If true is included as a second 62435 * argument, html is appended instead of replacing existing html. 62436 * If no arguments are given, returns 62437 * the inner HTML of the element. 62438 * 62439 * @for p5.Element 62440 * @method html 62441 * @returns {String} the inner HTML of the element 62442 * @example 62443 * <div class='norender'><code> 62444 * let div = createDiv('').size(100, 100); 62445 * div.html('hi'); 62446 * </code></div> 62447 * <div class='norender'><code> 62448 * let div = createDiv('Hello ').size(100, 100); 62449 * div.html('World', true); 62450 * </code></div> 62451 */ 62452 /** 62453 * @method html 62454 * @param {String} [html] the HTML to be placed inside the element 62455 * @param {boolean} [append] whether to append HTML to existing 62456 * @chainable 62457 */ 62458 _main.default.Element.prototype.html = function() { 62459 if (arguments.length === 0) { 62460 return this.elt.innerHTML; 62461 } else if (arguments[1]) { 62462 this.elt.insertAdjacentHTML('beforeend', arguments[0]); 62463 return this; 62464 } else { 62465 this.elt.innerHTML = arguments[0]; 62466 return this; 62467 } 62468 }; 62469 62470 /** 62471 * 62472 * Sets the position of the element. If no position type argument is given, the 62473 * position will be relative to (0, 0) of the window. 62474 * Essentially, this sets position:absolute and left and top 62475 * properties of style. If an optional third argument specifying position type is given, 62476 * the x and y coordinates will be interpreted based on the <a target="_blank" 62477 * href="https://developer.mozilla.org/en-US/docs/Web/CSS/position">positioning scheme</a>. 62478 * If no arguments given, the function returns the x and y position of the element. 62479 * 62480 * found documentation on how to be more specific with object type 62481 * https://stackoverflow.com/questions/14714314/how-do-i-comment-object-literal
62481s-in-yuidoc 62482 * 62483 * @method position 62484 * @returns {Object} object of form { x: 0, y: 0 } containing the position of the element in an object 62485 * @example 62486 * <div><code class='norender'> 62487 * function setup() { 62488 * let cnv = createCanvas(100, 100); 62489 * // positions canvas 50px to the right and 100px 62490 * // below upper left corner of the window 62491 * cnv.position(50, 100); 62492 * } 62493 * </code></div> 62494 * <div><code class='norender'> 62495 * function setup() { 62496 * let cnv = createCanvas(100, 100); 62497 * // positions canvas 50px to the right and 100px 62498 * // below upper left corner of the window 62499 * cnv.position(0, 0, 'fixed'); 62500 * } 62501 * </code></div> 62502 */ 62503 /** 62504 * @method position 62505 * @param {Number} [x] x-position relative to upper left of window (optional) 62506 * @param {Number} [y] y-position relative to upper left of window (optional) 62507 * @param {String} positionType it can be static, fixed, relative, sticky, initial or inherit (optional) 62508 * @chainable 62509 */ 62510 _main.default.Element.prototype.position = function() { 62511 if (arguments.length === 0) { 62512 return { x: this.elt.offsetLeft, y: this.elt.offsetTop }; 62513 } else { 62514 var positionType = 'absolute'; 62515 if ( 62516 arguments[2] === 'static' || 62517 arguments[2] === 'fixed' || 62518 arguments[2] === 'relative' || 62519 arguments[2] === 'sticky' || 62520 arguments[2] === 'initial' || 62521 arguments[2] === 'inherit' 62522 ) { 62523 positionType = arguments[2]; 62524 } 62525 this.elt.style.position = positionType; 62526 this.elt.style.left = arguments[0] + 'px'; 62527 this.elt.style.top = arguments[1] + 'px'; 62528 this.x = arguments[0]; 62529 this.y = arguments[1]; 62530 return this; 62531 } 62532 }; 62533 62534 /* Helper method called by p5.Element.style() */ 62535 _main.default.Element.prototype._translate = function() { 62536 this.elt.style.position = 'absolute'; 62537 // save out initial non-translate transform styling 62538 var transform = ''; 62539 if (this.elt.style.transform) { 62540 transform = this.elt.style.transform.replace(/translate3d\(.*\)/g, ''); 62541 transform = transform.replace(/translate[X-Z]?\(.*\)/g, ''); 62542 } 62543 if (arguments.length === 2) { 62544 this.elt.style.transform = 62545 'translate(' + arguments[0] + 'px, ' + arguments[1] + 'px)'; 62546 } else if (arguments.length > 2) { 62547 this.elt.style.transform = 62548 'translate3d(' + 62549 arguments[0] + 62550 'px,' + 62551 arguments[1] + 62552 'px,' + 62553 arguments[2] + 62554 'px)'; 62555 if (arguments.length === 3) { 62556 this.elt.parentElement.style.perspective = '1000px'; 62557 } else { 62558 this.elt.parentElement.style.perspective = arguments[3] + 'px'; 62559 } 62560 } 62561 // add any extra transform styling back on end 62562 this.elt.style.transform += transform; 62563 return this; 62564 }; 62565 62566 /* Helper method called by p5.Element.style() */ 62567 _main.default.Element.prototype._rotate = function() { 62568 // save out initial non-rotate transform styling 62569 var transform = ''; 62570 if (this.elt.style.transform) { 62571 transform = this.elt.style.transform.replace(/rotate3d\(.*\)/g, ''); 62572 transform = transform.replace(/rotate[X-Z]?\(.*\)/g, ''); 62573 } 62574 62575 if (arguments.length === 1) { 62576 this.elt.style.transform = 'rotate(' + arguments[0] + 'deg)'; 62577 } else if (arguments.length === 2) { 62578 this.elt.style.transform = 62579 'rotate(' + arguments[0] + 'deg, ' + arguments[1] + 'deg)'; 62580 } else if (arguments.length === 3) { 62581 this.elt.style.transform = 'rotateX(' + arguments[0] + 'deg)'; 62582 this.elt.style.transform += 'rotateY(' + arguments[1] + 'deg)'; 62583 this.elt.style.transform += 'rotateZ(' + arguments[2] + 'deg)'; 62584 } 62585 // add remaining transform back on 62586 this.elt.style.transform += transform; 62587 return this; 62588 }; 62589 62590 /** 62591 * Sets the given style (css) property (1st arg) of the element with the 62592 * given value (2nd arg). If a single argument is given, .style() 62593 * returns the value of the given property; however, if the single argument 62594 * is given in css syntax ('text-align:center'), .style() sets the css 62595 * appropriately. 62596 * 62597 * @method style 62598 * @param {String} property property to be set 62599 * @returns {String} value of property 62600 * @example 62601 * <div><code class='norender'> 62602 * let myDiv = createDiv('I like pandas.'); 62603 * myDiv.style('font-size', '18px'); 62604 * myDiv.style('color', '#ff0000'); 62605 * </code></div> 62606 * <div><code class='norender'> 62607 * let col = color(25, 23, 200, 50); 62608 * let button = createButton('button'); 62609 * button.style('background-color', col); 62610 * button.position(10, 10); 62611 * </code></div> 62612 * <div><code class='norender'> 62613 * let myDiv; 62614 * function setup() { 62615 * background(200); 62616 * myDiv = createDiv('I like gray.'); 62617 * myDiv.position(20, 20); 62618 * } 62619 * 62620 * function draw() { 62621 * myDiv.style('font-size', mouseX + 'px'); 62622 * } 62623 * </code></div> 62624 */ 62625 /** 62626 * @method style 62627 * @param {String} property 62628 * @param {String|p5.Color} value value to assign to property 62629 * @return {String} current value of property, if no value is given as second argument 62630 * @chainable 62631 */ 62632 _main.default.Element.prototype.style = function(prop, val) { 62633 var self = this; 62634 62635 if (val instanceof _main.default.Color) { 62636 val = 62637 'rgba(' + 62638 val.levels[0] + 62639 ',' + 62640 val.levels[1] + 62641 ',' + 62642 val.levels[2] + 62643 ',' + 62644 val.levels[3] / 255 + 62645 ')'; 62646 } 62647 62648 if (typeof val === 'undefined') { 62649 if (prop.indexOf(':') === -1) { 62650 // no value set, so assume requesting a value 62651 var styles = window.getComputedStyle(self.elt); 62652 var style = styles.getPropertyValue(prop); 62653 return style; 62654 } else { 62655 // value set using `:` in a single line string 62656 var attrs = prop.split(';'); 62657 for (var i = 0; i < attrs.length; i++) { 62658 var parts = attrs[i].split(':'); 62659 if (parts[0] && parts[1]) { 62660 this.elt.style[parts[0].trim()] = parts[1].trim(); 62661 } 62662 } 62663 } 62664 } else { 62665 // input provided as key,val pair 62666 this.elt.style[prop] = val; 62667 if ( 62668 prop === 'width' || 62669 prop === 'height' || 62670 prop === 'left' || 62671 prop === 'top' 62672 ) { 62673 var _styles = window.getComputedStyle(self.elt); 62674 var styleVal = _styles.getPropertyValue(prop); 62675 var numVal = styleVal.replace(/\D+/g, ''); 62676 this[prop] = parseInt(numVal, 10); 62677 } 62678 } 62679 return this; 62680 }; 62681 62682 /** 62683 *
62684 * Adds a new attribute or changes the value of an existing attribute 62685 * on the specified element. If no value is specified, returns the 62686 * value of the given attribute, or null if attribute is not set. 62687 * 62688 * @method attribute 62689 * @return {String} value of attribute 62690 * 62691 * @example 62692 * <div class='norender'><code> 62693 * let myDiv = createDiv('I like pandas.'); 62694 * myDiv.attribute('align', 'center'); 62695 * </code></div> 62696 */ 62697 /** 62698 * @method attribute 62699 * @param {String} attr attribute to set 62700 * @param {String} value value to assign to attribute 62701 * @chainable 62702 */ 62703 _main.default.Element.prototype.attribute = function(attr, value) { 62704 //handling for checkboxes and radios to ensure options get 62705 //attributes not divs 62706 if ( 62707 this.elt.firstChild != null && 62708 (this.elt.firstChild.type === 'checkbox' || 62709 this.elt.firstChild.type === 'radio') 62710 ) { 62711 if (typeof value === 'undefined') { 62712 return this.elt.firstChild.getAttribute(attr); 62713 } else { 62714 for (var i = 0; i < this.elt.childNodes.length; i++) { 62715 this.elt.childNodes[i].setAttribute(attr, value); 62716 } 62717 } 62718 } else if (typeof value === 'undefined') { 62719 return this.elt.getAttribute(attr); 62720 } else { 62721 this.elt.setAttribute(attr, value); 62722 return this; 62723 } 62724 }; 62725 62726 /** 62727 * 62728 * Removes an attribute on the specified element. 62729 * 62730 * @method removeAttribute 62731 * @param {String} attr attribute to remove 62732 * @chainable 62733 * 62734 * @example 62735 * <div><code> 62736 * let button; 62737 * let checkbox; 62738 * 62739 * function setup() { 62740 * checkbox = createCheckbox('enable', true); 62741 * checkbox.changed(enableButton); 62742 * button = createButton('button'); 62743 * button.position(10, 10); 62744 * } 62745 * 62746 * function enableButton() { 62747 * if (this.checked()) { 62748 * // Re-enable the button 62749 * button.removeAttribute('disabled'); 62750 * } else { 62751 * // Disable the button 62752 * button.attribute('disabled', ''); 62753 * } 62754 * } 62755 * </code></div> 62756 */ 62757 _main.default.Element.prototype.removeAttribute = function(attr) { 62758 if ( 62759 this.elt.firstChild != null && 62760 (this.elt.firstChild.type === 'checkbox' || 62761 this.elt.firstChild.type === 'radio') 62762 ) { 62763 for (var i = 0; i < this.elt.childNodes.length; i++) { 62764 this.elt.childNodes[i].removeAttribute(attr); 62765 } 62766 } 62767 this.elt.removeAttribute(attr); 62768 return this; 62769 }; 62770 62771 /** 62772 * Either returns the value of the element if no arguments 62773 * given, or sets the value of the element. 62774 * 62775 * @method value 62776 * @return {String|Number} value of the element 62777 * @example 62778 * <div class='norender'><code> 62779 * // gets the value 62780 * let inp; 62781 * function setup() { 62782 * inp = createInput(''); 62783 * } 62784 * 62785 * function mousePressed() { 62786 * print(inp.value()); 62787 * } 62788 * </code></div> 62789 * <div class='norender'><code> 62790 * // sets the value 62791 * let inp; 62792 * function setup() { 62793 * inp = createInput('myValue'); 62794 * } 62795 * 62796 * function mousePressed() { 62797 * inp.value('myValue'); 62798 * } 62799 * </code></div> 62800 */ 62801 /** 62802 * @method value 62803 * @param {String|Number} value 62804 * @chainable 62805 */ 62806 _main.default.Element.prototype.value = function() { 62807 if (arguments.length > 0) { 62808 this.elt.value = arguments[0]; 62809 return this; 62810 } else { 62811 if (this.elt.type === 'range') { 62812 return parseFloat(this.elt.value); 62813 } else return this.elt.value; 62814 } 62815 }; 62816 62817 /** 62818 * 62819 * Shows the current element. Essentially, setting display:block for the style. 62820 * 62821 * @method show 62822 * @chainable 62823 * @example 62824 * <div class='norender'><code> 62825 * let div = createDiv('div'); 62826 * div.style('display', 'none'); 62827 * div.show(); // turns display to block 62828 * </code></div> 62829 */ 62830 _main.default.Element.prototype.show = function() { 62831 this.elt.style.display = 'block'; 62832 return this; 62833 }; 62834 62835 /** 62836 * Hides the current element. Essentially, setting display:none for the style. 62837 * 62838 * @method hide 62839 * @chainable 62840 * @example 62841 * <div class='norender'><code> 62842 * let div = createDiv('this is a div'); 62843 * div.hide(); 62844 * </code></div> 62845 */ 62846 _main.default.Element.prototype.hide = function() { 62847 this.elt.style.display = 'none'; 62848 return this; 62849 }; 62850 62851 /** 62852 * 62853 * Sets the width and height of the element. AUTO can be used to 62854 * only adjust one dimension at a time. If no arguments are given, it 62855 * returns the width and height of the element in an object. In case of 62856 * elements which need to be loaded, such as images, it is recommended 62857 * to call the function after the element has finished loading. 62858 * 62859 * @method size 62860 * @return {Object} the width and height of the element in an object 62861 * @example 62862 * <div class='norender'><code> 62863 * let div = createDiv('this is a div'); 62864 * div.size(100, 100); 62865 * let img = createImg( 62866 * 'assets/rockies.jpg',
62867 * 'A tall mountain with a small forest and field in front of it on a sunny day', 62868 * '', 62869 * () => { 62870 * img.size(10, AUTO); 62871 * } 62872 * ); 62873 * </code></div> 62874 */ 62875 /** 62876 * @method size 62877 * @param {Number|Constant} w width of the element, either AUTO, or a number 62878 * @param {Number|Constant} [h] height of the element, either AUTO, or a number 62879 * @chainable 62880 */ 62881 _main.default.Element.prototype.size = function(w, h) { 62882 if (arguments.length === 0) { 62883 return { width: this.elt.offsetWidth, height: this.elt.offsetHeight }; 62884 } else { 62885 var aW = w; 62886 var aH = h; 62887 var AUTO = _main.default.prototype.AUTO; 62888 if (aW !== AUTO || aH !== AUTO) { 62889 if (aW === AUTO) { 62890 aW = h * this.width / this.height; 62891 } else if (aH === AUTO) { 62892 aH = w * this.height / this.width; 62893 } 62894 // set diff for cnv vs normal div 62895 if (this.elt instanceof HTMLCanvasElement) { 62896 var j = {}; 62897 var k = this.elt.getContext('2d'); 62898 var prop; 62899 for (prop in k) { 62900 j[prop] = k[prop]; 62901 } 62902 this.elt.setAttribute('width', aW * this._pInst._pixelDensity); 62903 this.elt.setAttribute('height', aH * this._pInst._pixelDensity); 62904 this.elt.style.width = aW + 'px'; 62905 this.elt.style.height = aH + 'px'; 62906 this._pInst.scale(this._pInst._pixelDensity, this._pInst._pixelDensity); 62907 for (prop in j) { 62908 this.elt.getContext('2d')[prop] = j[prop]; 62909 } 62910 } else { 62911 this.elt.style.width = aW + 'px'; 62912 this.elt.style.height = aH + 'px'; 62913 this.elt.width = aW; 62914 this.elt.height = aH; 62915 } 62916 62917 this.width = this.elt.offsetWidth; 62918 this.height = this.elt.offsetHeight; 62919 62920 if (this._pInst && this._pInst._curElement) { 62921 // main canvas associated with p5 instance 62922 if (this._pInst._curElement.elt === this.elt) { 62923 this._pInst._setProperty('width', this.elt.offsetWidth); 62924 this._pInst._setProperty('height', this.elt.offsetHeight); 62925 } 62926 } 62927 } 62928 return this; 62929 } 62930 }; 62931 62932 /** 62933 * Removes the element, stops all media streams, and deregisters all listeners. 62934 * @method remove 62935 * @example 62936 * <div class='norender'><code> 62937 * let myDiv = createDiv('this is some text'); 62938 * myDiv.remove(); 62939 * </code></div> 62940 */ 62941 _main.default.Element.prototype.remove = function() { 62942 // stop all audios/videos and detach all devices like microphone/camera etc 62943 // used as input/output for audios/videos. 62944 if (this instanceof _main.default.MediaElement) { 62945 this.stop(); 62946 var sources = this.elt.srcObject; 62947 if (sources !== null) { 62948 var tracks = sources.getTracks(); 62949 tracks.forEach(function(track) { 62950 track.stop(); 62951 }); 62952 } 62953 } 62954 62955 // delete the reference in this._pInst._elements 62956 var index = this._pInst._elements.indexOf(this); 62957 if (index !== -1) { 62958 this._pInst._elements.splice(index, 1); 62959 } 62960 62961 // deregister events 62962 for (var ev in this._events) { 62963 this.elt.removeEventListener(ev, this._events[ev]); 62964 } 62965 if (this.elt && this.elt.parentNode) { 62966 this.elt.parentNode.removeChild(this.elt); 62967 } 62968 }; 62969 62970 /** 62971 * Registers a callback that gets called every time a file that is 62972 * dropped on the element has been loaded. 62973 * p5 will load every dropped file into memory and pass it as a p5.File object to the callback. 62974 * Multiple files dropped at the same time will result in multiple calls to the callback. 62975 * 62976 * You can optionally pass a second callback which will be registered to the raw 62977 * <a href="https://developer.mozilla.org/en-US/docs/Web/Events/drop">drop</a> event. 62978 * The callback will thus be provided the original 62979 * <a href="https://developer.mozilla.org/en-US/docs/Web/API/DragEvent">DragEvent</a>. 62980 * Dropping multiple files at the same time will trigger the second callback once per drop, 62981 * whereas the first callback will trigger for each loaded file. 62982 * 62983 * @method drop 62984 * @param {Function} callback callback to receive loaded file, called for each file dropped. 62985 * @param {Function}
62985 [fxn] callback triggered once when files are dropped with the drop event. 62986 * @chainable 62987 * @example 62988 * <div><code> 62989 * function setup() { 62990 * let c = createCanvas(100, 100); 62991 * background(200); 62992 * textAlign(CENTER); 62993 * text('drop file', width / 2, height / 2); 62994 * c.drop(gotFile); 62995 * } 62996 * 62997 * function gotFile(file) { 62998 * background(200); 62999 * text('received file:', width / 2, height / 2); 63000 * text(file.name, width / 2, height / 2 + 50); 63001 * } 63002 * </code></div> 63003 * 63004 * <div><code> 63005 * let img; 63006 * 63007 * function setup() { 63008 * let c = createCanvas(100, 100); 63009 * background(200); 63010 * textAlign(CENTER); 63011 * text('drop image', width / 2, height / 2); 63012 * c.drop(gotFile); 63013 * } 63014 * 63015 * function draw() { 63016 * if (img) { 63017 * image(img, 0, 0, width, height); 63018 * } 63019 * } 63020 * 63021 * function gotFile(file) { 63022 * img = createImg(file.data, '').hide(); 63023 * } 63024 * </code></div> 63025 * 63026 * @alt 63027 * Canvas turns into whatever image is dragged/dropped onto it. 63028 */ 63029 _main.default.Element.prototype.drop = function(callback, fxn) { 63030 // Is the file stuff supported? 63031 if (window.File && window.FileReader && window.FileList && window.Blob) { 63032 if (!this._dragDisabled) { 63033 this._dragDisabled = true; 63034 63035 var preventDefault = function preventDefault(evt) { 63036 evt.preventDefault(); 63037 }; 63038 63039 // If you want to be able to drop you've got to turn off 63040 // a lot of default behavior. 63041 // avoid `attachListener` here, since it overrides other handlers. 63042 this.elt.addEventListener('dragover', preventDefault); 63043 63044 // If this is a drag area we need to turn off the default behavior 63045 this.elt.addEventListener('dragleave', preventDefault); 63046 } 63047 63048 // Deal with the files 63049 _main.default.Element._attachListener( 63050 'drop', 63051 function(evt) { 63052 evt.preventDefault(); 63053 // Call the second argument as a callback that receives the raw drop event 63054 if (typeof fxn === 'function') { 63055 fxn.call(this, evt); 63056 } 63057 // A FileList 63058 var files = evt.dataTransfer.files; 63059 63060 // Load each one and trigger the callback 63061 for (var i = 0; i < files.length; i++) { 63062 var f = files[i]; 63063 _main.default.File._load(f, callback); 63064 } 63065 }, 63066 this 63067 ); 63068 } else { 63069 console.log('The File APIs are not fully supported in this browser.'); 63070 } 63071 63072 return this; 63073 }; 63074 63075 // ============================================================================= 63076 // p5.MediaElement additions 63077 // ============================================================================= 63078 63079 /** 63080 * Extends <a href="#/p5.Element">p5.Element</a> to handle audio and video. In addition to the methods 63081 * of <a href="#/p5.Element">p5.Element</a>, it also contains methods for controlling media. It is not 63082 * called directly, but <a href="#/p5.MediaElement">p5.MediaElement</a>s are created by calling <a href="#/p5/createVideo">createVideo</a>, 63083 * <a href="#/p5/createAudio">createAudio</a>, and <a href="#/p5/createCapture">createCapture</a>. 63084 * 63085 * @class p5.MediaElement 63086 * @constructor 63087 * @param {String} elt DOM node that is wrapped 63088 */ 63089 _main.default.MediaElement = function(elt, pInst) { 63090 _main.default.Element.call(this, elt, pInst); 63091 63092 var self = this; 63093 this.elt.crossOrigin = 'anonymous'; 63094 63095 this._prevTime = 0; 63096 this._cueIDCounter = 0; 63097 this._cues = []; 63098 this._pixelsState = this; 63099 this._pixelDensity = 1; 63100 this._modified = false;
63101 63102 /** 63103 * Path to the media element source. 63104 * 63105 * @property src 63106 * @return {String} src 63107 * @example 63108 * <div><code> 63109 * let ele; 63110 * 63111 * function setup() { 63112 * background(250); 63113 * 63114 * //p5.MediaElement objects are usually created 63115 * //by calling the createAudio(), createVideo(), 63116 * //and createCapture() functions. 63117 * 63118 * //In this example we create 63119 * //a new p5.MediaElement via createAudio(). 63120 * ele = createAudio('assets/beat.mp3'); 63121 * 63122 * //We'll set up our example so that 63123 * //when you click on the text, 63124 * //an alert box displays the MediaElement's 63125 * //src field. 63126 * textAlign(CENTER); 63127 * text('Click Me!', width / 2, height / 2); 63128 * } 63129 * 63130 * function mouseClicked() { 63131 * //here we test if the mouse is over the 63132 * //canvas element when it's clicked 63133 * if (mouseX >= 0 && mouseX <= width && mouseY >= 0 && mouseY <= height) { 63134 * //Show our p5.MediaElement's src field 63135 * alert(ele.src); 63136 * } 63137 * } 63138 * </code></div> 63139 */ 63140 Object.defineProperty(self, 'src', { 63141 get: function get() { 63142 var firstChildSrc = self.elt.children[0].src; 63143 var srcVal = self.elt.src === window.location.href ? '' : self.elt.src; 63144 var ret = firstChildSrc === window.location.href ? srcVal : firstChildSrc; 63145 return ret; 63146 }, 63147 set: function set(newValue) { 63148 for (var i = 0; i < self.elt.children.length; i++) { 63149 self.elt.removeChild(self.elt.children[i]); 63150 } 63151 var source = document.createElement('source'); 63152 source.src = newValue; 63153 elt.appendChild(source); 63154 self.elt.src = newValue; 63155 self.modified = true; 63156 } 63157 }); 63158 63159 // private _onended callback, set by the method: onended(callback) 63160 self._onended = function() {}; 63161 self.elt.onended = function() { 63162 self._onended(self); 63163 }; 63164 }; 63165 _main.default.MediaElement.prototype = Object.create( 63166 _main.default.Element.prototype 63167 ); 63168 63169 /** 63170 * Play an HTML5 media element. 63171 * 63172 * @method play 63173 * @chainable 63174 * @example 63175 * <div><code> 63176 * let ele; 63177 * 63178 * function setup() { 63179 * //p5.MediaElement objects are usually created 63180 * //by calling the createAudio(), createVideo(), 63181 * //and createCapture() functions. 63182 * 63183 * //In this example we create 63184 * //a new p5.MediaElement via createAudio(). 63185 * ele = createAudio('assets/beat.mp3'); 63186 * 63187 * background(250); 63188 * textAlign(CENTER); 63189 * text('Click to Play!', width / 2, height / 2); 63190 * } 63191 * 63192 * function mouseClicked() { 63193 * //here we test if the mouse is over the 63194 * //canvas element when it's clicked 63195 * if (mouseX >= 0 && mouseX <= width && mouseY >= 0 && mouseY <= height) { 63196 * //Here we call the play() function on 63197 * //the p5.MediaElement we created above. 63198 * //This will start the audio sample. 63199 * ele.play(); 63200 * 63201 * background(200); 63202 * text('You clicked Play!', width / 2, height / 2); 63203 * } 63204 * } 63205 * </code></div> 63206 */ 63207 _main.default.MediaElement.prototype.play = function() { 63208 var _this = this; 63209 if (this.elt.currentTime === this.elt.duration) { 63210 this.elt.currentTime = 0; 63211 } 63212 var promise; 63213 if (this.elt.readyState > 1) { 63214 promise = this.elt.play(); 63215 } else { 63216 // in Chrome, playback cannot resume after being stopped and must reload 63217 this.elt.load(); 63218 promise = this.elt.play(); 63219 } 63220 if (promise && promise.catch) { 63221 promise.catch(function(e) { 63222 // if it's an autoplay failure error 63223 if (e.name === 'NotAllowedError') { 63224 _main.default._friendlyAutoplayError(_this.src
63224); 63225 } else { 63226 // any other kind of error 63227 console.error('Media play method encountered an unexpected error', e); 63228 } 63229 }); 63230 } 63231 return this; 63232 }; 63233 63234 /** 63235 * Stops an HTML5 media element (sets current time to zero). 63236 * 63237 * @method stop 63238 * @chainable 63239 * @example 63240 * <div><code> 63241 * //This example both starts 63242 * //and stops a sound sample 63243 * //when the user clicks the canvas 63244 * 63245 * //We will store the p5.MediaElement 63246 * //object in here 63247 * let ele; 63248 * 63249 * //while our audio is playing, 63250 * //this will be set to true 63251 * let sampleIsPlaying = false; 63252 * 63253 * function setup() { 63254 * //Here we create a p5.MediaElement object 63255 * //using the createAudio() function. 63256 * ele = createAudio('assets/beat.mp3'); 63257 * background(200); 63258 * textAlign(CENTER); 63259 * text('Click to play!', width / 2, height / 2); 63260 * } 63261 * 63262 * function mouseClicked() { 63263 * //here we test if the mouse is over the 63264 * //canvas element when it's clicked 63265 * if (mouseX >= 0 && mouseX <= width && mouseY >= 0 && mouseY <= height) { 63266 * background(200); 63267 * 63268 * if (sampleIsPlaying) { 63269 * //if the sample is currently playing 63270 * //calling the stop() function on 63271 * //our p5.MediaElement will stop 63272 * //it and reset its current 63273 * //time to 0 (i.e. it will start 63274 * //at the beginning the next time 63275 * //you play it) 63276 * ele.stop(); 63277 * 63278 * sampleIsPlaying = false; 63279 * text('Click to play!', width / 2, height / 2); 63280 * } else { 63281 * //loop our sound element until we 63282 * //call ele.stop() on it. 63283 * ele.loop(); 63284 * 63285 * sampleIsPlaying = true; 63286 * text('Click to stop!', width / 2, height / 2); 63287 * } 63288 * } 63289 * } 63290 * </code></div> 63291 */ 63292 _main.default.MediaElement.prototype.stop = function() { 63293 this.elt.pause(); 63294 this.elt.currentTime = 0; 63295 return this; 63296 }; 63297 63298 /** 63299 * Pauses an HTML5 media element. 63300 * 63301 * @method pause 63302 * @chainable 63303 * @example 63304 * <div><code> 63305 * //This example both starts 63306 * //and pauses a sound sample 63307 * //when the user clicks the canvas 63308 * 63309 * //We will store the p5.MediaElement 63310 * //object in here 63311 * let ele; 63312 * 63313 * //while our audio is playing, 63314 * //this will be set to true 63315 * let sampleIsPlaying = false; 63316 * 63317 * function setup() { 63318 * //Here we create a p5.MediaElement object 63319 * //using the createAudio() function. 63320 * ele = createAudio('assets/lucky_dragons.mp3'); 63321 * background(200); 63322 * textAlign(CENTER); 63323 * text('Click to play!', width / 2, height / 2); 63324 * } 63325 * 63326 * function mouseClicked() { 63327 * //here we test if the mouse is over the 63328 * //canvas element when it's clicked 63329 * if (mouseX >= 0 && mouseX <= width && mouseY >= 0 && mouseY <= height) { 63330 * background(200); 63331 * 63332 * if (sampleIsPlaying) { 63333 * //Calling pause() on our 63334 * //p5.MediaElement will stop it 63335 * //playing, but when we call the 63336 * //loop() or play() functions 63337 * //the sample will start from 63338 * //where we paused it. 63339 * ele.pause(); 63340 * 63341 * sampleIsPlaying = false;
63342 * text('Click to resume!', width / 2, height / 2); 63343 * } else { 63344 * //loop our sound element until we 63345 * //call ele.pause() on it. 63346 * ele.loop(); 63347 * 63348 * sampleIsPlaying = true; 63349 * text('Click to pause!', width / 2, height / 2); 63350 * } 63351 * } 63352 * } 63353 * </code></div> 63354 */ 63355 _main.default.MediaElement.prototype.pause = function() { 63356 this.elt.pause(); 63357 return this; 63358 }; 63359 63360 /** 63361 * Set 'loop' to true for an HTML5 media element, and starts playing. 63362 * 63363 * @method loop 63364 * @chainable 63365 * @example 63366 * <div><code> 63367 * //Clicking the canvas will loop 63368 * //the audio sample until the user 63369 * //clicks again to stop it 63370 * 63371 * //We will store the p5.MediaElement 63372 * //object in here 63373 * let ele; 63374 * 63375 * //while our audio is playing, 63376 * //this will be set to true 63377 * let sampleIsLooping = false; 63378 * 63379 * function setup() { 63380 * //Here we create a p5.MediaElement object 63381 * //using the createAudio() function. 63382 * ele = createAudio('assets/lucky_dragons.mp3'); 63383 * background(200); 63384 * textAlign(CENTER); 63385 * text('Click to loop!', width / 2, height / 2); 63386 * } 63387 * 63388 * function mouseClicked() { 63389 * //here we test if the mouse is over the 63390 * //canvas element when it's clicked 63391 * if (mouseX >= 0 && mouseX <= width && mouseY >= 0 && mouseY <= height) { 63392 * background(200); 63393 * 63394 * if (!sampleIsLooping) { 63395 * //loop our sound element until we 63396 * //call ele.stop() on it. 63397 * ele.loop(); 63398 * 63399 * sampleIsLooping = true; 63400 * text('Click to stop!', width / 2, height / 2); 63401 * } else { 63402 * ele.stop(); 63403 * 63404 * sampleIsLooping = false; 63405 * text('Click to loop!', width / 2, height / 2); 63406 * } 63407 * } 63408 * } 63409 * </code></div> 63410 */ 63411 _main.default.MediaElement.prototype.loop = function() { 63412 this.elt.setAttribute('loop', true); 63413 this.play(); 63414 return this; 63415 }; 63416 /** 63417 * Set 'loop' to false for an HTML5 media element. Element will stop 63418 * when it reaches the end. 63419 * 63420 * @method noLoop 63421 * @chainable 63422 * @example 63423 * <div><code> 63424 * //This example both starts 63425 * //and stops loop of sound sample 63426 * //when the user clicks the canvas 63427 * 63428 * //We will store the p5.MediaElement 63429 * //object in here 63430 * let ele; 63431 * //while our audio is playing, 63432 * //this will be set to true 63433 * let sampleIsPlaying = false; 63434 * 63435 * function setup() { 63436 * //Here we create a p5.MediaElement object 63437 * //using the createAudio() function. 63438 * ele = createAudio('assets/beat.mp3'); 63439 * background(200); 63440 * textAlign(CENTER); 63441 * text('Click to play!', width / 2, height / 2); 63442 * } 63443 * 63444 * function mouseClicked() { 63445 * //here we test if the mouse is over the 63446 * //canvas element when it's clicked 63447 * if (mouseX >= 0 && mouseX <= width && mouseY >= 0 && mouseY <= height) { 63448 * background(200); 63449 * 63450 * if (sampleIsPlaying) { 63451 * ele.noLoop(); 63452 * sampleIsPlaying = false; 63453 * text('No more Loops!', width / 2, height / 2); 63454 * } else { 63455 * ele.loop(); 63456 * sampleIsPlaying = true; 63457 * text('Click to stop looping!', width / 2, height / 2); 63458 * } 63459 * } 63460 * } 63461 * </code></div> 63462 */ 63463 _main.default.MediaElement.prototype.noLoop = function() { 63464 this.elt.removeAttribute('loop'); 63465 return this; 63466 }; 63467 63468 /** 63469 * Sets up logic to check that autoplay succeeded. 63470 * 63471 * @method setupAutoplayFailDetection 63472 * @private 63473 */ 63474 _main.default.MediaElement.prototype._setupAutoplayFailDetection = function() { 63475 var _this2 = this; 63476 var timeout = setTimeout(function() { 63477 return _main.default._friendlyAutoplayError(_this2.src); 63478 }, 500); 63479 this.elt.addEventListener( 63480 'play', 63481 function() { 63482 return clearTimeout(timeout); 63483 }, 63484 { 63485 passive: true, 63486 once: true 63487 } 63488 ); 63489 }; 63490 63491 /**
63492 * Set HTML5 media element to autoplay or not. If no argument is specified, by 63493 * default it will autoplay. 63494 * 63495 * @method autoplay 63496 * @param {Boolean} shouldAutoplay whether the element should autoplay 63497 * @chainable 63498 * @example 63499 * <div><code> 63500 * let videoElement; 63501 * function setup() { 63502 * noCanvas(); 63503 * videoElement = createVideo(['assets/small.mp4'], onVideoLoad); 63504 * } 63505 * function onVideoLoad() { 63506 * // The media will play as soon as it is loaded. 63507 * videoElement.autoplay(); 63508 * videoElement.volume(0); 63509 * videoElement.size(100, 100); 63510 * } 63511 * </code></div> 63512 * 63513 * <div><code> 63514 * let videoElement; 63515 * function setup() { 63516 * noCanvas(); 63517 * videoElement = createVideo(['assets/small.mp4'], onVideoLoad); 63518 * } 63519 * function onVideoLoad() { 63520 * // The media will not play untill some explicitly triggered. 63521 * videoElement.autoplay(false); 63522 * videoElement.volume(0); 63523 * videoElement.size(100, 100); 63524 * } 63525 * 63526 * function mouseClicked() { 63527 * videoElement.play(); 63528 * } 63529 * </code></div> 63530 * 63531 * @alt 63532 * An example of a video element which autoplays after it is loaded. 63533 * An example of a video element which waits for a trigger for playing. 63534 */ 63535 63536 _main.default.MediaElement.prototype.autoplay = function(val) { 63537 var _this3 = this; 63538 var oldVal = this.elt.getAttribute('autoplay'); 63539 this.elt.setAttribute('autoplay', val); 63540 // if we turned on autoplay 63541 if (val && !oldVal) { 63542 // bind method to this scope 63543 var setupAutoplayFailDetection = function setupAutoplayFailDetection() { 63544 return _this3._setupAutoplayFailDetection(); 63545 }; 63546 // if media is ready to play, schedule check now 63547 if (this.elt.readyState === 4) { 63548 setupAutoplayFailDetection(); 63549 } else { 63550 // otherwise, schedule check whenever it is ready 63551 this.elt.addEventListener('canplay', setupAutoplayFailDetection, { 63552 passive: true, 63553 once: true 63554 }); 63555 } 63556 } 63557 63558 return this; 63559 }; 63560 63561 /** 63562 * Sets volume for this HTML5 media element. If no argument is given, 63563 * returns the current volume. 63564 * 63565 * @method volume 63566 * @return {Number} current volume 63567 * 63568 * @example 63569 * <div><code> 63570 * let ele; 63571 * function setup() { 63572 * // p5.MediaElement objects are usually created 63573 * // by calling the createAudio(), createVideo(), 63574 * // and createCapture() functions. 63575 * // In this example we create 63576 * // a new p5.MediaElement via createAudio(). 63577 * ele = createAudio('assets/lucky_dragons.mp3'); 63578 * background(250); 63579 * textAlign(CENTER); 63580 * text('Click to Play!', width / 2, height / 2); 63581 * } 63582 * function mouseClicked() { 63583 * // Here we call the volume() function 63584 * // on the sound element to set its volume 63585 * // Volume must be between 0.0 and 1.0 63586 * ele.volume(0.2); 63587 * ele.play(); 63588 * background(200); 63589 * text('You clicked Play!', width / 2, height / 2); 63590 * } 63591 * </code></div> 63592 * <div><code> 63593 * let audio; 63594 * let counter = 0; 63595 * 63596 * function loaded() { 63597 * audio.play(); 63598 * } 63599 * 63600 * function setup() { 63601 * audio = createAudio('assets/lucky_dragons.mp3', loaded); 63602 * textAlign(CENTER); 63603 * } 63604 * 63605 * function draw() { 63606 * if (counter === 0) { 63607 * background(0, 255, 0); 63608 * text('volume(0.9)', width / 2, height / 2); 63609 * } else if (counter === 1) { 63610 * background(255, 255, 0); 63611 * text('volume(0.5)', width / 2, height / 2); 63612 * } else if (counter === 2) { 63613 * background(255, 0, 0); 63614 * text('volume(0.1)', width / 2, height / 2); 63615 * } 63616 * } 63617 * 63618 * function mousePressed() { 63619 * counter++; 63620 * if (counter === 0) { 63621 * audio.volume(0.9); 63622 * } else if (counter === 1) { 63623 * audio.volume(0.5); 63624 * } else if (counter === 2) { 63625 * audio.volume(0.1); 63626 * } else { 63627 * counter = 0; 63628 * audio.volume(0.9); 63629 * } 63630 * } 63631 * </code> 63632 * </div> 63633 */ 63634 /** 63635 * @method volume 63636 * @param {Number} val volume between 0.0 and 1.0 63637 * @chainable 63638 */ 63639 _main.default.MediaElement.prototype.volume = function(val) { 63640 if (typeof val === 'undefined') { 63641 return this.elt.volume; 63642 } else { 63643 this.elt.volume = val; 63644 } 63645 }; 63646 63647 /** 63648 * If no arguments are given, returns the current playback speed of the 63649 * element. The speed parameter sets the speed where 2.0 will play the 63650 * element twice as fast, 0.5 will play at half the speed, and -1 will play 63651 * the element in normal speed in reverse.(Note that not all browsers support 63652 * backward playback and even if they do, playback might not be smooth.) 63653 * 63654 * @method speed 63655 * @return {Number} current playback speed of the element 63656 * 63657 * @example 63658 * <div class='norender notest'><code> 63659 * //Clicking the canvas will loop 63660 * //the audio sample until the user 63661 * //clicks again to stop it 63662 * 63663 * //We will store the p5.MediaElement 63664 * //object in here 63665 * let ele; 63666 * let button; 63667 * 63668 * function setup() { 63669 * createCanvas(710, 400); 63670 * //Here we create a p5.MediaElement object 63671 * //using the createAudio() function. 63672 * ele = createAudio('assets/beat.mp3'); 63673 * ele.loop(); 63674 * background(200); 63675 * 63676 * button = createButton('2x speed'); 63677 * button.position(100, 68); 63678 * button.mousePressed(twice_speed); 63679 * 63680 * button = createButton('half speed'); 63681 * button.position(200, 68); 63682 * button.mousePressed(half_speed); 63683 * 63684 * button = createButton('reverse play'); 63685 * button.position(300, 68); 63686 * button.mousePressed(reverse_speed); 63687 * 63688 * button = createButton('STOP'); 63689 * button.position(400, 68); 63690 * button.mousePressed(stop_song); 63691 * 63692 * button = createButton('PLAY!'); 63693 * button.position(500, 68); 63694 * button.mousePressed(play_speed); 63695 * } 63696 * 63697 * function twice_speed() { 63698 * ele.speed(2); 63699 * } 63700 * 63701 * function half_speed() { 63702 * ele.speed(0.5); 63703 * } 63704 * 63705 * function reverse_speed() { 63706 * ele.speed(-1); 63707 * } 63708 * 63709 * function stop_song() { 63710 * ele.stop(); 63711 * } 63712 * 63713 * function play_speed() { 63714 * ele.play(); 63715 * } 63716 * </code></div> 63717 */ 63718 63719 /** 63720 * @method speed 63721 * @param {Number} speed speed multiplier for element playback 63722 * @chainable 63723 */ 63724 _main.default.MediaElement.prototype.speed = function(val) { 63725 if (typeof val === 'undefined') { 63726 return this.presetPlaybackRate || this.elt.playbackRate; 63727 } else { 63728 if (this.loadedmetadata) { 63729 this.elt.playbackRate = val; 63730 } else { 63731 this.presetPlaybackRate = val; 63732 } 63733 } 63734 }; 63735 63736 /** 63737 * If no arguments are given, returns the current time of the element. 63738 * If an argument is given the current time of the element is set to it. 63739 * 63740 * @method time 63741 * @return {Number} current time (in seconds) 63742 * 63743 * @example 63744 * <div><code> 63745 * let ele; 63746 * let beginning = true; 63747 * function setup() { 63748 * //p5.MediaElement objects are usually created 63749 * //by calling the createAudio(), createVideo(), 63750 * //and createCapture() functions. 63751 * 63752 * //In this example we create 63753 * //a new p5.MediaElement via createAudio(). 63754 * ele = createAudio('assets/lucky_dragons.mp3'); 63755 * background(250); 63756 * textAlign(CENTER); 63757 * text('start at beginning', width / 2, height / 2); 63758 * } 63759 *
63760 * // this function fires with click anywhere 63761 * function mousePressed() { 63762 * if (beginning === true) { 63763 * // here we start the sound at the beginning 63764 * // time(0) is not necessary here 63765 * // as this produces the same result as 63766 * // play() 63767 * ele.play().time(0); 63768 * background(200); 63769 * text('jump 2 sec in', width / 2, height / 2); 63770 * beginning = false; 63771 * } else { 63772 * // here we jump 2 seconds into the sound 63773 * ele.play().time(2); 63774 * background(250); 63775 * text('start at beginning', width / 2, height / 2); 63776 * beginning = true; 63777 * } 63778 * } 63779 * </code></div> 63780 */ 63781 /** 63782 * @method time 63783 * @param {Number} time time to jump to (in seconds) 63784 * @chainable 63785 */ 63786 _main.default.MediaElement.prototype.time = function(val) { 63787 if (typeof val === 'undefined') { 63788 return this.elt.currentTime; 63789 } else { 63790 this.elt.currentTime = val; 63791 return this; 63792 } 63793 }; 63794 63795 /** 63796 * Returns the duration of the HTML5 media element. 63797 * 63798 * @method duration 63799 * @return {Number} duration 63800 * 63801 * @example 63802 * <div><code> 63803 * let ele; 63804 * function setup() { 63805 * //p5.MediaElement objects are usually created 63806 * //by calling the createAudio(), createVideo(), 63807 * //and createCapture() functions. 63808 * //In this example we create 63809 * //a new p5.MediaElement via createAudio(). 63810 * ele = createAudio('assets/doorbell.mp3'); 63811 * background(250); 63812 * textAlign(CENTER); 63813 * text('Click to know the duration!', 10, 25, 70, 80); 63814 * } 63815 * function mouseClicked() { 63816 * ele.play(); 63817 * background(200); 63818 * //ele.duration dislpays the duration 63819 * text(ele.duration() + ' seconds', width / 2, height / 2); 63820 * } 63821 * </code></div> 63822 */ 63823 _main.default.MediaElement.prototype.duration = function() { 63824 return this.elt.duration; 63825 }; 63826 _main.default.MediaElement.prototype.pixels = []; 63827 _main.default.MediaElement.prototype._ensureCanvas = function() { 63828 if (!this.canvas) { 63829 this.canvas = document.createElement('canvas'); 63830 this.drawingContext = this.canvas.getContext('2d'); 63831 this.setModified(true); 63832 } 63833 if (this.loadedmetadata) { 63834 // wait for metadata for w/h 63835 if (this.canvas.width !== this.elt.width) { 63836 this.canvas.width = this.elt.width; 63837 this.canvas.height = this.elt.height; 63838 this.width = this.canvas.width; 63839 this.height = this.canvas.height; 63840 } 63841 63842 this.drawingContext.drawImage( 63843 this.elt, 63844 0, 63845 0, 63846 this.canvas.width, 63847 this.canvas.height 63848 ); 63849 63850 this.setModified(true); 63851 } 63852 }; 63853 _main.default.MediaElement.prototype.loadPixels = function() { 63854 this._ensureCanvas(); 63855 return _main.default.Renderer2D.prototype.loadPixels.apply(this, arguments); 63856 }; 63857 _main.default.MediaElement.prototype.updatePixels = function(x, y, w, h) { 63858 if (this.loadedmetadata) { 63859 // wait for metadata 63860 this._ensureCanvas(); 63861 _main.default.Renderer2D.prototype.updatePixels.call(this, x, y, w, h); 63862 } 63863 this.setModified(true); 63864 return this; 63865 }; 63866 _main.default.MediaElement.prototype.get = function() { 63867 this._ensureCanvas(); 63868 return _main.default.Renderer2D.prototype.get.apply(this, arguments); 63869 }; 63870 _main.default.MediaElement.prototype._getPixel = function() { 63871 this.loadPixels(); 63872 return _main.default.Renderer2D.prototype._getPixel.apply(this, arguments); 63873 }; 63874 63875 _main.default.MediaElement.prototype.set = function(x, y, imgOrCol) { 63876 if (this.loadedmetadata) { 63877 // wait for metadata 63878 this._ensureCanvas(); 63879 _main.default.Renderer2D.prototype.set.call(this, x, y, imgOrCol); 63880 this.setModified(true); 63881 } 63882 }; 63883 _main.default.MediaElement.prototype.copy = function() { 63884 this._ensureCanvas(); 63885 _main.default.prototype.copy.apply(this, arguments); 63886 }; 63887 _main.default.MediaElement.prototype.mask = function() { 63888 this.loadPixels(); 63889 this.setModified(true); 63890 _main.default.Image.prototype.mask.apply(this, arguments); 63891 }; 63892 /** 63893 * helper method for web GL mode to figure out if the element 63894 * has been modified and might need to be re-uploaded to texture 63895 * memory between frames. 63896 * @method isModified 63897 * @private 63898 * @return {boolean} a boolean indicating whether or not the 63899 * image has been updated or modified since last texture upload. 63900 */ 63901 _main.default.MediaElement.prototype.isModified = function() { 63902 return this._modified; 63903 }; 63904 /** 63905 * helper method for web GL mode to indicate that an element has been 63906 * changed or unchanged since last upload. gl texture upload will 63907 * set this value to false after uploading the texture; or might set 63908 * it to true if metadata has become available but there is no actual 63909 * texture data available yet.. 63910 * @method setModified 63911 * @param {boolean} val sets whether or not the element has been 63912 * modified. 63913 * @private 63914 */ 63915 _main.default.MediaElement.prototype.setModified = function(value) { 63916 this._modified = value; 63917 }; 63918 /** 63919 * Schedule an event to be called when the audio or video 63920 * element reaches the end. If the element is looping, 63921 * this will not be called. The element is passed in 63922 * as the argument to the onended callback. 63923 * 63924 * @method onended 63925 * @param {Function} callback function to call when the 63926 * soundfile has ended. The 63927 * media element will be passed 63928 * in as the argument to the 63929 * callback. 63930 * @chainable 63931 * @example 63932 * <div><code> 63933 * function setup() { 63934 * let audioEl = createAudio('assets/beat.mp3'); 63935 * audioEl.showControls(); 63936 * audioEl.onended(sayDone); 63937 * } 63938 * 63939 * function sayDone(elt) { 63940 * alert('done playing ' + elt.src); 63941 * } 63942 * </code></div> 63943 */ 63944 _main.default.MediaElement.prototype.onended = function(callback) { 63945 this._onended = callback; 63946 return this; 63947 }; 63948 63949 /*** CONNECT TO WEB AUDIO API / p5.sound.js ***/ 63950 63951 /** 63952 * Send the audio output of this element to a specified audioNode or 63953 * p5.sound object. If no element is provided, connects to p5's main 63954 * output. That connection is established when this method is first called. 63955 * All connections are removed by the .disconnect() method. 63956 * 63957 * This method is meant to be used with the p5.sound.js addon library. 63958 * 63959 * @method connect 63960 * @param {AudioNode|Object} audioNode AudioNode from the Web Audio API, 63961 * or an object from the p5.sound library 63962 */ 63963 _main.default.MediaElement.prototype.connect = function(obj) { 63964 var audioContext, mainOutput; 63965 63966 // if p5.sound exists, same audio context 63967 if (typeof _main.default.prototype.getAudioContext === 'function') { 63968 audioContext = _main.default.prototype.getAudioContext(); 63969 mainOutput = _main.default.soundOut.input; 63970 } else { 63971 try { 63972 audioContext = obj.context; 63973 mainOutput = audioContext.destination; 63974 } catch (e) { 63975 throw 'connect() is meant to be used with Web Audio API or p5.sound.js'; 63976 } 63977 } 63978 63979 // create a Web Audio MediaElementAudioSourceNode if none already exists 63980 if (!this.audioSourceNode) { 63981 this.audioSourceNode = audioContext.createMediaElementSource(this.elt); 63982 63983 // connect to main output when this method is first called 63984 this.audioSourceNode.connect(mainOutput); 63985 } 63986 63987 // connect to object if provided 63988 if (obj) { 63989 if (obj.input) { 63990 this.audioSourceNode.connect(obj.input); 63991 } else { 63992 this.audioSourceNode.connect(obj); 63993 } 63994 } else { 63995 // otherwise connect to main output of p5.sound / AudioContext 63996 this.audioSourceNode.connect(mainOutput); 63997 } 63998 }; 63999 64000 /** 64001 * Disconnect all Web Audio routing, including to main output. 64002 * This is useful if you want to re-route the output through 64003 * audio effects, for example. 64004 * 64005 * @method disconnect 64006 */ 64007 _main.default.MediaElement.prototype.disconnect = function() { 64008 if (this.audioSourceNode) { 64009 this.audioSourceNode.disconnect(); 64010 } else { 64011 throw 'nothing to disconnect'; 64012 } 64013 }; 64014 64015 /*** SHOW / HIDE CONTROLS ***/ 64016 64017 /** 64018 * Show the default MediaElement controls, as determined by the web browser. 64019 * 64020 * @method showControls 64021 * @example 64022 * <div><code> 64023 * let ele; 64024 * function setup() { 64025 * //p5.MediaElement objects are usually created 64026 * //by calling the createAudio(), createVideo(), 64027 * //and createCapture() functions. 64028 * //In this example we create 64029 * //a new p5.MediaElement via createAudio() 64030 * ele = createAudio('assets/lucky_dragons.mp3'); 64031 * background(200); 64032 * textAlign(CENTER); 64033 * text('Click to Show Controls!', 10, 25, 70, 80); 64034 * } 64035 * function mousePressed() { 64036 * ele.showControls(); 64037 * background(200); 64038 * text('Controls Shown', width / 2, height / 2); 64039 * } 64040 * </code></div> 64041 */ 64042 _main.default.MediaElement.prototype.showControls = function() { 64043 // must set style for the element to show on the page 64044 this.elt.style['text-align'] = 'inherit'; 64045 this.elt.controls = true; 64046 }; 64047 64048 /** 64049 * Hide the default mediaElement controls. 64050 * @method hideControls 64051 * @example 64052 * <div><code> 64053 * let ele; 64054 * function setup() { 64055 * //p5.MediaElement objects are usually created 64056 * //by calling the createAudio(), createVideo(), 64057 * //and createCapture() functions. 64058 * //In this example we create 64059 * //a new p5.MediaElement via createAudio() 64060 * ele = createAudio('assets/lucky_dragons.mp3'); 64061 * ele.showControls(); 64062 * background(200); 64063 * textAlign(CENTER); 64064 * text('Click to hide Controls!', 10, 25, 70, 80); 64065 * } 64066 * function mousePressed() { 64067 * ele.hideControls(); 64068 * background(200); 64069 * text('Controls hidden', width / 2, height / 2); 64070 * } 64071 * </code></div> 64072 */ 64073 _main.default.MediaElement.prototype.hideControls = function() { 64074 this.elt.controls = false;
64075 }; 64076 64077 /*** SCHEDULE EVENTS ***/ 64078 64079 // Cue inspired by JavaScript setTimeout, and the 64080 // Tone.js Transport Timeline Event, MIT License Yotam Mann 2015 tonejs.org 64081 var Cue = function Cue(callback, time, id, val) { 64082 this.callback = callback; 64083 this.time = time; 64084 this.id = id; 64085 this.val = val; 64086 }; 64087 64088 /** 64089 * Schedule events to trigger every time a MediaElement 64090 * (audio/video) reaches a playback cue point. 64091 * 64092 * Accepts a callback function, a time (in seconds) at which to trigger 64093 * the callback, and an optional parameter for the callback. 64094 * 64095 * Time will be passed as the first parameter to the callback function, 64096 * and param will be the second parameter. 64097 * 64098 * @method addCue 64099 * @param {Number} time Time in seconds, relative to this media 64100 * element's playback. For example, to trigger 64101 * an event every time playback reaches two 64102 * seconds, pass in the number 2. This will be 64103 * passed as the first parameter to 64104 * the callback function. 64105 * @param {Function} callback Name of a function that will be 64106 * called at the given time. The callback will 64107 * receive time and (optionally) param as its 64108 * two parameters. 64109 * @param {Object} [value] An object to be passed as the 64110 * second parameter to the 64111 * callback function. 64112 * @return {Number} id ID of this cue, 64113 * useful for removeCue(id) 64114 * @example 64115 * <div><code> 64116 * // 64117 * // 64118 * function setup() { 64119 * createCanvas(200, 200); 64120 * 64121 * let audioEl = createAudio('assets/beat.mp3'); 64122 * audioEl.showControls(); 64123 * 64124 * // schedule three calls to changeBackground 64125 * audioEl.addCue(0.5, changeBackground, color(255, 0, 0)); 64126 * audioEl.addCue(1.0, changeBackground, color(0, 255, 0)); 64127 * audioEl.addCue(2.5, changeBackground, color(0, 0, 255)); 64128 * audioEl.addCue(3.0, changeBackground, color(0, 255, 255)); 64129 * audioEl.addCue(4.2, changeBackground, color(255, 255, 0)); 64130 * audioEl.addCue(5.0, changeBackground, color(255, 255, 0)); 64131 * } 64132 * 64133 * function changeBackground(val) { 64134 * background(val); 64135 * } 64136 * </code></div> 64137 */ 64138 _main.default.MediaElement.prototype.addCue = function(time, callback, val) { 64139 var id = this._cueIDCounter++; 64140 64141 var cue = new Cue(callback, time, id, val); 64142 this._cues.push(cue); 64143 64144 if (!this.elt.ontimeupdate) { 64145 this.elt.ontimeupdate = this._onTimeUpdate.bind(this); 64146 } 64147 64148 return id; 64149 }; 64150 64151 /** 64152 * Remove a callback based on its ID. The ID is returned by the 64153 * addCue method. 64154 * @method removeCue 64155 * @param {Number} id ID of the cue, as returned by addCue 64156 * @example 64157 * <div><code> 64158 * let audioEl, id1, id2; 64159 * function setup() { 64160 * background(255, 255, 255); 64161 * audioEl = createAudio('assets/beat.mp3'); 64162 * audioEl.showControls(); 64163 * // schedule five calls to changeBackground 64164 * id1 = audioEl.addCue(0.5, changeBackground, color(255, 0, 0)); 64165 * audioEl.addCue(1.0, changeBackground, color(0, 255, 0)); 64166 * audioEl.addCue(2.5, changeBackground, color(0, 0, 255)); 64167 * audioEl.addCue(3.0, changeBackground, color(0, 255, 255));
64168 * id2 = audioEl.addCue(4.2, changeBackground, color(255, 255, 0)); 64169 * text('Click to remove first and last Cue!', 10, 25, 70, 80); 64170 * } 64171 * function mousePressed() { 64172 * audioEl.removeCue(id1); 64173 * audioEl.removeCue(id2); 64174 * } 64175 * function changeBackground(val) { 64176 * background(val); 64177 * } 64178 * </code></div> 64179 */ 64180 _main.default.MediaElement.prototype.removeCue = function(id) { 64181 for (var i = 0; i < this._cues.length; i++) { 64182 if (this._cues[i].id === id) { 64183 console.log(id); 64184 this._cues.splice(i, 1); 64185 } 64186 } 64187 64188 if (this._cues.length === 0) { 64189 this.elt.ontimeupdate = null; 64190 } 64191 }; 64192 64193 /** 64194 * Remove all of the callbacks that had originally been scheduled 64195 * via the addCue method. 64196 * @method clearCues 64197 * @param {Number} id ID of the cue, as returned by addCue 64198 * @example 64199 * <div><code> 64200 * let audioEl; 64201 * function setup() { 64202 * background(255, 255, 255); 64203 * audioEl = createAudio('assets/beat.mp3'); 64204 * //Show the default MediaElement controls, as determined by the web browser 64205 * audioEl.showControls(); 64206 * // schedule calls to changeBackground 64207 * background(200); 64208 * text('Click to change Cue!', 10, 25, 70, 80); 64209 * audioEl.addCue(0.5, changeBackground, color(255, 0, 0)); 64210 * audioEl.addCue(1.0, changeBackground, color(0, 255, 0)); 64211 * audioEl.addCue(2.5, changeBackground, color(0, 0, 255)); 64212 * audioEl.addCue(3.0, changeBackground, color(0, 255, 255)); 64213 * audioEl.addCue(4.2, changeBackground, color(255, 255, 0)); 64214 * } 64215 * function mousePressed() { 64216 * // here we clear the scheduled callbacks 64217 * audioEl.clearCues(); 64218 * // then we add some more callbacks 64219 * audioEl.addCue(1, changeBackground, color(2, 2, 2)); 64220 * audioEl.addCue(3, changeBackground, color(255, 255, 0)); 64221 * } 64222 * function changeBackground(val) { 64223 * background(val); 64224 * } 64225 * </code></div> 64226 */ 64227 _main.default.MediaElement.prototype.clearCues = function() { 64228 this._cues = []; 64229 this.elt.ontimeupdate = null; 64230 }; 64231 64232 // private method that checks for cues to be fired if events 64233 // have been scheduled using addCue(callback, time).
64234 _main.default.MediaElement.prototype._onTimeUpdate = function() { 64235 var playbackTime = this.time(); 64236 64237 for (var i = 0; i < this._cues.length; i++) { 64238 var callbackTime = this._cues[i].time; 64239 var val = this._cues[i].val; 64240 64241 if (this._prevTime < callbackTime && callbackTime <= playbackTime) { 64242 // pass the scheduled callbackTime as parameter to the callback 64243 this._cues[i].callback(val); 64244 } 64245 } 64246 64247 this._prevTime = playbackTime; 64248 }; 64249 64250 /** 64251 * Base class for a file. 64252 * Used for Element.drop and createFileInput. 64253 * 64254 * @class p5.File 64255 * @constructor 64256 * @param {File} file File that is wrapped 64257 */ 64258 _main.default.File = function(file, pInst) { 64259 /** 64260 * Underlying File object. All normal File methods can be called on this. 64261 * 64262 * @property file 64263 */ 64264 this.file = file; 64265 64266 this._pInst = pInst; 64267 64268 // Splitting out the file type into two components 64269 // This makes determining if image or text etc simpler 64270 var typeList = file.type.split('/'); 64271 /** 64272 * File type (image, text, etc.) 64273 * 64274 * @property type 64275 */ 64276 this.type = typeList[0]; 64277 /** 64278 * File subtype (usually the file extension jpg, png, xml, etc.) 64279 * 64280 * @property subtype 64281 */ 64282 this.subtype = typeList[1]; 64283 /** 64284 * File name 64285 * 64286 * @property name 64287 */ 64288 this.name = file.name; 64289 /** 64290 * File size 64291 * 64292 * @property size 64293 */ 64294 this.size = file.size; 64295 64296 /** 64297 * URL string containing either image data, the text contents of the file or 64298 * a parsed object if file is JSON and p5.XML if XML 64299 * 64300 * @property data 64301 */ 64302 this.data = undefined; 64303 }; 64304 64305 _main.default.File._createLoader = function(theFile, callback) { 64306 var reader = new FileReader(); 64307 reader.onload = function(e) { 64308 var p5file = new _main.default.File(theFile); 64309 if (p5file.file.type === 'application/json') { 64310 // Parse JSON and store the result in data 64311 p5file.data = JSON.parse(e.target.result); 64312 } else if (p5file.file.type === 'text/xml') { 64313 // Parse XML, wrap it in p5.XML and store the result in data 64314 var parser = new DOMParser(); 64315 var xml = parser.parseFromString(e.target.result, 'text/xml'); 64316 p5file.data = new _main.default.XML(xml.documentElement); 64317 } else { 64318 p5file.data = e.target.result; 64319 } 64320 callback(p5file); 64321 }; 64322 return reader; 64323 }; 64324 64325 _main.default.File._load = function(f, callback) { 64326 // Text or data? 64327 // This should likely be improved 64328 if (/^text\//.test(f.type) || f.type === 'application/json') { 64329 _main.default.File._createLoader(f, callback).readAsText(f); 64330 } else if (!/^(video|audio)\//.test(f.type)) { 64331 _main.default.File._createLoader(f, callback).readAsDataURL(f); 64332 } else { 64333 var file = new _main.default.File(f); 64334 file.data = URL.createObjectURL(f); 64335 callback(file); 64336 } 64337 }; 64338 var _default = _main.default; 64339 exports.default = _default; 64340 }, 64341 { '../core/main': 59 } 64342 ], 64343 76: [ 64344 function(_dereq_, module, exports) { 64345 'use strict'; 64346 function _typeof(obj) { 64347 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') { 64348 _typeof = function _typeof(obj) { 64349 return typeof obj; 64350 }; 64351 } else { 64352 _typeof = function _typeof(obj) { 64353 return obj && 64354 typeof Symbol === 'function' && 64355 obj.constructor === Symbol && 64356 obj !== Symbol.prototype 64357 ? 'symbol' 64358 : typeof obj; 64359 }; 64360 } 64361 return _typeof(obj); 64362 } 64363 Object.defineProperty(exports, '__esModule', { value: true }); 64364 exports.default = void 0; 64365 64366 var _main = _interopRequireDefault(_dereq_('../core/main')); 64367 var constants = _interopRequireWildcard(_dereq_('../core/constants')); 64368 function _getRequireWildcardCache() { 64369 if (typeof WeakMap !== 'function') return null; 64370 var cache = new WeakMap(); 64371 _getRequireWildcardCache = function _getRequireWildcardCache() { 64372 return cache; 64373 }; 64374 return cache; 64375 } 64376 function _interopRequireWildcard(obj) { 64377 if (obj && obj.__esModule) { 64378 return obj; 64379 } 64380 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) { 64381 return { default: obj }; 64382 } 64383 var cache = _getRequireWildcardCache(); 64384 if (cache && cache.has(obj)) { 64385 return cache.get(obj); 64386 } 64387 var newObj = {}; 64388 var hasPropertyDescriptor = 64389 Object.defineProperty && Object.getOwnPropertyDescriptor; 64390 for (var key in obj) { 64391 if (Object.prototype.hasOwnProperty.call(obj, key)) { 64392 var desc = hasPropertyDescriptor 64393 ? Object.getOwnPropertyDescriptor(obj, key) 64394 : null; 64395 if (desc && (desc.get || desc.set)) { 64396 Object.defineProperty(newObj, key, desc); 64397 } else { 64398 newObj[key] = obj[key]; 64399 } 64400 } 64401 } 64402 newObj.default = obj; 64403 if (cache) { 64404 cache.set(obj, newObj); 64405 } 64406 return newObj; 64407 } 64408 function _interopRequireDefault(obj) { 64409 return obj && obj.__esModule ? obj : { default: obj }; 64410 } 64411 /** 64412 * @module Events 64413 * @submodule Acceleration 64414 * @for p5 64415 * @requires core 64416 */ /** 64417 * The system variable deviceOrientation always contains the orientation of 64418 * the device. The value of this variable will either be set 'landscape' 64419 * or 'portrait'. If no data is available it will be set to 'undefined'. 64420 * either LANDSCAPE or PORTRAIT. 64421 * 64422 * @property {Constant} deviceOrientation 64423 * @readOnly 64424 */ _main.default.prototype.deviceOrientation = 64425 window.innerWidth / window.innerHeight > 1.0 ? 'landscape' : 'portrait'; 64426 /** 64427 * The system variable accelerationX always contains the acceleration of the
64428 * device along the x axis. Value is represented as meters per second squared. 64429 * 64430 * @property {Number} accelerationX 64431 * @readOnly 64432 * @example 64433 * <div> 64434 * <code> 64435 * // Move a touchscreen device to register 64436 * // acceleration changes. 64437 * function draw() { 64438 * background(220, 50); 64439 * fill('magenta'); 64440 * ellipse(width / 2, height / 2, accelerationX); 64441 * } 64442 * </code> 64443 * </div> 64444 * @alt 64445 * Magnitude of device acceleration is displayed as ellipse size 64446 */ 64447 _main.default.prototype.accelerationX = 0; 64448 64449 /** 64450 * The system variable accelerationY always contains the acceleration of the 64451 * device along the y axis. Value is represented as meters per second squared. 64452 * 64453 * @property {Number} accelerationY 64454 * @readOnly 64455 * @example 64456 * <div> 64457 * <code> 64458 * // Move a touchscreen device to register 64459 * // acceleration changes. 64460 * function draw() { 64461 * background(220, 50); 64462 * fill('magenta'); 64463 * ellipse(width / 2, height / 2, accelerationY); 64464 * } 64465 * </code> 64466 * </div> 64467 * @alt 64468 * Magnitude of device acceleration is displayed as ellipse size 64469 */ 64470 _main.default.prototype.accelerationY = 0; 64471 64472 /** 64473 * The system variable accelerationZ always contains the acceleration of the 64474 * device along the z axis. Value is represented as meters per second squared. 64475 * 64476 * @property {Number} accelerationZ 64477 * @readOnly 64478 * 64479 * @example 64480 * <div> 64481 * <code> 64482 * // Move a touchscreen device to register 64483 * // acceleration changes. 64484 * function draw() { 64485 * background(220, 50); 64486 * fill('magenta'); 64487 * ellipse(width / 2, height / 2, accelerationZ); 64488 * } 64489 * </code> 64490 * </div> 64491 * 64492 * @alt 64493 * Magnitude of device acceleration is displayed as ellipse size 64494 */ 64495 _main.default.prototype.accelerationZ = 0; 64496 64497 /** 64498 * The system variable pAccelerationX always contains the acceleration of the 64499 * device along the x axis in the frame previous to the current frame. Value 64500 * is represented as meters per second squared. 64501 * 64502 * @property {Number} pAccelerationX 64503 * @readOnly 64504 */ 64505 _main.default.prototype.pAccelerationX = 0; 64506 64507 /** 64508 * The system variable pAccelerationY always contains the acceleration of the 64509 * device along the y axis in the frame previous to the current frame. Value 64510 * is represented as meters per second squared. 64511 * 64512 * @property {Number} pAccelerationY 64513 * @readOnly 64514 */ 64515 _main.default.prototype.pAccelerationY = 0; 64516 64517 /** 64518 * The system variable pAccelerationZ always contains the acceleration of the 64519 * device along the z axis in the frame previous to the current frame. Value 64520 * is represented as meters per second squared. 64521 * 64522 * @property {Number} pAccelerationZ 64523 * @readOnly 64524 */ 64525 _main.default.prototype.pAccelerationZ = 0; 64526 64527 /** 64528 * _updatePAccelerations updates the pAcceleration values 64529 * 64530 * @private 64531 */ 64532 _main.default.prototype._updatePAccelerations = function() { 64533 this._setProperty('pAccelerationX', this.accelerationX); 64534 this._setProperty('pAccelerationY', this.accelerationY); 64535 this._setProperty('pAccelerationZ', this.accelerationZ); 64536 }; 64537 64538 /** 64539 * The system variable rotationX always contains the rotation of the 64540 * device along the x axis. If the sketch <a href="#/p5/angleMode"> 64541 * angleMode()</a> is set to DEGREES, the value will be -180 to 180. If 64542 * it is set to RADIANS, the value will be -PI to PI. 64543 * 64544 * Note: The order the rotations are called is important, ie. if used 64545 * together, it must be called in the order Z-X-Y or there might be 64546 * unexpected behaviour. 64547 * 64548 * @property {Number} rotationX 64549 * @readOnly 64550 * @example 64551 * <div> 64552 * <code> 64553 * function setup() { 64554 * createCanvas(100, 100, WEBGL); 64555 * } 64556 * 64557 * function draw() { 64558 * background(200); 64559 * //rotateZ(radians(rotationZ)); 64560 * rotateX(radians(rotationX)); 64561 * //rotateY(radians(rotationY)); 64562 * box(200, 200, 200); 64563 * } 64564 * </code> 64565 * </div> 64566 * @alt 64567 * red horizontal line right, green vertical line bottom. black background. 64568 */ 64569 _main.default.prototype.rotationX = 0; 64570 64571 /** 64572 * The system variable rotationY always contains the rotation of the 64573 * device along the y axis. If the sketch <a href="#/p5/angleMode"> 64574 * angleMode()</a> is set to DEGREES, the value will be -90 to 90. If 64575 * it is set to RADIANS, the value will be -PI/2 to PI/2. 64576 * 64577 * Note: The order the rotations are called is important, ie. if used 64578 * together, it must be called in the order Z-X-Y or there might be 64579 * unexpected behaviour. 64580 * 64581 * @property {Number} rotationY 64582 * @readOnly 64583 * @example 64584 * <div> 64585 * <code> 64586 * function setup() { 64587 * createCanvas(100, 100, WEBGL); 64588 * } 64589 * 64590 * function draw() { 64591 * background(200); 64592 * //rotateZ(radians(rotationZ)); 64593 * //rotateX(radians(rotationX)); 64594 * rotateY(radians(rotationY)); 64595 * box(200, 200, 200); 64596 * } 64597 * </code> 64598 * </div> 64599 * @alt 64600 * red horizontal line right, green vertical line bottom. black background. 64601 */ 64602 _main.default.prototype.rotationY = 0; 64603 64604 /** 64605 * The system variable rotationZ always contains the rotation of the 64606 * device along the z axis. If the sketch <a href="#/p5/angleMode"> 64607 * angleMode()</a> is set to DEGREES, the value will be 0 to 360. If 64608 * it is set to RADIANS, the value will be 0 to 2*PI. 64609 * 64610 * Unlike rotationX and rotationY, this variable is available for devices 64611 * with a built-in compass only. 64612 * 64613 * Note: The order the rotations are called is important, ie. if used 64614 * together, it must be called in the order Z-X-Y or there might be 64615 * unexpected behaviour. 64616 * 64617 * @example 64618 * <div> 64619 * <code> 64620 * function setup() { 64621 * createCanvas(100, 100, WEBGL); 64622 * } 64623 * 64624 * function draw() { 64625 * background(200); 64626 * rotateZ(radians(rotationZ)); 64627 * //rotateX(radians(rotationX)); 64628 * //rotateY(radians(rotationY)); 64629 * box(200, 200, 200); 64630 * } 64631 * </code> 64632 * </div> 64633 * 64634 * @property {Number} rotationZ 64635 * @readOnly 64636 * 64637 * @alt 64638 * red horizontal line right, green vertical line bottom. black background. 64639 */ 64640 _main.default.prototype.rotationZ = 0; 64641 64642 /** 64643 * The system variable pRotationX always contains the rotation of the 64644 * device along the x axis in the frame previous to the current frame. 64645 * If the sketch <a href="#/p5/angleMode"> angleMode()</a> is set to DEGREES, 64646 * the value will be -180 to 180. If it is set to RADIANS, the value will 64647 * be -PI to PI. 64648 * 64649 * pRotationX can also be used with rotationX to determine the rotate 64650 * direction of the device along the X-axis. 64651 * @example 64652 * <div class='norender'> 64653 * <code> 64654 * // A simple if statement looking at whether 64655 * // rotationX - pRotationX < 0 is true or not will be 64656 * // sufficient for determining the rotate direction 64657 * // in most cases. 64658 * 64659 * // Some extra logic is needed to account for cases where 64660 * // the angles wrap around. 64661 * let rotateDirection = 'clockwise'; 64662 * 64663 * // Simple range conversion to make things simpler. 64664 * // This is not absolutely necessary but the logic 64665 * // will be different in that case. 64666 * 64667 * let rX = rotationX + 180; 64668 * let pRX = pRotationX + 180; 64669 * 64670 * if ((rX - pRX > 0 && rX - pRX < 270) || rX - pRX < -270) { 64671 * rotateDirection = 'clockwise'; 64672 * } else if (rX - pRX < 0 || rX - pRX > 270) { 64673 * rotateDirection = 'counter-clockwise'; 64674 * } 64675 * 64676 * print(rotateDirection); 64677 * </code> 64678 * </div> 64679 * 64680 * @alt 64681 * no image to display. 64682 * 64683 * @property {Number} pRotationX 64684 * @readOnly 64685 */ 64686 _main.default.prototype.pRotationX = 0; 64687 64688 /** 64689 * The system variable pRotationY always contains the rotation of the 64690 * device along the y axis in the frame previous to the current frame. 64691 * If the sketch <a href="#/p5/angleMode"> angleMode()</a> is set to DEGREES, 64692 * the value will be -90 to 90. If it is set to RADIANS, the value will 64693 * be -PI/2 to PI/2. 64694 * 64695 * pRotationY can also be used with rotationY to determine the rotate 64696 * direction of the device along the Y-axis. 64697 * @example 64698 * <div class='norender'> 64699 * <code> 64700 * // A simple if statement looking at whether 64701 * // rotationY - pRotationY < 0 is true or not will be 64702 * // sufficient for determining the rotate direction 64703 * // in most cases. 64704 * 64705 * // Some extra logic is needed to account for cases where 64706 * // the angles wrap around. 64707 * let rotateDirection = 'clockwise'; 64708 * 64709 * // Simple range conversion to make things simpler. 64710 * // This is not absolutely necessary but the logic 64711 * // will be different in that case. 64712 * 64713 * let rY = rotationY + 180; 64714 * let pRY = pRotationY + 180; 64715 * 64716 * if ((rY - pRY > 0 && rY - pRY < 270) || rY - pRY < -270) { 64717 * rotateDirection = 'clockwise'; 64718 * } else if (rY - pRY < 0 || rY - pRY > 270) { 64719 * rotateDirection = 'counter-clockwise'; 64720 * } 64721 * print(rotateDirection); 64722 * </code> 64723 * </div> 64724 * 64725 * @alt 64726 * no image to display. 64727 * 64728 * @property {Number} pRotationY 64729 * @readOnly 64730 */ 64731 _main.default.prototype.pRotationY = 0; 64732 64733 /** 64734 * The system variable pRotationZ always contains the rotation of the 64735 * device along the z axis in the frame previous to the current frame. 64736 * If the sketch <a href="#/p5/angleMode"> angleMode()</a> is set to DEGREES, 64737 * the value will be 0 to 360. If it is set to RADIANS, the value will 64738 * be 0 to 2*PI. 64739 * 64740 * pRotationZ can also be used with rotationZ to determine the rotate 64741 * direction of the device along the Z-axis. 64742 * @example 64743 * <div class='norender'> 64744 * <code> 64745 * // A simple if statement looking at whether 64746 * // rotationZ - pRotationZ < 0 is true or not will be 64747 * // sufficient for determining the rotate direction 64748 * // in most cases. 64749 * 64750 * // Some extra logic is needed to account for cases where 64751 * // the angles wrap around. 64752 * let rotateDirection = 'clockwise'; 64753 * 64754 * if ( 64755 * (rotationZ - pRotationZ > 0 && rotationZ - pRotationZ < 270) || 64756 * rotationZ - pRotationZ < -270 64757 * ) { 64758 * rotateDirection = 'clockwise'; 64759 * } else if (rotationZ - pRotationZ < 0 || rotationZ - pRotationZ > 270) { 64760 * rotateDirection = 'counter-clockwise'; 64761 * } 64762 * print(rotateDirection); 64763 * </code> 64764 * </div> 64765 * 64766 * @alt 64767 * no image to display. 64768 * 64769 * @property {Number} pRotationZ 64770 * @readOnly 64771 */ 64772 _main.default.prototype.pRotationZ = 0; 64773 64774 var startAngleX = 0; 64775 var startAngleY = 0; 64776 var startAngleZ = 0; 64777 64778 var rotateDirectionX = 'clockwise'; 64779 var rotateDirectionY = 'clockwise'; 64780 var rotateDirectionZ = 'clockwise'; 64781 64782 _main.default.prototype.pRotateDirectionX = undefined; 64783 _main.default.prototype.pRotateDirectionY = undefined; 64784 _main.default.prototype.pRotateDirectionZ = undefined; 64785 64786 _main.default.prototype._updatePRotations = function() { 64787 this._setProperty('pRotationX', this.rotationX); 64788 this._setProperty('pRotationY', this.rotationY); 64789 this._setProperty('pRotationZ', this.rotationZ); 64790 }; 64791 64792 /** 64793 * When a device is rotated, the axis that triggers the <a href="#/p5/deviceTurned">deviceTurned()</a> 64794 * method is stored in the turnAxis variable. The turnAxis variable is only defined within 64795 * the scope of deviceTurned(). 64796 * @property {String} turnAxis 64797 * @readOnly 64798 * @example 64799 * <div> 64800 * <code> 64801 * // Run this example on a mobile device 64802 * // Rotate the device by 90 degrees in the 64803 * // X-axis to change the value. 64804 * 64805 * let value = 0; 64806 * function draw() { 64807 * fill(value); 64808 * rect(25, 25, 50, 50); 64809 * } 64810 * function deviceTurned() { 64811 * if (turnAxis === 'X') { 64812 * if (value === 0) { 64813 * value = 255; 64814 * }
64814 else if (value === 255) { 64815 * value = 0; 64816 * } 64817 * } 64818 * } 64819 * </code> 64820 * </div> 64821 * 64822 * @alt 64823 * 50x50 black rect in center of canvas. turns white on mobile when device turns 64824 * 50x50 black rect in center of canvas. turns white on mobile when x-axis turns 64825 */ 64826 _main.default.prototype.turnAxis = undefined; 64827 64828 var move_threshold = 0.5; 64829 var shake_threshold = 30; 64830 64831 /** 64832 * The <a href="#/p5/setMoveThreshold">setMoveThreshold()</a> function is used to set the movement threshold for 64833 * the <a href="#/p5/deviceMoved">deviceMoved()</a> function. The default threshold is set to 0.5. 64834 * 64835 * @method setMoveThreshold 64836 * @param {number} value The threshold value 64837 * @example 64838 * <div class="norender"> 64839 * <code> 64840 * // Run this example on a mobile device 64841 * // You will need to move the device incrementally further 64842 * // the closer the square's color gets to white in order to change the value. 64843 * 64844 * let value = 0; 64845 * let threshold = 0.5; 64846 * function setup() { 64847 * setMoveThreshold(threshold); 64848 * } 64849 * function draw() { 64850 * fill(value); 64851 * rect(25, 25, 50, 50); 64852 * } 64853 * function deviceMoved() { 64854 * value = value + 5; 64855 * threshold = threshold + 0.1; 64856 * if (value > 255) { 64857 * value = 0; 64858 * threshold = 30; 64859 * } 64860 * setMoveThreshold(threshold); 64861 * } 64862 * </code> 64863 * </div> 64864 * 64865 * @alt 64866 * 50x50 black rect in center of canvas. turns white on mobile when device moves 64867 */ 64868 64869 _main.default.prototype.setMoveThreshold = function(val) { 64870 _main.default._validateParameters('setMoveThreshold', arguments); 64871 move_threshold = val; 64872 }; 64873 64874 /** 64875 * The <a href="#/p5/setShakeThreshold">setShakeThreshold()</a> function is used to set the movement threshold for 64876 * the <a href="#/p5/deviceShaken">deviceShaken()</a> function. The default threshold is set to 30. 64877 * 64878 * @method setShakeThreshold 64879 * @param {number} value The threshold value 64880 * @example 64881 * <div class="norender"> 64882 * <code> 64883 * // Run this example on a mobile device 64884 * // You will need to shake the device more firmly 64885 * // the closer the box's fill gets to white in order to change the value. 64886 * 64887 * let value = 0; 64888 * let threshold = 30; 64889 * function setup() { 64890 * setShakeThreshold(threshold); 64891 * } 64892 * function draw() { 64893 * fill(value); 64894 * rect(25, 25, 50, 50); 64895 * } 64896 * function deviceMoved() { 64897 * value = value + 5; 64898 * threshold = threshold + 5; 64899 * if (value > 255) { 64900 * value = 0; 64901 * threshold = 30; 64902 * } 64903 * setShakeThreshold(threshold); 64904 * } 64905 * </code> 64906 * </div> 64907 * 64908 * @alt 64909 * 50x50 black rect in center of canvas. turns white on mobile when device 64910 * is being shaked 64911 */ 64912 64913 _main.default.prototype.setShakeThreshold = function(val) { 64914 _main.default._validateParameters('setShakeThreshold', arguments); 64915 shake_threshold = val; 64916 }; 64917 64918 /** 64919 * The <a href="#/p5/deviceMoved">deviceMoved()</a> function is called when the device is moved by more than 64920 * the threshold value along X, Y or Z axis. The default threshold is set to 0.5. 64921 * The threshold value can be changed using <a href="https://p5js.org/reference/#/p5/setMoveThreshold">setMoveThreshold()</a>. 64922 * 64923 * @method deviceMoved 64924 * @example 64925 * <div class="norender"> 64926 * <code> 64927 * // Run this example on a mobile device 64928 * // Move the device around 64929 * // to change the value. 64930 * 64931 * let value = 0; 64932 * function draw() { 64933 * fill(value); 64934 * rect(25, 25, 50, 50); 64935 * } 64936 * function deviceMoved() { 64937 * value = value + 5; 64938 * if (value > 255) { 64939 * value = 0; 64940 * } 64941 * } 64942 * </code> 64943 * </div> 64944 * 64945 * @alt 64946 * 50x50 black rect in center of canvas. turns white on mobile when device moves 64947 */ 64948 64949 /** 64950 * The <a href="#/p5/deviceTurned">deviceTurned()</a> function is called when the device rotates by 64951 * more than 90 degrees continuously. 64952 * 64953 * The axis that triggers the <a href="#/p5/deviceTurned">deviceTurned()</a> method is stored in the turnAxis 64954 * variable. The <a href="#/p5/deviceTurned">deviceTurned()</a> method can be locked to trigger on any axis: 64955 * X, Y or Z by comparing the turnAxis variable to 'X', 'Y' or 'Z'. 64956 * 64957 * @method deviceTurned 64958 * @example 64959 * <div class="norender"> 64960 * <code> 64961 * // Run this example on a mobile device 64962 * // Rotate the device by 90 degrees 64963 * // to change the value. 64964 * 64965 * let value = 0; 64966 * function draw() { 64967 * fill(value); 64968 * rect(25, 25, 50, 50); 64969 * } 64970 * function deviceTurned() { 64971 * if (value === 0) { 64972 * value = 255; 64973 * }
64973 else if (value === 255) { 64974 * value = 0; 64975 * } 64976 * } 64977 * </code> 64978 * </div> 64979 * <div> 64980 * <code> 64981 * // Run this example on a mobile device 64982 * // Rotate the device by 90 degrees in the 64983 * // X-axis to change the value. 64984 * 64985 * let value = 0; 64986 * function draw() { 64987 * fill(value); 64988 * rect(25, 25, 50, 50); 64989 * } 64990 * function deviceTurned() { 64991 * if (turnAxis === 'X') { 64992 * if (value === 0) { 64993 * value = 255; 64994 * } else if (value === 255) { 64995 * value = 0; 64996 * } 64997 * } 64998 * } 64999 * </code> 65000 * </div> 65001 * 65002 * @alt 65003 * 50x50 black rect in center of canvas. turns white on mobile when device turns 65004 * 50x50 black rect in center of canvas. turns white on mobile when x-axis turns 65005 */ 65006 65007 /** 65008 * The <a href="#/p5/deviceShaken">deviceShaken()</a> function is called when the device total acceleration 65009 * changes of accelerationX and accelerationY values is more than 65010 * the threshold value. The default threshold is set to 30. 65011 * The threshold value can be changed using <a href="https://p5js.org/reference/#/p5/setShakeThreshold">setShakeThreshold()</a>. 65012 * 65013 * @method deviceShaken 65014 * @example 65015 * <div class="norender"> 65016 * <code> 65017 * // Run this example on a mobile device 65018 * // Shake the device to change the value. 65019 * 65020 * let value = 0; 65021 * function draw() { 65022 * fill(value); 65023 * rect(25, 25, 50, 50); 65024 * } 65025 * function deviceShaken() { 65026 * value = value + 5; 65027 * if (value > 255) { 65028 * value = 0; 65029 * } 65030 * } 65031 * </code> 65032 * </div> 65033 * 65034 * @alt 65035 * 50x50 black rect in center of canvas. turns white on mobile when device shakes 65036 */ 65037 65038 _main.default.prototype._ondeviceorientation = function(e) { 65039 this._updatePRotations(); 65040 if (this._angleMode === constants.radians) { 65041 e.beta = e.beta * (_PI / 180.0); 65042 e.gamma = e.gamma * (_PI / 180.0); 65043 e.alpha = e.alpha * (_PI / 180.0); 65044 } 65045 this._setProperty('rotationX', e.beta); 65046 this._setProperty('rotationY', e.gamma); 65047 this._setProperty('rotationZ', e.alpha); 65048 this._handleMotion(); 65049 }; 65050 _main.default.prototype._ondevicemotion = function(e) { 65051 this._updatePAccelerations(); 65052 this._setProperty('accelerationX', e.acceleration.x * 2); 65053 this._setProperty('accelerationY', e.acceleration.y * 2); 65054 this._setProperty('accelerationZ', e.acceleration.z * 2); 65055 this._handleMotion(); 65056 }; 65057 _main.default.prototype._handleMotion = function() { 65058 if (window.orientation === 90 || window.orientation === -90) { 65059 this._setProperty('deviceOrientation', 'landscape'); 65060 } else if (window.orientation === 0) { 65061 this._setProperty('deviceOrientation', 'portrait'); 65062 } else if (window.orientation === undefined) { 65063 this._setProperty('deviceOrientation', 'undefined'); 65064 } 65065 var context = this._isGlobal ? window : this; 65066 if (typeof context.deviceMoved === 'function') { 65067 if ( 65068 Math.abs(this.accelerationX - this.pAccelerationX) > move_threshold || 65069 Math.abs(this.accelerationY - this.pAccelerationY) > move_threshold || 65070 Math.abs(this.accelerationZ - this.pAccelerationZ) > move_threshold 65071 ) { 65072 context.deviceMoved(); 65073 } 65074 } 65075 65076 if (typeof context.deviceTurned === 'function') { 65077 // The angles given by rotationX etc is from range -180 to 180. 65078 // The following will convert them to 0 to 360 for ease of calculation 65079 // of cases when the angles wrapped around. 65080 // _startAngleX will be converted back at the end and updated. 65081 var wRX = this.rotationX + 180; 65082 var wPRX = this.pRotationX + 180; 65083 var wSAX = startAngleX + 180; 65084 if ((wRX - wPRX > 0 && wRX - wPRX < 270) || wRX - wPRX < -270) { 65085 rotateDirectionX = 'clockwise'; 65086 } else if (wRX - wPRX < 0 || wRX - wPRX > 270) { 65087 rotateDirectionX = 'counter-clockwise'; 65088 } 65089 if (rotateDirectionX !== this.pRotateDirectionX) { 65090 wSAX = wRX; 65091 } 65092 if (Math.abs(wRX - wSAX) > 90 && Math.abs(wRX - wSAX) < 270) { 65093 wSAX = wRX; 65094 this._setProperty('turnAxis', 'X'); 65095 context.deviceTurned(); 65096 } 65097 this.pRotateDirectionX = rotateDirectionX; 65098 startAngleX = wSAX - 180; 65099 65100 // Y-axis is identical to X-axis except for changing some names. 65101 var wRY = this.rotationY + 180; 65102 var wPRY = this.pRotationY + 180; 65103 var wSAY = startAngleY + 180; 65104 if ((wRY - wPRY > 0 && wRY - wPRY < 270) || wRY - wPRY < -270) { 65105 rotateDirectionY = 'clockwise'; 65106 } else if (wRY - wPRY < 0 || wRY - this.pRotationY > 270) { 65107 rotateDirectionY = 'counter-clockwise'; 65108 } 65109 if (rotateDirectionY !== this.pRotateDirectionY) { 65110 wSAY = wRY; 65111 } 65112 if (Math.abs(wRY - wSAY) > 90 && Math.abs(wRY - wSAY) < 270) { 65113 wSAY = wRY; 65114 this._setProperty('turnAxis', 'Y'); 65115 context.deviceTurned(); 65116 } 65117 this.pRotateDirectionY = rotateDirectionY; 65118 startAngleY = wSAY - 180; 65119 65120 // Z-axis is already in the range 0 to 360 65121 // so no conversion is needed. 65122 if ( 65123 (this.rotationZ - this.pRotationZ > 0 && 65124 this.rotationZ - this.pRotationZ < 270) || 65125 this.rotationZ - this.pRotationZ < -270 65126 ) { 65127 rotateDirectionZ = 'clockwise'; 65128 } else if ( 65129 this.rotationZ - this.pRotationZ < 0 || 65130 this.rotationZ - this.pRotationZ > 270 65131 ) { 65132 rotateDirectionZ = 'counter-clockwise'; 65133 } 65134 if (rotateDirectionZ !== this.pRotateDirectionZ) { 65135 startAngleZ = this.rotationZ; 65136 } 65137 if ( 65138 Math.abs(this.rotationZ - startAngleZ) > 90 && 65139 Math.abs(this.rotationZ - startAngleZ) < 270 65140 ) { 65141 startAngleZ = this.rotationZ; 65142 this._setProperty('turnAxis', 'Z'); 65143 context.deviceTurned(); 65144 } 65145 this.pRotateDirectionZ = rotateDirectionZ; 65146 this._setProperty('turnAxis', undefined); 65147 } 65148 if (typeof context.deviceShaken === 'function') { 65149 var accelerationChangeX; 65150 var accelerationChangeY; 65151 // Add accelerationChangeZ if acceleration change on Z is needed 65152 if (this.pAccelerationX !== null) { 65153 accelerationChangeX = Math.abs(this.accelerationX - this.pAccelerationX); 65154 accelerationChangeY = Math.abs(this.accelerationY - this.pAccelerationY); 65155 } 65156 if (accelerationChangeX + accelerationChangeY > shake_threshold) { 65157 context.deviceShaken(); 65158 } 65159 } 65160 }; 65161 var _default = _main.default; 65162 exports.default = _default; 65163 }, 65164 { '../core/constants': 48, '../core/main': 59 } 65165 ], 65166 77: [
65167 function(_dereq_, module, exports) { 65168 'use strict'; 65169 Object.defineProperty(exports, '__esModule', { value: true }); 65170 exports.default = void 0; 65171 65172 var _main = _interopRequireDefault(_dereq_('../core/main')); 65173 function _interopRequireDefault(obj) { 65174 return obj && obj.__esModule ? obj : { default: obj }; 65175 } 65176 /** 65177 * @module Events 65178 * @submodule Keyboard 65179 * @for p5 65180 * @requires core 65181 */ /** 65182 * The boolean system variable <a href="#/p5/keyIsPressed">keyIsPressed</a> is true if any key is pressed 65183 * and false if no keys are pressed. 65184 * 65185 * @property {Boolean} keyIsPressed 65186 * @readOnly 65187 * @example 65188 * <div> 65189 * <code> 65190 * function draw() { 65191 * if (keyIsPressed === true) { 65192 * fill(0); 65193 * } else { 65194 * fill(255); 65195 * } 65196 * rect(25, 25, 50, 50); 65197 * } 65198 * </code> 65199 * </div> 65200 * 65201 * @alt 65202 * 50x50 white rect that turns black on keypress. 65203 */ _main.default.prototype.isKeyPressed = false; 65204 _main.default.prototype.keyIsPressed = false; // khan 65205 /** 65206 * The system variable key always contains the value of the most recent 65207 * key on the keyboard that was typed. To get the proper capitalization, it 65208 * is best to use it within <a href="#/p5/keyTyped">keyTyped()</a>. For non-ASCII keys, use the <a href="#/p5/keyCode">keyCode</a> 65209 * variable. 65210 * 65211 * @property {String} key 65212 * @readOnly 65213 * @example 65214 * <div><code> 65215 * // Click any key to display it! 65216 * // (Not Guaranteed to be Case Sensitive) 65217 * function setup() { 65218 * fill(245, 123, 158); 65219 * textSize(50); 65220 * } 65221 * 65222 * function draw() { 65223 * background(200); 65224 * text(key, 33, 65); // Display last key pressed. 65225 * } 65226 * </code></div> 65227 * 65228 * @alt 65229 * canvas displays any key value that is pressed in pink font. 65230 */ 65231 _main.default.prototype.key = ''; 65232 65233 /** 65234 * The variable keyCode is used to detect special keys such as BACKSPACE, 65235 * DELETE, ENTER, RETURN, TAB, ESCAPE, SHIFT, CONTROL, OPTION, ALT, UP_ARROW, 65236 * DOWN_ARROW, LEFT_ARROW, RIGHT_ARROW. 65237 * You can also check for custom keys by looking up the keyCode of any key 65238 * on a site like this: <a href="http://keycode.info/">keycode.info</a>. 65239 * 65240 * @property {Integer} keyCode 65241 * @readOnly 65242 * @example 65243 * <div><code> 65244 * let fillVal = 126; 65245 * function draw() { 65246 * fill(fillVal); 65247 * rect(25, 25, 50, 50); 65248 * } 65249 * 65250 * function keyPressed() { 65251 * if (keyCode === UP_ARROW) { 65252 * fillVal = 255; 65253 * } else if (keyCode === DOWN_ARROW) { 65254 * fillVal = 0; 65255 * } 65256 * } 65257 * </code></div> 65258 * <div><code> 65259 * function draw() {} 65260 * function keyPressed() { 65261 * background('yellow'); 65262 * text(`${key} ${keyCode}`, 10, 40); 65263 * print(key, ' ', keyCode); 65264 * } 65265 * </code></div> 65266 * @alt 65267 * Grey rect center. turns white when up arrow pressed and black when down 65268 * Display key pressed and its keyCode in a yellow box 65269 */ 65270 _main.default.prototype.keyCode = 0; 65271 65272 /** 65273 * The <a href="#/p5/keyPressed">keyPressed()</a> function is called once every time a key is pressed. The 65274 * keyCode for the key that was pressed is stored in the <a href="#/p5/keyCode">keyCode</a> variable. 65275 * 65276 * For non-ASCII keys, use the keyCode variable. You can check if the keyCode
65277 * equals BACKSPACE, DELETE, ENTER, RETURN, TAB, ESCAPE, SHIFT, CONTROL, 65278 * OPTION, ALT, UP_ARROW, DOWN_ARROW, LEFT_ARROW, RIGHT_ARROW. 65279 * 65280 * For ASCII keys, the key that was pressed is stored in the key variable. However, it 65281 * does not distinguish between uppercase and lowercase. For this reason, it 65282 * is recommended to use <a href="#/p5/keyTyped">keyTyped()</a> to read the key variable, in which the 65283 * case of the variable will be distinguished. 65284 * 65285 * Because of how operating systems handle key repeats, holding down a key 65286 * may cause multiple calls to <a href="#/p5/keyTyped">keyTyped()</a> (and <a href="#/p5/keyReleased">keyReleased()</a> as well). The 65287 * rate of repeat is set by the operating system and how each computer is 65288 * configured.<br><br> 65289 * Browsers may have different default 65290 * behaviors attached to various key events. To prevent any default 65291 * behavior for this event, add "return false" to the end of the method. 65292 * 65293 * @method keyPressed 65294 * @example 65295 * <div> 65296 * <code> 65297 * let value = 0; 65298 * function draw() { 65299 * fill(value); 65300 * rect(25, 25, 50, 50); 65301 * } 65302 * function keyPressed() { 65303 * if (value === 0) { 65304 * value = 255; 65305 * } else { 65306 * value = 0; 65307 * } 65308 * } 65309 * </code> 65310 * </div> 65311 * <div> 65312 * <code> 65313 * let value = 0; 65314 * function draw() { 65315 * fill(value); 65316 * rect(25, 25, 50, 50); 65317 * } 65318 * function keyPressed() { 65319 * if (keyCode === LEFT_ARROW) { 65320 * value = 255; 65321 * } else if (keyCode === RIGHT_ARROW) { 65322 * value = 0; 65323 * } 65324 * } 65325 * </code> 65326 * </div> 65327 * <div class="norender"> 65328 * <code> 65329 * function keyPressed() { 65330 * // Do something 65331 * return false; // prevent any default behaviour 65332 * } 65333 * </code> 65334 * </div> 65335 * 65336 * @alt 65337 * black rect center. turns white when key pressed and black when released 65338 * black rect center. turns white when left arrow pressed and black when right. 65339 */ 65340 _main.default.prototype._onkeydown = function(e) { 65341 if (this._downKeys[e.which]) { 65342 // prevent multiple firings 65343 return; 65344 } 65345 this._setProperty('isKeyPressed', true); 65346 this._setProperty('keyIsPressed', true); 65347 this._setProperty('keyCode', e.which); 65348 this._downKeys[e.which] = true; 65349 this._setProperty('key', e.key || String.fromCharCode(e.which) || e.which); 65350 var context = this._isGlobal ? window : this; 65351 if (typeof context.keyPressed === 'function' && !e.charCode) { 65352 var executeDefault = context.keyPressed(e); 65353 if (executeDefault === false) { 65354 e.preventDefault(); 65355 } 65356 } 65357 }; 65358 /** 65359 * The <a href="#/p5/keyReleased">keyReleased()</a> function is called once every time a key is released. 65360 * See <a href="#/p5/key">key</a> and <a href="#/p5/keyCode">keyCode</a> for more information.<br><br> 65361 * Browsers may have different default 65362 * behaviors attached to various key events. To prevent any default 65363 * behavior for this event, add "return false" to the end of the method. 65364 * 65365 * @method keyReleased 65366 * @example 65367 * <div> 65368 * <code> 65369 * let value = 0; 65370 * function draw() { 65371 * fill(value); 65372 * rect(25, 25, 50, 50); 65373 * } 65374 * function keyReleased() { 65375 * if (value === 0) { 65376 * value = 255; 65377 * } else { 65378 * value = 0; 65379 * } 65380 * return false; // prevent any default behavior 65381 * } 65382 * </code> 65383 * </div> 65384 * 65385 * @alt 65386 * black rect center. turns white when key pressed and black when pressed again 65387 */ 65388 _main.default.prototype._onkeyup = function(e) {
65389 this._downKeys[e.which] = false; 65390 65391 if (!this._areDownKeys()) { 65392 this._setProperty('isKeyPressed', false); 65393 this._setProperty('keyIsPressed', false); 65394 } 65395 65396 this._setProperty('_lastKeyCodeTyped', null); 65397 65398 this._setProperty('key', e.key || String.fromCharCode(e.which) || e.which); 65399 this._setProperty('keyCode', e.which); 65400 65401 var context = this._isGlobal ? window : this; 65402 if (typeof context.keyReleased === 'function') { 65403 var executeDefault = context.keyReleased(e); 65404 if (executeDefault === false) { 65405 e.preventDefault(); 65406 } 65407 } 65408 }; 65409 65410 /** 65411 * The <a href="#/p5/keyTyped">keyTyped()</a> function is called once every time a key is pressed, but 65412 * action keys such as Backspace, Delete, Ctrl, Shift, and Alt are ignored. If you are trying to detect 65413 * a keyCode for one of these keys, use the <a href="#/p5/keyPressed">keyPressed()</a> function instead. 65414 * The most recent key typed will be stored in the key variable. 65415 * 65416 * Because of how operating systems handle key repeats, holding down a key 65417 * will cause multiple calls to <a href="#/p5/keyTyped">keyTyped()</a> (and <a href="#/p5/keyReleased">keyReleased()</a> as well). The 65418 * rate of repeat is set by the operating system and how each computer is 65419 * configured.<br><br> 65420 * Browsers may have different default behaviors attached to various key 65421 * events. To prevent any default behavior for this event, add "return false" 65422 * to the end of the method. 65423 * 65424 * @method keyTyped 65425 * @example 65426 * <div> 65427 * <code> 65428 * let value = 0; 65429 * function draw() { 65430 * fill(value); 65431 * rect(25, 25, 50, 50); 65432 * } 65433 * function keyTyped() { 65434 * if (key === 'a') { 65435 * value = 255; 65436 * } else if (key === 'b') { 65437 * value = 0; 65438 * } 65439 * // uncomment to prevent any default behavior 65440 * // return false; 65441 * } 65442 * </code> 65443 * </div> 65444 * 65445 * @alt 65446 * black rect center. turns white when 'a' key typed and black when 'b' pressed 65447 */ 65448 _main.default.prototype._onkeypress = function(e) { 65449 if (e.which === this._lastKeyCodeTyped) { 65450 // prevent multiple firings 65451 return; 65452 } 65453 this._setProperty('_lastKeyCodeTyped', e.which); // track last keyCode 65454 this._setProperty('key', e.key || String.fromCharCode(e.which) || e.which); 65455 65456 var context = this._isGlobal ? window : this; 65457 if (typeof context.keyTyped === 'function') { 65458 var executeDefault = context.keyTyped(e); 65459 if (executeDefault === false) { 65460 e.preventDefault(); 65461 } 65462 } 65463 }; 65464 /** 65465 * The onblur function is called when the user is no longer focused 65466 * on the p5 element. Because the keyup events will not fire if the user is 65467 * not focused on the element we must assume all keys currently down have 65468 * been released. 65469 */ 65470 _main.default.prototype._onblur = function(e) { 65471 this._downKeys = {}; 65472 }; 65473 65474 /** 65475 * The <a href="#/p5/keyIsDown">keyIsDown()</a> function checks if the key is currently down, i.e. pressed. 65476 * It can be used if you have an object that moves, and you want several keys 65477 * to be able to affect its behaviour simultaneously, such as moving a 65478 * sprite diagonally. You can put in any number representing the keyCode of 65479 * the key, or use any of the variable <a href="#/p5/keyCode">keyCode</a> names listed 65480 * <a href="http://p5js.org/reference/#p5/keyCode">here</a>. 65481 * 65482 * @method keyIsDown 65483 * @param {Number} code The key to check for. 65484 * @return {Boolean} whether key is down or not 65485 * @example 65486 * <div><code> 65487 * let x = 100; 65488 * let y = 100; 65489 * 65490 * function setup() { 65491 * createCanvas(512, 512); 65492 * fill(255, 0, 0); 65493 * } 65494 * 65495 * function draw() { 65496 * if (keyIsDown(LEFT_ARROW)) { 65497 * x -= 5; 65498 * } 65499 * 65500 * if (keyIsDown(RIGHT_ARROW)) { 65501 * x += 5; 65502 * } 65503 * 65504 * if (keyIsDown(UP_ARROW)) { 65505 * y -= 5; 65506 * } 65507 * 65508 * if (keyIsDown(DOWN_ARROW)) { 65509 * y += 5; 65510 * } 65511 * 65512 * clear(); 65513 * ellipse(x, y, 50, 50); 65514 * } 65515 * </code></div> 65516 * 65517 * <div><code> 65518 * let diameter = 50; 65519 * 65520 * function setup() { 65521 * createCanvas(512, 512); 65522 * } 65523 * 65524 * function draw() { 65525 * // 107 and 187 are keyCodes for "+" 65526 * if (keyIsDown(107) || keyIsDown(187)) { 65527 * diameter += 1; 65528 * } 65529 *
65530 * // 109 and 189 are keyCodes for "-" 65531 * if (keyIsDown(109) || keyIsDown(189)) { 65532 * diameter -= 1; 65533 * } 65534 * 65535 * clear(); 65536 * fill(255, 0, 0); 65537 * ellipse(50, 50, diameter, diameter); 65538 * } 65539 * </code></div> 65540 * 65541 * @alt 65542 * 50x50 red ellipse moves left, right, up and down with arrow presses. 65543 * 50x50 red ellipse gets bigger or smaller when + or - are pressed. 65544 */ 65545 _main.default.prototype.keyIsDown = function(code) { 65546 _main.default._validateParameters('keyIsDown', arguments); 65547 return this._downKeys[code] || false; 65548 }; 65549 65550 /** 65551 * The _areDownKeys function returns a boolean true if any keys pressed 65552 * and a false if no keys are currently pressed. 65553 65554 * Helps avoid instances where multiple keys are pressed simultaneously and 65555 * releasing a single key will then switch the 65556 * keyIsPressed property to true. 65557 * @private 65558 **/ 65559 _main.default.prototype._areDownKeys = function() { 65560 for (var key in this._downKeys) { 65561 if (this._downKeys.hasOwnProperty(key) && this._downKeys[key] === true) { 65562 return true; 65563 } 65564 } 65565 return false; 65566 }; 65567 var _default = _main.default; 65568 exports.default = _default; 65569 }, 65570 { '../core/main': 59 } 65571 ], 65572 78: [ 65573 function(_dereq_, module, exports) { 65574 'use strict'; 65575 function _typeof(obj) { 65576 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') { 65577 _typeof = function _typeof(obj) { 65578 return typeof obj; 65579 }; 65580 } else { 65581 _typeof = function _typeof(obj) { 65582 return obj && 65583 typeof Symbol === 'function' && 65584 obj.constructor === Symbol && 65585 obj !== Symbol.prototype 65586 ? 'symbol' 65587 : typeof obj; 65588 }; 65589 } 65590 return _typeof(obj); 65591 } 65592 Object.defineProperty(exports, '__esModule', { value: true }); 65593 exports.default = void 0; 65594 65595 var _main = _interopRequireDefault(_dereq_('../core/main')); 65596 var constants = _interopRequireWildcard(_dereq_('../core/constants')); 65597 function _getRequireWildcardCache() { 65598 if (typeof WeakMap !== 'function') return null; 65599 var cache = new WeakMap(); 65600 _getRequireWildcardCache = function _getRequireWildcardCache() { 65601 return cache; 65602 }; 65603 return cache; 65604 } 65605 function _interopRequireWildcard(obj) { 65606 if (obj && obj.__esModule) { 65607 return obj; 65608 } 65609 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) { 65610 return { default: obj }; 65611 } 65612 var cache = _getRequireWildcardCache(); 65613 if (cache && cache.has(obj)) { 65614 return cache.get(obj); 65615 } 65616 var newObj = {}; 65617 var hasPropertyDescriptor = 65618 Object.defineProperty && Object.getOwnPropertyDescriptor; 65619 for (var key in obj) { 65620 if (Object.prototype.hasOwnProperty.call(obj, key)) { 65621 var desc = hasPropertyDescriptor 65622 ? Object.getOwnPropertyDescriptor(obj, key) 65623 : null; 65624 if (desc && (desc.get || desc.set)) { 65625 Object.defineProperty(newObj, key, desc); 65626 } else { 65627 newObj[key] = obj[key]; 65628 } 65629 } 65630 } 65631 newObj.default = obj; 65632 if (cache) { 65633 cache.set(obj, newObj); 65634 } 65635 return newObj; 65636 } 65637 function _interopRequireDefault(obj) { 65638 return obj && obj.__esModule ? obj : { default: obj }; 65639 } 65640 /** 65641 * @module Events 65642 * @submodule Mouse 65643 * @for p5 65644 * @requires core 65645 * @requires constants 65646 */ /** 65647 * 65648 * The variable movedX contains the horizontal movement of the mouse since the last frame 65649 * @property {Number} movedX 65650 * @readOnly 65651 * @example 65652 * <div class="notest"> 65653 * <code> 65654 * let x = 50; 65655 * function setup() { 65656 * rectMode(CENTER); 65657 * } 65658 * 65659 * function draw() { 65660 * if (x > 48) { 65661 * x -= 2; 65662 * } else if (x < 48) { 65663 * x += 2; 65664 * } 65665 * x += floor(movedX / 5); 65666 * background(237, 34, 93); 65667 * fill(0); 65668 * rect(x, 50, 50, 50); 65669 * } 65670 * </code> 65671 * </div> 65672 * @alt 65673 * box moves left and right according to mouse movement then slowly back towards the center 65674 */ _main.default.prototype.movedX = 0; 65675 /** 65676 * The variable movedY contains the vertical movement of the mouse since the last frame 65677 * @property {Number} movedY 65678 * @readOnly 65679 * @example 65680 * <div class="notest"> 65681 * <code> 65682 * let y = 50; 65683 * function setup() { 65684 * rectMode(CENTER); 65685 * } 65686 * 65687 * function draw() { 65688 * if (y > 48) { 65689 * y -= 2; 65690 * } else if (y < 48) { 65691 * y += 2; 65692 * } 65693 * y += floor(movedY / 5); 65694 * background(237, 34, 93); 65695 * fill(0); 65696 * rect(y, 50, 50, 50); 65697 * } 65698 * </code> 65699 * </div> 65700 * @alt 65701 * box moves up and down according to mouse movement then slowly back towards the center 65702 */ _main.default.prototype.movedY = 0; 65703 /* 65704 * This is a flag which is false until the first time 65705 * we receive a mouse event. The pmouseX and pmouseY 65706 * values will match the mouseX and mouseY values until 65707 * this interaction takes place. 65708 */ 65709 _main.default.prototype._hasMouseInteracted = false;
65710 65711 /** 65712 * The system variable mouseX always contains the current horizontal 65713 * position of the mouse, relative to (0, 0) of the canvas. The value at 65714 * the top-left corner is (0, 0) for 2-D and (-width/2, -height/2) for WebGL. 65715 * If touch is used instead of mouse input, mouseX will hold the x value 65716 * of the most recent touch point. 65717 * 65718 * @property {Number} mouseX 65719 * @readOnly 65720 * 65721 * @example 65722 * <div> 65723 * <code> 65724 * // Move the mouse across the canvas 65725 * function draw() { 65726 * background(244, 248, 252); 65727 * line(mouseX, 0, mouseX, 100); 65728 * } 65729 * </code> 65730 * </div> 65731 * 65732 * @alt 65733 * horizontal black line moves left and right with mouse x-position 65734 */ 65735 _main.default.prototype.mouseX = 0; 65736 65737 /** 65738 * The system variable mouseY always contains the current vertical 65739 * position of the mouse, relative to (0, 0) of the canvas. The value at 65740 * the top-left corner is (0, 0) for 2-D and (-width/2, -height/2) for WebGL. 65741 * If touch is used instead of mouse input, mouseY will hold the y value 65742 * of the most recent touch point. 65743 * 65744 * @property {Number} mouseY 65745 * @readOnly 65746 * 65747 * @example 65748 * <div> 65749 * <code> 65750 * // Move the mouse across the canvas 65751 * function draw() { 65752 * background(244, 248, 252); 65753 * line(0, mouseY, 100, mouseY); 65754 * } 65755 * </code> 65756 * </div> 65757 * 65758 * @alt 65759 * vertical black line moves up and down with mouse y-position 65760 */ 65761 _main.default.prototype.mouseY = 0; 65762 65763 /** 65764 * The system variable pmouseX always contains the horizontal position of 65765 * the mouse or finger in the frame previous to the current frame, relative to 65766 * (0, 0) of the canvas. The value at the top-left corner is (0, 0) for 2-D and 65767 * (-width/2, -height/2) for WebGL. Note: pmouseX will be reset to the current mouseX 65768 * value at the start of each touch event. 65769 * 65770 * @property {Number} pmouseX 65771 * @readOnly 65772 * 65773 * @example 65774 * <div> 65775 * <code> 65776 * // Move the mouse across the canvas to leave a trail 65777 * function setup() { 65778 * //slow down the frameRate to make it more visible 65779 * frameRate(10); 65780 * } 65781 * 65782 * function draw() { 65783 * background(244, 248, 252); 65784 * line(mouseX, mouseY, pmouseX, pmouseY); 65785 * print(pmouseX + ' -> ' + mouseX); 65786 * } 65787 * </code> 65788 * </div> 65789 * 65790 * @alt 65791 * line trail is created from cursor movements. faster movement make longer line. 65792 */ 65793 _main.default.prototype.pmouseX = 0; 65794 65795 /** 65796 * The system variable pmouseY always contains the vertical position of 65797 * the mouse or finger in the frame previous to the current frame, relative to 65798 * (0, 0) of the canvas. The value at the top-left corner is (0, 0) for 2-D and 65799 * (-width/2, -height/2) for WebGL. Note: pmouseY will be reset to the current mouseY 65800 * value at the start of each touch event. 65801 * 65802 * @property {Number} pmouseY 65803 * @readOnly 65804 * 65805 * @example 65806 * <div> 65807 * <code> 65808 * function draw() { 65809 * background(237, 34, 93); 65810 * fill(0); 65811 * //draw a square only if the mouse is not moving 65812 * if (mouseY === pmouseY && mouseX === pmouseX) { 65813 * rect(20, 20, 60, 60); 65814 * } 65815 * 65816 * print(pmouseY + ' -> ' + mouseY); 65817 * } 65818 * </code> 65819 * </div> 65820 * 65821 * @alt 65822 * 60x60 black rect center, fuchsia background. rect flickers on mouse movement 65823 */ 65824 _main.default.prototype.pmouseY = 0; 65825 65826 /** 65827 * The system variable winMouseX always contains the current horizontal 65828 * position of the mouse, relative to (0, 0) of the window. 65829 * 65830 * @property {Number} winMouseX 65831 * @readOnly 65832 * 65833 * @example 65834 * <div> 65835 * <code> 65836 * let myCanvas; 65837 * 65838 * function setup() { 65839 * //use a variable to store a pointer to the canvas 65840 * myCanvas = createCanvas(100, 100); 65841 * let body = document.getElementsByTagName('body')[0]; 65842 * myCanvas.parent(body); 65843 * } 65844 * 65845 * function draw() { 65846 * background(237, 34, 93); 65847 * fill(0); 65848 * 65849 * //move the canvas to the horizontal mouse position 65850 * //relative to the window 65851 * myCanvas.position(winMouseX + 1, windowHeight / 2); 65852 * 65853 * //the y of the square is relative to the canvas 65854 * rect(20, mouseY, 60, 60); 65855 * } 65856 * </code> 65857 * </div> 65858 * 65859 * @alt 65860 * 60x60 black rect y moves with mouse y and fuchsia canvas moves with mouse x 65861 */ 65862 _main.default.prototype.winMouseX = 0; 65863 65864 /** 65865 * The system variable winMouseY always contains the current vertical 65866 * position of the mouse, relative to (0, 0) of the window. 65867 * 65868 * @property {Number} winMouseY 65869 * @readOnly 65870 * 65871 * @example 65872 * <div> 65873 * <code> 65874 * let myCanvas; 65875 * 65876 * function setup() { 65877 * //use a variable to store a pointer to the canvas 65878 * myCanvas = createCanvas(100, 100); 65879 * let body = document.getElementsByTagName('body')[0]; 65880 * myCanvas.parent(body); 65881 * } 65882 * 65883 * function draw() { 65884 * background(237, 34, 93); 65885 * fill(0); 65886 * 65887 * //move the canvas to the vertical mouse position 65888 * //relative to the window
65889 * myCanvas.position(windowWidth / 2, winMouseY + 1); 65890 * 65891 * //the x of the square is relative to the canvas 65892 * rect(mouseX, 20, 60, 60); 65893 * } 65894 * </code> 65895 * </div> 65896 * 65897 * @alt 65898 * 60x60 black rect x moves with mouse x and fuchsia canvas y moves with mouse y 65899 */ 65900 _main.default.prototype.winMouseY = 0; 65901 65902 /** 65903 * The system variable pwinMouseX always contains the horizontal position 65904 * of the mouse in the frame previous to the current frame, relative to 65905 * (0, 0) of the window. Note: pwinMouseX will be reset to the current winMouseX 65906 * value at the start of each touch event. 65907 * 65908 * @property {Number} pwinMouseX 65909 * @readOnly 65910 * 65911 * @example 65912 * <div> 65913 * <code> 65914 * let myCanvas; 65915 * 65916 * function setup() { 65917 * //use a variable to store a pointer to the canvas 65918 * myCanvas = createCanvas(100, 100); 65919 * noStroke(); 65920 * fill(237, 34, 93); 65921 * } 65922 * 65923 * function draw() { 65924 * clear(); 65925 * //the difference between previous and 65926 * //current x position is the horizontal mouse speed 65927 * let speed = abs(winMouseX - pwinMouseX); 65928 * //change the size of the circle 65929 * //according to the horizontal speed 65930 * ellipse(50, 50, 10 + speed * 5, 10 + speed * 5); 65931 * //move the canvas to the mouse position 65932 * myCanvas.position(winMouseX + 1, winMouseY + 1); 65933 * } 65934 * </code> 65935 * </div> 65936 * 65937 * @alt 65938 * fuchsia ellipse moves with mouse x and y. Grows and shrinks with mouse speed 65939 */ 65940 _main.default.prototype.pwinMouseX = 0; 65941 65942 /** 65943 * The system variable pwinMouseY always contains the vertical position of 65944 * the mouse in the frame previous to the current frame, relative to (0, 0) 65945 * of the window. Note: pwinMouseY will be reset to the current winMouseY 65946 * value at the start of each touch event. 65947 * 65948 * @property {Number} pwinMouseY 65949 * @readOnly 65950 * 65951 * @example 65952 * <div> 65953 * <code> 65954 * let myCanvas; 65955 * 65956 * function setup() { 65957 * //use a variable to store a pointer to the canvas 65958 * myCanvas = createCanvas(100, 100); 65959 * noStroke(); 65960 * fill(237, 34, 93); 65961 * } 65962 * 65963 * function draw() { 65964 * clear(); 65965 * //the difference between previous and 65966 * //current y position is the vertical mouse speed 65967 * let speed = abs(winMouseY - pwinMouseY); 65968 * //change the size of the circle 65969 * //according to the vertical speed 65970 * ellipse(50, 50, 10 + speed * 5, 10 + speed * 5); 65971 * //move the canvas to the mouse position 65972 * myCanvas.position(winMouseX + 1, winMouseY + 1); 65973 * } 65974 * </code> 65975 * </div> 65976 * 65977 * @alt 65978 * fuchsia ellipse moves with mouse x and y. Grows and shrinks with mouse speed 65979 */ 65980 _main.default.prototype.pwinMouseY = 0; 65981 65982 /** 65983 * Processing automatically tracks if the mouse button is pressed and which 65984 * button is pressed. The value of the system variable mouseButton is either 65985 * LEFT, RIGHT, or CENTER depending on which button was pressed last. 65986 * Warning: different browsers may track mouseButton differently. 65987 * 65988 * @property {Constant} mouseButton 65989 * @readOnly 65990 * 65991 * @example 65992 * <div> 65993 * <code> 65994 * function draw() { 65995 * background(237, 34, 93); 65996 * fill(0); 65997 * 65998 * if (mouseIsPressed) { 65999 * if (mouseButton === LEFT) { 66000 * ellipse(50, 50, 50, 50); 66001 * } 66002 * if (mouseButton === RIGHT) { 66003 * rect(25, 25, 50, 50); 66004 * } 66005 * if (mouseButton === CENTER) { 66006 * triangle(23, 75, 50, 20, 78, 75); 66007 * } 66008 * } 66009 * 66010 * print(mouseButton); 66011 * } 66012 * </code> 66013 * </div> 66014 * 66015 * @alt 66016 * 50x50 black ellipse appears on center of fuchsia canvas on mouse click/press. 66017 */ 66018 _main.default.prototype.mouseButton = 0; 66019 66020 /** 66021 * The boolean system variable mouseIsPressed is true if the mouse is pressed 66022 * and false if not. 66023 * 66024 * @property {Boolean} mouseIsPressed 66025 * @readOnly 66026 * 66027 * @example 66028 * <div> 66029 * <code> 66030 * function draw() { 66031 * background(237, 34, 93); 66032 * fill(0); 66033 * 66034 * if (mouseIsPressed) { 66035 * ellipse(50, 50, 50, 50); 66036 * } else { 66037 * rect(25, 25, 50, 50); 66038 * } 66039 * 66040 * print(mouseIsPressed); 66041 * } 66042 * </code> 66043 * </div> 66044 * 66045 * @alt
66046 * black 50x50 rect becomes ellipse with mouse click/press. fuchsia background. 66047 */ 66048 _main.default.prototype.mouseIsPressed = false; 66049 66050 _main.default.prototype._updateNextMouseCoords = function(e) { 66051 if (this._curElement !== null && (!e.touches || e.touches.length > 0)) { 66052 var mousePos = getMousePos(this._curElement.elt, this.width, this.height, e); 66053 66054 this._setProperty('movedX', e.movementX); 66055 this._setProperty('movedY', e.movementY); 66056 this._setProperty('mouseX', mousePos.x); 66057 this._setProperty('mouseY', mousePos.y); 66058 this._setProperty('winMouseX', mousePos.winX); 66059 this._setProperty('winMouseY', mousePos.winY); 66060 } 66061 if (!this._hasMouseInteracted) { 66062 // For first draw, make previous and next equal 66063 this._updateMouseCoords(); 66064 this._setProperty('_hasMouseInteracted', true); 66065 } 66066 }; 66067 66068 _main.default.prototype._updateMouseCoords = function() { 66069 this._setProperty('pmouseX', this.mouseX); 66070 this._setProperty('pmouseY', this.mouseY); 66071 this._setProperty('pwinMouseX', this.winMouseX); 66072 this._setProperty('pwinMouseY', this.winMouseY); 66073 66074 this._setProperty('_pmouseWheelDeltaY', this._mouseWheelDeltaY); 66075 }; 66076 66077 function getMousePos(canvas, w, h, evt) { 66078 if (evt && !evt.clientX) { 66079 // use touches if touch and not mouse 66080 if (evt.touches) { 66081 evt = evt.touches[0]; 66082 } else if (evt.changedTouches) { 66083 evt = evt.changedTouches[0]; 66084 } 66085 } 66086 var rect = canvas.getBoundingClientRect(); 66087 var sx = canvas.scrollWidth / w || 1; 66088 var sy = canvas.scrollHeight / h || 1; 66089 return { 66090 x: (evt.clientX - rect.left) / sx, 66091 y: (evt.clientY - rect.top) / sy, 66092 winX: evt.clientX, 66093 winY: evt.clientY, 66094 id: evt.identifier 66095 }; 66096 } 66097 66098 _main.default.prototype._setMouseButton = function(e) { 66099 if (e.button === 1) { 66100 this._setProperty('mouseButton', constants.CENTER); 66101 } else if (e.button === 2) { 66102 this._setProperty('mouseButton', constants.RIGHT); 66103 } else { 66104 this._setProperty('mouseButton', constants.LEFT); 66105 } 66106 }; 66107 66108 /** 66109 * The <a href="#/p5/mouseMoved">mouseMoved()</a> function is called every time the mouse moves and a mouse 66110 * button is not pressed.<br><br> 66111 * Browsers may have different default 66112 * behaviors attached to various mouse events. To prevent any default 66113 * behavior for this event, add "return false" to the end of the method. 66114 * 66115 * @method mouseMoved 66116 * @param {Object} [event] optional MouseEvent callback argument. 66117 * @example 66118 * <div> 66119 * <code> 66120 * // Move the mouse across the page 66121 * // to change its value 66122 * 66123 * let value = 0; 66124 * function draw() { 66125 * fill(value); 66126 * rect(25, 25, 50, 50); 66127 * } 66128 * function mouseMoved() { 66129 * value = value + 5; 66130 * if (value > 255) { 66131 * value = 0; 66132 * } 66133 * } 66134 * </code> 66135 * </div> 66136 * 66137 * <div class="norender"> 66138 * <code> 66139 * function mouseMoved() { 66140 * ellipse(mouseX, mouseY, 5, 5); 66141 * // prevent default 66142 * return false; 66143 * } 66144 * </code> 66145 * </div> 66146 * 66147 * <div class="norender"> 66148 * <code> 66149 * // returns a MouseEvent object 66150 * // as a callback argument 66151 * function mouseMoved(event) { 66152 * console.log(event); 66153 * } 66154 * </code> 66155 * </div> 66156 * 66157 * @alt
66158 * black 50x50 rect becomes lighter with mouse movements until white then resets 66159 * no image displayed 66160 */ 66161 66162 /** 66163 * The <a href="#/p5/mouseDragged">mouseDragged()</a> function is called once every time the mouse moves and 66164 * a mouse button is pressed. If no <a href="#/p5/mouseDragged">mouseDragged()</a> function is defined, the 66165 * <a href="#/p5/touchMoved">touchMoved()</a> function will be called instead if it is defined.<br><br> 66166 * Browsers may have different default 66167 * behaviors attached to various mouse events. To prevent any default 66168 * behavior for this event, add "return false" to the end of the method. 66169 * 66170 * @method mouseDragged 66171 * @param {Object} [event] optional MouseEvent callback argument. 66172 * @example 66173 * <div> 66174 * <code> 66175 * // Drag the mouse across the page 66176 * // to change its value 66177 * 66178 * let value = 0; 66179 * function draw() { 66180 * fill(value); 66181 * rect(25, 25, 50, 50); 66182 * } 66183 * function mouseDragged() { 66184 * value = value + 5; 66185 * if (value > 255) { 66186 * value = 0; 66187 * } 66188 * } 66189 * </code> 66190 * </div> 66191 * 66192 * <div class="norender"> 66193 * <code> 66194 * function mouseDragged() { 66195 * ellipse(mouseX, mouseY, 5, 5); 66196 * // prevent default 66197 * return false; 66198 * } 66199 * </code> 66200 * </div> 66201 * 66202 * <div class="norender"> 66203 * <code> 66204 * // returns a MouseEvent object 66205 * // as a callback argument 66206 * function mouseDragged(event) { 66207 * console.log(event); 66208 * } 66209 * </code> 66210 * </div> 66211 * 66212 * @alt 66213 * black 50x50 rect turns lighter with mouse click and drag until white, resets 66214 * no image displayed 66215 */ 66216 _main.default.prototype._onmousemove = function(e) { 66217 var context = this._isGlobal ? window : this; 66218 var executeDefault; 66219 this._updateNextMouseCoords(e); 66220 if (!this.mouseIsPressed) { 66221 if (typeof context.mouseMoved === 'function') { 66222 executeDefault = context.mouseMoved(e); 66223 if (executeDefault === false) { 66224 e.preventDefault(); 66225 } 66226 } 66227 } else { 66228 if (typeof context.mouseDragged === 'function') { 66229 executeDefault = context.mouseDragged(e); 66230 if (executeDefault === false) { 66231 e.preventDefault(); 66232 } 66233 } else if (typeof context.touchMoved === 'function') { 66234 executeDefault = context.touchMoved(e); 66235 if (executeDefault === false) { 66236 e.preventDefault(); 66237 } 66238 } 66239 } 66240 }; 66241 66242 /** 66243 * The <a href="#/p5/mousePressed">mousePressed()</a> function is called once after every time a mouse button 66244 * is pressed. The mouseButton variable (see the related reference entry) 66245 * can be used to determine which button has been pressed. If no 66246 * <a href="#/p5/mousePressed">mousePressed()</a> function is defined, the <a href="#/p5/touchStarted">touchStarted()</a> function will be 66247 * called instead if it is defined.<br><br> 66248 * Browsers may have different default 66249 * behaviors attached to various mouse events. To prevent any default 66250 * behavior for this event, add "return false" to the end of the method. 66251 * 66252 * @method mousePressed 66253 * @param {Object} [event] optional MouseEvent callback argument. 66254 * @example 66255 * <div> 66256 * <code> 66257 * // Click within the image to change 66258 * // the value of the rectangle 66259 * 66260 * let value = 0; 66261 * function draw() { 66262 * fill(value); 66263 * rect(25, 25, 50, 50); 66264 * } 66265 * function mousePressed() { 66266 * if (value === 0) { 66267 * value = 255; 66268 * } else { 66269 * value = 0; 66270 * } 66271 * } 66272 * </code> 66273 * </div> 66274 * 66275 * <div class="norender"> 66276 * <code> 66277 * function mousePressed() { 66278 * ellipse(mouseX, mouseY, 5, 5); 66279 * // prevent default 66280 * return false;
66281 * } 66282 * </code> 66283 * </div> 66284 * 66285 * <div class="norender"> 66286 * <code> 66287 * // returns a MouseEvent object 66288 * // as a callback argument 66289 * function mousePressed(event) { 66290 * console.log(event); 66291 * } 66292 * </code> 66293 * </div> 66294 * 66295 * @alt 66296 * black 50x50 rect turns white with mouse click/press. 66297 * no image displayed 66298 */ 66299 _main.default.prototype._onmousedown = function(e) { 66300 var context = this._isGlobal ? window : this; 66301 var executeDefault; 66302 this._setProperty('mouseIsPressed', true); 66303 this._setMouseButton(e); 66304 this._updateNextMouseCoords(e); 66305 66306 if (typeof context.mousePressed === 'function') { 66307 executeDefault = context.mousePressed(e); 66308 if (executeDefault === false) { 66309 e.preventDefault(); 66310 } 66311 // only safari needs this manual fallback for consistency 66312 } else if ( 66313 navigator.userAgent.toLowerCase().includes('safari') && 66314 typeof context.touchStarted === 'function' 66315 ) { 66316 executeDefault = context.touchStarted(e); 66317 if (executeDefault === false) { 66318 e.preventDefault(); 66319 } 66320 } 66321 }; 66322 66323 /** 66324 * The <a href="#/p5/mouseReleased">mouseReleased()</a> function is called every time a mouse button is 66325 * released. If no <a href="#/p5/mouseReleased">mouseReleased()</a> function is defined, the <a href="#/p5/touchEnded">touchEnded()</a> 66326 * function will be called instead if it is defined.<br><br> 66327 * Browsers may have different default 66328 * behaviors attached to various mouse events. To prevent any default 66329 * behavior for this event, add "return false" to the end of the method. 66330 * 66331 * @method mouseReleased 66332 * @param {Object} [event] optional MouseEvent callback argument. 66333 * @example 66334 * <div> 66335 * <code> 66336 * // Click within the image to change 66337 * // the value of the rectangle 66338 * // after the mouse has been clicked 66339 * 66340 * let value = 0; 66341 * function draw() { 66342 * fill(value); 66343 * rect(25, 25, 50, 50); 66344 * } 66345 * function mouseReleased() { 66346 * if (value === 0) { 66347 * value = 255; 66348 * } else { 66349 * value = 0; 66350 * } 66351 * } 66352 * </code> 66353 * </div> 66354 * 66355 * <div class="norender"> 66356 * <code> 66357 * function mouseReleased() { 66358 * ellipse(mouseX, mouseY, 5, 5); 66359 * // prevent default 66360 * return false; 66361 * } 66362 * </code> 66363 * </div> 66364 * 66365 * <div class="norender"> 66366 * <code> 66367 * // returns a MouseEvent object 66368 * // as a callback argument 66369 * function mouseReleased(event) { 66370 * console.log(event); 66371 * } 66372 * </code> 66373 * </div> 66374 * 66375 * @alt 66376 * black 50x50 rect turns white with mouse click/press. 66377 * no image displayed 66378 */ 66379 _main.default.prototype._onmouseup = function(e) { 66380 var context = this._isGlobal ? window : this; 66381 var executeDefault; 66382 this._setProperty('mouseIsPressed', false); 66383 if (typeof context.mouseReleased === 'function') { 66384 executeDefault = context.mouseReleased(e); 66385 if (executeDefault === false) { 66386 e.preventDefault(); 66387 } 66388 } else if (typeof context.touchEnded === 'function') { 66389 executeDefault = context.touchEnded(e); 66390 if (executeDefault === false) { 66391 e.preventDefault(); 66392 } 66393 } 66394 }; 66395 66396 _main.default.prototype._ondragend = _main.default.prototype._onmouseup; 66397 _main.default.prototype._ondragover = _main.default.prototype._onmousemove; 66398 66399 /** 66400 * The <a href="#/p5/mouseClicked">mouseClicked()</a> function is called once after a mouse button has been 66401 * pressed and then released.<br><br> 66402 * Browsers handle clicks differently, so this function is only guaranteed to be 66403 * run when the left mouse button is clicked. To handle other mou
66403se buttons 66404 * being pressed or released, see <a href="#/p5/mousePressed">mousePressed()</a> or <a href="#/p5/mouseReleased">mouseReleased()</a>.<br><br> 66405 * Browsers may have different default 66406 * behaviors attached to various mouse events. To prevent any default 66407 * behavior for this event, add "return false" to the end of the method. 66408 * 66409 * @method mouseClicked 66410 * @param {Object} [event] optional MouseEvent callback argument. 66411 * @example 66412 * <div> 66413 * <code> 66414 * // Click within the image to change 66415 * // the value of the rectangle 66416 * // after the mouse has been clicked 66417 * 66418 * let value = 0; 66419 * function draw() { 66420 * fill(value); 66421 * rect(25, 25, 50, 50); 66422 * } 66423 * 66424 * function mouseClicked() { 66425 * if (value === 0) { 66426 * value = 255; 66427 * } else { 66428 * value = 0; 66429 * } 66430 * } 66431 * </code> 66432 * </div> 66433 * 66434 * <div class="norender"> 66435 * <code> 66436 * function mouseClicked() { 66437 * ellipse(mouseX, mouseY, 5, 5); 66438 * // prevent default 66439 * return false; 66440 * } 66441 * </code> 66442 * </div> 66443 * 66444 * <div class="norender"> 66445 * <code> 66446 * // returns a MouseEvent object 66447 * // as a callback argument 66448 * function mouseClicked(event) { 66449 * console.log(event); 66450 * } 66451 * </code> 66452 * </div> 66453 * 66454 * @alt 66455 * black 50x50 rect turns white with mouse click/press. 66456 * no image displayed 66457 */ 66458 _main.default.prototype._onclick = function(e) { 66459 var context = this._isGlobal ? window : this; 66460 if (typeof context.mouseClicked === 'function') { 66461 var executeDefault = context.mouseClicked(e); 66462 if (executeDefault === false) { 66463 e.preventDefault(); 66464 } 66465 } 66466 }; 66467 66468 /** 66469 * The <a href="#/p5/doubleClicked">doubleClicked()</a> function is executed every time a event 66470 * listener has detected a dblclick event which is a part of the 66471 * DOM L3 specification. The doubleClicked event is fired when a 66472 * pointing device button (usually a mouse's primary button) 66473 * is clicked twice on a single element. For more info on the 66474 * dblclick event refer to mozilla's documentation here: 66475 * https://developer.mozilla.org/en-US/docs/Web/Events/dblclick 66476 * 66477 * @method doubleClicked 66478 * @param {Object} [event] optional MouseEvent callback argument. 66479 * @example 66480 * <div> 66481 * <code> 66482 * // Click within the image to change 66483 * // the value of the rectangle 66484 * // after the mouse has been double clicked 66485 * 66486 * let value = 0; 66487 * function draw() { 66488 * fill(value); 66489 * rect(25, 25, 50, 50); 66490 * } 66491 * 66492 * function doubleClicked() { 66493 * if (value === 0) { 66494 * value = 255; 66495 * } else { 66496 * value = 0; 66497 * } 66498 * } 66499 * </code> 66500 * </div> 66501 * 66502 * <div class="norender"> 66503 * <code> 66504 * function doubleClicked() { 66505 * ellipse(mouseX, mouseY, 5, 5); 66506 * // prevent default 66507 * return false; 66508 * } 66509 * </code> 66510 * </div> 66511 * 66512 * <div class="norender"> 66513 * <code> 66514 * // returns a MouseEvent object 66515 * // as a callback argument 66516 * function doubleClicked(event) { 66517 * console.log(event); 66518 * } 66519 * </code> 66520 * </div> 66521 * 66522 * @alt 66523 * black 50x50 rect turns white with mouse doubleClick/press. 66524 * no image displayed 66525 */ 66526 66527 _main.default.prototype._ondblclick = function(e) { 66528 var context = this._isGlobal ? window : this; 66529 if (typeof context.doubleClicked === 'function') { 66530 var executeDefault = context.doubleClicked(e); 66531 if (executeDefault === false) { 66532 e.preventDefault(); 66533 } 66534 } 66535 }; 66536 66537 /** 66538 * For use with WebGL orbitControl. 66539 * @property {Number} _mouseWheelDeltaY 66540 * @readOnly 66541 * @private 66542 */ 66543 _main.default.prototype._mouseWheelDeltaY = 0; 66544 66545 /** 66546 * For use with WebGL orbitControl. 66547 * @property {Number} _pmouseWheelDeltaY 66548 * @readOnly 66549 * @private 66550 */ 66551 _main.default.prototype._pmouseWheelDeltaY = 0; 66552 66553 /** 66554 * The function <a href="#/p5/mouseWheel">mouseWheel()</a> is executed every time a vertical mouse wheel 66555 * event is detected either triggered by an actual mouse wheel or by a 66556 * touchpad.<br><br> 66557 * The event.delta property returns the amount the mouse wheel 66558 * have scrolled. The values can be positive or negative depending on the 66559 * scroll direction (on OS X with "natural" scrolling enabled, the signs 66560 * are inverted).<br><br> 66561 * Browsers may have different default behaviors attached to various 66562 * mouse events. To prevent any default behavior for this event, add 66563 * "return false" to the end of the method.<br><br> 66564 * Due to the current support of the "wheel" event on Safari, the function 66565 * may only work as expected if "return false" is included while using Safari. 66566 * 66567 * @method mouseWheel 66568 * @param {Object} [event] optional WheelEvent callback argument. 66569 * 66570 * @example 66571 * <div> 66572 * <code> 66573 * let pos = 25; 66574 * 66575 * function draw() { 66576 * background(237, 34, 93); 66577 * fill(0); 66578 * rect(25, pos, 50, 50); 66579 * } 66580 * 66581 * function mouseWheel(event) { 66582 * print(event.delta); 66583 * //move the square according to the vertical scroll amount 66584 * pos += event.delta; 66585 * //uncomment to block page scrolling 66586 * //return false;
66587 * } 66588 * </code> 66589 * </div> 66590 * 66591 * @alt 66592 * black 50x50 rect moves up and down with vertical scroll. fuchsia background 66593 */ 66594 _main.default.prototype._onwheel = function(e) { 66595 var context = this._isGlobal ? window : this; 66596 this._setProperty('_mouseWheelDeltaY', e.deltaY); 66597 if (typeof context.mouseWheel === 'function') { 66598 e.delta = e.deltaY; 66599 var executeDefault = context.mouseWheel(e); 66600 if (executeDefault === false) { 66601 e.preventDefault(); 66602 } 66603 } 66604 }; 66605 66606 /** 66607 * The function <a href="#/p5/requestPointerLock">requestPointerLock()</a> 66608 * locks the pointer to its current position and makes it invisible. 66609 * Use <a href="#/p5/movedX">movedX</a> and <a href="#/p5/movedY">movedY</a> to get the difference the mouse was moved since 66610 * the last call of draw. 66611 * Note that not all browsers support this feature. 66612 * This enables you to create experiences that aren't limited by the mouse moving out of the screen 66613 * even if it is repeatedly moved into one direction. 66614 * For example, a first person perspective experience. 66615 * 66616 * @method requestPointerLock 66617 * @example 66618 * <div class="notest"> 66619 * <code> 66620 * let cam; 66621 * function setup() { 66622 * createCanvas(100, 100, WEBGL); 66623 * requestPointerLock(); 66624 * cam = createCamera(); 66625 * } 66626 * 66627 * function draw() { 66628 * background(255); 66629 * cam.pan(-movedX * 0.001); 66630 * cam.tilt(movedY * 0.001); 66631 * sphere(25); 66632 * } 66633 * </code> 66634 * </div> 66635 * 66636 * @alt 66637 * 3D scene moves according to mouse mouse movement in a first person perspective 66638 */ 66639 _main.default.prototype.requestPointerLock = function() { 66640 // pointer lock object forking for cross browser 66641 var canvas = this._curElement.elt; 66642 canvas.requestPointerLock = 66643 canvas.requestPointerLock || canvas.mozRequestPointerLock; 66644 if (!canvas.requestPointerLock) { 66645 console.log('requestPointerLock is not implemented in this browser'); 66646 return false; 66647 } 66648 canvas.requestPointerLock(); 66649 return true; 66650 }; 66651 66652 /** 66653 * The function <a href="#/p5/exitPointerLock">exitPointerLock()</a> 66654 * exits a previously triggered <a href="#/p5/requestPointerLock">pointer Lock</a> 66655 * for example to make ui elements usable etc 66656 * 66657 * @method exitPointerLock 66658 * @example 66659 * <div class="notest"> 66660 * <code> 66661 * //click the canvas to lock the pointer 66662 * //click again to exit (otherwise escape) 66663 * let locked = false; 66664 * function draw() { 66665 * background(237, 34, 93); 66666 * } 66667 * function mouseClicked() { 66668 * if (!locked) { 66669 * locked = true; 66670 * requestPointerLock(); 66671 * } else { 66672 * exitPointerLock(); 66673 * locked = false; 66674 * } 66675 * } 66676 * </code> 66677 * </div> 66678 * 66679 * @alt 66680 * cursor gets locked / unlocked on mouse-click 66681 */ 66682 _main.default.prototype.exitPointerLock = function() { 66683 document.exitPointerLock(); 66684 }; 66685 var _default = _main.default; 66686 exports.default = _default; 66687 }, 66688 { '../core/constants': 48, '../core/main': 59 } 66689 ], 66690 79: [ 66691 function(_dereq_, module, exports) { 66692 'use strict'; 66693 Object.defineProperty(exports, '__esModule', { value: true }); 66694 exports.default = void 0; 66695 66696 var _main = _interopRequireDefault(_dereq_('../core/main')); 66697 function _interopRequireDefault(obj) { 66698 return obj && obj.__esModule ? obj : { default: obj }; 66699 } 66700 /** 66701 * @module Events 66702 * @submodule Touch 66703 * @for p5 66704 * @requires core 66705 */ /** 66706 * The system variable touches[] contains an array of the positions of all 66707 * current touch points, relative to (0, 0) of the canvas, and IDs identifying a 66708 * unique touch as it moves. Each element in the array is an object with x, y, 66709 * and id properties. 66710 * 66711 * The touches[] array is not supported on Safari and IE on touch-based 66712 * desktops (laptops). 66713 * 66714 * @property {Object[]} touches 66715 * @readOnly 66716 * 66717 * @example 66718 * <div> 66719 * <code> 66720 * // On a touchscreen device, touch 66721 * // the canvas using one or more fingers 66722 * // at the same time 66723 * function draw() { 66724 * clear(); 66725 * let display = touches.length + ' touches'; 66726 * text(display, 5, 10); 66727 * } 66728 * </code> 66729 * </div> 66730 * 66731 * @alt 66732 * Number of touches currently registered are displayed on the canvas 66733 */ _main.default.prototype.touches = []; 66734 _main.default.prototype._updateTouchCoords = function(e) { 66735 if (this._curElement !== null) { 66736 var touches = []; 66737 for (var i = 0; i < e.touches.length; i++) { 66738 touches[i] = getTouchInfo( 66739 this._curElement.elt, 66740 this.width, 66741 this.height, 66742 e, 66743 i 66744 ); 66745 } 66746 this._setProperty('touches', touches); 66747 } 66748 }; 66749 66750 function getTouchInfo(canvas, w, h, e) { 66751 var i = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0; 66752 var rect = canvas.getBoundingClientRect(); 66753 var sx = canvas.scrollWidth / w || 1; 66754 var sy = canvas.scrollHeight / h || 1; 66755 var touch = e.touches[i] || e.changedTouches[i]; 66756 return { 66757 x: (touch.clientX - rect.left) / sx, 66758 y: (touch.clientY - rect.top) / sy, 66759 winX: touch.clientX, 66760 winY: touch.clientY, 66761 id: touch.identifier 66762 }; 66763 } 66764 66765 /** 66766 * The touchStarted() function is called once after every time a touch is 66767 * registered. If no <a href="#/p5/touchStarted">touchStarted()</a> function is defined, the <a href="#/p5/mousePressed">mousePressed()</a> 66768 * function will be called instead if it is defined.<br><br> 66769 * Browsers may have different default behaviors attached to various touch 66770 * events. To prevent any default behavior for this event, add "return false" 66771 * to the end of the method. 66772 * 66773 * @method touchStarted 66774 * @param {Object} [event] optional TouchEvent callback argument. 66775 * @example 66776 * <div> 66777 * <code> 66778 * // Touch within the image to change 66779 * // the value of the rectangle 66780 * 66781 * let value = 0; 66782 * function draw() { 66783 * fill(value); 66784 * rect(25, 25, 50, 50); 66785 * } 66786 * function touchStarted() { 66787 * if (value === 0) { 66788 * value = 255; 66789 * } else { 66790 * value = 0; 66791 * } 66792 * } 66793 * </code> 66794 * </div> 66795 * 66796 * <div class="norender"> 66797 * <code> 66798 * function touchStarted() { 66799 * ellipse(mouseX, mouseY, 5, 5); 66800 * // prevent default 66801 * return false;
66802 * } 66803 * </code> 66804 * </div> 66805 * 66806 * <div class="norender"> 66807 * <code> 66808 * // returns a TouchEvent object 66809 * // as a callback argument 66810 * function touchStarted(event) { 66811 * console.log(event); 66812 * } 66813 * </code> 66814 * </div> 66815 * 66816 * @alt 66817 * 50x50 black rect turns white with touch event. 66818 * no image displayed 66819 */ 66820 _main.default.prototype._ontouchstart = function(e) { 66821 var context = this._isGlobal ? window : this; 66822 var executeDefault; 66823 this._setProperty('mouseIsPressed', true); 66824 this._updateTouchCoords(e); 66825 this._updateNextMouseCoords(e); 66826 this._updateMouseCoords(); // reset pmouseXY at the start of each touch event 66827 66828 if (typeof context.touchStarted === 'function') { 66829 executeDefault = context.touchStarted(e); 66830 if (executeDefault === false) { 66831 e.preventDefault(); 66832 } 66833 // only safari needs this manual fallback for consistency 66834 } else if ( 66835 navigator.userAgent.toLowerCase().includes('safari') && 66836 typeof context.mousePressed === 'function' 66837 ) { 66838 executeDefault = context.mousePressed(e); 66839 if (executeDefault === false) { 66840 e.preventDefault(); 66841 } 66842 } 66843 }; 66844 66845 /** 66846 * The <a href="#/p5/touchMoved">touchMoved()</a> function is called every time a touch move is registered. 66847 * If no <a href="#/p5/touchMoved">touchMoved()</a> function is defined, the <a href="#/p5/mouseDragged">mouseDragged()</a> function will 66848 * be called instead if it is defined.<br><br> 66849 * Browsers may have different default behaviors attached to various touch 66850 * events. To prevent any default behavior for this event, add "return false" 66851 * to the end of the method. 66852 * 66853 * @method touchMoved 66854 * @param {Object} [event] optional TouchEvent callback argument. 66855 * @example 66856 * <div> 66857 * <code> 66858 * // Move your finger across the page 66859 * // to change its value 66860 * 66861 * let value = 0; 66862 * function draw() { 66863 * fill(value); 66864 * rect(25, 25, 50, 50); 66865 * } 66866 * function touchMoved() { 66867 * value = value + 5; 66868 * if (value > 255) { 66869 * value = 0; 66870 * } 66871 * } 66872 * </code> 66873 * </div> 66874 * 66875 * <div class="norender"> 66876 * <code> 66877 * function touchMoved() { 66878 * ellipse(mouseX, mouseY, 5, 5); 66879 * // prevent default 66880 * return false; 66881 * } 66882 * </code> 66883 * </div> 66884 * 66885 * <div class="norender"> 66886 * <code> 66887 * // returns a TouchEvent object 66888 * // as a callback argument 66889 * function touchMoved(event) { 66890 * console.log(event); 66891 * } 66892 * </code> 66893 * </div> 66894 * 66895 * @alt 66896 * 50x50 black rect turns lighter with touch until white. resets 66897 * no image displayed 66898 */ 66899 _main.default.prototype._ontouchmove = function(e) { 66900 var context = this._isGlobal ? window : this; 66901 var executeDefault; 66902 this._updateTouchCoords(e); 66903 this._updateNextMouseCoords(e); 66904 if (typeof context.touchMoved === 'function') { 66905 executeDefault = context.touchMoved(e); 66906 if (executeDefault === false) { 66907 e.preventDefault(); 66908 } 66909 } else if (typeof context.mouseDragged === 'function') { 66910 executeDefault = context.mouseDragged(e); 66911 if (executeDefault === false) { 66912 e.preventDefault(); 66913 } 66914 } 66915 }; 66916 66917 /** 66918 * The <a href="#/p5/touchEnded">touchEnded()</a> function is called every time a touch ends. If no 66919 * <a href="#/p5/touchEnded">touchEnded()</a> function is defined, the <a href="#/p5/mouseReleased">mouseReleased()</a> function will be
66920 * called instead if it is defined.<br><br> 66921 * Browsers may have different default behaviors attached to various touch 66922 * events. To prevent any default behavior for this event, add "return false" 66923 * to the end of the method. 66924 * 66925 * @method touchEnded 66926 * @param {Object} [event] optional TouchEvent callback argument. 66927 * @example 66928 * <div> 66929 * <code> 66930 * // Release touch within the image to 66931 * // change the value of the rectangle 66932 * 66933 * let value = 0; 66934 * function draw() { 66935 * fill(value); 66936 * rect(25, 25, 50, 50); 66937 * } 66938 * function touchEnded() { 66939 * if (value === 0) { 66940 * value = 255; 66941 * } else { 66942 * value = 0; 66943 * } 66944 * } 66945 * </code> 66946 * </div> 66947 * 66948 * <div class="norender"> 66949 * <code> 66950 * function touchEnded() { 66951 * ellipse(mouseX, mouseY, 5, 5); 66952 * // prevent default 66953 * return false; 66954 * } 66955 * </code> 66956 * </div> 66957 * 66958 * <div class="norender"> 66959 * <code> 66960 * // returns a TouchEvent object 66961 * // as a callback argument 66962 * function touchEnded(event) { 66963 * console.log(event); 66964 * } 66965 * </code> 66966 * </div> 66967 * 66968 * @alt 66969 * 50x50 black rect turns white with touch. 66970 * no image displayed 66971 */ 66972 _main.default.prototype._ontouchend = function(e) { 66973 this._setProperty('mouseIsPressed', false); 66974 this._updateTouchCoords(e); 66975 this._updateNextMouseCoords(e); 66976 var context = this._isGlobal ? window : this; 66977 var executeDefault; 66978 if (typeof context.touchEnded === 'function') { 66979 executeDefault = context.touchEnded(e); 66980 if (executeDefault === false) { 66981 e.preventDefault(); 66982 } 66983 } else if (typeof context.mouseReleased === 'function') { 66984 executeDefault = context.mouseReleased(e); 66985 if (executeDefault === false) { 66986 e.preventDefault(); 66987 } 66988 } 66989 }; 66990 var _default = _main.default; 66991 exports.default = _default; 66992 }, 66993 { '../core/main': 59 } 66994 ], 66995 80: [ 66996 function(_dereq_, module, exports) { 66997 'use strict'; 66998 Object.defineProperty(exports, '__esModule', { value: true }); 66999 exports.default = void 0; /*global ImageData:false */ 67000 67001 /** 67002 * This module defines the filters for use with image buffers. 67003 * 67004 * This module is basically a collection of functions stored in an object 67005 * as opposed to modules. The functions are destructive, modifying 67006 * the passed in canvas rather than creating a copy. 67007 * 67008 * Generally speaking users of this module will use the Filters.apply method 67009 * on a canvas to create an effect. 67010 * 67011 * A number of functions are borrowed/adapted from 67012 * http://www.html5rocks.com/en/tutorials/canvas/imagefilters/ 67013 * or the java processing implementation. 67014 */ 67015 67016 var Filters = {}; 67017 67018 /* 67019 * Helper functions 67020 */ 67021 67022 /** 67023 * Returns the pixel buffer for a canvas 67024 * 67025 * @private 67026 * 67027 * @param {Canvas|ImageData} canvas the canvas to get pixels from 67028 * @return {Uint8ClampedArray} a one-dimensional array containing 67029 * the data in thc RGBA order, with integer 67030 * values between 0 and 255 67031 */ 67032 Filters._toPixels = function(canvas) { 67033 if (canvas instanceof ImageData) { 67034 return canvas.data; 67035 } else { 67036 return canvas.getContext('2d').getImageData(0, 0, canvas.width, canvas.height) 67037 .data; 67038 } 67039 }; 67040 67041 /** 67042 * Returns a 32 bit number containing ARGB data at ith pixel in the 67043 * 1D array containing pixels data. 67044 * 67045 * @private 67046 * 67047 * @param {Uint8ClampedArray} data array returned by _toPixels() 67048 * @param {Integer} i index of a 1D Image Array 67049 * @return {Integer} 32 bit integer value representing 67050 * ARGB value. 67051 */ 67052 Filters._getARGB = function(data, i) { 67053 var offset = i * 4; 67054 return ( 67055 ((data[offset + 3] << 24) & 0xff000000) | 67056 ((data[offset] << 16) & 0x00ff0000) | 67057 ((data[offset + 1] << 8) & 0x0000ff00) | 67058 (data[offset + 2] & 0x000000ff) 67059 ); 67060 }; 67061 67062 /** 67063 * Modifies pixels RGBA values to values contained in the data object. 67064 * 67065 * @private 67066 * 67067 * @param {Uint8ClampedArray} pixels array returned by _toPixels() 67068 * @param {Int32Array} data source 1D array where each value 67069 * represents ARGB values 67070 */ 67071 Filters._setPixels = function(pixels, data) { 67072 var offset = 0; 67073 for (var i = 0, al = pixels.length; i < al; i++) { 67074 offset = i * 4; 67075 pixels[offset + 0] = (data[i] & 0x00ff0000) >>> 16; 67076 pixels[offset + 1] = (data[i] & 0x0000ff00) >>> 8; 67077 pixels[offset + 2] = data[i] & 0x000000ff; 67078 pixels[offset + 3] = (data[i] & 0xff000000) >>> 24; 67079 } 67080 }; 67081 67082 /** 67083 * Returns the ImageData object for a canvas 67084 * https://developer.mozilla.org/en-US/docs/Web/API/ImageData 67085 * 67086 * @private 67087 *
67088 * @param {Canvas|ImageData} canvas canvas to get image data from 67089 * @return {ImageData} Holder of pixel data (and width and 67090 * height) for a canvas 67091 */ 67092 Filters._toImageData = function(canvas) { 67093 if (canvas instanceof ImageData) { 67094 return canvas; 67095 } else { 67096 return canvas 67097 .getContext('2d') 67098 .getImageData(0, 0, canvas.width, canvas.height); 67099 } 67100 }; 67101 67102 /** 67103 * Returns a blank ImageData object. 67104 * 67105 * @private 67106 * 67107 * @param {Integer} width 67108 * @param {Integer} height 67109 * @return {ImageData} 67110 */ 67111 Filters._createImageData = function(width, height) { 67112 Filters._tmpCanvas = document.createElement('canvas'); 67113 Filters._tmpCtx = Filters._tmpCanvas.getContext('2d'); 67114 return this._tmpCtx.createImageData(width, height); 67115 }; 67116 67117 /** 67118 * Applys a filter function to a canvas. 67119 * 67120 * The difference between this and the actual filter functions defined below 67121 * is that the filter functions generally modify the pixel buffer but do 67122 * not actually put that data back to the canvas (where it would actually 67123 * update what is visible). By contrast this method does make the changes 67124 * actually visible in the canvas. 67125 * 67126 * The apply method is the method that callers of this module would generally 67127 * use. It has been separated from the actual filters to support an advanced 67128 * use case of creating a filter chain that executes without actually updating 67129 * the canvas in between everystep. 67130 * 67131 * @private 67132 * @param {HTMLCanvasElement} canvas [description] 67133 * @param {function(ImageData,Object)} func [description] 67134 * @param {Object} filterParam [description] 67135 */ 67136 Filters.apply = function(canvas, func, filterParam) { 67137 var pixelsState = canvas.getContext('2d'); 67138 var imageData = pixelsState.getImageData(0, 0, canvas.width, canvas.height); 67139 67140 //Filters can either return a new ImageData object, or just modify 67141 //the one they received. 67142 var newImageData = func(imageData, filterParam); 67143 if (newImageData instanceof ImageData) { 67144 pixelsState.putImageData( 67145 newImageData, 67146 0, 67147 0, 67148 0, 67149 0, 67150 canvas.width, 67151 canvas.height 67152 ); 67153 } else { 67154 pixelsState.putImageData(imageData, 0, 0, 0, 0, canvas.width, canvas.height); 67155 } 67156 }; 67157 67158 /* 67159 * Filters 67160 */ 67161 67162 /** 67163 * Converts the image to black and white pixels depending if they are above or 67164 * below the threshold defined by the level parameter. The parameter must be 67165 * between 0.0 (black) and 1.0 (white). If no level is specified, 0.5 is used. 67166 * 67167 * Borrowed from http://www.html5rocks.com/en/tutorials/canvas/imagefilters/ 67168 * 67169 * @private 67170 * @param {Canvas} canvas 67171 * @param {Float} level 67172 */ 67173 Filters.threshold = function(canvas, level) { 67174 var pixels = Filters._toPixels(canvas); 67175 67176 if (level === undefined) { 67177 level = 0.5; 67178 } 67179 var thresh = Math.floor(level * 255); 67180 67181 for (var i = 0; i < pixels.length; i += 4) { 67182 var r = pixels[i]; 67183 var g = pixels[i + 1]; 67184 var b = pixels[i + 2]; 67185 var gray = 0.2126 * r + 0.7152 * g + 0.0722 * b; 67186 var val = void 0; 67187 if (gray >= thresh) { 67188 val = 255; 67189 } else { 67190 val = 0; 67191 } 67192 pixels[i] = pixels[i + 1] = pixels[i + 2] = val; 67193 } 67194 }; 67195 67196 /** 67197 * Converts any colors in the image to grayscale equivalents. 67198 * No parameter is used. 67199 * 67200 * Borrowed from http://www.html5rocks.com/en/tutorials/canvas/imagefilters/ 67201 * 67202 * @private 67203 * @param {Canvas} canvas 67204 */ 67205 Filters.gray = function(canvas) { 67206 var pixels = Filters._toPixels(canvas); 67207 67208 for (var i = 0; i < pixels.length; i += 4) { 67209 var r = pixels[i]; 67210 var g = pixels[i + 1]; 67211 var b = pixels[i + 2]; 67212 67213 // CIE luminance for RGB 67214 var gray = 0.2126 * r + 0.7152 * g + 0.0722 * b; 67215 pixels[i] = pixels[i + 1] = pixels[i + 2] = gray; 67216 } 67217 }; 67218 67219 /** 67220 * Sets the alpha channel to entirely opaque. No parameter is used. 67221 * 67222 * @private 67223 * @param {Canvas} canvas 67224 */ 67225 Filters.opaque = function(canvas) { 67226 var pixels = Filters._toPixels(canvas); 67227 67228 for (var i = 0; i < pixels.length; i += 4) { 67229 pixels[i + 3] = 255; 67230 } 67231 67232 return pixels; 67233 }; 67234 67235 /** 67236 * Sets each pixel to its inverse value. No parameter is used. 67237 * @private
67238 * @param {Canvas} canvas 67239 */ 67240 Filters.invert = function(canvas) { 67241 var pixels = Filters._toPixels(canvas); 67242 67243 for (var i = 0; i < pixels.length; i += 4) { 67244 pixels[i] = 255 - pixels[i]; 67245 pixels[i + 1] = 255 - pixels[i + 1]; 67246 pixels[i + 2] = 255 - pixels[i + 2]; 67247 } 67248 }; 67249 67250 /** 67251 * Limits each channel of the image to the number of colors specified as 67252 * the parameter. The parameter can be set to values between 2 and 255, but 67253 * results are most noticeable in the lower ranges. 67254 * 67255 * Adapted from java based processing implementation 67256 * 67257 * @private 67258 * @param {Canvas} canvas 67259 * @param {Integer} level 67260 */ 67261 Filters.posterize = function(canvas, level) { 67262 var pixels = Filters._toPixels(canvas); 67263 67264 if (level < 2 || level > 255) { 67265 throw new Error( 67266 'Level must be greater than 2 and less than 255 for posterize' 67267 ); 67268 } 67269 67270 var levels1 = level - 1; 67271 for (var i = 0; i < pixels.length; i += 4) { 67272 var rlevel = pixels[i]; 67273 var glevel = pixels[i + 1]; 67274 var blevel = pixels[i + 2]; 67275 67276 pixels[i] = ((rlevel * level) >> 8) * 255 / levels1; 67277 pixels[i + 1] = ((glevel * level) >> 8) * 255 / levels1; 67278 pixels[i + 2] = ((blevel * level) >> 8) * 255 / levels1; 67279 } 67280 }; 67281 67282 /** 67283 * reduces the bright areas in an image 67284 * @private 67285 * @param {Canvas} canvas 67286 */ 67287 Filters.dilate = function(canvas) { 67288 var pixels = Filters._toPixels(canvas); 67289 var currIdx = 0; 67290 var maxIdx = pixels.length ? pixels.length / 4 : 0; 67291 var out = new Int32Array(maxIdx); 67292 var currRowIdx, maxRowIdx, colOrig, colOut, currLum; 67293 67294 var idxRight, idxLeft, idxUp, idxDown; 67295 var colRight, colLeft, colUp, colDown; 67296 var lumRight, lumLeft, lumUp, lumDown; 67297 67298 while (currIdx < maxIdx) { 67299 currRowIdx = currIdx; 67300 maxRowIdx = currIdx + canvas.width; 67301 while (currIdx < maxRowIdx) { 67302 colOrig = colOut = Filters._getARGB(pixels, currIdx); 67303 idxLeft = currIdx - 1; 67304 idxRight = currIdx + 1; 67305 idxUp = currIdx - canvas.width; 67306 idxDown = currIdx + canvas.width; 67307 67308 if (idxLeft < currRowIdx) { 67309 idxLeft = currIdx; 67310 } 67311 if (idxRight >= maxRowIdx) { 67312 idxRight = currIdx; 67313 } 67314 if (idxUp < 0) { 67315 idxUp = 0; 67316 } 67317 if (idxDown >= maxIdx) { 67318 idxDown = currIdx; 67319 } 67320 colUp = Filters._getARGB(pixels, idxUp); 67321 colLeft = Filters._getARGB(pixels, idxLeft); 67322 colDown = Filters._getARGB(pixels, idxDown); 67323 colRight = Filters._getARGB(pixels, idxRight); 67324 67325 //compute luminance 67326 currLum = 67327 77 * ((colOrig >> 16) & 0xff) + 67328 151 * ((colOrig >> 8) & 0xff) + 67329 28 * (colOrig & 0xff); 67330 lumLeft = 67331 77 * ((colLeft >> 16) & 0xff) + 67332 151 * ((colLeft >> 8) & 0xff) + 67333 28 * (colLeft & 0xff); 67334 lumRight = 67335 77 * ((colRight >>
67335 16) & 0xff) + 67336 151 * ((colRight >> 8) & 0xff) + 67337 28 * (colRight & 0xff); 67338 lumUp = 67339 77 * ((colUp >> 16) & 0xff) + 67340 151 * ((colUp >> 8) & 0xff) + 67341 28 * (colUp & 0xff); 67342 lumDown = 67343 77 * ((colDown >> 16) & 0xff) + 67344 151 * ((colDown >> 8) & 0xff) + 67345 28 * (colDown & 0xff); 67346 67347 if (lumLeft > currLum) { 67348 colOut = colLeft; 67349 currLum = lumLeft; 67350 } 67351 if (lumRight > currLum) { 67352 colOut = colRight; 67353 currLum = lumRight; 67354 } 67355 if (lumUp > currLum) { 67356 colOut = colUp; 67357 currLum = lumUp; 67358 } 67359 if (lumDown > currLum) { 67360 colOut = colDown; 67361 currLum = lumDown; 67362 } 67363 out[currIdx++] = colOut; 67364 } 67365 } 67366 Filters._setPixels(pixels, out); 67367 }; 67368 67369 /** 67370 * increases the bright areas in an image 67371 * @private 67372 * @param {Canvas} canvas 67373 */ 67374 Filters.erode = function(canvas) { 67375 var pixels = Filters._toPixels(canvas); 67376 var currIdx = 0; 67377 var maxIdx = pixels.length ? pixels.length / 4 : 0; 67378 var out = new Int32Array(maxIdx); 67379 var currRowIdx, maxRowIdx, colOrig, colOut, currLum; 67380 var idxRight, idxLeft, idxUp, idxDown; 67381 var colRight, colLeft, colUp, colDown; 67382 var lumRight, lumLeft, lumUp, lumDown; 67383 67384 while (currIdx < maxIdx) { 67385 currRowIdx = currIdx; 67386 maxRowIdx = currIdx + canvas.width; 67387 while (currIdx < maxRowIdx) { 67388 colOrig = colOut = Filters._getARGB(pixels, currIdx); 67389 idxLeft = currIdx - 1; 67390 idxRight = currIdx + 1; 67391 idxUp = currIdx - canvas.width; 67392 idxDown = currIdx + canvas.width; 67393 67394 if (idxLeft < currRowIdx) { 67395 idxLeft = currIdx; 67396 } 67397 if (idxRight >= maxRowIdx) { 67398 idxRight = currIdx; 67399 } 67400 if (idxUp < 0) { 67401 idxUp = 0; 67402 } 67403 if (idxDown >= maxIdx) { 67404 idxDown = currIdx; 67405 } 67406 colUp = Filters._getARGB(pixels, idxUp); 67407 colLeft = Filters._getARGB(pixels, idxLeft); 67408 colDown = Filters._getARGB(pixels, idxDown); 67409 colRight = Filters._getARGB(pixels, idxRight); 67410 67411 //compute luminance 67412 currLum = 67413 77 * ((colOrig >> 16) & 0xff) + 67414 151 * ((colOrig >> 8) & 0xff) + 67415 28 * (colOrig & 0xff); 67416 lumLeft = 67417 77 * ((colLeft >> 16) & 0xff) + 67418 151 * ((colLeft >> 8) & 0xff) + 67419 28 * (colLeft & 0xff); 67420 lumRight = 67421 77 * ((colRight >>
67421 16) & 0xff) + 67422 151 * ((colRight >> 8) & 0xff) + 67423 28 * (colRight & 0xff); 67424 lumUp = 67425 77 * ((colUp >> 16) & 0xff) + 67426 151 * ((colUp >> 8) & 0xff) + 67427 28 * (colUp & 0xff); 67428 lumDown = 67429 77 * ((colDown >> 16) & 0xff) + 67430 151 * ((colDown >> 8) & 0xff) + 67431 28 * (colDown & 0xff); 67432 67433 if (lumLeft < currLum) { 67434 colOut = colLeft; 67435 currLum = lumLeft; 67436 } 67437 if (lumRight < currLum) { 67438 colOut = colRight; 67439 currLum = lumRight; 67440 } 67441 if (lumUp < currLum) { 67442 colOut = colUp; 67443 currLum = lumUp; 67444 } 67445 if (lumDown < currLum) { 67446 colOut = colDown; 67447 currLum = lumDown; 67448 } 67449 67450 out[currIdx++] = colOut; 67451 } 67452 } 67453 Filters._setPixels(pixels, out); 67454 }; 67455 67456 // BLUR 67457 67458 // internal kernel stuff for the gaussian blur filter 67459 var blurRadius; 67460 var blurKernelSize; 67461 var blurKernel; 67462 var blurMult; 67463 67464 /* 67465 * Port of https://github.com/processing/processing/blob/ 67466 * main/core/src/processing/core/PImage.java#L1250 67467 * 67468 * Optimized code for building the blur kernel. 67469 * further optimized blur code (approx. 15% for radius=20) 67470 * bigger speed gains for larger radii (~30%) 67471 * added support for various image types (ALPHA, RGB, ARGB) 67472 * [toxi 050728] 67473 */ 67474 function buildBlurKernel(r) { 67475 var radius = (r * 3.5) | 0; 67476 radius = radius < 1 ? 1 : radius < 248 ? radius : 248; 67477 67478 if (blurRadius !== radius) { 67479 blurRadius = radius; 67480 blurKernelSize = (1 + blurRadius) << 1; 67481 blurKernel = new Int32Array(blurKernelSize); 67482 blurMult = new Array(blurKernelSize); 67483 for (var l = 0; l < blurKernelSize; l++) { 67484 blurMult[l] = new Int32Array(256); 67485 } 67486 67487 var bk, bki; 67488 var bm, bmi; 67489
67490 for (var i = 1, radiusi = radius - 1; i < radius; i++) { 67491 blurKernel[radius + i] = blurKernel[radiusi] = bki = radiusi * radiusi; 67492 bm = blurMult[radius + i]; 67493 bmi = blurMult[radiusi--]; 67494 for (var j = 0; j < 256; j++) { 67495 bm[j] = bmi[j] = bki * j; 67496 } 67497 } 67498 bk = blurKernel[radius] = radius * radius; 67499 bm = blurMult[radius]; 67500 67501 for (var k = 0; k < 256; k++) { 67502 bm[k] = bk * k; 67503 } 67504 } 67505 } 67506 67507 // Port of https://github.com/processing/processing/blob/ 67508 // main/core/src/processing/core/PImage.java#L1433 67509 function blurARGB(canvas, radius) { 67510 var pixels = Filters._toPixels(canvas); 67511 var width = canvas.width; 67512 var height = canvas.height; 67513 var numPackedPixels = width * height; 67514 var argb = new Int32Array(numPackedPixels); 67515 for (var j = 0; j < numPackedPixels; j++) { 67516 argb[j] = Filters._getARGB(pixels, j); 67517 } 67518 var sum, cr, cg, cb, ca; 67519 var read, ri, ym, ymi, bk0; 67520 var a2 = new Int32Array(numPackedPixels); 67521 var r2 = new Int32Array(numPackedPixels); 67522 var g2 = new Int32Array(numPackedPixels); 67523 var b2 = new Int32Array(numPackedPixels); 67524 var yi = 0; 67525 buildBlurKernel(radius); 67526 var x, y, i; 67527 var bm; 67528 for (y = 0; y < height; y++) { 67529 for (x = 0; x < width; x++) { 67530 cb = cg = cr = ca = sum = 0; 67531 read = x - blurRadius; 67532 if (read < 0) { 67533 bk0 = -read; 67534 read = 0; 67535 } else { 67536 if (read >= width) { 67537 break; 67538 } 67539 bk0 = 0; 67540 } 67541 for (i = bk0; i < blurKernelSize; i++) { 67542 if (read >= width) { 67543 break; 67544 } 67545 var c = argb[read + yi]; 67546 bm = blurMult[i]; 67547 ca += bm[(c & -16777216) >>> 24]; 67548 cr += bm[(c & 16711680) >> 16]; 67549 cg += bm[(c & 65280) >> 8]; 67550 cb += bm[c & 255]; 67551 sum += blurKernel[i]; 67552 read++; 67553 } 67554 ri = yi + x; 67555 a2[ri] = ca / sum; 67556 r2[ri] = cr / sum; 67557 g2[ri] = cg / sum; 67558 b2[ri] = cb / sum; 67559 } 67560 yi += width; 67561 } 67562 yi = 0; 67563 ym = -blurRadius; 67564 ymi = ym * width; 67565 for (y = 0; y < height; y++) { 67566 for (x = 0; x < width; x++) { 67567 cb = cg = cr = ca = sum = 0; 67568 if (ym < 0) { 67569 bk0 = ri = -ym; 67570 read = x; 67571 } else { 67572 if (ym >= height) { 67573 break; 67574 } 67575 bk0 = 0; 67576 ri = ym; 67577 read = x + ymi; 67578 } 67579 for (i = bk0; i < blurKernelSize; i++) { 67580 if (ri >= height) { 67581 break; 67582 } 67583 bm = blurMult[i]; 67584 ca += bm[a2[read]]; 67585 cr += bm[r2[read]]; 67586 cg += bm[g2[read]]; 67587 cb += bm[b2[read]]; 67588 sum += blurKernel[i]; 67589 ri++; 67590 read += width; 67591 } 67592 argb[x + yi] = 67593 ((ca / sum) << 24) | ((cr / sum) << 16) | ((cg / sum) << 8) | (cb / sum); 67594 } 67595 yi += width; 67596 ymi += width; 67597 ym++; 67598 } 67599 Filters._setPixels(pixels, argb); 67600 } 67601 67602 Filters.blur = function(canvas, radius) { 67603 blurARGB(canvas, radius); 67604 }; 67605 var _default = Filters; 67606 exports.default = _default; 67607 }, 67608 {} 67609 ], 67610 81: [
67611 function(_dereq_, module, exports) { 67612 'use strict'; 67613 Object.defineProperty(exports, '__esModule', { value: true }); 67614 exports.default = void 0; 67615 67616 var _main = _interopRequireDefault(_dereq_('../core/main')); 67617 var _omggif = _interopRequireDefault(_dereq_('omggif')); 67618 function _interopRequireDefault(obj) { 67619 return obj && obj.__esModule ? obj : { default: obj }; 67620 } 67621 function _toConsumableArray(arr) { 67622 return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); 67623 } 67624 function _nonIterableSpread() { 67625 throw new TypeError('Invalid attempt to spread non-iterable instance'); 67626 } 67627 function _iterableToArray(iter) { 67628 if ( 67629 Symbol.iterator in Object(iter) || 67630 Object.prototype.toString.call(iter) === '[object Arguments]' 67631 ) 67632 return Array.from(iter); 67633 } 67634 function _arrayWithoutHoles(arr) { 67635 if (Array.isArray(arr)) { 67636 for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { 67637 arr2[i] = arr[i]; 67638 } 67639 return arr2; 67640 } 67641 } 67642 67643 /** 67644 * Creates a new <a href="#/p5.Image">p5.Image</a> (the datatype for storing images). This provides a 67645 * fresh buffer of pixels to play with. Set the size of the buffer with the 67646 * width and height parameters. 67647 * 67648 * .<a href="#/p5.Image/pixels">pixels</a> gives access to an array containing the values for all the pixels 67649 * in the display window. 67650 * These values are numbers. This array is the size (including an appropriate 67651 * factor for the <a href="#/p5/pixelDensity">pixelDensity</a>) of the display window x4, 67652 * representing the R, G, B, A values in order for each pixel, moving from 67653 * left to right across each row, then down each column. See .<a href="#/p5.Image/pixels">pixels</a> for 67654 * more info. It may also be simpler to use <a href="#/p5.Image/set">set()</a> or <a href="#/p5.Image/get">get()</a>. 67655 * 67656 * Before accessing the pixels of an image, the data must loaded with the 67657 * <a href="#/p5.Image/loadPixels">loadPixels()</a> function. After the array data has been modified, the 67658 * <a href="#/p5.Image/updatePixels">updatePixels()</a> function must be run to update the changes. 67659 * 67660 * @method createImage 67661 * @param {Integer} width width in pixels 67662 * @param {Integer} height height in pixels 67663 * @return {p5.Image} the <a href="#/p5.Image">p5.Image</a> object 67664 * @example 67665 * <div> 67666 * <code> 67667 * let img = createImage(66, 66); 67668 * img.loadPixels(); 67669 * for (let i = 0; i < img.width; i++) { 67670 * for (let j = 0; j < img.height; j++) { 67671 * img.set(i, j, color(0, 90, 102)); 67672 * } 67673 * } 67674 * img.updatePixels(); 67675 * image(img, 17, 17); 67676 * </code> 67677 * </div> 67678 * 67679 * <div> 67680 * <code> 67681 * let img = createImage(66, 66); 67682 * img.loadPixels(); 67683 * for (let i = 0; i < img.width; i++) { 67684 * for (let j = 0; j < img.height; j++) { 67685 * img.set(i, j, color(0, 90, 102, (i % img.width) * 2)); 67686 * } 67687 * } 67688 * img.updatePixels(); 67689 * image(img, 17, 17); 67690 * image(img, 34, 34); 67691 * </code> 67692 * </div> 67693 * 67694 * <div> 67695 * <code> 67696 * let pink = color(255, 102, 204); 67697 * let img = createImage(66, 66); 67698 * img.loadPixels(); 67699 * let d = pixelDensity(); 67700 * let halfImage = 4 * (img.width * d) * (img.height / 2 * d); 67701 * for (let i = 0; i < halfImage; i += 4) { 67702 * img.pixels[i] = red(pink); 67703 * img.pixels[i + 1] = green(pink); 67704 * img.pixels[i + 2] = blue(pink); 67705 * img.pixels[i + 3] = alpha(pink); 67706 * } 67707 * img.updatePixels();
67708 * image(img, 17, 17); 67709 * </code> 67710 * </div> 67711 * 67712 * @alt 67713 * 66x66 dark turquoise rect in center of canvas. 67714 * 2 gradated dark turquoise rects fade left. 1 center 1 bottom right of canvas 67715 * no image displayed 67716 */ 67717 _main.default.prototype.createImage = function(width, height) { 67718 _main.default._validateParameters('createImage', arguments); 67719 return new _main.default.Image(width, height); 67720 }; 67721 67722 /** 67723 * Save the current canvas as an image. The browser will either save the 67724 * file immediately, or prompt the user with a dialogue window. 67725 * 67726 * @method saveCanvas 67727 * @param {p5.Element|HTMLCanvasElement} selectedCanvas a variable 67728 * representing a specific html5 canvas (optional) 67729 * @param {String} [filename] 67730 * @param {String} [extension] 'jpg' or 'png' 67731 * 67732 * @example 67733 * <div class='norender notest'><code> 67734 * function setup() { 67735 * let c = createCanvas(100, 100); 67736 * background(255, 0, 0); 67737 * saveCanvas(c, 'myCanvas', 'jpg'); 67738 * } 67739 * </code></div> 67740 * <div class='norender notest'><code> 67741 * // note that this example has the same result as above 67742 * // if no canvas is specified, defaults to main canvas 67743 * function setup() { 67744 * let c = createCanvas(100, 100); 67745 * background(255, 0, 0); 67746 * saveCanvas('myCanvas', 'jpg'); 67747 * 67748 * // all of the following are valid 67749 * saveCanvas(c, 'myCanvas', 'jpg'); 67750 * saveCanvas(c, 'myCanvas.jpg'); 67751 * saveCanvas(c, 'myCanvas'); 67752 * saveCanvas(c); 67753 * saveCanvas('myCanvas', 'png'); 67754 * saveCanvas('myCanvas'); 67755 * saveCanvas(); 67756 * } 67757 * </code></div> 67758 * 67759 * @alt 67760 * no image displayed 67761 * no image displayed 67762 * no image displayed 67763 */ 67764 /** 67765 * @method saveCanvas 67766 * @param {String} [filename] 67767 * @param {String} [extension] 67768 */ 67769 _main.default.prototype.saveCanvas = function() { 67770 _main.default._validateParameters('saveCanvas', arguments); 67771 67772 // copy arguments to array 67773 var args = [].slice.call(arguments); 67774 var htmlCanvas, filename, extension; 67775 67776 if (arguments[0] instanceof HTMLCanvasElement) { 67777 htmlCanvas = arguments[0]; 67778 args.shift(); 67779 } else if (arguments[0] instanceof _main.default.Element) { 67780 htmlCanvas = arguments[0].elt; 67781 args.shift(); 67782 } else { 67783 htmlCanvas = this._curElement && this._curElement.elt; 67784 } 67785 67786 if (args.length >= 1) { 67787 filename = args[0]; 67788 } 67789 if (args.length >= 2) { 67790 extension = args[1]; 67791 } 67792 67793 extension = 67794 extension || 67795 _main.default.prototype._checkFileExtension(filename, extension)[1] || 67796 'png'; 67797 67798 var mimeType; 67799 switch (extension) { 67800 default: 67801 //case 'png': 67802 mimeType = 'image/png'; 67803 break; 67804 case 'jpeg': 67805 case 'jpg': 67806 mimeType = 'image/jpeg'; 67807 break; 67808 } 67809 67810 htmlCanvas.toBlob(function(blob) { 67811 _main.default.prototype.downloadFile(blob, filename, extension); 67812 }, mimeType); 67813 }; 67814 67815 _main.default.prototype.saveGif = function(pImg, filename) { 67816 var props = pImg.gifProperties; 67817 67818 //convert loopLimit back into Netscape Block formatting 67819 var loopLimit = props.loopLimit; 67820 if (loopLimit === 1) { 67821 loopLimit = null; 67822 } else if (loopLimit === null) { 67823 loopLimit = 0; 67824 } 67825 var buffer = new Uint8Array(pImg.width * pImg.height * props.numFrames); 67826 67827 var allFramesPixelColors = []; 67828 67829 // Used to determine the occurrence of unique palettes and the frames 67830 // which use them 67831 var paletteFreqsAndFrames = {}; 67832 67833 // Pass 1: 67834 //loop over frames and get the frequency of each palette 67835 for (var i = 0; i < props.numFrames; i++) { 67836 var paletteSet = new Set(); 67837 var data = props.frames[i].image.data; 67838 var dataLength = data.length; 67839 // The color for each pixel in this frame ( for easier lookup later ) 67840 var pixelColors = new Uint32Array(pImg.width * pImg.height); 67841 for (var j = 0, k = 0; j < dataLength; j += 4, k++) { 67842 var r = data[j + 0]; 67843 var g = data[j + 1]; 67844 var b = data[j + 2]; 67845 var color = (r << 16) | (g << 8) | (b << 0); 67846 paletteSet.add(color); 67847 67848 // What color does this pixel have in this frame ? 67849 pixelColors[k] = color; 67850 } 67851 67852 // A way to put use the entire palette as an object key 67853 var paletteStr = _toConsumableArray(paletteSet) 67854 .sort() 67855 .toString(); 67856 if (paletteFreqsAndFrames[paletteStr] === undefined) { 67857 paletteFreqsAndFrames[paletteStr] = { freq: 1, frames: [i] }; 67858 } else { 67859 paletteFreqsAndFrames[paletteStr].freq += 1; 67860 paletteFreqsAndFrames[paletteStr].frames.push(i); 67861 } 67862 67863 allFramesPixelColors.push(pixelColors); 67864 } 67865 67866 var framesUsingGlobalPalette = []; 67867 67868 // Now to build the global palette 67869 // Sort all the unique palettes in descending order of their occurence
67870 var palettesSortedByFreq = Object.keys(paletteFreqsAndFrames).sort(function( 67871 a, 67872 b 67873 ) { 67874 return paletteFreqsAndFrames[b].freq - paletteFreqsAndFrames[a].freq; 67875 }); 67876 67877 // The initial global palette is the one with the most occurence 67878 var globalPalette = palettesSortedByFreq[0].split(',').map(function(a) { 67879 return parseInt(a); 67880 }); 67881 67882 framesUsingGlobalPalette = framesUsingGlobalPalette.concat( 67883 paletteFreqsAndFrames[globalPalette].frames 67884 ); 67885 67886 var globalPaletteSet = new Set(globalPalette); 67887 67888 // Build a more complete global palette 67889 // Iterate over the remaining palettes in the order of 67890 // their occurence and see if the colors in this palette which are 67891 // not in the global palette can be added there, while keeping the length 67892 // of the global palette <= 256 67893 for (var _i = 1; _i < palettesSortedByFreq.length; _i++) { 67894 var palette = palettesSortedByFreq[_i].split(',').map(function(a) { 67895 return parseInt(a); 67896 }); 67897 67898 var difference = palette.filter(function(x) { 67899 return !globalPaletteSet.has(x); 67900 }); 67901 if (globalPalette.length + difference.length <= 256) { 67902 for (var _j = 0; _j < difference.length; _j++) { 67903 globalPalette.push(difference[_j]); 67904 globalPaletteSet.add(difference[_j]); 67905 } 67906 67907 // All frames using this palette now use the global palette 67908 framesUsingGlobalPalette = framesUsingGlobalPalette.concat( 67909 paletteFreqsAndFrames[palettesSortedByFreq[_i]].frames 67910 ); 67911 } 67912 } 67913 67914 framesUsingGlobalPalette = new Set(framesUsingGlobalPalette); 67915 67916 // Build a lookup table of the index of each color in the global palette 67917 // Maps a color to its index 67918 var globalIndicesLookup = {}; 67919 for (var _i2 = 0; _i2 < globalPalette.length; _i2++) { 67920 if (!globalIndicesLookup[globalPalette[_i2]]) { 67921 globalIndicesLookup[globalPalette[_i2]] = _i2; 67922 } 67923 } 67924 67925 // force palette to be power of 2 67926 var powof2 = 1; 67927 while (powof2 < globalPalette.length) { 67928 powof2 <<= 1; 67929 } 67930 globalPalette.length = powof2; 67931 67932 // global opts 67933 var opts = { 67934 loop: loopLimit, 67935 palette: new Uint32Array(globalPalette) 67936 }; 67937 67938 var gifWriter = new _omggif.default.GifWriter( 67939 buffer, 67940 pImg.width, 67941 pImg.height, 67942 opts 67943 ); 67944 var previousFrame = {}; 67945 67946 // Pass 2 67947 // Determine if the frame needs a local palette 67948 // Also apply transparency optimization. This function will often blow up 67949 // the size of a GIF if not for transparency. If a pixel in one frame has 67950 // the same color in the previous frame, that pixel can be marked as 67951 // transparent. We decide one particular color as transparent and make all 67952 // transparent pixels take this color. This helps in later in compression. 67953 var _loop = function _loop(_i3) { 67954 var localPaletteRequired = !framesUsingGlobalPalette.has(_i3); 67955 var palette = localPaletteRequired ? [] : globalPalette; 67956 var pixelPaletteIndex = new Uint8Array(pImg.width * pImg.height); 67957 67958 // Lookup table mapping color to its indices 67959 var colorIndicesLookup = {}; 67960 67961 // All the colors that cannot be marked transparent in this frame 67962 var cannotBeTransparent = new Set(); 67963 67964 for (var _k = 0; _k < allFramesPixelColors[_i3].length; _k++) { 67965 var _color = allFramesPixelColors[_i3][_k]; 67966 if (localPaletteRequired) { 67967 if (colorIndicesLookup[_color] === undefined) { 67968 colorIndicesLookup[_color] = palette.length; 67969 palette.push(_color); 67970 } 67971 pixelPaletteIndex[_k] = colorIndicesLookup[_color]; 67972 } else { 67973 pixelPaletteIndex[_k] = globalIndicesLookup[_color]; 67974 } 67975 67976 if (_i3 > 0) { 67977 // If even one pixel of this color has changed in this frame 67978 // from the previous frame, we cannot mark it as transparent 67979 if (allFramesPixelColors[_i3 - 1][_k] !== _color) { 67980 cannotBeTransparent.add(_color); 67981 } 67982 } 67983 } 67984 67985 var frameOpts = {}; 67986 67987 // Transparency optimization 67988 var canBeTransparent = palette.filter(function(a) { 67989 return !cannotBeTransparent.has(a); 67990 }); 67991 if (canBeTransparent.length > 0) { 67992 // Select a color to mark as transparent 67993 var transparent = canBeTransparent[0]; 67994 var transparentIndex = localPaletteRequired 67995 ? colorIndicesLookup[transparent] 67996 : globalIndicesLookup[transparent]; 67997 if (_i3 > 0) { 67998 for (var _k2 = 0; _k2 < allFramesPixelColors[_i3].length; _k2++) { 67999 // If this pixel in this frame has the same color in previous frame 68000 if ( 68001 allFramesPixelColors[_i3 - 1][_k2] === allFramesPixelColors[_i3][_k2] 68002 ) { 68003 pixelPaletteIndex[_k2] = transparentIndex; 68004 } 68005 } 68006 frameOpts.transparent = transparentIndex; 68007 // If this frame has any transparency, do not dispose the previous frame 68008 previousFrame.frameOpts.disposal = 1; 68009 } 68010 }
68011 frameOpts.delay = props.frames[_i3].delay / 10; // Move timing back into GIF formatting 68012 if (localPaletteRequired) { 68013 // force palette to be power of 2 68014 var _powof = 1; 68015 while (_powof < palette.length) { 68016 _powof <<= 1; 68017 } 68018 palette.length = _powof; 68019 frameOpts.palette = new Uint32Array(palette); 68020 } 68021 if (_i3 > 0) { 68022 // add the frame that came before the current one 68023 gifWriter.addFrame( 68024 0, 68025 0, 68026 pImg.width, 68027 pImg.height, 68028 previousFrame.pixelPaletteIndex, 68029 previousFrame.frameOpts 68030 ); 68031 } 68032 // previous frame object should now have details of this frame 68033 previousFrame = { 68034 pixelPaletteIndex: pixelPaletteIndex, 68035 frameOpts: frameOpts 68036 }; 68037 }; 68038 for (var _i3 = 0; _i3 < props.numFrames; _i3++) { 68039 _loop(_i3); 68040 } 68041 68042 previousFrame.frameOpts.disposal = 1; 68043 // add the last frame 68044 gifWriter.addFrame( 68045 0, 68046 0, 68047 pImg.width, 68048 pImg.height, 68049 previousFrame.pixelPaletteIndex, 68050 previousFrame.frameOpts 68051 ); 68052 68053 var extension = 'gif'; 68054 var blob = new Blob([buffer.slice(0, gifWriter.end())], { 68055 type: 'image/gif' 68056 }); 68057 68058 _main.default.prototype.downloadFile(blob, filename, extension); 68059 }; 68060 68061 /** 68062 * Capture a sequence of frames that can be used to create a movie. 68063 * Accepts a callback. For example, you may wish to send the frames 68064 * to a server where they can be stored or converted into a movie. 68065 * If no callback is provided, the browser will pop up save dialogues in an 68066 * attempt to download all of the images that have just been created. With the 68067 * callback provided the image data isn't saved by default but instead passed 68068 * as an argument to the callback function as an array of objects, with the 68069 * size of array equal to the total number of frames. 68070 * 68071 * Note that <a href="#/p5.Image/saveFrames">saveFrames()</a> will only save the first 15 frames of an animation. 68072 * To export longer animations, you might look into a library like 68073 * <a href="https://github.com/spite/ccapture.js/">ccapture.js</a>. 68074 * 68075 * @method saveFrames 68076 * @param {String} filename 68077 * @param {String} extension 'jpg' or 'png' 68078 * @param {Number} duration Duration in seconds to save the frames for. 68079 * @param {Number} framerate Framerate to save the frames in. 68080 * @param {function(Array)} [callback] A callback function that will be executed 68081 to handle the image data. This function 68082 should accept an array as argument. The 68083 array will contain the specified number of 68084 frames of objects. Each object has three 68085 properties: imageData - an 68086 image/octet-stream, filename and extension. 68087 * @example 68088 * <div><code> 68089 * function draw() { 68090 * background(mouseX); 68091 * } 68092 * 68093 * function mousePressed() { 68094 * saveFrames('out', 'png', 1, 25, data => { 68095 * print(data); 68096 * }); 68097 * } 68098 </code></div> 68099 * 68100 * @alt 68101 * canvas background goes from light to dark with mouse x. 68102 */ 68103 _main.default.prototype.saveFrames = function( 68104 fName, 68105 ext, 68106 _duration, 68107 _fps, 68108 callback 68109 ) { 68110 _main.default._validateParameters('saveFrames', arguments); 68111 var duration = _duration || 3; 68112 duration = _main.default.prototype.constrain(duration, 0, 15); 68113 duration = duration * 1000; 68114 var fps = _fps || 15; 68115 fps = _main.default.prototype.constrain(fps, 0, 22); 68116 var count = 0; 68117 68118 var makeFrame = _main.default.prototype._makeFrame; 68119 var cnv = this._curElement.elt; 68120 var frames = []; 68121 var frameFactory = setInterval(function() { 68122 frames.push(makeFrame(fName + count, ext, cnv)); 68123 count++; 68124 }, 1000 / fps); 68125 68126 setTimeout(function() { 68127 clearInterval(frameFactory); 68128 if (callback) { 68129 callback(frames); 68130 } else { 68131 var _iteratorNormalCompletion = true; 68132 var _didIteratorError = false;
68133 var _iteratorError = undefined; 68134 try { 68135 for ( 68136 var _iterator = frames[Symbol.iterator](), _step; 68137 !(_iteratorNormalCompletion = (_step = _iterator.next()).done); 68138 _iteratorNormalCompletion = true 68139 ) { 68140 var f = _step.value; 68141 _main.default.prototype.downloadFile(f.imageData, f.filename, f.ext); 68142 } 68143 } catch (err) { 68144 _didIteratorError = true; 68145 _iteratorError = err; 68146 } finally { 68147 try { 68148 if (!_iteratorNormalCompletion && _iterator.return != null) { 68149 _iterator.return(); 68150 } 68151 } finally { 68152 if (_didIteratorError) { 68153 throw _iteratorError; 68154 } 68155 } 68156 } 68157 } 68158 frames = []; // clear frames 68159 }, duration + 0.01); 68160 }; 68161 68162 _main.default.prototype._makeFrame = function(filename, extension, _cnv) { 68163 var cnv; 68164 if (this) { 68165 cnv = this._curElement.elt; 68166 } else { 68167 cnv = _cnv; 68168 } 68169 var mimeType; 68170 if (!extension) { 68171 extension = 'png'; 68172 mimeType = 'image/png'; 68173 } else { 68174 switch (extension.toLowerCase()) { 68175 case 'png': 68176 mimeType = 'image/png'; 68177 break; 68178 case 'jpeg': 68179 mimeType = 'image/jpeg'; 68180 break; 68181 case 'jpg': 68182 mimeType = 'image/jpeg'; 68183 break; 68184 default: 68185 mimeType = 'image/png'; 68186 break; 68187 } 68188 } 68189 var downloadMime = 'image/octet-stream'; 68190 var imageData = cnv.toDataURL(mimeType); 68191 imageData = imageData.replace(mimeType, downloadMime); 68192 68193 var thisFrame = {}; 68194 thisFrame.imageData = imageData; 68195 thisFrame.filename = filename; 68196 thisFrame.ext = extension; 68197 return thisFrame; 68198 }; 68199 var _default = _main.default; 68200 exports.default = _default; 68201 }, 68202 { '../core/main': 59, omggif: 33 } 68203 ], 68204 82: [ 68205 function(_dereq_, module, exports) { 68206 'use strict'; 68207 function _typeof(obj) { 68208 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') { 68209 _typeof = function _typeof(obj) { 68210 return typeof obj; 68211 }; 68212 } else { 68213 _typeof = function _typeof(obj) { 68214 return obj && 68215 typeof Symbol === 'function' && 68216 obj.constructor === Symbol && 68217 obj !== Symbol.prototype 68218 ? 'symbol' 68219 : typeof obj; 68220 }; 68221 } 68222 return _typeof(obj); 68223 } 68224 Object.defineProperty(exports, '__esModule', { value: true }); 68225 exports.default = void 0; 68226 68227 var _main = _interopRequireDefault(_dereq_('../core/main')); 68228 var _filters = _interopRequireDefault(_dereq_('./filters')); 68229 var _helpers = _interopRequireDefault(_dereq_('../core/helpers')); 68230 var constants = _interopRequireWildcard(_dereq_('../core/constants')); 68231 var _omggif = _interopRequireDefault(_dereq_('omggif')); 68232 68233 _dereq_('../core/friendly_errors/validate_params'); 68234 _dereq_('../core/friendly_errors/file_errors'); 68235 _dereq_('../core/friendly_errors/fes_core'); 68236 function _getRequireWildcardCache() { 68237 if (typeof WeakMap !== 'function') return null; 68238 var cache = new WeakMap(); 68239 _getRequireWildcardCache = function _getRequireWildcardCache() { 68240 return cache; 68241 }; 68242 return cache; 68243 } 68244 function _interopRequireWildcard(obj) { 68245 if (obj && obj.__esModule) { 68246 return obj; 68247 } 68248 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) { 68249 return { default: obj }; 68250 } 68251 var cache = _getRequireWildcardCache(); 68252 if (cache && cache.has(obj)) { 68253 return cache.get(obj); 68254 } 68255 var newObj = {}; 68256 var hasPropertyDescriptor = 68257 Object.defineProperty && Object.getOwnPropertyDescriptor; 68258 for (var key in obj) { 68259 if (Object.prototype.hasOwnProperty.call(obj, key)) { 68260 var desc = hasPropertyDescriptor 68261 ? Object.getOwnPropertyDescriptor(obj, key) 68262 : null; 68263 if (desc && (desc.get || desc.set)) { 68264 Object.defineProperty(newObj, key, desc); 68265 } else { 68266 newObj[key] = obj[key]; 68267 } 68268 } 68269 } 68270 newObj.default = obj; 68271 if (cache) { 68272 cache.set(obj, newObj); 68273 } 68274 return newObj; 68275 } 68276 function _interopRequireDefault(obj) { 68277 return obj && obj.__esModule ? obj : { default: obj }; 68278 } 68279 /** 68280 * @module Image 68281 * @submodule Loading & Displaying 68282 * @for p5 68283 * @requires core 68284 */ /** 68285 * Loads an image from a path and creates a <a href="#/p5.Image">p5.Image</a> from it. 68286 * 68287 * The image may not be immediately available for rendering. 68288 * If you want to ensure that the image is ready before doing 68289 * anything with it, place the <a href="#/p5/loadImage">loadImage()</a> call in <a href="#/p5/preload">preload()</a>. 68290 * You may also supply a callback function to handle the image when it's ready. 68291 * 68292 * The path to the image should be relative to the HTML file 68293 * that links in your sketch. Loading an image from a URL or other 68294
68294 * remote location may be blocked due to your browser's built-in 68295 * security. 68296 68297 * You can also pass in a string of a base64 encoded image as an alternative to the file path. 68298 * Remember to add "data:image/png;base64," in front of the string. 68299 * 68300 * @method loadImage 68301 * @param {String} path Path of the image to be loaded 68302 * @param {function(p5.Image)} [successCallback] Function to be called once 68303 * the image is loaded. Will be passed the 68304 * <a href="#/p5.Image">p5.Image</a>. 68305 * @param {function(Event)} [failureCallback] called with event error if 68306 * the image fails to load. 68307 * @return {p5.Image} the <a href="#/p5.Image">p5.Image</a> object 68308 * @example 68309
68309 * <div> 68310 * <code> 68311 * let img; 68312 * function preload() { 68313 * img = loadImage('assets/laDefense.jpg'); 68314 * } 68315 * function setup() { 68316 * image(img, 0, 0); 68317 * } 68318 * </code> 68319 * </div> 68320 * <div> 68321 * <code> 68322 * function setup() { 68323 * // here we use a callback to display the image after loading 68324
68324 * loadImage('assets/laDefense.jpg', img => { 68325 * image(img, 0, 0); 68326 * }); 68327 * } 68328 * </code> 68329 * </div> 68330 * 68331 * @alt 68332 * image of the underside of a white umbrella and grided ceililng above 68333 * image of the underside of a white umbrella and grided ceililng above 68334 */ _main.default.prototype.loadImage = function( 68335 path, 68336 successCallback, 68337 failureCallback 68338 ) { 68339 _main.default._validateParameters('loadImage', arguments); 68340 var pImg = new _main.default.Image(1, 1, this); 68341 var self = this; 68342
68343 var req = new Request(path, { 68344 method: 'GET', 68345 mode: 'cors' 68346 }); 68347 68348 fetch(path, req).then(function(response) { 68349 // GIF section 68350 var contentType = response.headers.get('content-type'); 68351 if (contentType === null) { 68352 console.warn( 68353 'The image you loaded does not have a Content-Type header. If you are using the online editor consider reuploading the asset.' 68354 ); 68355 } 68356 if (contentType && contentType.includes('image/gif')) { 68357 response.arrayBuffer().then( 68358 function(arrayBuffer) { 68359 if (arrayBuffer) { 68360 var byteArray = new Uint8Array(arrayBuffer); 68361 _createGif( 68362 byteArray, 68363 pImg, 68364 successCallback, 68365 failureCallback, 68366 function(pImg) { 68367 self._decrementPreload(); 68368 }.bind(self) 68369 ); 68370 } 68371 }, 68372 function(e) { 68373 if (typeof failureCallback === 'function') { 68374 failureCallback(e); 68375 } else { 68376 console.error(e); 68377 } 68378 } 68379 ); 68380 } else { 68381 // Non-GIF Section 68382 var img = new Image(); 68383 68384 img.onload = function() { 68385 pImg.width = pImg.canvas.width = img.width; 68386 pImg.height = pImg.canvas.height = img.height; 68387 68388 // Draw the image into the backing canvas of the p5.Image 68389 pImg.drawingContext.drawImage(img, 0, 0); 68390 pImg.modified = true; 68391 if (typeof successCallback === 'function') { 68392 successCallback(pImg); 68393 } 68394 self._decrementPreload(); 68395 }; 68396 68397 img.onerror = function(e) { 68398 _main.default._friendlyFileLoadError(0, img.src); 68399 if (typeof failureCallback === 'function') { 68400 failureCallback(e); 68401 } else { 68402 console.error(e); 68403 } 68404 }; 68405 68406 // Set crossOrigin in case image is served with CORS headers. 68407 // This will let us draw to the canvas without tainting it. 68408 // See https://developer.mozilla.org/en-US/docs/HTML/CORS_Enabled_Image 68409 // When using data-uris the file will be loaded locally 68410 // so we don't need to worry about crossOrigin with base64 file types. 68411 if (path.indexOf('data:image/') !== 0) { 68412 img.crossOrigin = 'Anonymous'; 68413 } 68414 // start loading the image 68415 img.src = path; 68416 } 68417 pImg.modified = true; 68418 }); 68419 return pImg; 68420 }; 68421 68422 /** 68423 * Helper function for loading GIF-based images 68424 */ 68425 function _createGif( 68426 arrayBuffer, 68427 pImg, 68428 successCallback, 68429 failureCallback, 68430 finishCallback 68431 ) { 68432 var gifReader = new _omggif.default.GifReader(arrayBuffer); 68433 pImg.width = pImg.canvas.width = gifReader.width; 68434 pImg.height = pImg.canvas.height = gifReader.height; 68435 var frames = []; 68436 var numFrames = gifReader.numFrames(); 68437 var framePixels = new Uint8ClampedArray(pImg.width * pImg.height * 4); 68438 if (numFrames > 1) { 68439 var loadGIFFrameIntoImage = function loadGIFFrameIntoImage( 68440 frameNum, 68441 gifReader 68442 ) { 68443 try { 68444 gifReader.decodeAndBlitFrameRGBA(frameNum, framePixels); 68445 } catch (e) { 68446 _main.default._friendlyFileLoadError(8, pImg.src); 68447 if (typeof failureCallback === 'function') { 68448 failureCallback(e); 68449 } else { 68450 console.error(e); 68451 } 68452 } 68453 }; 68454 for (var j = 0; j < numFrames; j++) { 68455 var frameInfo = gifReader.frameInfo(j); 68456 // Some GIFs are encoded so that they expect the previous frame 68457 // to be under the current frame. This can occur at a sub-frame level 68458 // There are possible disposal codes but I didn't encounter any 68459 if (gifReader.frameInfo(j).disposal === 1 && j > 0) { 68460 pImg.drawingContext.putImageData(frames[j - 1].image, 0, 0
68460); 68461 } else { 68462 pImg.drawingContext.clearRect(0, 0, pImg.width, pImg.height); 68463 framePixels = new Uint8ClampedArray(pImg.width * pImg.height * 4); 68464 } 68465 loadGIFFrameIntoImage(j, gifReader); 68466 var imageData = new ImageData(framePixels, pImg.width, pImg.height); 68467 pImg.drawingContext.putImageData(imageData, 0, 0); 68468 frames.push({ 68469 image: pImg.drawingContext.getImageData(0, 0, pImg.width, pImg.height), 68470 delay: frameInfo.delay * 10 //GIF stores delay in one-hundredth of a second, shift to ms 68471 }); 68472 } 68473 68474 //Uses Netscape block encoding 68475 //to repeat forever, this will be 0 68476 //to repeat just once, this will be null 68477 //to repeat N times (1<N), should contain integer for loop number 68478 //this is changed to more usable values for us 68479 //to repeat forever, loopCount = null 68480 //everything else is just the number of loops 68481 var loopLimit = gifReader.loopCount(); 68482 if (loopLimit === null) { 68483 loopLimit = 1; 68484 } else if (loopLimit === 0) { 68485 loopLimit = null; 68486 } 68487 68488 // we used the pImg for painting and saving during load 68489 // so we have to reset it to the first frame 68490 pImg.drawingContext.putImageData(frames[0].image, 0, 0); 68491 68492 pImg.gifProperties = { 68493 displayIndex: 0, 68494 loopLimit: loopLimit, 68495 loopCount: 0, 68496 frames: frames, 68497 numFrames: numFrames, 68498 playing: true, 68499 timeDisplayed: 0, 68500 lastChangeTime: 0 68501 }; 68502 } 68503 68504 if (typeof successCallback === 'function') { 68505 successCallback(pImg); 68506 } 68507 finishCallback(); 68508 } 68509 68510 /** 68511 * Validates clipping params. Per drawImage spec sWidth and sHight cannot be 68512 * negative or greater than image intrinsic width and height 68513 * @private 68514 * @param {Number} sVal 68515 * @param {Number} iVal 68516 * @returns {Number} 68517 * @private 68518 */ 68519 function _sAssign(sVal, iVal) { 68520 if (sVal > 0 && sVal < iVal) { 68521 return sVal; 68522 } else { 68523 return iVal; 68524 } 68525 } 68526 68527 /** 68528 * Draw an image to the p5.js canvas. 68529 * 68530 * This function can be used with different numbers of parameters. The 68531 * simplest use requires only three parameters: img, x, and yâwhere (x, y) is 68532 * the position of the image. Two more parameters can optionally be added to 68533 * specify the width and height of the image. 68534 * 68535 * This function can also be used with all eight Number parameters. To 68536 * differentiate between all these parameters, p5.js uses the language of 68537 * "destination rectangle" (which corresponds to "dx", "dy", etc.) and "source 68538 * image" (which corresponds to "sx", "sy", etc.) below. Specifying the 68539 * "source image" dimensions can be useful when you want to display a 68540 * subsection of the source image instead of the whole thing. Here's a diagram 68541 * to explain further: 68542 * <img src="assets/drawImage.png"></img> 68543 * 68544 * @method image 68545 * @param {p5.Image|p5.Element} img the image to display 68546 * @param {Number} x the x-coordinate of the top-left corner of the image 68547 * @param {Number} y the y-coordinate of the top-left corner of the image 68548 * @param {Number} [width] the width to draw the image 68549 * @param {Number} [height] the height to draw the image 68550 * @example 68551 * <div> 68552 * <code> 68553 * let img; 68554 * function preload() { 68555 * img = loadImage('assets/laDefense.jpg'); 68556 * } 68557 * function setup() { 68558 * // Top-left corner of the img is at (0, 0) 68559 * // Width and height are the img's original width and height 68560 * image(img, 0, 0); 68561 * } 68562 * </code> 68563 * </div> 68564 * <div> 68565 * <code> 68566 * let img; 68567 * function preload() { 68568 * img = loadImage('assets/laDefense.jpg'); 68569 * } 68570 * function setup() { 68571 * background(50); 68572 * // Top-left corner of the img is at (10, 10) 68573 * // Width and height are 50 x 50
68574 * image(img, 10, 10, 50, 50); 68575 * } 68576 * </code> 68577 * </div> 68578 * <div> 68579 * <code> 68580 * function setup() { 68581 * // Here, we use a callback to display the image after loading 68582 * loadImage('assets/laDefense.jpg', img => { 68583 * image(img, 0, 0); 68584 * }); 68585 * } 68586 * </code> 68587 * </div> 68588 * <div> 68589 * <code> 68590 * let img; 68591 * function preload() { 68592 * img = loadImage('assets/gradient.png'); 68593 * } 68594 * function setup() { 68595 * // 1. Background image 68596 * // Top-left corner of the img is at (0, 0) 68597 * // Width and height are the img's original width and height, 100 x 100 68598 * image(img, 0, 0); 68599 * // 2. Top right image 68600 * // Top-left corner of destination rectangle is at (50, 0) 68601 * // Destination rectangle width and height are 40 x 20 68602 * // The next parameters are relative to the source image: 68603 * // - Starting at position (50, 50) on the source image, capture a 50 x 50 68604 * // subsection 68605 * // - Draw this subsection to fill the dimensions of the destination rectangle 68606 * image(img, 50, 0, 40, 20, 50, 50, 50, 50); 68607 * } 68608 * </code> 68609 * </div> 68610 * @alt 68611 * image of the underside of a white umbrella and gridded ceiling above 68612 * image of the underside of a white umbrella and gridded ceiling above 68613 */ 68614 /** 68615 * @method image 68616 * @param {p5.Image|p5.Element} img 68617 * @param {Number} dx the x-coordinate of the destination 68618 * rectangle in which to draw the source image 68619 * @param {Number} dy the y-coordinate of the destination 68620 * rectangle in which to draw the source image 68621 * @param {Number} dWidth the width of the destination rectangle 68622 * @param {Number} dHeight the height of the destination rectangle 68623 * @param {Number} sx the x-coordinate of the subsection of the source 68624 * image to draw into the destination rectangle 68625 * @param {Number} sy the y-coordinate of the subsection of the source 68626 * image to draw into the destination rectangle 68627 * @param {Number} [sWidth] the width of the subsection of the 68628 * source image to draw into the destination 68629 * rectangle 68630 * @param {Number} [sHeight] the height of the subsection of the 68631 * source image to draw into the destination rectangle 68632 */ 68633 _main.default.prototype.image = function( 68634 img, 68635 dx, 68636 dy, 68637 dWidth, 68638 dHeight, 68639 sx, 68640 sy, 68641 sWidth, 68642 sHeight 68643 ) { 68644 // set defaults per spec: https://goo.gl/3ykfOq 68645 68646 _main.default._validateParameters('image', arguments); 68647 68648 var defW = img.width; 68649 var defH = img.height; 68650 68651 if (img.elt && img.elt.videoWidth && !img.canvas) { 68652 // video no canvas 68653 defW = img.elt.videoWidth; 68654 defH = img.elt.videoHeight; 68655 } 68656 68657 var _dx = dx; 68658 var _dy = dy; 68659 var _dw = dWidth || defW; 68660 var _dh = dHeight || defH; 68661 var _sx = sx || 0; 68662 var _sy = sy || 0; 68663 var _sw = sWidth || defW; 68664 var _sh = sHeight || defH; 68665 68666 _sw = _sAssign(_sw, defW); 68667 _sh = _sAssign(_sh, defH); 68668 68669 // This part needs cleanup and unit tests 68670 // see issues https://github.com/processing/p5.js/issues/1741 68671 // and https://github.com/processing/p5.js/issues/1673 68672 var pd = 1; 68673 68674 if (img.elt && !img.canvas && img.elt.style.width) { 68675 //if img is video and img.elt.size() has been used and 68676 //no width passed to image() 68677 if (img.elt.videoWidth && !dWidth) { 68678 pd = img.elt.videoWidth; 68679 } else { 68680 //all other cases 68681 pd = img.elt.width; 68682 } 68683 pd /= parseInt(img.elt.style.width, 10); 68684 } 68685 68686 _sx *= pd; 68687 _sy *= pd; 68688 _sh *= pd; 68689 _sw *= pd; 68690 68691 var vals = _helpers.default.modeAdjust( 68692 _dx, 68693 _dy, 68694 _dw, 68695 _dh, 68696 this._renderer._imageMode 68697 ); 68698 68699 // tint the image if there is a tint 68700 this._renderer.image(img, _sx, _sy, _sw, _sh, vals.x, vals.y, vals.w, vals.h); 68701 }; 68702 68703 /** 68704 * Sets the fill value for displaying images. Images can be tinted to 68705 * specified colors or made transparent by including an alpha value. 68706 * 68707 * To apply transparency to an image without affecting its color, use 68708 * white as the tint color and specify an alpha value. For instance, 68709 * tint(255, 128) will make an image 50% transparent (assuming the default 68710 * alpha range of 0-255, which can be changed with <a href="#/p5/colorMode">colorMode()</a>). 68711 * 68712 * The value for the gray parameter must be less than or equal to the current 68713 * maximum value as specified by <a href="#/p5/colorMode">colorMode()</a>. The default maximum value is 68714 * 255. 68715 * 68716 * @method tint 68717 * @param {Number} v1 red or hue value relative to 68718 * the current color range 68719 * @param {Number} v2 green or saturation value 68720 * relative to the current color range 68721 * @param {Number} v3 blue or brightness value 68722 * relative to the current color range 68723 * @param {Number} [alpha] 68724 * 68725 * @example 68726 * <div> 68727 * <code> 68728 * let img; 68729 * function preload() { 68730 * img = loadImage('assets/laDefense.jpg'); 68731 * } 68732 * function setup() { 68733 * image(img, 0, 0); 68734 * tint(0, 153, 204); // Tint blue 68735 * image(img, 50, 0); 68736 * } 68737 * </code> 68738 * </div> 68739 * 68740 * <div> 68741 * <code> 68742 * let img; 68743 * function preload() { 68744 * img = loadImage('assets/laDefense.jpg'); 68745 * } 68746 * function setup() { 68747 * image(img, 0, 0); 68748 * tint(0, 153, 204, 126); // Tint blue and set transparency 68749 * image(img, 50, 0); 68750 * } 68751 * </code> 68752 * </div> 68753 * 68754 * <div> 68755 * <code> 68756 * let img; 68757 * function preload() { 68758 * img = loadImage('assets/laDefense.jpg'); 68759 * } 68760 * function setup() { 68761 * image(img, 0, 0); 68762 * tint(255, 126); // Apply transparency without changing color 68763 * image(img, 50, 0); 68764 * } 68765 * </code> 68766 * </div> 68767 * 68768 * @alt 68769 * 2 side by side images of umbrella and ceiling, one image with blue tint 68770 * Images of umbrella and ceiling, one half of image with blue tint 68771 * 2 side by side images of umbrella and ceiling, one image translucent 68772 */ 68773 68774 /** 68775 * @method tint 68776 * @param {String} value a color string 68777 */ 68778 68779 /** 68780 * @method tint 68781 * @param {Number} gray a gray value 68782 * @param {Number} [alpha] 68783 */ 68784 68785 /** 68786 * @method tint 68787 * @param {Number[]} values an array containing the red,green,blue & 68788 * and alpha components of the color 68789 */ 68790 68791 /** 68792 * @method tint 68793 * @param {p5.Color} color the tint color 68794 */ 68795 _main.default.prototype.tint = function() { 68796 for ( 68797 var _len = arguments.length, args = new Array(_len), _key = 0; 68798 _key < _len; 68799 _key++ 68800 ) { 68801 args[_key] = arguments[_key]; 68802 } 68803 _main.default._validateParameters('tint', args); 68804 var c = this.color.apply(this, args); 68805 this._renderer._tint = c.levels; 68806 }; 68807 68808 /** 68809 * Removes the current fill value for displaying images and reverts to 68810 * displaying images with their original hues. 68811 * 68812 * @method noTint 68813 * @example 68814 * <div> 68815 * <code> 68816 * let img; 68817 * function preload() { 68818 * img = loadImage('assets/bricks.jpg'); 68819 * } 68820 * function setup() { 68821 * tint(0, 153, 204); // Tint blue 68822 * image(img, 0, 0); 68823 * noTint(); // Disable tint 68824 * image(img, 50, 0); 68825 * } 68826 * </code> 68827 * </div> 68828 * 68829 * @alt 68830 * 2 side by side images of bricks, left image with blue tint 68831 */ 68832 _main.default.prototype.noTint = function() { 68833 this._renderer._tint = null; 68834 }; 68835 68836 /** 68837 * Apply the current tint color to the input image, return the resulting 68838 * canvas. 68839 * 68840 * @private 68841 * @param {p5.Image} The image to be tinted 68842 * @return {canvas} The resulting tinted canvas 68843 */ 68844 _main.default.prototype._getTintedImageCanvas = function(img) { 68845 if (!img.canvas) { 68846 return img; 68847 } 68848 var pixels = _filters.default._toPixels(img.canvas); 68849 var tmpCanvas = document.createElement('canvas'); 68850 tmpCanvas.width = img.canvas.width; 68851 tmpCanvas.height = img.canvas.height; 68852 var tmpCtx = tmpCanvas.getContext('2d'); 68853 var id = tmpCtx.createImageData(img.canvas.width, img.canvas.height); 68854 var newPixels = id.data; 68855 68856 for (var i = 0; i < pixels.length; i += 4) { 68857 var r = pixels[i]; 68858 var g = pixels[i + 1]; 68859 var b = pixels[i + 2]; 68860 var a = pixels[i + 3]; 68861
68862 newPixels[i] = r * this._renderer._tint[0] / 255; 68863 newPixels[i + 1] = g * this._renderer._tint[1] / 255; 68864 newPixels[i + 2] = b * this._renderer._tint[2] / 255; 68865 newPixels[i + 3] = a * this._renderer._tint[3] / 255; 68866 } 68867 68868 tmpCtx.putImageData(id, 0, 0); 68869 return tmpCanvas; 68870 }; 68871 68872 /** 68873 * Set image mode. Modifies the location from which images are drawn by 68874 * changing the way in which parameters given to <a href="#/p5/image">image()</a> are interpreted. 68875 * The default mode is imageMode(CORNER), which interprets the second and 68876 * third parameters of <a href="#/p5/image">image()</a> as the upper-left corner of the image. If 68877 * two additional parameters are specified, they are used to set the image's 68878 * width and height. 68879 * 68880 * imageMode(CORNERS) interprets the second and third parameters of <a href="#/p5/image">image()</a> 68881 * as the location of one corner, and the fourth and fifth parameters as the 68882 * opposite corner. 68883 * 68884 * imageMode(CENTER) interprets the second and third parameters of <a href="#/p5/image">image()</a> 68885 * as the image's center point. If two additional parameters are specified, 68886 * they are used to set the image's width and height. 68887 * 68888 * @method imageMode 68889 * @param {Constant} mode either CORNER, CORNERS, or CENTER 68890 * @example 68891 * 68892 * <div> 68893 * <code> 68894 * let img; 68895 * function preload() { 68896 * img = loadImage('assets/bricks.jpg'); 68897 * } 68898 * function setup() { 68899 * imageMode(CORNER); 68900 * image(img, 10, 10, 50, 50); 68901 * } 68902 * </code> 68903 * </div> 68904 * 68905 * <div> 68906 * <code> 68907 * let img; 68908 * function preload() { 68909 * img = loadImage('assets/bricks.jpg'); 68910 * } 68911 * function setup() { 68912 * imageMode(CORNERS); 68913 * image(img, 10, 10, 90, 40); 68914 * } 68915 * </code> 68916 * </div> 68917 * 68918 * <div> 68919 * <code> 68920 * let img; 68921 * function preload() { 68922 * img = loadImage('assets/bricks.jpg'); 68923 * } 68924 * function setup() { 68925 * imageMode(CENTER); 68926 * image(img, 50, 50, 80, 80); 68927 * } 68928 * </code> 68929 * </div> 68930 * 68931 * @alt 68932 * small square image of bricks 68933 * horizontal rectangle image of bricks 68934 * large square image of bricks 68935 */ 68936 _main.default.prototype.imageMode = function(m) { 68937 _main.default._validateParameters('imageMode', arguments); 68938 if ( 68939 m === constants.CORNER || 68940 m === constants.CORNERS || 68941 m === constants.CENTER 68942 ) { 68943 this._renderer._imageMode = m; 68944 } 68945 }; 68946 var _default = _main.default; 68947 exports.default = _default; 68948 }, 68949 { 68950 '../core/constants': 48, 68951 '../core/friendly_errors/fes_core': 51, 68952 '../core/friendly_errors/file_errors': 52, 68953 '../core/friendly_errors/validate_params': 54, 68954 '../core/helpers': 55, 68955 '../core/main': 59, 68956 './filters': 80, 68957 omggif: 33 68958 } 68959 ], 68960 83: [ 68961 function(_dereq_, module, exports) { 68962 'use strict'; 68963 Object.defineProperty(exports, '__esModule', { value: true }); 68964 exports.default = void 0; 68965 68966 var _main = _interopRequireDefault(_dereq_('../core/main')); 68967 var _filters = _interopRequireDefault(_dereq_('./filters')); 68968 function _interopRequireDefault(obj) { 68969 return obj && obj.__esModule ? obj : { default: obj }; 68970 } 68971 /** 68972 * @module Image 68973 * @submodule Image 68974 * @requires core 68975 * @requires constants 68976 * @requires filters 68977 */ /** 68978 * This module defines the <a href="#/p5.Image">p5.Image</a> class and P5 methods for 68979 * drawing images to the main display canvas. 68980 */ /* 68981 * Class methods 68982 */ /** 68983 * 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 68984 * image. 68985 * 68986 * p5 can display .gif, .jpg and .png images. Images may be displayed 68987 * in 2D and 3D space. Before an image is used, it must be loaded with the 68988 * <a href="#/p5/loadImage">loadImage()</a> function. The <a href="#/p5.Image">p5.Image</a> class contains fields for the width and 68989 * height of the image, as well as an array called <a href="#/p5.Image/pixels">pixels[]</a> that contains the 68990 * values for every pixel in the image. 68991 * 68992 * The methods described below allow easy access to the image's pixels and 68993 * alpha channel and simplify the process of compositing. 68994 * 68995 * 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 68996 * the image to make sure that the pixel data is properly loaded. 68997 * @example 68998 * <div><code> 68999 * function setup() { 69000 * let img = createImage(100, 100); // same as new p5.Image(100, 100); 69001 * img.loadPixels(); 69002 * createCanvas(100, 100); 69003 * background(0); 69004 * 69005 * // helper for writing color to array 69006 * function writeColor(image, x, y, red, green, blue, alpha) { 69007 * let index = (x + y * width) * 4; 69008 * image.pixels[index] = red; 69009 * image.pixels[index + 1] = green; 69010 * image.pixels[index + 2] = blue; 69011 * image.pixels[index + 3] = alpha; 69012 * } 69013 * 69014 * let x, y; 69015 * // fill with random colors 69016 * for (y = 0;
69016 y < img.height; y++) { 69017 * for (x = 0; x < img.width; x++) { 69018 * let red = random(255); 69019 * let green = random(255); 69020 * let blue = random(255); 69021 * let alpha = 255; 69022 * writeColor(img, x, y, red, green, blue, alpha); 69023 * } 69024 * } 69025 * 69026 * // draw a red line 69027 * y = 0; 69028 * for (x = 0; x < img.width; x++) { 69029 * writeColor(img, x, y, 255, 0, 0, 255); 69030 * } 69031 * 69032 * // draw a green line 69033 * y = img.height - 1; 69034 * for (x = 0; x < img.width; x++) { 69035 * writeColor(img, x, y, 0, 255, 0, 255); 69036 * } 69037 * 69038 * img.updatePixels(); 69039 * image(img, 0, 0); 69040 * } 69041 * </code></div> 69042 * 69043 * @class p5.Image 69044 * @constructor 69045 * @param {Number} width 69046 * @param {Number} height 69047 */ _main.default.Image = function(width, height) { 69048 /** 69049 * Image width. 69050 * @property {Number} width 69051 * @readOnly 69052 * @example 69053 * <div><code> 69054 * let img; 69055 * function preload() { 69056 * img = loadImage('assets/rockies.jpg'); 69057 * } 69058 * 69059 * function setup() { 69060 * createCanvas(100, 100); 69061 * image(img, 0, 0); 69062 * for (let i = 0; i < img.width; i++) { 69063 * let c = img.get(i, img.height / 2); 69064 * stroke(c); 69065 * line(i, height / 2, i, height); 69066 * } 69067 * } 69068 * </code></div> 69069 * 69070 * @alt 69071 * rocky mountains in top and horizontal lines in corresponding colors in bottom. 69072 * 69073 */ this.width = width; 69074 /** 69075 * Image height. 69076 * @property {Number} height 69077 * @readOnly 69078 * @example 69079 * <div><code> 69080 * let img; 69081 * function preload() { 69082 * img = loadImage('assets/rockies.jpg'); 69083 * } 69084 * 69085 * function setup() { 69086 * createCanvas(100, 100); 69087 * image(img, 0, 0); 69088 * for (let i = 0; i < img.height; i++) { 69089 * let c = img.get(img.width / 2, i); 69090 * stroke(c); 69091 * line(0, i, width / 2, i); 69092 * } 69093 * } 69094 * </code></div> 69095 * 69096 * @alt 69097 * rocky mountains on right and vertical lines in corresponding colors on left. 69098 * 69099 */ this.height = height; 69100 this.canvas = document.createElement('canvas'); 69101 this.canvas.width = this.width; 69102 this.canvas.height = this.height; 69103 this.drawingContext = this.canvas.getContext('2d'); 69104 this._pixelsState = this; 69105 this._pixelDensity = 1; 69106 //Object for working with GIFs, defaults to null 69107 this.gifProperties = null; 69108 //For WebGL Texturing only: used to determine whether to reupload texture to GPU 69109 this._modified = false; 69110 /** 69111 * Array containing the values for all the pixels in the display window. 69112 * These values are numbers. This array is the size (include an appropriate 69113 * factor for pixelDensity) of the display window x4, 69114 * representing the R, G, B, A values in order for each pixel, moving from 69115 * left to right across each row, then down each column. Retina and other 69116 * high density displays may have more pixels (by a factor of 69117 * pixelDensity^2). 69118 * For example, if the image is 100x100 pixels, there will be 40,000. With 69119 * pixelDensity = 2, there will be 160,000. The first four values 69120 * (indices 0-3) in the array will be the R, G, B, A values of the pixel at 69121 * (0, 0). The second four values (indices 4-7) will contain the R, G, B, A 69122 * values of the pixel at (1, 0). More generally, to set values for a pixel 69123 * at (x, y): 69124 * ```javascript 69125 * let d = pixelDensity(); 69126 * for (let i = 0; i < d; i++) { 69127 * for (let j = 0; j < d; j++) { 69128 * // loop over 69129 * index = 4 * ((y * d + j) * width * d + (x * d + i
69129)); 69130 * pixels[index] = r; 69131 * pixels[index+1] = g; 69132 * pixels[index+2] = b; 69133 * pixels[index+3] = a; 69134 * } 69135 * } 69136 * ``` 69137 * 69138 * Before accessing this array, the data must loaded with the <a href="#/p5.Image/loadPixels">loadPixels()</a> 69139 * function. After the array data has been modified, the <a href="#/p5.Image/updatePixels">updatePixels()</a> 69140 * function must be run to update the changes. 69141 * @property {Number[]} pixels 69142 * @example 69143 * <div> 69144 * <code> 69145 * let img = createImage(66, 66); 69146 * img.loadPixels(); 69147 * for (let i = 0; i < img.width; i++) { 69148 * for (let j = 0; j < img.height; j++) { 69149 * img.set(i, j, color(0, 90, 102)); 69150 * } 69151 * } 69152 * img.updatePixels(); 69153 * image(img, 17, 17); 69154 * </code> 69155 * </div> 69156 * <div> 69157 * <code> 69158 * let pink = color(255, 102, 204); 69159 * let img = createImage(66, 66); 69160 * img.loadPixels(); 69161 * for (let i = 0; i < 4 * (width * height / 2); i += 4) { 69162 * img.pixels[i] = red(pink); 69163 * img.pixels[i + 1] = green(pink); 69164 * img.pixels[i + 2] = blue(pink); 69165 * img.pixels[i + 3] = alpha(pink); 69166 * } 69167 * img.updatePixels(); 69168 * image(img, 17, 17); 69169 * </code> 69170 * </div> 69171 * 69172 * @alt 69173 * 66x66 turquoise rect in center of canvas 69174 * 66x66 pink rect in center of canvas 69175 * 69176 */ 69177 this.pixels = []; 69178 }; 69179 69180 /** 69181 * Helper function for animating GIF-based images with time 69182 */ 69183 _main.default.Image.prototype._animateGif = function(pInst) { 69184 var props = this.gifProperties; 69185 var curTime = pInst._lastFrameTime + pInst.deltaTime; 69186 if (props.lastChangeTime === 0) { 69187 props.lastChangeTime = curTime; 69188 } 69189 if (props.playing) { 69190 props.timeDisplayed = curTime - props.lastChangeTime; 69191 var curDelay = props.frames[props.displayIndex].delay; 69192 if (props.timeDisplayed >= curDelay) { 69193 //GIF is bound to 'realtime' so can skip frames 69194 var skips = Math.floor(props.timeDisplayed / curDelay); 69195 props.timeDisplayed = 0; 69196 props.lastChangeTime = curTime; 69197 props.displayIndex += skips; 69198 props.loopCount = Math.floor(props.displayIndex / props.numFrames); 69199 if (props.loopLimit !== null && props.loopCount >= props.loopLimit) { 69200 props.playing = false; 69201 } else { 69202 var ind = props.displayIndex % props.numFrames; 69203 this.drawingContext.putImageData(props.frames[ind].image, 0, 0); 69204 props.displayIndex = ind; 69205 this.setModified(true); 69206 } 69207 } 69208 } 69209 }; 69210 69211 /** 69212 * Helper fxn for sharing pixel methods 69213 */ 69214 _main.default.Image.prototype._setProperty = function(prop, value) { 69215 this[prop] = value; 69216 this.setModified(true); 69217 }; 69218 69219 /** 69220 * Loads the pixels data for this image into the [pixels] attribute. 69221 * 69222 * @method loadPixels 69223 * @example 69224 * <div><code> 69225 * let myImage; 69226 * let halfImage; 69227 * 69228 * function preload() { 69229 * myImage = loadImage('assets/rockies.jpg'); 69230 * } 69231 * 69232 * function setup() { 69233 * myImage.loadPixels(); 69234 * halfImage = 4 * myImage.width * myImage.height / 2; 69235 * for (let i = 0; i < halfImage; i++) { 69236 * myImage.pixels[i + halfImage] = myImage.pixels[i]; 69237 * } 69238 * myImage.updatePixels(); 69239 * } 69240 * 69241 * function draw() { 69242 * image(myImage, 0, 0, width, height); 69243 * } 69244 * </code></div> 69245 * 69246 * @alt 69247 * 2 images of rocky mountains vertically stacked 69248 */ 69249 _main.default.Image.prototype.loadPixels = function() { 69250 _main.default.Renderer2D.prototype.loadPixels.call(this); 69251 this.setModified(true); 69252 }; 69253 69254 /** 69255 * Updates the backing canvas for this image with the contents of 69256 * the [pixels] array. 69257 * 69258 * If this image is an animated GIF then the pixels will be updated 69259 * in the frame that is currently displayed. 69260 * 69261 * @method updatePixels 69262 * @param {Integer} x x-offset of the target update area for the 69263 * underlying canvas 69264 * @param {Integer} y y-offset of the target update area for the 69265 * underlying canvas 69266 * @param {Integer} w height of the target update area for the 69267 * underlying canvas 69268 * @param {Integer} h height of the target update area for the 69269 * underlying canvas 69270 * @example 69271 * <div><code> 69272 * let myImage; 69273 * let halfImage; 69274 * 69275 * function preload() { 69276 * myImage = loadImage('assets/rockies.jpg'); 69277 * } 69278 * 69279 * function setup() { 69280 * myImage.loadPixels(); 69281 * halfImage = 4 * myImage.width * myImage.height / 2; 69282 * for (let i = 0; i < halfImage; i++) { 69283 * myImage.pixels[i + halfImage] = myImage.pixels[i]; 69284 * } 69285 * myImage.updatePixels(); 69286 * } 69287 * 69288 * function draw() { 69289 * image(myImage, 0, 0, width, height); 69290 * } 69291 * </code></div> 69292 * 69293 * @alt 69294 * 2 images of rocky mountains vertically stacked 69295 */ 69296 /** 69297 * @method updatePixels 69298 */ 69299 _main.default.Image.prototype.updatePixels = function(x, y, w, h) { 69300 _main.default.Renderer2D.prototype.updatePixels.call(this, x, y, w, h); 69301 this.setModified(true); 69302 }; 69303 69304 /** 69305 * Get a region of pixels from an image. 69306 * 69307 * If no params are passed, the whole image is returned. 69308 * If x and y are the only params passed a single pixel is extracted. 69309 * If all params are passed a rectangle region is extracted and a <a href="#/p5.Image">p5.Image</a> 69310 * is returned. 69311 * 69312 * @method get 69313 * @param {Number} x x-coordinate of the pixel 69314 * @param {Number} y y-coordinate of the pixel 69315 * @param {Number} w width 69316 * @param {Number} h height 69317 * @return {p5.Image} the rectangle <a href="#/p5.Image">p5.Image</a> 69318 * @example 69319 * <div><code> 69320 * let myImage; 69321 * let c; 69322 * 69323 * function preload() { 69324 * myImage = loadImage('assets/rockies.jpg'); 69325 * } 69326 * 69327 * function setup() { 69328 * background(myImage); 69329 * noStroke(); 69330 * c = myImage.get(60, 90); 69331 * fill(c); 69332 * rect(25, 25, 50, 50); 69333 * } 69334 * 69335 * //get() returns color here 69336 * </code></div> 69337 * 69338 * @alt 69339 * image of rocky mountains with 50x50 green rect in front 69340 */ 69341 /** 69342 * @method get 69343 * @return {p5.Image} the whole <a href="#/p5.Image">p5.Image</a> 69344 */ 69345 /** 69346 * @method get 69347 * @param {Number} x 69348 * @param {Number} y 69349 * @return {Number[]} color of pixel at x,y in array format [R, G, B, A] 69350 */ 69351 _main.default.Image.prototype.get = function(x, y, w, h) { 69352 _main.default._validateParameters('p5.Image.get', arguments); 69353 return _main.default.Renderer2D.prototype.get.apply(this, arguments); 69354 }; 69355 69356 _main.default.Image.prototype._getPixel = 69357 _main.default.Renderer2D.prototype._getPixel; 69358 69359 /** 69360 * Set the color of a single pixel or write an image into 69361 * this <a href="#/p5.Image">p5.Image</a>. 69362 * 69363 * Note that for a large number of pixels this will 69364 * be slower than directly manipulating the pixels array 69365 * and then calling <a href="#/p5.Image/updatePixels">updatePixels()</a>. 69366 * 69367 * @method set 69368 * @param {Number} x x-coordinate of the pixel 69369 * @param {Number} y y-coordinate of the pixel 69370 * @param {Number|Number[]|Object} a grayscale value | pixel array | 69371 * a <a href="#/p5.Color">p5.Color</a> | image to copy 69372 * @example 69373 * <div> 69374 * <code> 69375 * let img = createImage(66, 66); 69376 * img.loadPixels(); 69377 * for (let i = 0; i < img.width; i++) { 69378 * for (let j = 0;
69378 j < img.height; j++) { 69379 * img.set(i, j, color(0, 90, 102, (i % img.width) * 2)); 69380 * } 69381 * } 69382 * img.updatePixels(); 69383 * image(img, 17, 17); 69384 * image(img, 34, 34); 69385 * </code> 69386 * </div> 69387 * 69388 * @alt 69389 * 2 gradated dark turquoise rects fade left. 1 center 1 bottom right of canvas 69390 */ 69391 _main.default.Image.prototype.set = function(x, y, imgOrCol) { 69392 _main.default.Renderer2D.prototype.set.call(this, x, y, imgOrCol); 69393 this.setModified(true); 69394 }; 69395 69396 /** 69397 * Resize the image to a new width and height. To make the image scale 69398 * proportionally, use 0 as the value for the wide or high parameter. 69399 * For instance, to make the width of an image 150 pixels, and change 69400 * the height using the same proportion, use resize(150, 0). 69401 * 69402 * @method resize 69403 * @param {Number} width the resized image width 69404 * @param {Number} height the resized image height 69405 * @example 69406 * <div><code> 69407 * let img; 69408 * 69409 * function preload() { 69410 * img = loadImage('assets/rockies.jpg'); 69411 * } 69412 69413 * function draw() { 69414 * image(img, 0, 0); 69415 * } 69416 * 69417 * function mousePressed() { 69418 * img.resize(50, 100); 69419 * } 69420 * </code></div> 69421 * 69422 * @alt 69423 * image of rocky mountains. zoomed in 69424 */ 69425 _main.default.Image.prototype.resize = function(width, height) { 69426 // Copy contents to a temporary canvas, resize the original 69427 // and then copy back. 69428 // 69429 // There is a faster approach that involves just one copy and swapping the 69430 // this.canvas reference. We could switch to that approach if (as i think 69431 // is the case) there an expectation that the user would not hold a 69432 // reference to the backing canvas of a p5.Image. But since we do not 69433 // enforce that at the moment, I am leaving in the slower, but safer 69434 // implementation. 69435 69436 // auto-resize 69437 if (width === 0 && height === 0) { 69438 width = this.canvas.width; 69439 height = this.canvas.height; 69440 } else if (width === 0) { 69441 width = this.canvas.width * height / this.canvas.height; 69442 } else if (height === 0) { 69443 height = this.canvas.height * width / this.canvas.width; 69444 } 69445 69446 width = Math.floor(width); 69447 height = Math.floor(height); 69448 69449 var tempCanvas = document.createElement('canvas'); 69450 tempCanvas.width = width; 69451 tempCanvas.height = height; 69452 69453 if (this.gifProperties) { 69454 var props = this.gifProperties; 69455 //adapted from github.com/LinusU/resize-image-data 69456 var nearestNeighbor = function nearestNeighbor(src, dst) { 69457 var pos = 0; 69458 for (var y = 0; y < dst.height; y++) { 69459 for (var x = 0; x < dst.width; x++) { 69460 var srcX = Math.floor(x * src.width / dst.width); 69461 var srcY = Math.floor(y * src.height / dst.height); 69462 var srcPos = (srcY * src.width + srcX) * 4; 69463 dst.data[pos++] = src.data[srcPos++]; // R 69464 dst.data[pos++] = src.data[srcPos++]; // G 69465 dst.data[pos++] = src.data[srcPos++]; // B 69466 dst.data[pos++] = src.data[srcPos++]; // A 69467 } 69468 } 69469 }; 69470 for (var i = 0; i < props.numFrames; i++) { 69471 var resizedImageData = this.drawingContext.createImageData(width, height); 69472 69473 nearestNeighbor(props.frames[i].image, resizedImageData); 69474 props.frames[i].image = resizedImageData; 69475 } 69476 } 69477 69478 // prettier-ignore 69479 tempCanvas.getContext('2d').drawImage( 69480 this.canvas, 69481 0, 0, this.canvas.width, this.canvas.height, 69482 0, 0, tempCanvas.width, tempCanvas.height); 69483 69484 // Resize the original canvas, which will clear its contents 69485 this.canvas.width = this.width = width; 69486 this.canvas.height = this.height = height; 69487 69488 //Copy the image back 69489 69490 // prettier-ignore 69491 this.drawingContext.drawImage( 69492 tempCanvas, 69493 0, 0, width, height, 69494 0, 0, width, height); 69495 69496 if (this.pixels.length > 0) { 69497 this.loadPixels(); 69498 } 69499 69500 this.setModified(true); 69501 }; 69502 69503 /** 69504 * Copies a region of pixels from one image to another. If no 69505 * srcImage is specified this is used as the source. If the source 69506 * and destination regions aren't the same size, it will 69507 * automatically resize source pixels to fit the specified 69508 * target region. 69509 * 69510 * @method copy 69511 * @param {p5.Image|p5.Element} srcImage source image 69512 * @param {Integer} sx X coordinate of the source's upper left corner 69513 * @param {Integer} sy Y coordinate of the source's upper left corner 69514 * @param {Integer} sw source image width 69515 * @param {Integer} sh source image height 69516 * @param {Integer} dx X coordinate of the destination's upper left corner 69517 * @param {Integer} dy Y coordinate of the destination's upper left corner 69518 * @param {Integer} dw destination image width 69519 * @param {Integer} dh destination image height 69520 * @example 69521 * <div><code> 69522 * let photo; 69523 * let bricks; 69524 * let x; 69525 * let y; 69526 * 69527 * function preload() { 69528 * photo = loadImage('assets/rockies.jpg'); 69529 * bricks = loadImage('assets/bricks.jpg'); 69530 * } 69531 * 69532 * function setup() { 69533 * x = bricks.width / 2; 69534 * y = bricks.height / 2; 69535 * photo.copy(bricks, 0, 0, x, y, 0, 0, x, y); 69536 * image(photo, 0, 0); 69537 * } 69538 * </code></div> 69539 * 69540 * @alt 69541 * image of rocky mountains and smaller image on top of bricks at top left 69542 */ 69543 /** 69544 * @method copy 69545 * @param {Integer} sx 69546 * @param {Integer} sy 69547 * @param {Integer} sw 69548 * @param {Integer} sh 69549 * @param {Integer} dx 69550 * @param {Integer} dy 69551 * @param {Integer} dw 69552 * @param {Integer} dh 69553 */ 69554 _main.default.Image.prototype.copy = function() { 69555 for ( 69556 var _len = arguments.length, args = new Array(_len), _key = 0; 69557 _key < _len; 69558 _key++ 69559 ) { 69560 args[_key] = arguments[_key]; 69561 } 69562 _main.default.prototype.copy.apply(this, args); 69563 }; 69564 69565 /** 69566 * Masks part of an image from displaying by loading another 69567 * image and using its alpha channel as an alpha channel for 69568 * this image. 69569 * 69570 * @method mask 69571 * @param {p5.Image} srcImage source image 69572 * @example 69573 * <div><code> 69574 * let photo, maskImage; 69575 * function preload() { 69576 * photo = loadImage('assets/rockies.jpg'); 69577 * maskImage = loadImage('assets/mask2.png'); 69578 * } 69579 * 69580 * function setup() { 69581 * createCanvas(100, 100); 69582 * photo.mask(maskImage); 69583 * image(photo, 0, 0); 69584 * } 69585 * </code></div> 69586 * 69587 * @alt 69588 * image of rocky mountains with white at right 69589 * 69590 * http://blogs.adobe.com/webplatform/2013/01/28/blending-features-in-canvas/ 69591 */ 69592 // TODO: - Accept an array of alpha values. 69593 // - Use other channels of an image. p5 uses the 69594 // blue channel (which feels kind of arbitrary). Note: at the 69595 // moment this method does not match native processing's original 69596 // functionality exactly. 69597 _main.default.Image.prototype.mask = function(p5Image) { 69598 if (p5Image === undefined) { 69599 p5Image = this; 69600 } 69601 var currBlend = this.drawingContext.globalCompositeOperation; 69602 69603 var scaleFactor = 1; 69604 if (p5Image instanceof _main.default.Renderer) { 69605 scaleFactor = p5Image._pInst._pixelDensity; 69606 } 69607 69608 var copyArgs = [ 69609 p5Image, 69610 0, 69611 0, 69612 scaleFactor * p5Image.width, 69613 scaleFactor * p5Image.height, 69614 0, 69615 0, 69616 this.width, 69617 this.height 69618 ]; 69619 69620 this.drawingContext.globalCompositeOperation = 'destination-in'; 69621 _main.default.Image.prototype.copy.apply(this, copyArgs); 69622 this.drawingContext.globalCompositeOperation = currBlend; 69623 this.setModified(true); 69624 }; 69625 69626 /** 69627 * Applies an image filter to a <a href="#/p5.Image">p5.Image</a> 69628 * 69629 * @method filter 69630 * @param {Constant} filterType either THRESHOLD, GRAY, OPAQUE, INVERT, 69631 * POSTERIZE, ERODE, DILATE or BLUR. 69632 * See Filters.js for docs on 69633 * each available filter 69634 * @param {Number} [filterParam] an optional parameter unique 69635 * to each filter, see above 69636 * @example 69637 * <div><code> 69638 * let photo1; 69639 * let photo2; 69640 * 69641 * function preload() { 69642 * photo1 = loadImage('assets/rockies.jpg'); 69643 * photo2 = loadImage('assets/rockies.jpg'); 69644 * } 69645 * 69646 * function setup() { 69647 * photo2.filter(GRAY); 69648 * image(photo1, 0, 0); 69649 * image(photo2, width / 2, 0); 69650 * } 69651 * </code></div> 69652 * 69653 * @alt 69654 * 2 images of rocky mountains left one in color, right in black and white 69655 */ 69656 _main.default.Image.prototype.filter = function(operation, value) { 69657 _filters.default.apply(this.canvas, _filters.default[operation], value); 69658 this.setModified(true); 69659 }; 69660 69661 /** 69662 * Copies a region of pixels from one image to another, using a specified 69663 * blend mode to do the operation. 69664 * 69665 * @method blend 69666 * @param {p5.Image} srcImage source image 69667 * @param {Integer} sx X coordinate of the source's upper left corner 69668 * @param {Integer} sy Y coordinate of the source's upper left corner 69669 * @param {Integer} sw source image width 69670 * @param {Integer} sh source image height 69671 * @param {Integer} dx X coordinate of the destination's upper left corner 69672 * @param {Integer} dy Y coordinate of the destination's upper left corner 69673 * @param {Integer} dw destination image width 69674 * @param {Integer} dh destination image height 69675 * @param {Constant} blendMode the blend mode. either 69676 * BLEND, DARKEST, LIGHTEST, DIFFERENCE, 69677 * MULTIPLY, EXCLUSION, SCREEN, REPLACE, OVERLAY, HARD_LIGHT, 69678 * SOFT_LIGHT, DODGE, BURN, ADD or NORMAL. 69679 * 69680 * Available blend modes are: normal | multiply | screen | overlay | 69681 * darken | lighten | color-dodge | color-burn | hard-light | 69682 * soft-light | difference | exclusion | hue | saturation | 69683 * color | luminosity 69684 * 69685 * http://blogs.adobe.com/webplatform/2013/01/28/blending-features-in-canvas/ 69686 * @example 69687 * <div><code> 69688 * let mountains; 69689 * let bricks; 69690 * 69691 * function preload() { 69692 * mountains = loadImage('assets/rockies.jpg'); 69693 * bricks = loadImage('assets/bricks_third.jpg'); 69694 * } 69695 * 69696 * function setup() { 69697 * mountains.blend(bricks, 0, 0, 33, 100, 67, 0, 33, 100, ADD); 69698 * image(mountains, 0, 0); 69699 * image(bricks, 0, 0); 69700 * } 69701 * </code></div> 69702 * <div><code> 69703 * let mountains; 69704 * let bricks; 69705 * 69706 * function preload() { 69707 * mountains = loadImage('assets/rockies.jpg'); 69708 * bricks = loadImage('assets/bricks_third.jpg'); 69709 * } 69710 * 69711 * function setup() { 69712 * mountains.blend(bricks, 0, 0, 33, 100, 67, 0, 33, 100, DARKEST); 69713 * image(mountains, 0, 0); 69714 * image(bricks, 0, 0); 69715 * } 69716 * </code></div> 69717 * <div><code> 69718 * let mountains; 69719 * let bricks; 69720 * 69721 * function preload() { 69722 * mountains = loadImage('assets/rockies.jpg'); 69723 * bricks = loadImage('assets/bricks_third.jpg'); 69724 * } 69725 * 69726 * function setup() { 69727 * mountains.blend(bricks, 0, 0, 33, 100, 67, 0, 33, 100, LIGHTEST); 69728 * image(mountains, 0, 0); 69729 * image(bricks, 0, 0); 69730 * } 69731 * </code></div> 69732 * 69733 * @alt 69734 * image of rocky mountains. Brick images on left and right. Right overexposed 69735 * image of rockies. Brickwall images on left and right. Right mortar transparent 69736 * image of rockies. Brickwall images on left and right. Right translucent 69737 */ 69738 /** 69739 * @method blend 69740 * @param {Integer} sx 69741 * @param {Integer} sy 69742 * @param {Integer} sw 69743 * @param {Integer} sh 69744 * @param {Integer} dx 69745 * @param {Integer} dy 69746 * @param {Integer} dw 69747 * @param {Integer} dh 69748 * @param {Constant} blendMode 69749 */ 69750 _main.default.Image.prototype.blend = function() { 69751 for ( 69752 var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; 69753 _key2 < _len2; 69754 _key2++ 69755 ) { 69756 args[_key2] = arguments[_key2]; 69757 } 69758 _main.default._validateParameters('p5.Image.blend', arguments); 69759 _main.default.prototype.blend.apply(this, args); 69760 this.setModified(true); 69761 }; 69762 69763 /** 69764 * helper method for web GL mode to indicate that an image has been 69765 * changed or unchanged since last upload. gl texture upload will 69766 * set this value to false after uploading the texture. 69767 * @method setModified 69768 * @param {boolean} val sets whether or not the image has been 69769 * modified. 69770 * @private 69771 */ 69772 _main.default.Image.prototype.setModified = function(val) { 69773 this._modified = val; //enforce boolean? 69774 }; 69775 69776 /** 69777 * helper method for web GL mode to figure out if the image 69778 * has been modified and might need to be re-uploaded to texture 69779 * memory between frames. 69780 * @method isModified 69781 * @private 69782 * @return {boolean} a boolean indicating whether or not the 69783 * image has been updated or modified since last texture upload. 69784 */ 69785 _main.default.Image.prototype.isModified = function() { 69786 return this._modified; 69787 }; 69788 69789 /** 69790 * Saves the image to a file and force the browser to download it. 69791 * Accepts two strings for filename and file extension 69792 * Supports png (default), jpg, and gif 69793 *<br><br> 69794 * Note that the file will only be downloaded as an animated GIF 69795 * if the p5.Image was loaded from a GIF file. 69796 * @method save 69797 * @param {String} filename give your file a name 69798 * @param {String} extension 'png' or 'jpg' 69799 * @example 69800 * <div><code> 69801 * let photo; 69802 * 69803 * function preload() { 69804 * photo = loadImage('assets/rockies.jpg'); 69805 * } 69806 * 69807 * function draw() { 69808
69808 * image(photo, 0, 0); 69809 * } 69810 * 69811 * function keyTyped() { 69812 * if (key === 's') { 69813 * photo.save('photo', 'png'); 69814 * } 69815 * } 69816 * </code></div> 69817 * 69818 * @alt 69819 * image of rocky mountains. 69820 */ 69821 _main.default.Image.prototype.save = function(filename, extension) { 69822 if (this.gifProperties) { 69823 _main.default.prototype.saveGif(this, filename); 69824 } else { 69825 _main.default.prototype.saveCanvas(this.canvas, filename, extension); 69826 } 69827 }; 69828 69829 // GIF Section 69830 /** 69831 * Starts an animated GIF over at the beginning state. 69832 * 69833 * @method reset 69834 * @example 69835 * <div><code> 69836 * let gif; 69837 * 69838 * function preload() { 69839 * gif = loadImage('assets/arnott-wallace-wink-loop-once.gif'); 69840 * } 69841 * 69842 * function draw() { 69843 * background(255); 69844 * // The GIF file that we loaded only loops once 69845 * // so it freezes on the last frame after playing through 69846 * image(gif, 0, 0); 69847 * } 69848 * 69849 * function mousePressed() { 69850 * // Click to reset the GIF and begin playback from start 69851 * gif.reset(); 69852 * } 69853 * </code></div> 69854 * @alt 69855 * Animated image of a cartoon face that winks once and then freezes 69856 * When you click it animates again, winks once and freezes 69857 */ 69858 _main.default.Image.prototype.reset = function() { 69859 if (this.gifProperties) { 69860 var props = this.gifProperties; 69861 props.playing = true; 69862 props.timeSinceStart = 0; 69863 props.timeDisplayed = 0; 69864 props.lastChangeTime = 0; 69865 props.loopCount = 0; 69866 props.displayIndex = 0; 69867 this.drawingContext.putImageData(props.frames[0].image, 0, 0); 69868 } 69869 }; 69870 69871 /** 69872 * Gets the index for the frame that is currently visible in an animated GIF. 69873 * 69874 * @method getCurrentFrame 69875 * @return {Number} The index for the currently displaying frame in animated GIF 69876 * @example 69877 * <div><code> 69878 * let gif; 69879 * 69880 * function preload() { 69881 * gif = loadImage('assets/arnott-wallace-eye-loop-forever.gif'); 69882 * } 69883 * 69884 * function draw() { 69885 * let frame = gif.getCurrentFrame(); 69886 * image(gif, 0, 0); 69887 * text(frame, 10, 90); 69888 * } 69889 * </code></div> 69890 * @alt 69891 * Animated image of a cartoon eye looking around and then 69892 * looking outwards, in the lower-left hand corner a number counts 69893 * up quickly to 124 and then starts back over at 0 69894 */ 69895 _main.default.Image.prototype.getCurrentFrame = function() { 69896 if (this.gifProperties) { 69897 var props = this.gifProperties; 69898 return props.displayIndex % props.numFrames; 69899 } 69900 }; 69901 69902 /** 69903 * Sets the index of the frame that is currently visible in an animated GIF 69904 * 69905 * @method setFrame 69906 * @param {Number} index the index for the frame that should be displayed 69907 * @example 69908 * <div><code> 69909 * let gif; 69910 * 69911 * function preload() { 69912 * gif = loadImage('assets/arnott-wallace-eye-loop-forever.gif'); 69913 * } 69914 * 69915 * // Move your mouse up and down over canvas to see the GIF 69916 * // frames animate 69917 * function draw() { 69918 * gif.pause(); 69919 * image(gif, 0, 0); 69920 * // Get the highest frame number which is the number of frames - 1 69921 * let maxFrame = gif.numFrames() - 1; 69922 * // Set the current frame that is mapped to be relative to mouse position 69923 * let frameNumber = floor(map(mouseY, 0, height, 0, maxFrame, true));
69924 * gif.setFrame(frameNumber); 69925 * } 69926 * </code></div> 69927 * @alt 69928 * A still image of a cartoon eye that looks around when you move your mouse 69929 * up and down over the canvas 69930 */ 69931 _main.default.Image.prototype.setFrame = function(index) { 69932 if (this.gifProperties) { 69933 var props = this.gifProperties; 69934 if (index < props.numFrames && index >= 0) { 69935 props.timeDisplayed = 0; 69936 props.lastChangeTime = 0; 69937 props.displayIndex = index; 69938 this.drawingContext.putImageData(props.frames[index].image, 0, 0); 69939 } else { 69940 console.log( 69941 'Cannot set GIF to a frame number that is higher than total number of frames or below zero.' 69942 ); 69943 } 69944 } 69945 }; 69946 69947 /** 69948 * Returns the number of frames in an animated GIF 69949 * 69950 * @method numFrames 69951 * @return {Number} 69952 * @example The number of frames in the animated GIF 69953 * <div><code> 69954 * let gif; 69955 * 69956 * function preload() { 69957 * gif = loadImage('assets/arnott-wallace-eye-loop-forever.gif'); 69958 * } 69959 * 69960 * // Move your mouse up and down over canvas to see the GIF 69961 * // frames animate 69962 * function draw() { 69963 * gif.pause(); 69964 * image(gif, 0, 0); 69965 * // Get the highest frame number which is the number of frames - 1 69966 * let maxFrame = gif.numFrames() - 1; 69967 * // Set the current frame that is mapped to be relative to mouse position 69968 * let frameNumber = floor(map(mouseY, 0, height, 0, maxFrame, true)); 69969 * gif.setFrame(frameNumber); 69970 * } 69971 * </code></div> 69972 * @alt 69973 * A still image of a cartoon eye that looks around when you move your mouse 69974 * up and down over the canvas 69975 */ 69976 _main.default.Image.prototype.numFrames = function() { 69977 if (this.gifProperties) { 69978 return this.gifProperties.numFrames; 69979 } 69980 }; 69981 69982 /** 69983 * Plays an animated GIF that was paused with 69984 * <a href="#/p5.Image/pause">pause()</a> 69985 * 69986 * @method play 69987 * @example 69988 * <div><code> 69989 * let gif; 69990 * 69991 * function preload() { 69992 * gif = loadImage('assets/nancy-liang-wind-loop-forever.gif'); 69993 * } 69994 * 69995 * function draw() { 69996 * background(255); 69997 * image(gif, 0, 0); 69998 * } 69999 * 70000 * function mousePressed() { 70001 * gif.pause(); 70002 * } 70003 * 70004 * function mouseReleased() { 70005 * gif.play(); 70006 * } 70007 * </code></div> 70008 * @alt 70009 * An animated GIF of a drawing of small child with 70010 * hair blowing in the wind, when you click the image 70011 * freezes when you release it animates again 70012 */ 70013 _main.default.Image.prototype.play = function() { 70014 if (this.gifProperties) { 70015 this.gifProperties.playing = true; 70016 } 70017 }; 70018 70019 /** 70020 * Pauses an animated GIF. 70021 * 70022 * @method pause 70023 * @example 70024 * <div><code> 70025 * let gif; 70026 * 70027 * function preload() { 70028 * gif = loadImage('assets/nancy-liang-wind-loop-forever.gif'); 70029 * } 70030 * 70031 * function draw() { 70032 * background(255); 70033 * image(gif, 0, 0); 70034 * } 70035 * 70036 * function mousePressed() { 70037 * gif.pause(); 70038 * } 70039 * 70040 * function mouseReleased() { 70041 * gif.play(); 70042 * } 70043 * </code></div> 70044 * @alt 70045 * An animated GIF of a drawing of small child with 70046 * hair blowing in the wind, when you click the image 70047 * freezes when you release it animates again 70048 */ 70049 _main.default.Image.prototype.pause = function() { 70050 if (this.gifProperties) { 70051 this.gifProperties.playing = false;
70052 } 70053 }; 70054 70055 /** 70056 * Changes the delay between frames in an animated GIF. There is an optional second parameter that 70057 * indicates an index for a specific frame that should have its delay modified. If no index is given, all frames 70058 * will have the new delay. 70059 * 70060 * @method delay 70061 * @param {Number} d the amount in milliseconds to delay between switching frames 70062 * @param {Number} [index] the index of the frame that should have the new delay value {optional} 70063 * @example 70064 * <div><code> 70065 * let gifFast, gifSlow; 70066 * 70067 * function preload() { 70068 * gifFast = loadImage('assets/arnott-wallace-eye-loop-forever.gif'); 70069 * gifSlow = loadImage('assets/arnott-wallace-eye-loop-forever.gif'); 70070 * } 70071 * 70072 * function setup() { 70073 * gifFast.resize(width / 2, height / 2); 70074 * gifSlow.resize(width / 2, height / 2); 70075 * 70076 * //Change the delay here 70077 * gifFast.delay(10); 70078 * gifSlow.delay(100); 70079 * } 70080 * 70081 * function draw() { 70082 * background(255); 70083 * image(gifFast, 0, 0); 70084 * image(gifSlow, width / 2, 0); 70085 * } 70086 * </code></div> 70087 * @alt 70088 * Two animated gifs of cartoon eyes looking around 70089 * The gif on the left animates quickly, on the right 70090 * the animation is much slower 70091 */ 70092 _main.default.Image.prototype.delay = function(d, index) { 70093 if (this.gifProperties) { 70094 var props = this.gifProperties; 70095 if (index < props.numFrames && index >= 0) { 70096 props.frames[index].delay = d; 70097 } else { 70098 // change all frames 70099 var _iteratorNormalCompletion = true; 70100 var _didIteratorError = false; 70101 var _iteratorError = undefined; 70102 try { 70103 for ( 70104 var _iterator = props.frames[Symbol.iterator](), _step; 70105 !(_iteratorNormalCompletion = (_step = _iterator.next()).done); 70106 _iteratorNormalCompletion = true 70107 ) { 70108 var frame = _step.value; 70109 frame.delay = d; 70110 } 70111 } catch (err) { 70112 _didIteratorError = true; 70113 _iteratorError = err; 70114 } finally { 70115 try { 70116 if (!_iteratorNormalCompletion && _iterator.return != null) { 70117 _iterator.return(); 70118 } 70119 } finally { 70120 if (_didIteratorError) { 70121 throw _iteratorError; 70122 } 70123 } 70124 } 70125 } 70126 } 70127 }; 70128 var _default = _main.default.Image; 70129 exports.default = _default; 70130 }, 70131 { '../core/main': 59, './filters': 80 } 70132 ], 70133 84: [ 70134 function(_dereq_, module, exports) { 70135 'use strict'; 70136 Object.defineProperty(exports, '__esModule', { value: true }); 70137 exports.default = void 0; 70138 70139 var _main = _interopRequireDefault(_dereq_('../core/main')); 70140 var _filters = _interopRequireDefault(_dereq_('./filters')); 70141 _dereq_('../color/p5.Color'); 70142 function _interopRequireDefault(obj) { 70143 return obj && obj.__esModule ? obj : { default: obj }; 70144 } 70145 /** 70146 * @module Image 70147 * @submodule Pixels 70148 * @for p5 70149 * @requires core 70150 */ /** 70151 * <a href='https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference 70152 * /Global_Objects/Uint8ClampedArray' target='_blank'>Uint8ClampedArray</a> 70153 * containing the values for all the pixels in the display window. 70154 * These values are numbers. This array is the size (include an appropriate 70155 * factor for <a href="#/p5/pixelDensity">pixelDensity</a>) of the display window x4, 70156 * representing the R, G, B, A values in order for each pixel, mov
70156ing from 70157 * left to right across each row, then down each column. Retina and other 70158 * high density displays will have more pixels[] (by a factor of 70159 * pixelDensity^2). 70160 * For example, if the image is 100x100 pixels, there will be 40,000. On a 70161 * retina display, there will be 160,000. 70162 * 70163 * The first four values (indices 0-3) in the array will be the R, G, B, A 70164 * values of the pixel at (0, 0). The second four values (indices 4-7) will 70165 * contain the R, G, B, A values of the pixel at (1, 0). More generally, to 70166 * set values for a pixel at (x, y): 70167 * ```javascript 70168 * let d = pixelDensity(); 70169 * for (let i = 0; i < d; i++) { 70170 * for (let j = 0; j < d; j++) { 70171 * // loop over 70172 * index = 4 * ((y * d + j) * width * d + (x * d + i)); 70173 * pixels[index] = r; 70174 * pixels[index+1] = g; 70175 * pixels[index+2] = b; 70176 * pixels[index+3] = a; 70177 * } 70178 * } 70179 * ``` 70180 * While the above method is complex, it is flexible enough to work with 70181 * any pixelDensity. Note that <a href="#/p5/set">set()</a> will automatically take care of 70182 * setting all the appropriate values in <a href="#/p5/pixels">pixels[]</a> for a given (x, y) at 70183 * any pixelDensity, but the performance may not be as fast when lots of 70184 * modifications are made to the pixel array. 70185 * 70186 * Before accessing this array, the data must loaded with the <a href="#/p5/loadPixels">loadPixels()</a> 70187 * function. After the array data has been modified, the <a href="#/p5/updatePixels">updatePixels()</a> 70188 * function must be run to update the changes. 70189 * 70190 * Note that this is not a standard javascript array. This means that 70191 * standard javascript functions such as <a href="#/p5/slice">slice()</a> or 70192 * <a href="#/p5/arrayCopy">arrayCopy()</a> do not 70193 * work. 70194 * 70195 * @property {Number[]} pixels 70196 * @example 70197 * <div> 70198 * <code> 70199 * let pink = color(255, 102, 204); 70200 * loadPixels(); 70201 * let d = pixelDensity(); 70202 * let halfImage = 4 * (width * d) * (height / 2 * d); 70203 * for (let i = 0; i < halfImage; i += 4) { 70204 * pixels[i] = red(pink); 70205 * pixels[i + 1] = green(pink); 70206 * pixels[i + 2] = blue(pink); 70207 * pixels[i + 3] = alpha(pink); 70208 * } 70209 * updatePixels(); 70210 * </code> 70211 * </div> 70212 * 70213 * @alt 70214 * top half of canvas pink, bottom grey 70215 */ _main.default.prototype.pixels = []; /** 70216 * Copies a region of pixels from one image to another, using a specified 70217 * blend mode to do the operation. 70218 * 70219 * @method blend 70220 * @param {p5.Image} srcImage source image 70221 * @param {Integer} sx X coordinate of the source's upper left corner 70222 * @param {Integer} sy Y coordinate of the source's upper left corner 70223 * @param {Integer} sw source image width 70224 * @param {Integer} sh source image height 70225 * @param {Integer} dx X coordinate of the destination's upper left corner 70226 * @param {Integer} dy Y coordinate of the destination's upper left corner 70227 * @param {Integer} dw destination image width 70228 * @param {Integer} dh destination image height 70229 * @param {Constant} blendMode the blend mode. either 70230 * BLEND, DARKEST, LIGHTEST, DIFFERENCE, 70231 * MULTIPLY, EXCLUSION, SCREEN, REPLACE, OVERLAY, HARD_LIGHT, 70232 * SOFT_LIGHT, DODGE, BURN, ADD or NORMAL. 70233 * 70234 * @example 70235 * <div><code> 70236 * let img0; 70237 * let img1; 70238 * 70239 * function preload() { 70240 * img0 = loadImage('assets/rockies.jpg'); 70241 * img1 = loadImage('assets/bricks_third.jpg'); 70242 * } 70243 * 70244 * function setup() { 70245 * background(img0); 70246 * image(img1, 0, 0); 70247 * blend(img1, 0, 0, 33, 100, 67, 0, 33, 100, LIGHTEST); 70248 * } 70249 * </code></div> 70250 * <div><code> 70251 * let img0; 70252 * let img1; 70253 * 70254 * function preload() { 70255 * img0 = loadImage('assets/rockies.jpg'); 70256 * img1 = loadImage('assets/bricks_third.jpg'); 70257 * } 70258 * 70259 * function setup() { 70260 * background(img0); 70261 * image(img1, 0, 0); 70262 * blend(img1, 0, 0, 33, 100, 67, 0, 33, 100, DARKEST); 70263 * } 70264 * </code></div> 70265 * <div><code> 70266 * let img0; 70267 * let img1; 70268 * 70269 * function preload() { 70270 * img0 = loadImage('assets/rockies.jpg'); 70271 * img1 = loadImage('assets/bricks_third.jpg'); 70272 * } 70273 * 70274 * function setup() { 70275 * background(img0); 70276 * image(img1, 0, 0); 70277 * blend(img1, 0, 0, 33, 100, 67, 0, 33, 100, ADD); 70278 * } 70279 * </code></div> 70280 * 70281 * @alt 70282 * image of rocky mountains. Brick images on left and right. Right overexposed 70283 * image of rockies. Brickwall images on left and right. Right mortar transparent 70284 * image of rockies. Brickwall images on left and right. Right translucent 70285 * 70286 */ 70287 /** 70288 * @method blend 70289 * @param {Integer} sx 70290 * @param {Integer} sy 70291 * @param {Integer} sw 70292 * @param {Integer} sh 70293 * @param {Integer} dx 70294 * @param {Integer} dy 70295 * @param {Integer} dw 70296 * @param {Integer} dh 70297 * @param {Constant} blendMode 70298 */ 70299 _main.default.prototype.blend = function() { 70300 for ( 70301 var _len = arguments.length, args = new Array(_len), _key = 0; 70302 _key < _len; 70303 _key++ 70304 ) { 70305 args[_key] = arguments[_key]; 70306 } 70307 _main.default._validateParameters('blend', args); 70308 if (this._renderer) { 70309 var _this$_renderer; 70310 (_this$_renderer = this._renderer).blend.apply(_this$_renderer, args); 70311 } else { 70312 _main.default.Renderer2D.prototype.blend.apply(this, args); 70313 } 70314 }; 70315 70316 /** 70317 * Copies a region of the canvas to another region of the canvas 70318 * and copies a region of pixels from an image used as the srcImg parameter 70319 * into the canvas srcImage is specified this is used as the source. If 70320 * the source and destination regions aren't the same size, it will 70321 * automatically resize source pixels to fit the specified 70322 * target region. 70323 * 70324 * @method copy 70325 * @param {p5.Image|p5.Element} srcImage source image 70326 * @param {Integer} sx X coordinate of the source's upper left corner 70327 * @param {Integer} sy Y coordinate of the source's upper left corner 70328 * @param {Integer} sw source image width 70329 * @param {Integer} sh source image height 70330 * @param {Integer} dx X coordinate of the destination's upper left corner 70331 * @param {Integer} dy Y coordinate of the destination's upper left corner 70332 * @param {Integer} dw destination image width 70333 * @param {Integer} dh destination image height 70334 * 70335 * @example 70336 * <div><code> 70337 * let img; 70338 * 70339 * function preload() { 70340 * img = loadImage('assets/rockies.jpg'); 70341 * } 70342 * 70343 * function setup() { 70344 * background(img); 70345 * copy(img, 7, 22, 10, 10, 35, 25, 50, 50);
70346 * stroke(255); 70347 * noFill(); 70348 * // Rectangle shows area being copied 70349 * rect(7, 22, 10, 10); 70350 * } 70351 * </code></div> 70352 * 70353 * @alt 70354 * image of rocky mountains. Brick images on left and right. Right overexposed 70355 * image of rockies. Brickwall images on left and right. Right mortar transparent 70356 * image of rockies. Brickwall images on left and right. Right translucent 70357 */ 70358 /** 70359 * @method copy 70360 * @param {Integer} sx 70361 * @param {Integer} sy 70362 * @param {Integer} sw 70363 * @param {Integer} sh 70364 * @param {Integer} dx 70365 * @param {Integer} dy 70366 * @param {Integer} dw 70367 * @param {Integer} dh 70368 */ 70369 _main.default.prototype.copy = function() { 70370 for ( 70371 var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; 70372 _key2 < _len2; 70373 _key2++ 70374 ) { 70375 args[_key2] = arguments[_key2]; 70376 } 70377 _main.default._validateParameters('copy', args); 70378 70379 var srcImage, sx, sy, sw, sh, dx, dy, dw, dh; 70380 if (args.length === 9) { 70381 srcImage = args[0]; 70382 sx = args[1]; 70383 sy = args[2]; 70384 sw = args[3]; 70385 sh = args[4]; 70386 dx = args[5]; 70387 dy = args[6]; 70388 dw = args[7]; 70389 dh = args[8]; 70390 } else if (args.length === 8) { 70391 srcImage = this; 70392 sx = args[0]; 70393 sy = args[1]; 70394 sw = args[2]; 70395 sh = args[3]; 70396 dx = args[4]; 70397 dy = args[5]; 70398 dw = args[6]; 70399 dh = args[7]; 70400 } else { 70401 throw new Error('Signature not supported'); 70402 } 70403 70404 _main.default.prototype._copyHelper( 70405 this, 70406 srcImage, 70407 sx, 70408 sy, 70409 sw, 70410 sh, 70411 dx, 70412 dy, 70413 dw, 70414 dh 70415 ); 70416 }; 70417 70418 _main.default.prototype._copyHelper = function( 70419 dstImage, 70420 srcImage, 70421 sx, 70422 sy, 70423 sw, 70424 sh, 70425 dx, 70426 dy, 70427 dw, 70428 dh 70429 ) { 70430 srcImage.loadPixels(); 70431 var s = srcImage.canvas.width / srcImage.width; 70432 // adjust coord system for 3D when renderer 70433 // ie top-left = -width/2, -height/2 70434 var sxMod = 0; 70435 var syMod = 0; 70436 if (srcImage._renderer && srcImage._renderer.isP3D) { 70437 sxMod = srcImage.width / 2; 70438 syMod = srcImage.height / 2; 70439 } 70440 if (dstImage._renderer && dstImage._renderer.isP3D) { 70441 _main.default.RendererGL.prototype.image.call( 70442 dstImage._renderer, 70443 srcImage, 70444 sx + sxMod, 70445 sy + syMod, 70446 sw, 70447 sh, 70448 dx, 70449 dy, 70450 dw, 70451 dh 70452 ); 70453 } else { 70454 dstImage.drawingContext.drawImage( 70455 srcImage.canvas, 70456 s * (sx + sxMod), 70457 s * (sy + syMod), 70458 s * sw, 70459 s * sh, 70460 dx, 70461 dy, 70462 dw, 70463 dh 70464 ); 70465 } 70466 }; 70467 70468 /** 70469 * Applies a filter to the canvas. The presets options are: 70470 * 70471 * THRESHOLD 70472 * Converts the image to black and white pixels depending if they are above or 70473 * below the threshold defined by the level parameter. The parameter must be 70474 * between 0.0 (black) and 1.0 (white). If no level is specified, 0.5 is used. 70475 * 70476 * GRAY 70477 * Converts any colors in the image to grayscale equivalents. No parameter 70478 * is used. 70479 * 70480 * OPAQUE 70481 * Sets the alpha channel to entirely opaque. No parameter is used. 70482 * 70483 * INVERT 70484 * Sets each pixel to its inverse value. No parameter is used. 70485 * 70486 * POSTERIZE 70487 * Limits each channel of the image to the number of colors specified as the 70488 * parameter. The parameter can be set to values between 2 and 255, but 70489 * results are most noticeable in the lower ranges. 70490 * 70491 * BLUR 70492 * Executes a Gaussian blur with the level parameter specifying the extent 70493 * of the blurring. If no parameter is used, the blur is equivalent to 70494 * Gaussian blur of radius 1. Larger values increase the blur. 70495 * 70496 * ERODE 70497 * Reduces the light areas. No parameter is used. 70498 * 70499 * DILATE 70500 * Increases the light areas. No parameter is used. 70501 * 70502 * filter() does not work in WEBGL mode. 70503 * A similar effect can be achieved in WEBGL mode using custom 70504 * shaders. Adam Ferriss has written 70505 * a <a href="https://github.com/aferriss/p5jsShaderExamples" 70506 * target='_blank'>selection of shader examples</a> that contains many 70507 * of the effects present in the filter examples. 70508 * 70509 * @method filter 70510 * @param {Constant} filterType either THRESHOLD, GRAY, OPAQUE, INVERT, 70511 * POSTERIZE, BLUR, ERODE, DILATE or BLUR. 70512 * See Filters.js for docs on 70513 * each available filter 70514 * @param {Number} [filterParam] an optional parameter unique 70515 * to each filter, see above 70516 * 70517 * @example 70518 * <div> 70519 * <code> 70520 * let img; 70521 * function preload() { 70522 * img = loadImage('assets/bricks.jpg'); 70523 * } 70524 * function setup() { 70525 * image(img, 0, 0); 70526 * filter(THRESHOLD); 70527 * } 70528 * </code> 70529 * </div> 70530 * 70531 * <div> 70532 * <code> 70533 * let img; 70534 * function preload() { 70535 * img = loadImage('assets/bricks.jpg'); 70536 * } 70537 * function setup() { 70538 * image(img, 0, 0); 70539 * filter(GRAY); 70540 * } 70541 * </code> 70542 * </div> 70543 * 70544 * <div> 70545 * <code> 70546 * let img; 70547 * function preload() { 70548 * img = loadImage('assets/bricks.jpg'); 70549 * } 70550 * function setup() { 70551 * image(img, 0, 0); 70552 * filter(OPAQUE); 70553 * } 70554 * </code> 70555 * </div> 70556 * 70557 * <div> 70558 * <code> 70559 * let img; 70560 * function preload() { 70561 * img = loadImage('assets/bricks.jpg'); 70562 * } 70563 * function setup() { 70564 * image(img, 0, 0); 70565 * filter(INVERT); 70566 * } 70567 * </code> 70568 * </div> 70569 * 70570 * <div> 70571 * <code> 70572 * let img; 70573 * function preload() { 70574 * img = loadImage('assets/bricks.jpg'); 70575 * } 70576 * function setup() { 70577 * image(img, 0, 0); 70578 * filter(POSTERIZE, 3); 70579 * } 70580 * </code> 70581 * </div> 70582 * 70583 * <div> 70584 * <code> 70585 * let img; 70586 * function preload() { 70587 * img = loadImage('assets/bricks.jpg'); 70588 * } 70589 * function setup() { 70590 * image(img, 0, 0); 70591 * filter(DILATE); 70592 * } 70593 * </code> 70594 * </div> 70595 * 70596 * <div> 70597 * <code> 70598 * let img; 70599 * function preload() { 70600 * img = loadImage('assets/bricks.jpg'); 70601 * } 70602 * function setup() { 70603 * image(img, 0, 0);
70604 * filter(BLUR, 3); 70605 * } 70606 * </code> 70607 * </div> 70608 * 70609 * <div> 70610 * <code> 70611 * let img; 70612 * function preload() { 70613 * img = loadImage('assets/bricks.jpg'); 70614 * } 70615 * function setup() { 70616 * image(img, 0, 0); 70617 * filter(ERODE); 70618 * } 70619 * </code> 70620 * </div> 70621 * 70622 * @alt 70623 * black and white image of a brick wall. 70624 * greyscale image of a brickwall 70625 * image of a brickwall 70626 * jade colored image of a brickwall 70627 * red and pink image of a brickwall 70628 * image of a brickwall 70629 * blurry image of a brickwall 70630 * image of a brickwall 70631 * image of a brickwall with less detail 70632 */ 70633 _main.default.prototype.filter = function(operation, value) { 70634 _main.default._validateParameters('filter', arguments); 70635 if (this.canvas !== undefined) { 70636 _filters.default.apply(this.canvas, _filters.default[operation], value); 70637 } else { 70638 _filters.default.apply(this.elt, _filters.default[operation], value); 70639 } 70640 }; 70641 70642 /** 70643 * Get a region of pixels, or a single pixel, from the canvas. 70644 * 70645 * Returns an array of [R,G,B,A] values for any pixel or grabs a section of 70646 * an image. If no parameters are specified, the entire image is returned. 70647 * Use the x and y parameters to get the value of one pixel. Get a section of 70648 * the display window by specifying additional w and h parameters. When 70649 * getting an image, the x and y parameters define the coordinates for the 70650 * upper-left corner of the image, regardless of the current <a href="#/p5/imageMode">imageMode()</a>. 70651 * 70652 * Getting the color of a single pixel with get(x, y) is easy, but not as fast 70653 * as grabbing the data directly from <a href="#/p5/pixels">pixels[]</a>. The equivalent statement to 70654 * get(x, y) using <a href="#/p5/pixels">pixels[]</a> with pixel density d is 70655 * ```javascript 70656 * let x, y, d; // set these to the coordinates 70657 * let off = (y * width + x) * d * 4; 70658 * let components = [ 70659 * pixels[off], 70660 * pixels[off + 1], 70661 * pixels[off + 2], 70662 * pixels[off + 3] 70663 * ]; 70664 * print(components); 70665 * ``` 70666 * See the reference for <a href="#/p5/pixels">pixels[]</a> for more information. 70667 * 70668 * If you want to extract an array of colors or a subimage from an p5.Image object, 70669 * take a look at <a href="#/p5.Image/get">p5.Image.get()</a> 70670 * 70671 * @method get 70672 * @param {Number} x x-coordinate of the pixel 70673 * @param {Number} y y-coordinate of the pixel 70674 * @param {Number} w width 70675 * @param {Number} h height 70676 * @return {p5.Image} the rectangle <a href="#/p5.Image">p5.Image</a> 70677 * @example 70678 * <div> 70679 * <code> 70680 * let img; 70681 * function preload() { 70682 * img = loadImage('assets/rockies.jpg'); 70683 * } 70684 * function setup() { 70685 * image(img, 0, 0); 70686 * let c = get(); 70687 * image(c, width / 2, 0); 70688 * } 70689 * </code> 70690 * </div> 70691 * 70692 * <div> 70693 * <code> 70694 * let img; 70695 * function preload() { 70696 * img = loadImage('assets/rockies.jpg'); 70697 * } 70698 * function setup() { 70699 * image(img, 0, 0); 70700 * let c = get(50, 90); 70701 * fill(c); 70702 * noStroke(); 70703 * rect(25, 25, 50, 50); 70704 * } 70705 * </code> 70706 * </div> 70707 * 70708 * @alt 70709 * 2 images of the rocky mountains, side-by-side 70710 * Image of the rocky mountains with 50x50 green rect in center of canvas 70711 */ 70712 /** 70713 * @method get 70714 * @return {p5.Image} the whole <a href="#/p5.Image">p5.Image</a> 70715 */ 70716 /** 70717 * @method get 70718 * @param {Number} x 70719 * @param {Number} y 70720 * @return {Number[]} color of pixel at x,y in array format [R, G, B, A] 70721 */ 70722 _main.default.prototype.get = function(x, y, w, h) { 70723 var _this$_renderer2; 70724 _main.default._validateParameters('get', arguments); 70725 return (_this$_renderer2 = this._renderer).get.apply( 70726 _this$_renderer2, 70727 arguments 70728 ); 70729 }; 70730 70731 /** 70732 * Loads the pixel data for the display window into the <a href="#/p5/pixels">pixels[]</a> array. This
70733 * function must always be called before reading from or writing to <a href="#/p5/pixels">pixels[]</a>. 70734 * Note that only changes made with <a href="#/p5/set">set()</a> or direct manipulation of <a href="#/p5/pixels">pixels[]</a> 70735 * will occur. 70736 * 70737 * @method loadPixels 70738 * @example 70739 * <div> 70740 * <code> 70741 * let img; 70742 * function preload() { 70743 * img = loadImage('assets/rockies.jpg'); 70744 * } 70745 * 70746 * function setup() { 70747 * image(img, 0, 0, width, height); 70748 * let d = pixelDensity(); 70749 * let halfImage = 4 * (width * d) * (height * d / 2); 70750 * loadPixels(); 70751 * for (let i = 0; i < halfImage; i++) { 70752 * pixels[i + halfImage] = pixels[i]; 70753 * } 70754 * updatePixels(); 70755 * } 70756 * </code> 70757 * </div> 70758 * 70759 * @alt 70760 * two images of the rocky mountains. one on top, one on bottom of canvas. 70761 */ 70762 _main.default.prototype.loadPixels = function() { 70763 for ( 70764 var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; 70765 _key3 < _len3; 70766 _key3++ 70767 ) { 70768 args[_key3] = arguments[_key3]; 70769 } 70770 _main.default._validateParameters('loadPixels', args); 70771 this._renderer.loadPixels(); 70772 }; 70773 70774 /** 70775 * Changes the color of any pixel, or writes an image directly to the 70776 * display window. 70777 * The x and y parameters specify the pixel to change and the c parameter 70778 * specifies the color value. This can be a <a href="#/p5.Color">p5.Color</a> object, or [R, G, B, A] 70779 * pixel array. It can also be a single grayscale value. 70780 * When setting an image, the x and y parameters define the coordinates for 70781 * the upper-left corner of the image, regardless of the current <a href="#/p5/imageMode">imageMode()</a>. 70782 * 70783 * After using <a href="#/p5/set">set()</a>, you must call <a href="#/p5/updatePixels">updatePixels()</a> for your changes to appear. 70784 * This should be called once all pixels have been set, and must be called before 70785 * calling .<a href="#/p5/get">get()</a> or drawing the image. 70786 * 70787 * Setting the color of a single pixel with set(x, y) is easy, but not as 70788 * fast as putting the data directly into <a href="#/p5/pixels">pixels[]</a>. Setting the <a href="#/p5/pixels">pixels[]</a> 70789 * values directly may be complicated when working with a retina display, 70790 * but will perform better when lots of pixels need to be set directly on 70791 * every loop. See the reference for <a href="#/p5/pixels">pixels[]</a> for more information. 70792 * 70793 * @method set 70794 * @param {Number} x x-coordinate of the pixel 70795 * @param {Number} y y-coordinate of the pixel 70796 * @param {Number|Number[]|Object} c insert a grayscale value | a pixel array | 70797 * a <a href="#/p5.Color">p5.Color</a> object | a <a href="#/p5.Image">p5.Image</a> to copy 70798 * @example 70799 * <div> 70800 * <code> 70801 * let black = color(0); 70802 * set(30, 20, black); 70803 * set(85, 20, black); 70804 * set(85, 75, black); 70805 * set(30, 75, black); 70806 * updatePixels(); 70807 * </code> 70808 * </div> 70809 * 70810 * <div> 70811 * <code> 70812 * for (let i = 30; i < width - 15; i++) { 70813 * for (let j = 20; j < height - 25; j++) { 70814 * let c = color(204 - j, 153 - i, 0); 70815 * set(i, j, c); 70816 * } 70817 * } 70818 * updatePixels(); 70819 * </code> 70820 * </div> 70821 * 70822 * <div> 70823 * <code> 70824 * let img; 70825 * function preload() { 70826 * img = loadImage('assets/rockies.jpg'); 70827 * } 70828 * 70829 * function setup() { 70830 * set(0, 0, img); 70831 * updatePixels(); 70832 * line(0, 0, width, height); 70833 * line(0, height, width, 0); 70834 * } 70835 * </code> 70836 * </div> 70837 * 70838 * @alt 70839 * 4 black points in the shape of a square middle-right of canvas. 70840 * square with orangey-brown gradient lightening at bottom right. 70841 * image of the rocky mountains. with lines like an 'x' through the center. 70842 */ 70843 _main.default.prototype.set = function(x, y, imgOrCol) { 70844 this._renderer.set(x, y, imgOrCol); 70845 }; 70846 /** 70847 * Updates the display window with the data in the <a href="#/p5/pixels">pixels[]</a> array. 70848 * Use in conjunction with <a href="#/p5/loadPixels">loadPixels()</a>. If you're only reading pixels from 70849 * the array, there's no need to call <a href="#/p5/updatePixels">updatePixels()</a> â updating is only 70850 * necessary to apply changes. <a href="#/p5/updatePixels">updatePixels()</a> should be called anytime the 70851 * pixels array is manipulated or <a href="#/p5/set">set()</a> is called, and only changes made with 70852 * <a href="#/p5/set">set()</a> or direct changes to <a href="#/p5/pixels">pixels[]</a> will occur. 70853 * 70854 * @method updatePixels 70855 * @param {Number} [x] x-coordinate of the upper-left corner of region 70856 * to update 70857 * @param {Number} [y] y-coordinate of the upper-left corner of region 70858 * to update 70859 * @param {Number} [w] width of region to update 70860 * @param {Number} [h] height of region to update 70861 * @example 70862 * <div> 70863 * <code> 70864 * let img; 70865 * function preload() { 70866 * img = loadImage('assets/rockies.jpg'); 70867 * } 70868 * 70869 * function setup() { 70870 * image(img, 0, 0, width, height); 70871 * let d = pixelDensity(); 70872 * let halfImage = 4 * (width * d) * (height * d / 2); 70873 * loadPixels(); 70874 * for (let i = 0; i < halfImage; i++) { 70875 * pixels[i + halfImage] = pixels[i]; 70876 * } 70877 * updatePixels(); 70878 * } 70879 * </code> 70880 * </div> 70881 * @alt 70882 * two images of the rocky mountains. one on top, one on bottom of canvas. 70883 */ 70884 _main.default.prototype.updatePixels = function(x, y, w, h) { 70885 _main.default._validateParameters('updatePixels', arguments); 70886 // graceful fail - if loadPixels() or set() has not been called, pixel 70887 // array will be empty, ignore call to updatePixels() 70888 if (this.pixels.length === 0) { 70889 return; 70890 } 70891 this._renderer.updatePixels(x, y, w, h); 70892 }; 70893 var _default = _main.default; 70894 exports.default = _default; 70895 }, 70896 { '../color/p5.Color': 46, '../core/main': 59, './filters': 80 } 70897 ], 70898 85: [
vendor: 4,587 bytes, lines 70899-70939
70899 function(_dereq_, module, exports) { 70900 'use strict'; 70901 Object.defineProperty(exports, '__esModule', { value: true }); 70902 exports.default = void 0; 70903 70904 var _main = _interopRequireDefault(_dereq_('../core/main')); 70905 _dereq_('whatwg-fetch'); 70906 _dereq_('es6-promise/auto'); 70907 var _fetchJsonp = _interopRequireDefault(_dereq_('fetch-jsonp')); 70908 var _fileSaver = _interopRequireDefault(_dereq_('file-saver')); 70909 _dereq_('../core/friendly_errors/validate_params'); 70910 _dereq_('../core/friendly_errors/file_errors'); 70911 _dereq_('../core/friendly_errors/fes_core'); 70912 function _interopRequireDefault(obj) { 70913 return obj && obj.__esModule ? obj : { default: obj }; 70914 } 70915 function _typeof(obj) { 70916 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') { 70917 _typeof = function _typeof(obj) { 70918 return typeof obj; 70919 }; 70920 } else { 70921 _typeof = function _typeof(obj) { 70922 return obj && 70923 typeof Symbol === 'function' && 70924 obj.constructor === Symbol && 70925 obj !== Symbol.prototype 70926 ? 'symbol' 70927 : typeof obj; 70928 }; 70929 } 70930 return _typeof(obj); 70931 } 70932 70933 /** 70934 * Loads a JSON file from a file or a URL, and returns an Object. 70935 * Note that even if the JSON file contains an Array, an Object will be 70936 * returned with index numbers as keys. 70937 * 70938 * This method is asynchronous, meaning it may not finish before the next 70939 * line in your sketch is executed. JSONP is supported via a polyfill and
70939you 70940 * can pass in as the second argument an object with definitions of the json 70941 * callback following the syntax specified <a href="https://github.com/camsong/ 70942 * fetch-jsonp">here</a>. 70943 * 70944 * This method is suitable for fetching files up to size of 64MB. 70945 * @method loadJSON 70946 * @param {String} path name of the file or url to load 70947 * @param {Object} [jsonpOptions] options object for jsonp related settings 70948 * @param {String} [datatype] "json" or "jsonp" 70949 * @param {function} [callback] function to be executed after 70950 * <a href="#/p5/loadJSON">loadJSON()</a> completes, data is passed 70951 * in as first argument 70952 * @param {function} [errorCallback] function to be executed if 70953 * there is an error, response is passed 70954 * in as first argument 70955 * @return {Object|Array} JSON data 70956 * @example 70957 * 70958 * Calling <a href="#/p5/loadJSON">loadJSON()</a> inside <a href="#/p5/preload">preload()</a> guarantees to complete the 70959 * operation before <a href="#/p5/setup">setup()</a> and <a href="#/p5/draw">draw()</a> are called. 70960 * 70961 * <div><code> 70962 * // Examples use USGS Earthquake API: 70963 * // https://earthquake.usgs.gov/fdsnws/event/1/#methods 70964 * let earthquakes; 70965 * function preload() { 70966 * // Get the most recent earthquake in the database 70967 * let url = 70968 'https://earthquake.usgs.gov/earthquakes/feed/v1.0/' + 70969 * 'summary/all_day.geojson'; 70970 * earthquakes = loadJSON(url); 70971
70971 * } 70972 * 70973 * function setup() { 70974 * noLoop(); 70975 * } 70976 * 70977 * function draw() { 70978 * background(200); 70979 * // Get the magnitude and name of the earthquake out of the loaded JSON 70980 * let earthquakeMag = earthquakes.features[0].properties.mag; 70981 * let earthquakeName = earthquakes.features[0].properties.place; 70982 * ellipse(width / 2, height / 2, earthquakeMag * 10, earthquakeMag * 10); 70983 * textAlign(CENTER); 70984 * text(earthquakeName, 0, height - 30, width, 30
70984); 70985 * } 70986 * </code></div> 70987 * 70988 * Outside of preload(), you may supply a callback function to handle the 70989 * object: 70990 * <div><code> 70991 * function setup() { 70992 * noLoop(); 70993 * let url = 70994 'https://earthquake.usgs.gov/earthquakes/feed/v1.0/' + 70995 * 'summary/all_day.geojson'; 70996 * loadJSON(url, drawEarthquake); 70997 * } 70998 * 70999 * function draw() { 71000 * background(200); 71001 * } 71002 * 71003 * function drawEarthquake(earthquakes) { 71004 * // Get the magnitude and name of the earthquake out of the loaded JSON 71005 * let earthquakeMag = earthquakes.features[0].properties.mag; 71006 * let earthquakeName = earthquakes.features[0].properties.place; 71007 * ellipse(width / 2, height / 2, earthquakeMag * 10, earthquakeMag * 10); 71008 * textAlign(CENTER); 71009 * text(earthquakeName, 0, height - 30, width, 30
71009); 71010 * } 71011 * </code></div> 71012 * 71013 * @alt 71014 * 50x50 ellipse that changes from black to white depending on the current humidity 71015 * 50x50 ellipse that changes from black to white depending on the current humidity 71016 */ 71017 /** 71018 * @method loadJSON 71019 * @param {String} path 71020 * @param {String} datatype 71021 * @param {function} [callback] 71022 * @param {function} [errorCallback] 71023 * @return {Object|Array} 71024 */ 71025 /** 71026 * @method loadJSON 71027 * @param {String} path 71028 * @param {function} callback 71029 * @param {function} [errorCallback] 71030 * @return {Object|Array} 71031 */ 71032 _main.default.prototype.loadJSON = function() { 71033 for ( 71034 var _len = arguments.length, args = new Array(_len), _key = 0; 71035 _key < _len; 71036 _key++ 71037 ) { 71038 args[_key] = arguments[_key]; 71039 } 71040 _main.default._validateParameters('loadJSON', args); 71041 var path = args[0]; 71042 var callback; 71043 var errorCallback; 71044 var options; 71045 71046 var ret = {}; // object needed for preload 71047 var t = 'json'; 71048 71049 // check for explicit data type argument 71050 for (var i = 1; i < args.length; i++) { 71051 var arg = args[i]; 71052 if (typeof arg === 'string') { 71053 if (arg === 'jsonp' || arg === 'json') { 71054 t = arg; 71055 } 71056 } else if (typeof arg === 'function') { 71057 if (!callback) { 71058 callback = arg; 71059 } else { 71060 errorCallback = arg; 71061 } 71062 } else if ( 71063 _typeof(arg) === 'object' && 71064 (arg.hasOwnProperty('jsonpCallback') || 71065 arg.hasOwnProperty('jsonpCallbackFunction')) 71066 ) { 71067 t = 'jsonp'; 71068 options = arg; 71069 } 71070 } 71071 71072 var self = this; 71073 this.httpDo( 71074 path, 71075 'GET', 71076 options, 71077 t, 71078 function(resp) { 71079 for (var k in resp) { 71080 ret[k] = resp[k]; 71081 } 71082 if (typeof callback !== 'undefined') { 71083 callback(resp); 71084 } 71085 71086 self._decrementPreload(); 71087 }, 71088 function(err) { 71089 // Error handling 71090 _main.default._friendlyFileLoadError(5, path); 71091 71092 if (errorCallback) { 71093 errorCallback(err); 71094 } else { 71095 throw err; 71096 } 71097 } 71098 ); 71099 71100 return ret; 71101 }; 71102 71103 /** 71104 * Reads the contents of a file and creates a String array of its individual 71105 * lines. If the name of the file is used as the parameter, as in the above 71106 * example, the file must be located in the sketch directory/folder. 71107 * 71108 * Alternatively, the file maybe be loaded from anywhere on the local 71109 * computer using an absolute path (something that starts with / on Unix and 71110 * Linux, or a drive letter on Windows), or the filename parameter can be a 71111 * URL for a file found on a network. 71112 * 71113 * This method is asynchronous, meaning it may not finish before the next 71114 * line in your sketch is executed. 71115 * 71116 * This method is suitable for fetching files up to size of 64MB. 71117 * @method loadStrings 71118 * @param {String} filename name of the file or url to load 71119 * @param {function} [callback] function to be executed after <a href="#/p5/loadStrings">loadStrings()</a> 71120 * completes, Array is passed in as first 71121 * argument 71122 * @param {function} [errorCallback] function to be executed if 71123 * there is an error, response is passed 71124 * in as first argument 71125 * @return {String[]} Array of Strings 71126 * @example 71127 * 71128 * Calling loadStrings() inside <a href="#/p5/preload">preload()</a> guarantees to complete the 71129 * operation before <a href="#/p5/setup">setup()</a> and <a href="#/p5/draw">draw()</a> are called. 71130 * 71131 * <div><code> 71132 * let result; 71133 * function preload() { 71134 * result = loadStrings('assets/test.txt'); 71135 * } 71136 71137 * function setup() { 71138 * background(200); 71139 * text(random(result), 10, 10, 80, 80); 71140 * } 71141 * </code></div> 71142 * 71143 * Outside of preload(), you may supply a callback function to handle the 71144 * object: 71145 * 71146 * <div><code> 71147 * function setup() { 71148 * loadStrings('assets/test.txt', pickString); 71149 * } 71150 * 71151 * function pickString(result) { 71152 * background(200); 71153 * text(random(result), 10, 10, 80, 80); 71154 * } 71155 * </code></div> 71156 * 71157 * @alt 71158 * randomly generated text from a file, for example "i smell like butter" 71159 * randomly generated text from a file, for example "i have three feet" 71160 */ 71161 _main.default.prototype.loadStrings = function() { 71162 for ( 71163 var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; 71164 _key2 < _len2; 71165 _key2++ 71166 ) { 71167 args[_key2] = arguments[_key2]; 71168 } 71169 _main.default._validateParameters('loadStrings', args); 71170 71171 var ret = []; 71172 var callback, errorCallback; 71173 71174 for (var i = 1; i < args.length; i++) { 71175 var arg = args[i]; 71176 if (typeof arg === 'function') { 71177 if (typeof callback === 'undefined') { 71178 callback = arg; 71179 } else if (typeof errorCallback === 'undefined') { 71180 errorCallback = arg; 71181 } 71182 } 71183 } 71184 71185 var self = this; 71186 _main.default.prototype.httpDo.call( 71187 this, 71188 args[0], 71189 'GET', 71190 'text', 71191 function(data) { 71192 // split lines handling mac/windows/linux endings 71193 var lines = data 71194 .replace(/\r\n/g, '\r') 71195 .replace(/\n/g, '\r') 71196 .split(/\r/); 71197 71198 // safe insert approach which will not blow up stack when inserting 71199 // >100k lines, but still be faster than iterating line-by-line. based on 71200 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply#Examples 71201 var QUANTUM = 32768; 71202 for (var _i = 0, len = lines.length; _i < len; _i += QUANTUM) { 71203 Array.prototype.push.apply( 71204 ret, 71205 lines.slice(_i, Math.min(_i + QUANTUM, len)) 71206 ); 71207 } 71208 71209 if (typeof callback !== 'undefined') { 71210 callback(ret); 71211 } 71212 71213 self._decrementPreload(); 71214 }, 71215 function(err) { 71216 // Error handling 71217 _main.default._friendlyFileLoadError(3, arguments[0]); 71218 71219 if (errorCallback) { 71220 errorCallback(err); 71221 } else { 71222 throw err; 71223 } 71224 } 71225 ); 71226 71227 return ret; 71228 }; 71229 71230 /** 71231 * Reads the contents of a file or URL and creates a <a href="#/p5.Table">p5.Table</a> object with 71232 * its values. If a file is specified, it must be located in the sketch's 71233 * "data" folder. The filename parameter can also be a URL to a file found 71234 * online. By default, the file is assumed to be comma-separated (in CSV 71235 * format). Table only looks for a header row if the 'header' option is 71236 * included. 71237 * 71238 * This method is asynchronous, meaning it may not finish before the next 71239 * line in your sketch is executed. Calling <a href="#/p5/loadTable">loadTable()</a> inside <a href="#/p5/preload">preload()</a> 71240 * guarantees to complete the operation before <a href="#/p5/setup">setup()</a> and <a href="#/p5/draw">draw()</a> are called. 71241 * Outside of <a href="#/p5/preload">preload()</a>, you may supply a callback function to handle the 71242 * object: 71243 * 71244 * All files loaded and saved use UTF-8 encoding. This method is suitable for fetching files up to size of 64MB. 71245 * @method loadTable 71246 * @param {String} filename name of the file or URL to load 71247 * @param {String} [extension] parse the table by comma-separated values "csv", semicolon-separated 71248 * values "ssv", or tab-separated values "tsv" 71249 * @param {String} [header] "header" to indicate table has header row 71250 * @param {function} [callback] function to be executed after 71251 * <a href="#/p5/loadTable">loadTable()</a> completes. On success, the 71252 * <a href="#/p5.Table">Table</a> object is passed in as the 71253 * first argument. 71254 * @param {function} [errorCallback] function to be executed if 71255 * there is an error, response is passed 71256 * in as first argument 71257 * @return {Object} <a href="#/p5.Table">Table</a>
71257 object containing data 71258 * 71259 * @example 71260 * <div class='norender'> 71261 * <code> 71262 * // Given the following CSV file called "mammals.csv" 71263 * // located in the project's "assets" folder: 71264 * // 71265 * // id,species,name 71266 * // 0,Capra hircus,Goat 71267 * // 1,Panthera pardus,Leopard 71268 * // 2,Equus zebra,Zebra 71269 * 71270 * let table; 71271 * 71272 * function preload() { 71273 * //my table is comma separated value "csv" 71274 * //and has a header specifying the columns labels 71275 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 71276 * //the file can be remote 71277 * //table = loadTable("http://p5js.org/reference/assets/mammals.csv", 71278 * // "csv", "header"); 71279 * } 71280 * 71281 * function setup() { 71282 * //count the columns 71283 * print(table.getRowCount() + ' total rows in table'); 71284 * print(table.getColumnCount() + ' total columns in table'); 71285 * 71286 * print(table.getColumn('name')); 71287 * //["Goat", "Leopard", "Zebra"] 71288 * 71289 * //cycle through the table 71290 * for (let r = 0; r < table.getRowCount(); r++) 71291 * for (let c = 0; c < table.getColumnCount(); c++) { 71292 * print(table.getString(r, c)); 71293 * } 71294 * } 71295 * </code> 71296 * </div> 71297 * 71298 * @alt 71299 * randomly generated text from a file, for example "i smell like butter" 71300 * randomly generated text from a file, for example "i have three feet" 71301 */ 71302 _main.default.prototype.loadTable = function(path) { 71303 // p5._validateParameters('loadTable', arguments); 71304 var callback; 71305 var errorCallback; 71306 var options = []; 71307 var header = false;
71308 var ext = path.substring(path.lastIndexOf('.') + 1, path.length); 71309 71310 var sep; 71311 if (ext === 'csv') { 71312 sep = ','; 71313 } else if (ext === 'ssv') { 71314 sep = ';'; 71315 } else if (ext === 'tsv') { 71316 sep = '\t'; 71317 } 71318 71319 for (var i = 1; i < arguments.length; i++) { 71320 if (typeof arguments[i] === 'function') { 71321 if (typeof callback === 'undefined') { 71322 callback = arguments[i]; 71323 } else if (typeof errorCallback === 'undefined') { 71324 errorCallback = arguments[i]; 71325 } 71326 } else if (typeof arguments[i] === 'string') { 71327 options.push(arguments[i]); 71328 if (arguments[i] === 'header') { 71329 header = true; 71330 } 71331 if (arguments[i] === 'csv') { 71332 sep = ','; 71333 } else if (arguments[i] === 'ssv') { 71334 sep = ';'; 71335 } else if (arguments[i] === 'tsv') { 71336 sep = '\t'; 71337 } 71338 } 71339 } 71340 71341 var t = new _main.default.Table(); 71342 71343 var self = this; 71344 this.httpDo( 71345 path, 71346 'GET', 71347 'table', 71348 function(resp) { 71349 var state = {}; 71350 71351 // define constants 71352 var PRE_TOKEN = 0, 71353 MID_TOKEN = 1, 71354 POST_TOKEN = 2, 71355 POST_RECORD = 4; 71356 71357 var QUOTE = '"', 71358 CR = '\r', 71359 LF = '\n'; 71360 71361 var records = []; 71362 var offset = 0; 71363 var currentRecord = null; 71364 var currentChar; 71365 71366 var tokenBegin = function tokenBegin() { 71367 state.currentState = PRE_TOKEN; 71368 state.token = ''; 71369 }; 71370 71371 var tokenEnd = function tokenEnd() { 71372 currentRecord.push(state.token); 71373 tokenBegin(); 71374 }; 71375 71376 var recordBegin = function recordBegin() { 71377 state.escaped = false; 71378 currentRecord = []; 71379 tokenBegin(); 71380 }; 71381 71382 var recordEnd = function recordEnd() { 71383 state.currentState = POST_RECORD; 71384 records.push(currentRecord); 71385 currentRecord = null; 71386 }; 71387 71388 for (;;) { 71389 currentChar = resp[offset++]; 71390 71391 // EOF 71392 if (currentChar == null) { 71393 if (state.escaped) { 71394 throw new Error('Unclosed quote in file.'); 71395 } 71396 if (currentRecord) { 71397 tokenEnd(); 71398 recordEnd(); 71399 break; 71400 } 71401 } 71402 if (currentRecord === null) { 71403 recordBegin(); 71404 } 71405 71406 // Handle opening quote 71407 if (state.currentState === PRE_TOKEN) { 71408 if (currentChar === QUOTE) { 71409 state.escaped = true; 71410 state.currentState = MID_TOKEN; 71411 continue; 71412 } 71413 state.currentState = MID_TOKEN; 71414 } 71415 71416 // mid-token and escaped, look for sequences and end quote 71417 if (state.currentState === MID_TOKEN && state.escaped) { 71418 if (currentChar === QUOTE) { 71419 if (resp[offset] === QUOTE) { 71420 state.token += QUOTE; 71421 offset++; 71422 } else { 71423 state.escaped = false; 71424 state.currentState = POST_TOKEN; 71425 } 71426 } else if (currentChar === CR) { 71427 continue; 71428 } else { 71429 state.token += currentChar; 71430 } 71431 continue; 71432 } 71433 71434 // fall-through: mid-token or post-token, not escaped 71435 if (currentChar === CR) { 71436 if (resp[offset] === LF) { 71437 offset++; 71438 } 71439 tokenEnd(); 71440 recordEnd(); 71441 } else if (currentChar === LF) { 71442 tokenEnd(); 71443 recordEnd(); 71444 } else if (currentChar === sep) { 71445 tokenEnd(); 71446 } else if (state.currentState === MID_TOKEN) { 71447 state.token += currentChar; 71448 } 71449 } 71450 71451 // set up column names 71452 if (header) { 71453 t.columns = records.shift(); 71454 } else { 71455 for (var _i2 = 0; _i2 < records[0].length; _i2++) { 71456 t.columns[_i2] = 'null';
71457 } 71458 } 71459 var row; 71460 for (var _i3 = 0; _i3 < records.length; _i3++) { 71461 //Handles row of 'undefined' at end of some CSVs 71462 if (records[_i3].length === 1) { 71463 if (records[_i3][0] === 'undefined' || records[_i3][0] === '') { 71464 continue; 71465 } 71466 } 71467 row = new _main.default.TableRow(); 71468 row.arr = records[_i3]; 71469 row.obj = makeObject(records[_i3], t.columns); 71470 t.addRow(row); 71471 } 71472 if (typeof callback === 'function') { 71473 callback(t); 71474 } 71475 71476 self._decrementPreload(); 71477 }, 71478 function(err) { 71479 // Error handling 71480 _main.default._friendlyFileLoadError(2, path); 71481 71482 if (errorCallback) { 71483 errorCallback(err); 71484 } else { 71485 console.error(err); 71486 } 71487 } 71488 ); 71489 71490 return t; 71491 }; 71492 71493 // helper function to turn a row into a JSON object 71494 function makeObject(row, headers) { 71495 var ret = {}; 71496 headers = headers || []; 71497 if (typeof headers === 'undefined') { 71498 for (var j = 0; j < row.length; j++) { 71499 headers[j.toString()] = j; 71500 } 71501 } 71502 for (var i = 0; i < headers.length; i++) { 71503 var key = headers[i]; 71504 var val = row[i]; 71505 ret[key] = val; 71506 } 71507 return ret; 71508 } 71509 71510 /** 71511 * Reads the contents of a file and creates an XML object with its values. 71512 * If the name of the file is used as the parameter, as in the above example, 71513 * the file must be located in the sketch directory/folder. 71514 * 71515 * Alternatively, the file maybe be loaded from anywhere on the local 71516 * computer using an absolute path (something that starts with / on Unix and 71517 * Linux, or a drive letter on Windows), or the filename parameter can be a 71518 * URL for a file found on a network. 71519 * 71520 * This method is asynchronous, meaning it may not finish before the next 71521 * line in your sketch is executed. Calling <a href="#/p5/loadXML">loadXML()</a> inside <a href="#/p5/preload">preload()</a> 71522 * guarantees to complete the operation before <a href="#/p5/setup">setup()</a> and <a href="#/p5/draw">draw()</a> are called. 71523 * 71524 * Outside of <a href="#/p5/preload">preload()</a>, you may supply a callback function to handle the 71525 * object. 71526 * 71527 * This method is suitable for fetching files up to size of 64MB. 71528 * @method loadXML 71529 * @param {String} filename name of the file or URL to load 71530 * @param {function} [callback] function to be executed after <a href="#/p5/loadXML">loadXML()</a> 71531 * completes, XML object is passed in as 71532 * first argument 71533 * @param {function} [errorCallback] function to be executed if 71534 * there is an error, response is passed 71535 * in as first argument 71536 * @return {Object} XML object containing data 71537 * @example 71538 * <div class='norender'><code> 71539 * // The following short XML file called "mammals.xml" is parsed 71540 * // in the code below. 71541 * // 71542 * // <?xml version="1.0"?> 71543 * // <mammals> 71544 * // <animal id="0" species="Capra hircus">Goat</animal> 71545 * // <animal id="1" species="Panthera pardus">Leopard</animal> 71546 * // <animal id="2" species="Equus zebra">Zebra</animal> 71547 * // </mammals> 71548 * 71549 * let xml; 71550 * 71551 * function preload() { 71552 * xml = loadXML('assets/mammals.xml'); 71553 * } 71554 * 71555 * function setup() { 71556 * let children = xml.getChildren('animal'); 71557 * 71558 * for (let i = 0; i < children.length; i++) { 71559 * let id = children[i].getNum('id'); 71560 * let coloring = children[i].getString('species'); 71561 * let name = children[i].getContent(); 71562 * print(id + ', ' + coloring + ', ' + name); 71563 * } 71564 * } 71565 * 71566 * // Sketch prints: 71567 * // 0, Capra hircus, Goat 71568 * // 1, Panthera pardus, Leopard 71569 * // 2, Equus zebra, Zebra 71570 * </code></div> 71571 * 71572 * @alt 71573 * no image displayed 71574 */ 71575 _main.default.prototype.loadXML = function() { 71576 for ( 71577 var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; 71578 _key3 < _len3; 71579 _key3++ 71580 ) { 71581 args[_key3] = arguments[_key3]; 71582 } 71583 var ret = new _main.default.XML(); 71584 var callback, errorCallback; 71585 71586 for (var i = 1; i < args.length; i++) { 71587 var arg = args[i]; 71588 if (typeof arg === 'function') { 71589 if (typeof callback === 'undefined') { 71590 callback = arg; 71591 } else if (typeof errorCallback === 'undefined') { 71592 errorCallback = arg; 71593 } 71594 } 71595 } 71596 71597 var self = this; 71598 this.httpDo( 71599 args[0], 71600 'GET', 71601 'xml', 71602 function(xml) { 71603 for (var key in xml) { 71604 ret[key] = xml[key]; 71605 } 71606 if (typeof callback !== 'undefined') { 71607 callback(ret); 71608 } 71609 71610 self._decrementPreload(); 71611 }, 71612 function(err) { 71613 // Error handling 71614 _main.default._friendlyFileLoadError(1, arguments[0]); 71615 71616 if (errorCallback) { 71617 errorCallback(err); 71618 } else { 71619 throw err; 71620 } 71621 } 71622 ); 71623 71624 return ret; 71625 }; 71626 71627 /** 71628 * This method is suitable for fetching files up to size of 64MB. 71629 * @method loadBytes 71630 * @param {string} file name of the file or URL to load 71631 * @param {function} [callback] function to be executed after <a href="#/p5/loadBytes">loadBytes()</a> 71632 * completes 71633 * @param {function} [errorCallback] function to be executed if there 71634 * is an error 71635 * @returns {Object} an object whose 'bytes' property will be the loaded buffer 71636 * 71637 * @example 71638 * <div class='norender'><code> 71639 * let data; 71640 * 71641 * function preload() { 71642 * data = loadBytes('assets/mammals.xml'); 71643 * } 71644 * 71645 * function setup() { 71646 * for (let i = 0; i < 5; i++) { 71647 * console.log(data.bytes[i].toString(16)); 71648 * } 71649 * } 71650 * </code></div> 71651 * 71652 * @alt 71653 * no image displayed 71654 */ 71655 _main.default.prototype.loadBytes = function(file, callback, errorCallback) { 71656 var ret = {}; 71657 71658 var self = this; 71659 this.httpDo( 71660 file, 71661 'GET', 71662 'arrayBuffer', 71663 function(arrayBuffer) { 71664 ret.bytes = new Uint8Array(arrayBuffer); 71665 71666 if (typeof callback === 'function') { 71667 callback(ret); 71668 } 71669 71670 self._decrementPreload(); 71671 }, 71672 function(err) { 71673 // Error handling 71674 _main.default._friendlyFileLoadError(6, file); 71675 71676 if (errorCallback) { 71677 errorCallback(err); 71678 } else { 71679 throw err; 71680 } 71681 } 71682 ); 71683 71684 return ret; 71685 }; 71686 71687 /** 71688 * Method for executing an HTTP GET request. If data type is not specified, 71689 * p5 will try to guess based on the URL, defaulting to text. This is equivalent to 71690 * calling <code>httpDo(path, 'GET')</code>. The 'binary' datatype will return 71691 * a Blob object, and the 'arrayBuffer' datatype will return an ArrayBuffer 71692 * which can be used to initialize typed arrays (such as Uint8Array). 71693 * 71694 * @method httpGet 71695 * @param {String} path name of the file or url to load 71696 * @param {String} [datatype] "json", "jsonp", "binary", "arrayBuffer", 71697 * "xml", or "text" 71698 * @param {Object|Boolean} [data] param data passed sent with request 71699 * @param {function} [callback] function to be executed after 71700 * <a href="#/p5/httpGet">httpGet()</a> completes, data is passed in 71701 * as first argument 71702 * @param {function} [errorCallback] function to be executed if 71703 * there is an error, response is passed 71704 * in as first argument 71705 * @return {Promise} A promise that resolves with the data when the operation 71706 * completes successfully or rejects with the error after 71707 * one occurs. 71708 * @example 71709 * <div class='norender'><code> 71710 * // Examples use USGS Earthquake API: 71711 * // https://earthquake.usgs.gov/fdsnws/event/1/#methods 71712 * let earthquakes; 71713 * function preload() { 71714 * // Get the most recent earthquake in the database 71715 * let url = 71716 'https://earthquake.usgs.gov/fdsnws/event/1/query?' + 71717 * 'format=geojson&limit=1&orderby=time'; 71718 * httpGet(url, 'jsonp', false, function(response) { 71719 * // when the HTTP request completes, populate the variable that holds the 71720 * // earthquake data used in the visualization. 71721 * earthquakes = response; 71722 * }); 71723 * } 71724 * 71725 * function draw() { 71726 * if (!earthquakes) { 71727 * // Wait until the earthquake data has loaded before drawing. 71728 * return; 71729 * } 71730 * background(200); 71731 * // Get the magnitude and name of the earthquake out of the loaded JSON 71732 * let earthquakeMag = earthquakes.features[0].properties.mag; 71733 * let earthquakeName = earthquakes.features[0].properties.place; 71734 * ellipse(width / 2, height / 2, earthquakeMag * 10, earthquakeMag * 10); 71735 * textAlign(CENTER);
71736 * text(earthquakeName, 0, height - 30, width, 30); 71737 * noLoop(); 71738 * } 71739 * </code></div> 71740 */ 71741 /** 71742 * @method httpGet 71743 * @param {String} path 71744 * @param {Object|Boolean} data 71745 * @param {function} [callback] 71746 * @param {function} [errorCallback] 71747 * @return {Promise} 71748 */ 71749 /** 71750 * @method httpGet 71751 * @param {String} path 71752 * @param {function} callback 71753 * @param {function} [errorCallback] 71754 * @return {Promise} 71755 */ 71756 _main.default.prototype.httpGet = function() { 71757 _main.default._validateParameters('httpGet', arguments); 71758 71759 var args = Array.prototype.slice.call(arguments); 71760 args.splice(1, 0, 'GET'); 71761 return _main.default.prototype.httpDo.apply(this, args); 71762 }; 71763 71764 /** 71765 * Method for executing an HTTP POST request. If data type is not specified, 71766 * p5 will try to guess based on the URL, defaulting to text. This is equivalent to 71767 * calling <code>httpDo(path, 'POST')</code>. 71768 * 71769 * @method httpPost 71770 * @param {String} path name of the file or url to load 71771 * @param {String} [datatype] "json", "jsonp", "xml", or "text". 71772 * If omitted, <a href="#/p5/httpPost">httpPost()</a> will guess. 71773 * @param {Object|Boolean} [data] param data passed sent with request 71774 * @param {function} [callback] function to be executed after 71775 * <a href="#/p5/httpPost">httpPost()</a> completes, data is passed in 71776 * as first argument 71777 * @param {function} [errorCallback] function to be executed if 71778 * there is an error, response is passed 71779 * in as first argument 71780 * @return {Promise} A promise that resolves with the data when the operation 71781 * completes successfully or rejects with the error after 71782 * one occurs. 71783 * 71784 * @example 71785 * <div> 71786 * <code> 71787 * // Examples use jsonplaceholder.typicode.com for a Mock Data API 71788 * 71789 * let url = 'https://jsonplaceholder.typicode.com/posts'; 71790 * let postData = { userId: 1, title: 'p5 Clicked!', body: 'p5.js is very cool.' }; 71791 * 71792 * function setup() { 71793 * createCanvas(100, 100); 71794 * background(200); 71795 * } 71796 * 71797 * function mousePressed() { 71798 * httpPost(url, 'json', postData, function(result) { 71799 * strokeWeight(2); 71800 * text(result.body, mouseX, mouseY); 71801 * }); 71802 * } 71803 * </code> 71804 * </div> 71805 * 71806 * <div><code> 71807 * let url = 'ttps://invalidURL'; // A bad URL that will cause errors 71808 * let postData = { title: 'p5 Clicked!', body: 'p5.js is very cool.' }; 71809 * 71810 * function setup() { 71811 * createCanvas(100, 100); 71812 * background(200); 71813 * } 71814 * 71815 * function mousePressed() { 71816 * httpPost( 71817 * url, 71818 * 'json', 71819 * postData, 71820 * function(result) { 71821 * // ... won't be called 71822 * }, 71823 * function(error) { 71824 * strokeWeight(2); 71825 * text(error.toString(), mouseX, mouseY); 71826 * } 71827 * ); 71828 * } 71829 * </code></div> 71830 */ 71831 /** 71832 * @method httpPost 71833 * @param {String} path 71834 * @param {Object|Boolean} data 71835 * @param {function} [callback] 71836 * @param {function} [errorCallback] 71837 * @return {Promise} 71838 */ 71839 /** 71840 * @method httpPost 71841 * @param {String} path 71842 * @param {function} callback 71843 * @param {function} [errorCallback] 71844 * @return {Promise} 71845 */ 71846 _main.default.prototype.httpPost = function() { 71847 _main.default._validateParameters('httpPost', arguments); 71848 71849 var args = Array.prototype.slice.call(arguments); 71850 args.splice(1, 0, 'POST'); 71851 return _main.default.prototype.httpDo.apply(this, args); 71852 }; 71853 71854 /** 71855 * Method for executing an HTTP request. If data type is not specified, 71856 * p5 will try to guess based on the URL, defaulting to text.<br><br> 71857 * For more advanced use, you may also pass in the path as the first argument 71858 * and a object as the second argument, the signature follows the one specified 71859 * in the Fetch API specification. 71860 * This method is suitable for fetching files up to size of 64MB when "GET" is used. 71861 * 71862 * @method httpDo 71863 * @param {String} path name of the file or url to load 71864 * @param {String} [method] either "GET", "POST", or "PUT", 71865 * defaults to "GET" 71866 * @param {String} [datatype] "json", "jsonp", "xml", or "text" 71867 * @param {Object} [data] param data passed sent with request 71868 * @param {function} [callback] function to be executed after 71869 * <a href="#/p5/httpGet">httpGet()</a> completes, data is passed in 71870 * as first argument 71871 * @param {function} [errorCallback] function to be executed if 71872 * there is an error, response is passed 71873 * in as first argument 71874 * @return {Promise} A promise that resolves with the data when the operation 71875 * completes successfully or rejects with the error after 71876 * one occurs. 71877 * 71878 * @example 71879 * <div> 71880 * <code> 71881 * // Examples use USGS Earthquake API: 71882 * // https://earthquake.usgs.gov/fdsnws/event/1/#methods 71883 * 71884 * // displays an animation of all USGS earthquakes 71885 * let earthquakes; 71886 * let eqFeatureIndex = 0; 71887 * 71888 * function preload() { 71889 * let url = 'https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson'; 71890 * httpDo( 71891 * url, 71892 * { 71893 * method: 'GET', 71894 * // Other Request options, like special headers for apis 71895 * headers: { authorization: 'Bearer secretKey' } 71896 * }, 71897 * function(res) { 71898 * earthquakes = res; 71899 * } 71900 * ); 71901 * } 71902 * 71903 * function draw() { 71904 * // wait until the data is loaded 71905 * if (!earthquakes || !earthquakes.features[eqFeatureIndex]) { 71906 * return; 71907 * } 71908 * clear(); 71909 * 71910 * let feature = earthquakes.features[eqFeatureIndex]; 71911 * let mag = feature.properties.mag; 71912 * let rad = mag / 11 * ((width + height) / 2); 71913 * fill(255, 0, 0, 100); 71914 * ellipse(width / 2 + random(-2, 2), height / 2 + random(-2, 2), rad, rad); 71915 * 71916 * if (eqFeatureIndex >= earthquakes.features.length) { 71917 * eqFeatureIndex = 0; 71918 * } else { 71919 * eqFeatureIndex += 1; 71920 * } 71921 * } 71922 * </code> 71923 * </div> 71924 */ 71925 /** 71926 * @method httpDo 71927 * @param {String} path 71928 * @param {Object} options Request object options as documented in the 71929 * "fetch" API 71930 * <a href="https://developer.mozilla.org/en/docs/Web/API/Fetch_API">reference</a> 71931 * @param {function} [callback] 71932 * @param {function} [errorCallback] 71933 * @return {Promise} 71934 */ 71935 _main.default.prototype.httpDo = function() { 71936 var type; 71937 var callback; 71938 var errorCallback; 71939 var request; 71940 var promise; 71941 var jsonpOptions = {}; 71942 var cbCount = 0; 71943 var contentType = 'text/plain'; 71944 // Trim the callbacks off the end to get an idea of how many arguments are passed 71945 for (var i = arguments.length - 1; i > 0; i--) { 71946 if ( 71947 typeof (i < 0 || arguments.length <= i ? undefined : arguments[i]) === 71948 'function' 71949 ) { 71950 cbCount++; 71951 } else { 71952 break; 71953 } 71954 } 71955 // The number of arguments minus callbacks 71956 var argsCount = arguments.length - cbCount; 71957 var path = arguments.length <= 0 ? undefined : arguments[0]; 71958 if ( 71959 argsCount === 2 && 71960 typeof path === 'string' && 71961 _typeof(arguments.length <= 1 ? undefined : arguments[1]) === 'object' 71962 ) { 71963 // Intended for more advanced use, pass in Request parameters directly
71964 request = new Request(path, arguments.length <= 1 ? undefined : arguments[1]); 71965 callback = arguments.length <= 2 ? undefined : arguments[2]; 71966 errorCallback = arguments.length <= 3 ? undefined : arguments[3]; 71967 } else { 71968 // Provided with arguments 71969 var method = 'GET'; 71970 var data; 71971 71972 for (var j = 1; j < arguments.length; j++) { 71973 var a = j < 0 || arguments.length <= j ? undefined : arguments[j]; 71974 if (typeof a === 'string') { 71975 if (a === 'GET' || a === 'POST' || a === 'PUT' || a === 'DELETE') { 71976 method = a; 71977 } else if ( 71978 a === 'json' || 71979 a === 'jsonp' || 71980 a === 'binary' || 71981 a === 'arrayBuffer' || 71982 a === 'xml' || 71983 a === 'text' || 71984 a === 'table' 71985 ) { 71986 type = a; 71987 } else { 71988 data = a; 71989 } 71990 } else if (typeof a === 'number') { 71991 data = a.toString(); 71992 } else if (_typeof(a) === 'object') { 71993 if ( 71994 a.hasOwnProperty('jsonpCallback') || 71995 a.hasOwnProperty('jsonpCallbackFunction') 71996 ) { 71997 for (var attr in a) { 71998 jsonpOptions[attr] = a[attr]; 71999 } 72000 } else if (a instanceof _main.default.XML) { 72001 data = a.serialize(); 72002 contentType = 'application/xml'; 72003 } else { 72004 data = JSON.stringify(a); 72005 contentType = 'application/json'; 72006 } 72007 } else if (typeof a === 'function') { 72008 if (!callback) { 72009 callback = a; 72010 } else { 72011 errorCallback = a; 72012 } 72013 } 72014 } 72015 72016 var headers = 72017 method === 'GET' 72018 ? new Headers() 72019 : new Headers({ 'Content-Type': contentType }); 72020 72021 request = new Request(path, { 72022 method: method, 72023 mode: 'cors', 72024 body: data, 72025 headers: headers 72026 }); 72027 } 72028 // do some sort of smart type checking 72029 if (!type) { 72030 if (path.includes('json')) { 72031 type = 'json'; 72032 } else if (path.includes('xml')) { 72033 type = 'xml'; 72034 } else { 72035 type = 'text'; 72036 } 72037 } 72038 72039 if (type === 'jsonp') { 72040 promise = (0, _fetchJsonp.default)(path, jsonpOptions); 72041 } else { 72042 promise = fetch(request); 72043 } 72044 promise = promise.then(function(res) { 72045 if (!res.ok) { 72046 var err = new Error(res.body); 72047 err.status = res.status; 72048 err.ok = false; 72049 throw err; 72050 } else { 72051 var fileSize = 0; 72052 if (type !== 'jsonp') { 72053 fileSize = res.headers.get('content-length'); 72054 } 72055 if (fileSize && fileSize > 64000000) { 72056 _main.default._friendlyFileLoadError(7, path); 72057 } 72058 switch (type) { 72059 case 'json': 72060 case 'jsonp': 72061 return res.json(); 72062 case 'binary': 72063 return res.blob(); 72064 case 'arrayBuffer': 72065 return res.arrayBuffer(); 72066 case 'xml': 72067 return res.text().then(function(text) { 72068 var parser = new DOMParser(); 72069 var xml = parser.parseFromString(text, 'text/xml'); 72070 return new _main.default.XML(xml.documentElement); 72071 }); 72072 default: 72073 return res.text(); 72074 } 72075 } 72076 }); 72077 promise.then(callback || function() {}); 72078 promise.catch(errorCallback || console.error); 72079 return promise; 72080 }; 72081 72082 /** 72083 * @module IO 72084 * @submodule Output 72085 * @for p5 72086 */ 72087 72088 window.URL = window.URL || window.webkitURL; 72089 72090 // private array of p5.PrintWriter objects 72091 _main.default.prototype._pWriters = []; 72092 72093 /** 72094 * @method createWriter 72095 * @param {String} name name of the file to be created 72096 * @param {String} [extension] 72097 * @return {p5.PrintWriter} 72098 * @example 72099 * <div> 72100 * <code> 72101 * function setup() { 72102 * createCanvas(100, 100); 72103 * background(200); 72104 * text('click here to save', 10, 10, 70, 80); 72105 * } 72106 * 72107 * function mousePressed() { 72108 * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) { 72109 * const writer = createWriter('squares.txt'); 72110 * for (let i = 0; i < 10; i++) { 72111 * writer.print(i * i); 72112 * } 72113 * writer.close(); 72114 * writer.clear(); 72115 * } 72116 * } 72117 * </code> 72118 * </div> 72119 */ 72120 _main.default.prototype.createWriter = function(name, extension) { 72121 var newPW; 72122 // check that it doesn't already exist 72123 for (var i in _main.default.prototype._pWriters) { 72124 if (_main.default.prototype._pWriters[i].name === name) { 72125 // if a p5.PrintWriter w/ this name already exists... 72126 // return p5.prototype._pWriters[i]; // return it w/ contents intact. 72127 // or, could return a new, empty one with a unique name: 72128 newPW = new _main.default.PrintWriter(name + this.millis(), extension); 72129 _main.default.prototype._pWriters.push(newPW); 72130 return newPW; 72131 } 72132 } 72133 newPW = new _main.default.PrintWriter(name, extension); 72134 _main.default.prototype._pWriters.push(newPW); 72135 return newPW; 72136 }; 72137 72138 /** 72139 * @class p5.PrintWriter 72140 * @param {String} filename 72141 * @param {String} [extension] 72142 */ 72143 _main.default.PrintWriter = function(filename, extension) { 72144 var self = this; 72145 this.name = filename; 72146 this.content = ''; 72147 //Changed to write because it was being overloaded by function below. 72148 /** 72149 * Writes data to the PrintWriter stream 72150 * @method write 72151 * @param {Array} data all data to be written by the PrintWriter 72152 * @example 72153 * <div class="norender notest"> 72154 * <code> 72155 * // creates a file called 'newFile.txt' 72156 * let writer = createWriter('newFile.txt'); 72157 * // write 'Hello world!'' to the file 72158 * writer.write(['Hello world!']); 72159 * // close the PrintWriter and save the file 72160 * writer.close(); 72161 * </code> 72162 * </div> 72163 * <div class='norender notest'> 72164 * <code> 72165 * // creates a file called 'newFile2.txt' 72166 * let writer = createWriter('newFile2.txt'); 72167 * // write 'apples,bananas,123' to the file 72168 * writer.write(['apples', 'bananas', 123]); 72169 * // close the PrintWriter and save the file 72170 * writer.close(); 72171 * </code> 72172 * </div> 72173 * <div class='norender notest'> 72174 * <code> 72175 * // creates a file called 'newFile3.txt' 72176 * let writer = createWriter('newFile3.txt'); 72177 * // write 'My name is: Teddy' to the file 72178 * writer.write('My name is:'); 72179 * writer.write(' Teddy'); 72180 * // close the PrintWriter and save the file 72181 * writer.close(); 72182 * </code> 72183 * </div> 72184 * <div> 72185 * <code> 72186 * function setup() { 72187 * createCanvas(100, 100); 72188 * button = createButton('SAVE FILE'); 72189 * button.position(21, 40); 72190 * button.mousePressed(createFile); 72191 * } 72192 * 72193 * function createFile() { 72194 * // creates a file called 'newFile.txt' 72195 * let writer = createWriter('newFile.txt'); 72196 * // write 'Hello world!'' to the file 72197 * writer.write(['Hello world!']); 72198 * // close the PrintWriter and save the file 72199 * writer.close(); 72200 * } 72201 * </code> 72202 * </div> 72203 */ 72204 this.write = function(data) { 72205 this.content += data; 72206 }; 72207 /** 72208 * Writes data to the PrintWriter stream, and adds a new line at the end 72209 * @method print 72210 * @param {Array} data all data to be printed by the PrintWriter 72211 * @example 72212 * <div class='norender notest'> 72213 * <code> 72214 * // creates a file called 'newFile.txt' 72215 * let writer = createWriter('newFile.txt'); 72216 * // creates a file containing 72217 * // My name is: 72218 * // Teddy 72219 * writer.print('My name is:'); 72220 * writer.print('Teddy'); 72221 * // close the PrintWriter and save the file 72222 * writer.close(); 72223 * </code> 72224 * </div> 72225 * <div class='norender notest'> 72226 * <code> 72227 * let writer; 72228 * 72229 * function setup() { 72230 * createCanvas(400, 400); 72231 * // create a PrintWriter 72232 * writer = createWriter('newFile.txt'); 72233 * } 72234 * 72235 * function draw() { 72236 * writer.print([mouseX, mouseY]); 72237 * } 72238 * 72239 * function mouseClicked() { 72240 * writer.close(); 72241 * } 72242 * </code> 72243 * </div> 72244 */ 72245 this.print = function(data) { 72246 this.content += ''.concat(data, '\n'); 72247 }; 72248 /** 72249 * Clears the data already written to the PrintWriter object 72250 * @method clear 72251 * @example 72252 * <div class ="norender notest"><code> 72253 * // create writer object 72254 * let writer = createWriter('newFile.txt'); 72255 * writer.write(['clear me']); 72256 * // clear writer object here 72257 * writer.clear(); 72258 * // close writer 72259 * writer.close(); 72260 * </code></div> 72261 * <div> 72262 * <code> 72263 * function setup() { 72264 * button = createButton('CLEAR ME'); 72265 * button.position(21, 40); 72266 * button.mousePressed(createFile); 72267 * } 72268 * 72269 * function createFile() { 72270 * let writer = createWriter('newFile.txt'); 72271 * writer.write(['clear me']); 72272 * writer.clear(); 72273 * writer.close(); 72274 * } 72275 * </code> 72276 * </div> 72277 * 72278 */ 72279 this.clear = function() { 72280 this.content = ''; 72281 }; 72282 /** 72283 * Closes the PrintWriter 72284 * @method close 72285 * @example 72286 * <div class="norender notest"> 72287 * <code> 72288 * // create a file called 'newFile.txt' 72289 * let writer = createWriter('newFile.txt'); 72290 * // close the PrintWriter and save the file 72291 * writer.close(); 72292 * </code> 72293 * </div> 72294 * <div class='norender notest'> 72295 * <code> 72296 * // create a file called 'newFile2.txt' 72297 * let writer = createWriter('newFile2.txt'); 72298 * // write some data to the file 72299 * writer.write([100, 101, 102]); 72300 * // close the PrintWriter and save the file 72301 * writer.close(); 72302 * </code> 72303 * </div> 72304 */ 72305 this.close = function() { 72306 // convert String to Array for the writeFile Blob 72307 var arr = []; 72308 arr.push(this.content); 72309 _main.default.prototype.writeFile(arr, filename, extension); 72310 // remove from _pWriters array and delete self 72311 for (var i in _main.default.prototype._pWriters) { 72312 if (_main.default.prototype._pWriters[i].name === this.name) { 72313 // remove from _pWriters array 72314 _main.default.prototype._pWriters.splice(i, 1); 72315 } 72316 } 72317 self.clear(); 72318 self = {}; 72319 }; 72320 }; 72321 72322 /** 72323 * @module IO 72324 * @submodule Output 72325 * @for p5 72326 */ 72327 72328 // object, filename, options --> saveJSON, saveStrings, 72329 // filename, [extension] [canvas] --> saveImage 72330 72331 /** 72332 * Saves a given element(image, text, json, csv, wav, or html) to the client's 72333 * computer. The first parameter can be a pointer to element we want to save. 72334 * The element can be one of <a href="#/p5.Element">p5.Element</a>,an Array of 72335 * Strings, an Array of JSON, a JSON object, a <a href="#/p5.Table">p5.Table 72336 * </a>, a <a href="#/p5.Image">p5.Image</a>, or a p5.SoundFile (requires 72337 * p5.sound). The second parameter is a filename (including extension).The 72338 * third parameter is for options specific to this type of object. This method 72339 * will save a file that fits the given parameters. 72340 * If it is called without specifying an element, by default it will save the 72341 * whole canvas as an image file. You can optionally specify a filename as 72342 * the first parameter in such a case. 72343 * **Note that it is not recommended to 72344 * call this method within draw, as it will open a new save dialog on every 72345 * render.** 72346 * 72347 * @method save 72348 * @param {Object|String} [objectOrFilename] If filename is provided, will 72349 * save canvas as an image with 72350 * either png or jpg extension 72351 * depending on the filename. 72352 * If object is provided, will 72353 * save depending on the object 72354 * and filename (see examples 72355 * above). 72356 * @param {String} [filename] If an object is provided as the first 72357 * parameter, then the second parameter 72358 * indicates the filename, 72359 * and should include an appropriate 72360 * file extension (see examples above). 72361 * @param {Boolean|String} [options] Additional options depend on 72362 * filetype. For example, when saving JSON, 72363 * <code>true</code> indicates that the 72364 * output will be optimized for filesize, 72365 * rather than readability. 72366 * 72367 * @example 72368 * <div class="norender"><code> 72369 * // Saves the canvas as an image 72370 * cnv = createCanvas(300, 300); 72371 * save(cnv, 'myCanvas.jpg'); 72372 * 72373 * // Saves the canvas as an image by default 72374 * save('myCanvas.jpg'); 72375 * </code></div> 72376 * 72377 * <div class="norender"><code> 72378 * // Saves p5.Image as an image 72379
72379* img = createImage(10, 10); 72380 * save(img, 'myImage.png'); 72381 * </code></div> 72382 * 72383 * <div class="norender"><code> 72384 * // Saves p5.Renderer object as an image 72385 * obj = createGraphics(100, 100); 72386 * save(obj, 'myObject.png'); 72387 * </code></div> 72388 * 72389 * <div class="norender"><code> 72390 * let myTable = new p5.Table(); 72391 * // Saves table as html file 72392 * save(myTable, 'myTable.html'); 72393 * 72394 * // Comma Separated Values 72395 * save(myTable, 'myTable.csv'); 72396 * 72397 * // Tab Separated Values 72398 * save(myTable, 'myTable.tsv'); 72399 * </code></div> 72400 * 72401 * <div class="norender"><code> 72402 * let myJSON = { a: 1, b: true }; 72403 * 72404 * // Saves pretty JSON 72405 * save(myJSON, 'my.json'); 72406 * 72407 * // Optimizes JSON filesize 72408 * save(myJSON, 'my.json', true); 72409 * </code></div> 72410 * 72411 * <div class="norender"><code> 72412 * // Saves array of strings to text file with line breaks after each item 72413 * let arrayOfStrings = ['a', 'b']; 72414 * save(arrayOfStrings, 'my.txt'); 72415 * </code></div> 72416 * 72417 * @alt 72418 * An example for saving a canvas as an image. 72419 * An example for saving a p5.Image element as an image. 72420 * An example for saving a p5.Renderer element. 72421 * An example showing how to save a table in formats of HTML, CSV and TSV. 72422 * An example for saving JSON to a txt file with some extra arguments. 72423 * An example for saving an array of strings to text file with line breaks. 72424 */ 72425 72426 _main.default.prototype.save = function(object, _filename, _options) { 72427 // parse the arguments and figure out which things we are saving 72428 var args = arguments; 72429 // ================================================= 72430 // OPTION 1: saveCanvas... 72431 72432 // if no arguments are provided, save canvas 72433 var cnv = this._curElement ? this._curElement.elt : this.elt; 72434 if (args.length === 0) { 72435 _main.default.prototype.saveCanvas(cnv); 72436 return; 72437 } else if ( 72438 args[0] instanceof _main.default.Renderer || 72439 args[0] instanceof _main.default.Graphics 72440 ) { 72441 // otherwise, parse the arguments 72442 72443 // if first param is a p5Graphics, then saveCanvas 72444 _main.default.prototype.saveCanvas(args[0].elt, args[1], args[2]); 72445 return; 72446 } else if (args.length === 1 && typeof args[0] === 'string') { 72447 // if 1st param is String and only one arg, assume it is canvas filename 72448 _main.default.prototype.saveCanvas(cnv, args[0]); 72449 } else { 72450 // ================================================= 72451 // OPTION 2: extension clarifies saveStrings vs. saveJSON 72452 var extension = _checkFileExtension(args[1], args[2])[1]; 72453 switch (extension) { 72454 case 'json': 72455 _main.default.prototype.saveJSON(args[0], args[1], args[2]); 72456 return; 72457 case 'txt': 72458 _main.default.prototype.saveStrings(args[0], args[1], args[2]); 72459 return; 72460 // ================================================= 72461 // OPTION 3: decide based on object... 72462 default: 72463 if (args[0] instanceof Array) { 72464 _main.default.prototype.saveStrings(args[0], args[1], args[2]); 72465 } else if (args[0] instanceof _main.default.Table) { 72466 _main.default.prototype.saveTable(args[0], args[1], args[2]); 72467 } else if (args[0] instanceof _main.default.Image) { 72468 _main.default.prototype.saveCanvas(args[0].canvas, args[1]); 72469 } else if (args[0] instanceof _main.default.SoundFile) { 72470 _main.default.prototype.saveSound(args[0], args[1], args[2], args[3]); 72471 } 72472 } 72473 } 72474 }; 72475 72476 /** 72477 * Writes the contents of an Array or a JSON object to a .json file. 72478 * The file saving process and location of the saved file will 72479 * vary between web browsers. 72480 * 72481 * @method saveJSON 72482 * @param {Array|Object} json 72483 * @param {String} filename 72484 * @param {Boolean} [optimize] If true, removes line breaks 72485 * and spaces from the output 72486 * file to optimize filesize 72487 * (but not readability). 72488 * @example 72489 * <div><code> 72490 * let json = {}; // new JSON Object 72491 * 72492 * json.id = 0; 72493 * json.species = 'Panthera leo'; 72494 * json.name = 'Lion'; 72495 * 72496 * function setup() { 72497 * createCanvas(100, 100); 72498 * background(200); 72499 * text('click here to save', 10, 10, 70, 80); 72500 * } 72501 * 72502 * function mousePressed() { 72503 * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) { 72504 * saveJSON(json, 'lion.json'); 72505 * } 72506 * } 72507 * 72508 * // saves the following to a file called "lion.json": 72509 * // { 72510 * // "id": 0, 72511 * // "species": "Panthera leo", 72512 * // "name": "Lion" 72513 * // } 72514 * </code></div> 72515 * 72516 * @alt 72517 * no image displayed 72518 */ 72519 _main.default.prototype.saveJSON = function(json, filename, opt) { 72520 _main.default._validateParameters('saveJSON', arguments); 72521 var stringify; 72522 if (opt) {
72523 stringify = JSON.stringify(json); 72524 } else { 72525 stringify = JSON.stringify(json, undefined, 2); 72526 } 72527 this.saveStrings(stringify.split('\n'), filename, 'json'); 72528 }; 72529 72530 _main.default.prototype.saveJSONObject = _main.default.prototype.saveJSON; 72531 _main.default.prototype.saveJSONArray = _main.default.prototype.saveJSON; 72532 72533 /** 72534 * Writes an array of Strings to a text file, one line per String. 72535 * The file saving process and location of the saved file will 72536 * vary between web browsers. 72537 * 72538 * @method saveStrings 72539 * @param {String[]} list string array to be written 72540 * @param {String} filename filename for output 72541 * @param {String} [extension] the filename's extension 72542 * @param {Boolean} [isCRLF] if true, change line-break to CRLF 72543 * @example 72544 * <div><code> 72545 * let words = 'apple bear cat dog'; 72546 * 72547 * // .split() outputs an Array 72548 * let list = split(words, ' '); 72549 * 72550 * function setup() { 72551 * createCanvas(100, 100); 72552 * background(200); 72553 * text('click here to save', 10, 10, 70, 80); 72554 * } 72555 * 72556 * function mousePressed() { 72557 * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) { 72558 * saveStrings(list, 'nouns.txt'); 72559 * } 72560 * } 72561 * 72562 * // Saves the following to a file called 'nouns.txt': 72563 * // 72564 * // apple 72565 * // bear 72566 * // cat 72567 * // dog 72568 * </code></div> 72569 * 72570 * @alt 72571 * no image displayed 72572 */ 72573 _main.default.prototype.saveStrings = function( 72574 list, 72575 filename, 72576 extension, 72577 isCRLF 72578 ) { 72579 _main.default._validateParameters('saveStrings', arguments); 72580 var ext = extension || 'txt'; 72581 var pWriter = this.createWriter(filename, ext); 72582 for (var i = 0; i < list.length; i++) { 72583 isCRLF ? pWriter.write(list[i] + '\r\n') : pWriter.write(list[i] + '\n'); 72584 } 72585 pWriter.close(); 72586 pWriter.clear(); 72587 }; 72588 72589 // ======= 72590 // HELPERS 72591 // ======= 72592 72593 function escapeHelper(content) { 72594 return content 72595 .replace(/&/g, '&') 72596 .replace(/</g, '<') 72597 .replace(/>/g, '>') 72598 .replace(/"/g, '"') 72599 .replace(/'/g, '''); 72600 } 72601 72602 /** 72603 * Writes the contents of a <a href="#/p5.Table">Table</a> object to a file. Defaults to a 72604 * text file with comma-separated-values ('csv') but can also 72605 * use tab separation ('tsv'), or generate an HTML table ('html'). 72606 * The file saving process and location of the saved file will 72607 * vary between web browsers. 72608 * 72609 * @method saveTable 72610 * @param {p5.Table} Table the <a href="#/p5.Table">Table</a> object to save to a file 72611 * @param {String} filename the filename to which the Table should be saved 72612 * @param {String} [options] can be one of "tsv", "csv", or "html" 72613 * @example 72614 * <div><code> 72615 * let table; 72616 * 72617 * function setup() { 72618 * table = new p5.Table(); 72619 * 72620 * table.addColumn('id'); 72621 * table.addColumn('species'); 72622 * table.addColumn('name'); 72623 * 72624 * let newRow = table.addRow(); 72625 * newRow.setNum('id', table.getRowCount() - 1); 72626 * newRow.setString('species', 'Panthera leo'); 72627 * newRow.setString('name', 'Lion'); 72628 * 72629 * // To save, un-comment next line then click 'run' 72630 * // saveTable(table, 'new.csv'); 72631 * } 72632 * 72633 * // Saves the following to a file called 'new.csv': 72634 * // id,species,name 72635 * // 0,Panthera leo,Lion 72636 * </code></div> 72637 * 72638 * @alt 72639 * no image displayed 72640 */ 72641 _main.default.prototype.saveTable = function(table, filename, options) { 72642 _main.default._validateParameters('saveTable', arguments); 72643 var ext; 72644 if (options === undefined) { 72645 ext = filename.substring(filename.lastIndexOf('.') + 1, filename.length); 72646 } else { 72647 ext = options; 72648 } 72649 var pWriter = this.createWriter(filename, ext); 72650 72651 var header = table.columns; 72652 72653 var sep = ','; // default to CSV 72654 if (ext === 'tsv') { 72655 sep = '\t'; 72656 } 72657 if (ext !== 'html') { 72658 // make header if it has values 72659 if (header[0] !== '0') { 72660 for (var h = 0; h < header.length; h++) { 72661 if (h < header.length - 1) { 72662 pWriter.write(header[h] + sep); 72663 } else { 72664 pWriter.write(header[h]); 72665 } 72666 } 72667 pWriter.write('\n'); 72668 } 72669 72670 // make rows 72671 for (var i = 0; i < table.rows.length; i++) { 72672 var j = void 0; 72673 for (j = 0; j < table.rows[i].arr.length; j++) { 72674 if (j < table.rows[i].arr.length - 1) { 72675 //double quotes should be inserted in csv only if c
72675ontains comma separated single value 72676 if (ext === 'csv' && table.rows[i].arr[j].includes(',')) { 72677 pWriter.write('"' + table.rows[i].arr[j] + '"' + sep); 72678 } else { 72679 pWriter.write(table.rows[i].arr[j] + sep); 72680 } 72681 } else { 72682 //double quotes should be inserted in csv only if contains comma separated single value 72683 if (ext === 'csv' && table.rows[i].arr[j].includes(',')) { 72684 pWriter.write('"' + table.rows[i].arr[j] + '"'); 72685 } else { 72686 pWriter.write(table.rows[i].arr[j]); 72687 } 72688 } 72689 } 72690 pWriter.write('\n'); 72691 } 72692 } else { 72693 // otherwise, make HTML 72694 pWriter.print('<html>'); 72695 pWriter.print('<head>'); 72696 var str = ' <meta http-equiv="content-type" content'; 72697 str += '="text/html;charset=utf-8" />'; 72698 pWriter.print(str); 72699 pWriter.print('</head>'); 72700 72701 pWriter.print('<body>'); 72702 pWriter.print(' <table>'); 72703 72704 // make header if it has values 72705 if (header[0] !== '0') { 72706 pWriter.print(' <tr>'); 72707 for (var k = 0; k < header.length; k++) { 72708 var e = escapeHelper(header[k]); 72709 pWriter.print(' <td>'.concat(e)); 72710 pWriter.print(' </td>'); 72711 } 72712 pWriter.print(' </tr>'); 72713 } 72714 72715 // make rows 72716 for (var row = 0; row < table.rows.length; row++) { 72717 pWriter.print(' <tr>'); 72718 for (var col = 0; col < table.columns.length; col++) { 72719 var entry = table.rows[row].getString(col); 72720 var htmlEntry = escapeHelper(entry); 72721 pWriter.print(' <td>'.concat(htmlEntry)); 72722 pWriter.print(' </td>'); 72723 } 72724 pWriter.print(' </tr>'); 72725 } 72726 pWriter.print(' </table>'); 72727 pWriter.print('</body>'); 72728 pWriter.print('</html>'); 72729 } 72730 // close and clear the pWriter 72731 pWriter.close(); 72732 pWriter.clear(); 72733 }; // end saveTable() 72734 72735 /** 72736 * Generate a blob of file data as a url to prepare for download. 72737 * Accepts an array of data, a filename, and an extension (optional). 72738 * This is a private function because it does not do any formatting, 72739 * but it is used by <a href="#/p5/saveStrings">
72739saveStrings</a>, <a href="#/p5/saveJSON">saveJSON</a>, <a href="#/p5/saveTable">saveTable</a> etc. 72740 * 72741 * @param {Array} dataToDownload 72742 * @param {String} filename 72743 * @param {String} [extension] 72744 * @private 72745 */ 72746 _main.default.prototype.writeFile = function( 72747 dataToDownload, 72748 filename, 72749 extension 72750 ) { 72751 var type = 'application/octet-stream'; 72752 if (_main.default.prototype._isSafari()) { 72753 type = 'text/plain'; 72754 } 72755 var blob = new Blob(dataToDownload, { 72756 type: type 72757 }); 72758 72759 _main.default.prototype.downloadFile(blob, filename, extension); 72760 }; 72761 72762 /** 72763 * Forces download. Accepts a url to filedata/blob, a filename, 72764 * and an extension (optional). 72765 * This is a private function because it does not do any formatting, 72766 * but it is used by <a href="#/p5/saveStrings">saveStrings</a>, <a href="#/p5/saveJSON">saveJSON</a>, <a href="#/p5/saveTable">saveTable</a> etc. 72767 * 72768 * @method downloadFile 72769 * @private 72770 * @param {String|Blob} data either an href generated by createObjectURL, 72771 * or a Blob object containing the data 72772 * @param {String} [filename] 72773 * @param {String} [extension] 72774 */ 72775 _main.default.prototype.downloadFile = function(data, fName, extension) { 72776 var fx = _checkFileExtension(fName, extension); 72777 var filename = fx[0]; 72778 72779 if (data instanceof Blob) { 72780 _fileSaver.default.saveAs(data, filename); 72781 return; 72782 } 72783 72784 var a = document.createElement('a'); 72785 a.href = data; 72786 a.download = filename; 72787 72788 // Firefox requires the link to be added to the DOM before click() 72789 a.onclick = function(e) { 72790 destroyClickedElement(e); 72791 e.stopPropagation(); 72792 }; 72793 72794 a.style.display = 'none'; 72795 document.body.appendChild(a); 72796 72797 // Safari will open this file in the same page as a confusing Blob. 72798 if (_main.default.prototype._isSafari()) { 72799 var aText = 'Hello, Safari user! To download this file...\n'; 72800 aText += '1. Go to File --> Save As.\n'; 72801 aText += '2. Choose "Page Source" as the Format.\n'; 72802 aText += '3. Name it with this extension: ."'.concat(fx[1], '"'); 72803 alert(aText); 72804 } 72805 a.click(); 72806 }; 72807 72808 /** 72809 * Returns a file extension, or another string 72810 * if the provided parameter has no extension. 72811 * 72812 * @param {String} filename 72813 * @param {String} [extension] 72814 * @return {String[]} [fileName, fileExtension] 72815 * 72816 * @private 72817 */ 72818 function _checkFileExtension(filename, extension) { 72819 if (!extension || extension === true || extension === 'true') { 72820 extension = ''; 72821 } 72822 if (!filename) { 72823 filename = 'untitled'; 72824 } 72825 var ext = ''; 72826 // make sure the file will have a name, see if filename needs extension 72827 if (filename && filename.includes('.')) { 72828 ext = filename.split('.').pop(); 72829 } 72830 // append extension if it doesn't exist 72831 if (extension) { 72832 if (ext !== extension) { 72833 ext = extension; 72834 filename = ''.concat(filename, '.').concat(ext); 72835 } 72836 } 72837 return [filename, ext]; 72838 } 72839 _main.default.prototype._checkFileExtension = _checkFileExtension; 72840 72841 /** 72842 * Returns true if the browser is Safari, false if not. 72843 * Safari makes trouble for downloading files. 72844 * 72845 * @return {Boolean} [description] 72846 * @private 72847 */ 72848 _main.default.prototype._isSafari = function() { 72849 var x = Object.prototype.toString.call(window.HTMLElement); 72850 return x.indexOf('Constructor') > 0; 72851 }; 72852 72853 /** 72854 * Helper function, a callback for download that deletes 72855 * an invisible anchor element from the DOM once the file 72856 * has been automatically downloaded.
72857 * 72858 * @private 72859 */ 72860 function destroyClickedElement(event) { 72861 document.body.removeChild(event.target); 72862 } 72863 var _default = _main.default; 72864 exports.default = _default; 72865 }, 72866 { 72867 '../core/friendly_errors/fes_core': 51, 72868 '../core/friendly_errors/file_errors': 52, 72869 '../core/friendly_errors/validate_params': 54, 72870 '../core/main': 59, 72871 'es6-promise/auto': 23, 72872 'fetch-jsonp': 25, 72873 'file-saver': 26, 72874 'whatwg-fetch': 37 72875 } 72876 ], 72877 86: [ 72878 function(_dereq_, module, exports) { 72879 'use strict'; 72880 Object.defineProperty(exports, '__esModule', { value: true }); 72881 exports.default = void 0; 72882 72883 var _main = _interopRequireDefault(_dereq_('../core/main')); 72884 function _interopRequireDefault(obj) { 72885 return obj && obj.__esModule ? obj : { default: obj }; 72886 } /** 72887 * <a href="#/p5.Table">Table</a> objects store data with multiple rows and columns, much 72888 * like in a traditional spreadsheet. Tables can be generated from 72889 * scratch, dynamically, or using data from an existing file. 72890 * 72891 * @class p5.Table 72892 * @constructor 72893 * @param {p5.TableRow[]} [rows] An array of p5.TableRow objects 72894 */ /** 72895 * @module IO 72896 * @submodule Table 72897 * @requires core 72898 */ /** 72899 * Table Options 72900 * Generic class for handling tabular data, typically from a 72901 * CSV, TSV, or other sort of spreadsheet file. 72902 * CSV files are 72903 * <a href="http://en.wikipedia.org/wiki/Comma-separated_values"> 72904 * comma separated values</a>, often with the data in quotes. TSV 72905 * files use tabs as separators, and usually don't bother with the 72906 * quotes. 72907 * File names should end with .csv if they're comma separated. 72908 * A rough "spec" for CSV can be found 72909 * <a href="http://tools.ietf.org/html/rfc4180">here</a>. 72910 * To load files, use the <a href="#/p5/loadTable">loadTable</a> method. 72911 * To save tables to your computer, use the <a href="#/p5/save">save</a> method 72912 * or the <a href="#/p5/saveTable">saveTable</a> method. 72913 * 72914 * Possible options include: 72915 * <ul> 72916 * <li>csv - parse the table as comma-separated values 72917 * <li>tsv - parse the table as tab-separated values 72918 * <li>header - this table has a header (title) row 72919 * </ul> 72920 */ 72921 _main.default.Table = function(rows) { 72922 /** 72923 * An array containing the names of the columns in the table, if the "header" the table is 72924 * loaded with the "header" parameter. 72925 * @property columns {String[]} 72926 * @example 72927 * <div class="norender"> 72928 * <code> 72929 * // Given the CSV file "mammals.csv" 72930 * // in the project's "assets" folder: 72931 * // 72932 * // id,species,name 72933 * // 0,Capra hircus,Goat 72934 * // 1,Panthera pardus,Leopard 72935 * // 2,Equus zebra,Zebra 72936 * 72937 * let table; 72938 * 72939 * function preload() { 72940 * //my table is comma separated value "csv" 72941 * //and has a header specifying the columns labels 72942 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 72943 * } 72944 * 72945 * function setup() { 72946 * //print the column names 72947 * for (let c = 0; c < table.getColumnCount(); c++) { 72948 * print('column ' + c + ' is named ' + table.columns[c]); 72949 * } 72950 * } 72951 * </code> 72952 * </div> 72953 */ 72954 this.columns = []; 72955 72956 /** 72957 * An array containing the <a href="#/p5.Table">p5.TableRow</a> objects that make up the 72958 * rows of the table. The same result as calling <a href="#/p5/getRows">getRows()</a> 72959 * @property rows {p5.TableRow[]} 72960 */ 72961 this.rows = []; 72962 }; 72963 72964 /** 72965 * 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, 72966 * an empty row is created. Typically, you would store a reference to 72967 * the new row in a TableRow object (see newRow in the example above), 72968 * and then set individual values using <a href="#/p5/set">set()</a>. 72969 * 72970 * If a <a href="#/p5.TableRow">p5.TableRow</a> object is included as a parameter, then that row is 72971 * duplicated and added to the table. 72972 * 72973 * @method addRow 72974 * @param {p5.TableRow} [row] row to be added to the table 72975 * @return {p5.TableRow} the row that was added 72976 * 72977 * @example 72978 * <div class="norender"> 72979 * <code> 72980 * // Given the CSV file "mammals.csv" 72981 * // in the project's "assets" folder: 72982 * // 72983 * // id,species,name 72984 * // 0,Capra hircus,Goat 72985 * // 1,Panthera pardus,Leopard 72986 * // 2,Equus zebra,Zebra 72987 * 72988 * let table; 72989 * 72990 * function preload() { 72991 * //my table is comma separated value "csv" 72992 * //and has a header specifying the columns labels 72993 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 72994 * } 72995 * 72996 * function setup() { 72997 * //add a row 72998 * let newRow = table.addRow(); 72999 * newRow.setString('id', table.getRowCount() - 1); 73000 * newRow.setString('species', 'Canis Lupus'); 73001 * newRow.setString('name', 'Wolf'); 73002 * 73003 * //print the results 73004 * for (let r = 0; r < table.getRowCount(); r++) 73005 * for (let c = 0; c < table.getColumnCount(); c++) 73006 * print(table.getString(r, c)); 73007 * } 73008 * </code> 73009 * </div> 73010 * 73011 * @alt 73012 * no image displayed 73013 */ 73014 _main.default.Table.prototype.addRow = function(row) { 73015 // make sure it is a valid TableRow 73016 var r = row || new _main.default.TableRow(); 73017 73018 if (typeof r.arr === 'undefined' || typeof r.obj === 'undefined') { 73019 //r = new p5.prototype.TableRow(r); 73020 throw new Error('invalid TableRow: '.concat(r)); 73021 } 73022 r.table = this; 73023 this.rows.push(r); 73024 return r; 73025 }; 73026 73027 /** 73028 * Removes a row from the table object. 73029 * 73030 * @method removeRow 73031 * @param {Integer} id ID number of the row to remove 73032 * 73033 * @example 73034 * <div class="norender"> 73035 * <code> 73036 * // Given the CSV file "mammals.csv" 73037 * // in the project's "assets" folder: 73038 * // 73039 * // id,species,name 73040 * // 0,Capra hircus,Goat 73041 * // 1,Panthera pardus,Leopard 73042 * // 2,Equus zebra,Zebra 73043 * 73044 * let table; 73045 * 73046 * function preload() { 73047 * //my table is comma separated value "csv" 73048 * //and has a header specifying the columns labels 73049 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 73050 * } 73051 * 73052 * function setup() { 73053 * //remove the first row 73054 * table.removeRow(0); 73055 * 73056 * //print the results 73057 * for (let r = 0; r < table.getRowCount(); r++) 73058 * for (let c = 0; c < table.getColumnCount(); c++) 73059 * print(table.getString(r, c)); 73060 * } 73061 * </code> 73062 * </div> 73063 * 73064 * @alt 73065 * no image displayed 73066 */ 73067 _main.default.Table.prototype.removeRow = function(id) { 73068 this.rows[id].table = null; // remove reference to table 73069 var chunk = this.rows.splice(id + 1, this.rows.length); 73070 this.rows.pop(); 73071 this.rows = this.rows.concat(chunk); 73072 }; 73073 73074 /** 73075 * Returns a reference to the specified <a href="#/p5.TableRow">p5.TableRow</a>. The reference 73076 * can then be used to get and set values of the selected row. 73077 * 73078 * @method getRow 73079 * @param {Integer} rowID ID number of the row to get 73080 * @return {p5.TableRow} <a href="#/p5.TableRow">p5.TableRow</a> object 73081 * 73082 * @example 73083 * <div class="norender"> 73084 * <code> 73085 * // Given the CSV file "mammals.csv" 73086 * // in the project's "assets" folder: 73087 * // 73088 * // id,species,name 73089 * // 0,Capra hircus,Goat 73090 * // 1,Panthera pardus,Leopard 73091 * // 2,Equus zebra,Zebra 73092 * 73093 * let table; 73094 * 73095 * function preload() { 73096 * //my table is comma separated value "csv" 73097 * //and has a header specifying the columns labels 73098 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 73099 * } 73100 * 73101 * function setup() { 73102 * let row = table.getRow(1); 73103 * //print it column by column 73104 * //note: a row is an object, not an array 73105 * for (let c = 0; c < table.getColumnCount(); c++) { 73106 * print(row.getString(c)); 73107 * } 73108 * } 73109 * </code> 73110 * </div> 73111 * 73112 *@alt 73113 * no image displayed 73114 */ 73115 _main.default.Table.prototype.getRow = function(r) { 73116 return this.rows[r]; 73117 }; 73118 73119 /** 73120 * Gets all rows from the table. Returns an array of <a href="#/p5.TableRow">p5.TableRow</a>s. 73121 * 73122 * @method getRows 73123 * @return {p5.TableRow[]} Array of <a href="#/p5.TableRow">p5.TableRow</a>s 73124 * 73125 * @example 73126 * <div class="norender"> 73127 * <code> 73128 * // Given the CSV file "mammals.csv" 73129 * // in the project's "assets" folder: 73130 * // 73131 * // id,species,name 73132 * // 0,Capra hircus,Goat 73133 * // 1,Panthera pardus,Leopard 73134 * // 2,Equus zebra,Zebra 73135 * 73136 * let table; 73137 * 73138 * function preload() { 73139 * //my table is comma separated value "csv" 73140 * //and has a header specifying the columns labels 73141 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 73142 * } 73143 * 73144 * function setup() { 73145 * let rows = table.getRows(); 73146 * 73147 * //warning: rows is an array of objects 73148 * for (let r = 0; r < rows.length; r++) { 73149 * rows[r].set('name', 'Unicorn'); 73150 * } 73151 * 73152 * //print the results 73153 * for (let r = 0; r < table.getRowCount(); r++) 73154 * for (let c = 0; c < table.getColumnCount(); c++) 73155 * print(table.getString(r, c)); 73156 * } 73157 * </code> 73158 * </div> 73159 * 73160 * @alt 73161 * no image displayed 73162 */ 73163 _main.default.Table.prototype.getRows = function() { 73164 return this.rows; 73165 }; 73166 73167 /** 73168 * Finds the first row in the Table that contains the value 73169 * provided, and returns a reference to that row. Even if 73170 * multiple rows are possible matches, only the first matching 73171 * row is returned. The column to search may be specified by 73172 * either its ID or title. 73173 * 73174 * @method findRow 73175 * @param {String} value The value to match 73176 * @param {Integer|String} column ID number or title of the 73177 * column to search 73178 * @return {p5.TableRow} 73179 * 73180 * @example 73181 * <div class="norender"> 73182 * <code> 73183 * // Given the CSV file "mammals.csv" 73184 * // in the project's "assets" folder: 73185 * // 73186 * // id,species,name 73187 * // 0,Capra hircus,Goat 73188 * // 1,Panthera pardus,Leopard 73189 * // 2,Equus zebra,Zebra 73190 * 73191 * let table; 73192 * 73193 * function preload() { 73194 * //my table is comma separated value "csv" 73195 * //and has a header specifying the columns labels 73196 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 73197 * } 73198 * 73199 * function setup() { 73200 * //find the animal named zebra 73201 * let row = table.findRow('Zebra', 'name'); 73202 * //find the corresponding species 73203 * print(row.getString('species')); 73204 * } 73205 * </code> 73206 * </div> 73207 * 73208 * @alt 73209 * no image displayed 73210 */ 73211 _main.default.Table.prototype.findRow = function(value, column) { 73212 // try the Object 73213 if (typeof column === 'string') { 73214 for (var i = 0; i < this.rows.length; i++) { 73215 if (this.rows[i].obj[column] === value) { 73216 return this.rows[i]; 73217 } 73218 } 73219 } else { 73220 // try the Array 73221 for (var j = 0; j < this.rows.length; j++) { 73222 if (this.rows[j].arr[column] === value) { 73223 return this.rows[j]; 73224 } 73225 } 73226 } 73227 // otherwise... 73228 return null; 73229 }; 73230 73231 /** 73232 * Finds the rows in the Table that contain the value 73233 * provided, and returns references to those rows. Returns an 73234 * Array, so for must be used to iterate through all the rows, 73235 * as shown in the example above. The column to search may be 73236 * specified by either its ID or title. 73237 * 73238 * @method findRows 73239 * @param {String} value The value to match 73240 * @param {Integer|String} column ID number or title of the 73241 * column to search 73242 * @return {p5.TableRow[]} An Array of TableRow objects 73243 * 73244 * @example 73245 * <div class="norender"> 73246 * <code> 73247 * // Given the CSV file "mammals.csv" 73248 * // in the project's "assets" folder: 73249 * // 73250 * // id,species,name 73251 * // 0,Capra hircus,Goat 73252 * // 1,Panthera pardus,Leopard 73253 * // 2,Equus zebra,Zebra 73254 * 73255 * let table; 73256 * 73257 * function preload() { 73258 * //my table is comma separated value "csv" 73259 * //and has a header specifying the columns labels 73260 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 73261 * } 73262 * 73263 * function setup() { 73264 * //add another goat 73265 * let newRow = table.addRow(); 73266 * newRow.setString('id', table.getRowCount() - 1); 73267 * newRow.setString('species', 'Scape Goat'); 73268 * newRow.setString('name', 'Goat'); 73269 * 73270 * //find the rows containing animals named Goat 73271 * let rows = table.findRows('Goat', 'name'); 73272 * print(rows.length + ' Goats found'); 73273 * } 73274 * </code> 73275 * </div> 73276 * 73277 *@alt 73278 * no image displayed 73279 */ 73280 _main.default.Table.prototype.findRows = function(value, column) { 73281 var ret = []; 73282 if (typeof column === 'string') { 73283 for (var i = 0; i < this.rows.length; i++) { 73284 if (this.rows[i].obj[column] === value) {
73285 ret.push(this.rows[i]); 73286 } 73287 } 73288 } else { 73289 // try the Array 73290 for (var j = 0; j < this.rows.length; j++) { 73291 if (this.rows[j].arr[column] === value) { 73292 ret.push(this.rows[j]); 73293 } 73294 } 73295 } 73296 return ret; 73297 }; 73298 73299 /** 73300 * Finds the first row in the Table that matches the regular 73301 * expression provided, and returns a reference to that row. 73302 * Even if multiple rows are possible matches, only the first 73303 * matching row is returned. The column to search may be 73304 * specified by either its ID or title. 73305 * 73306 * @method matchRow 73307 * @param {String|RegExp} regexp The regular expression to match 73308 * @param {String|Integer} column The column ID (number) or 73309 * title (string) 73310 * @return {p5.TableRow} TableRow object 73311 * 73312 * @example 73313 * <div class="norender"> 73314 * <code> 73315 * // Given the CSV file "mammals.csv" 73316 * // in the project's "assets" folder: 73317 * // 73318 * // id,species,name 73319 * // 0,Capra hircus,Goat 73320 * // 1,Panthera pardus,Leopard 73321 * // 2,Equus zebra,Zebra 73322 * 73323 * let table; 73324 * 73325 * function preload() { 73326 * //my table is comma separated value "csv" 73327 * //and has a header specifying the columns labels 73328 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 73329 * } 73330 * 73331 * function setup() { 73332 * //Search using specified regex on a given column, return TableRow object 73333 * let mammal = table.matchRow(new RegExp('ant'), 1); 73334 * print(mammal.getString(1)); 73335 * //Output "Panthera pardus" 73336 * } 73337 * </code> 73338 * </div> 73339 */ 73340 _main.default.Table.prototype.matchRow = function(regexp, column) { 73341 if (typeof column === 'number') { 73342 for (var j = 0; j < this.rows.length; j++) { 73343 if (this.rows[j].arr[column].match(regexp)) { 73344 return this.rows[j]; 73345 } 73346 } 73347 } else { 73348 for (var i = 0; i < this.rows.length; i++) { 73349 if (this.rows[i].obj[column].match(regexp)) { 73350 return this.rows[i]; 73351 } 73352 } 73353 } 73354 return null; 73355 }; 73356 73357 /** 73358 * Finds the rows in the Table that match the regular expression provided, 73359 * and returns references to those rows. Returns an array, so for must be 73360 * used to iterate through all the rows, as shown in the example. The 73361 * column to search may be specified by either its ID or title. 73362 * 73363 * @method matchRows 73364 * @param {String} regexp The regular expression to match 73365 * @param {String|Integer} [column] The column ID (number) or 73366 * title (string) 73367 * @return {p5.TableRow[]} An Array of TableRow objects 73368 * @example 73369 * <div class="norender"> 73370 * <code> 73371 * let table; 73372 * 73373 * function setup() { 73374 * table = new p5.Table(); 73375 * 73376 * table.addColumn('name'); 73377 * table.addColumn('type'); 73378 * 73379 * let newRow = table.addRow(); 73380 * newRow.setString('name', 'Lion'); 73381 * newRow.setString('type', 'Mammal'); 73382 * 73383 * newRow = table.addRow(); 73384 * newRow.setString('name', 'Snake'); 73385 * newRow.setString('type', 'Reptile'); 73386 * 73387 * newRow = table.addRow(); 73388 * newRow.setString('name', 'Mosquito'); 73389 * newRow.setString('type', 'Insect'); 73390 * 73391 * newRow = table.addRow(); 73392 * newRow.setString('name', 'Lizard'); 73393 * newRow.setString('type', 'Reptile'); 73394 * 73395 * let rows = table.matchRows('R.*', 'type'); 73396 * for (let i = 0; i < rows.length; i++) { 73397 * print(rows[i].getString('name') + ': ' + rows[i].getString('type')); 73398 * } 73399 * } 73400 * // Sketch prints: 73401 * // Snake: Reptile 73402 * // Lizard: Reptile 73403 * </code> 73404 * </div> 73405 */ 73406 _main.default.Table.prototype.matchRows = function(regexp, column) { 73407 var ret = []; 73408 if (typeof column === 'number') { 73409 for (var j = 0; j < this.rows.length; j++) { 73410 if (this.rows[j].arr[column].match(regexp)) {
73411 ret.push(this.rows[j]); 73412 } 73413 } 73414 } else { 73415 for (var i = 0; i < this.rows.length; i++) { 73416 if (this.rows[i].obj[column].match(regexp)) { 73417 ret.push(this.rows[i]); 73418 } 73419 } 73420 } 73421 return ret; 73422 }; 73423 73424 /** 73425 * Retrieves all values in the specified column, and returns them 73426 * as an array. The column may be specified by either its ID or title. 73427 * 73428 * @method getColumn 73429 * @param {String|Number} column String or Number of the column to return 73430 * @return {Array} Array of column values 73431 * 73432 * @example 73433 * <div class="norender"> 73434 * <code> 73435 * // Given the CSV file "mammals.csv" 73436 * // in the project's "assets" folder: 73437 * // 73438 * // id,species,name 73439 * // 0,Capra hircus,Goat 73440 * // 1,Panthera pardus,Leopard 73441 * // 2,Equus zebra,Zebra 73442 * 73443 * let table; 73444 * 73445 * function preload() { 73446 * //my table is comma separated value "csv" 73447 * //and has a header specifying the columns labels 73448 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 73449 * } 73450 * 73451 * function setup() { 73452 * //getColumn returns an array that can be printed directly 73453 * print(table.getColumn('species')); 73454 * //outputs ["Capra hircus", "Panthera pardus", "Equus zebra"] 73455 * } 73456 * </code> 73457 * </div> 73458 * 73459 *@alt 73460 * no image displayed 73461 */ 73462 _main.default.Table.prototype.getColumn = function(value) { 73463 var ret = []; 73464 if (typeof value === 'string') { 73465 for (var i = 0; i < this.rows.length; i++) { 73466 ret.push(this.rows[i].obj[value]); 73467 } 73468 } else { 73469 for (var j = 0; j < this.rows.length; j++) { 73470 ret.push(this.rows[j].arr[value]); 73471 } 73472 } 73473 return ret; 73474 }; 73475 73476 /** 73477 * Removes all rows from a Table. While all rows are removed, 73478 * columns and column titles are maintained. 73479 * 73480 * @method clearRows 73481 * 73482 * @example 73483 * <div class="norender"> 73484 * <code> 73485 * // Given the CSV file "mammals.csv" 73486 * // in the project's "assets" folder: 73487 * // 73488 * // id,species,name 73489 * // 0,Capra hircus,Goat 73490 * // 1,Panthera pardus,Leopard 73491 * // 2,Equus zebra,Zebra 73492 * 73493 * let table; 73494 * 73495 * function preload() { 73496 * //my table is comma separated value "csv" 73497 * //and has a header specifying the columns labels 73498 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 73499 * } 73500 * 73501 * function setup() { 73502 * table.clearRows(); 73503 * print(table.getRowCount() + ' total rows in table'); 73504 * print(table.getColumnCount() + ' total columns in table'); 73505 * } 73506 * </code> 73507 * </div> 73508 * 73509 *@alt 73510 * no image displayed 73511 */ 73512 _main.default.Table.prototype.clearRows = function() { 73513 delete this.rows; 73514 this.rows = []; 73515 }; 73516 73517 /** 73518 * Use <a href="#/p5/addColumn">addColumn()</a> to add a new column to a <a href="#/p5.Table">Table</a> object. 73519 * Typically, you will want to specify a title, so the column 73520 * may be easily referenced later by name. (If no title is 73521 * specified, the new column's title will be null.) 73522 * 73523 * @method addColumn 73524 * @param {String} [title] title of the given column 73525 * 73526 * @example 73527 * <div class="norender"> 73528 * <code> 73529 * // Given the CSV file "mammals.csv" 73530 * // in the project's "assets" folder: 73531 * // 73532 * // id,species,name 73533 * // 0,Capra hircus,Goat 73534 * // 1,Panthera pardus,Leopard 73535 * // 2,Equus zebra,Zebra 73536 * 73537 * let table; 73538 * 73539 * function preload() { 73540 * //my table is comma separated value "csv" 73541 * //and has a header specifying the columns labels 73542 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 73543 * } 73544 * 73545 * function setup() { 73546 * table.addColumn('carnivore'); 73547 * table.set(0, 'carnivore', 'no'); 73548 * table.set(1, 'carnivore', 'yes'); 73549 * table.set(2, 'carnivore', 'no'); 73550 * 73551 * //print the results 73552 * for (let r = 0; r < table.getRowCount(); r++) 73553 * for (let c = 0; c < table.getColumnCount(); c++) 73554 * print(table.getString(r, c)); 73555 * } 73556 * </code> 73557 * </div> 73558 * 73559 *@alt 73560 * no image displayed 73561 */ 73562 _main.default.Table.prototype.addColumn = function(title) { 73563 var t = title || null; 73564 this.columns.push(t); 73565 }; 73566 73567 /** 73568 * Returns the total number of columns in a Table. 73569 * 73570 * @method getColumnCount 73571 * @return {Integer} Number of columns in this table 73572 * @example 73573 * <div> 73574 * <code> 73575 * // given the cvs file "blobs.csv" in /assets directory 73576 * // ID, Name, Flavor, Shape, Color 73577 * // Blob1, Blobby, Sweet, Blob, Pink 73578 * // Blob2, Saddy, Savory, Blob, Blue 73579 * 73580 * let table; 73581 * 73582 * function preload() { 73583 * table = loadTable('assets/blobs.csv'); 73584 * } 73585 * 73586 * function setup() { 73587 * createCanvas(200, 100); 73588 * textAlign(CENTER); 73589 * background(255); 73590 * } 73591 * 73592 * function draw() { 73593 * let numOfColumn = table.getColumnCount(); 73594 * text('There are ' + numOfColumn + ' columns in the table.', 100, 50); 73595 * } 73596 * </code> 73597 * </div> 73598 */ 73599 _main.default.Table.prototype.getColumnCount = function() { 73600 return this.columns.length; 73601 }; 73602 73603 /** 73604 * Returns the total number of rows in a Table. 73605 * 73606 * @method getRowCount 73607 * @return {Integer} Number of rows in this table 73608 * @example 73609 * <div> 73610 * <code> 73611 * // given the cvs file "blobs.csv" in /assets directory 73612 * // 73613 * // ID, Name, Flavor, Shape, Color 73614 * // Blob1, Blobby, Sweet, Blob, Pink 73615 * // Blob2, Saddy, Savory, Blob, Blue 73616 * 73617 * let table; 73618 * 73619 * function preload() { 73620 * table = loadTable('assets/blobs.csv'); 73621 * } 73622 * 73623 * function setup() { 73624 * createCanvas(200, 100); 73625 * textAlign(CENTER); 73626 * background(255); 73627 * } 73628 * 73629 * function draw() { 73630 * text('There are ' + table.getRowCount() + ' rows in the table.', 100, 50); 73631 * } 73632 * </code> 73633 * </div> 73634 */ 73635 _main.default.Table.prototype.getRowCount = function() { 73636 return this.rows.length; 73637 }; 73638 73639 /** 73640 * Removes any of the specified characters (or "tokens"). 73641 * 73642 * If no column is specified, then the values in all columns and 73643 * rows are processed. A specific column may be referenced by 73644 * either its ID or title. 73645 * 73646 * @method removeTokens 73647 * @param {String} chars String listing characters to be removed 73648 * @param {String|Integer} [column] Column ID (number) 73649 * or name (string) 73650 * 73651 * @example 73652 * <div class="norender"><code> 73653 * function setup() { 73654 * let table = new p5.Table(); 73655 * 73656 * table.addColumn('name'); 73657 * table.addColumn('type'); 73658 * 73659 * let newRow = table.addRow(); 73660 * newRow.setString('name', ' $Lion ,'); 73661 * newRow.setString('type', ',,,Mammal'); 73662 * 73663 * newRow = table.addRow(); 73664 * newRow.setString('name', '$Snake '); 73665 * newRow.setString('type', ',,,Reptile'); 73666 * 73667 * table.removeTokens(',$ '); 73668 * print(table.getArray()); 73669 * } 73670 * 73671 * // prints: 73672 * // 0 "Lion" "Mamal" 73673 * // 1 "Snake" "Reptile" 73674 * </code></div> 73675 */ 73676 _main.default.Table.prototype.removeTokens = function(ch
73676ars, column) { 73677 var escape = function escape(s) { 73678 return s.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&'); 73679 }; 73680 var charArray = []; 73681 for (var i = 0; i < chars.length; i++) { 73682 charArray.push(escape(chars.charAt(i))); 73683 } 73684 var regex = new RegExp(charArray.join('|'), 'g'); 73685 73686 if (typeof column === 'undefined') { 73687 for (var c = 0; c < this.columns.length; c++) { 73688 for (var d = 0; d < this.rows.length; d++) { 73689 var s = this.rows[d].arr[c]; 73690 s = s.replace(regex, ''); 73691 this.rows[d].arr[c] = s; 73692 this.rows[d].obj[this.columns[c]] = s; 73693 } 73694 } 73695 } else if (typeof column === 'string') { 73696 for (var j = 0; j < this.rows.length; j++) { 73697 var val = this.rows[j].obj[column]; 73698 val = val.replace(regex, ''); 73699 this.rows[j].obj[column] = val; 73700 var pos = this.columns.indexOf(column); 73701 this.rows[j].arr[pos] = val; 73702 } 73703 } else { 73704 for (var k = 0; k < this.rows.length; k++) { 73705 var str = this.rows[k].arr[column]; 73706 str = str.replace(regex, ''); 73707 this.rows[k].arr[column] = str; 73708 this.rows[k].obj[this.columns[column]] = str; 73709 } 73710 } 73711 }; 73712 73713 /** 73714 * Trims leading and trailing whitespace, such as spaces and tabs, 73715 * from String table values. If no column is specified, then the 73716 * values in all columns and rows are trimmed. A specific column 73717 * may be referenced by either its ID or title. 73718 * 73719 * @method trim 73720 * @param {String|Integer} [column] Column ID (number) 73721 * or name (string) 73722 * @example 73723 * <div class="norender"><code> 73724 * function setup() { 73725 * let table = new p5.Table(); 73726 * 73727 * table.addColumn('name'); 73728 * table.addColumn('type'); 73729 * 73730 * let newRow = table.addRow(); 73731 * newRow.setString('name', ' Lion ,'); 73732 * newRow.setString('type', ' Mammal '); 73733 * 73734 * newRow = table.addRow(); 73735 * newRow.setString('name', ' Snake '); 73736 * newRow.setString('type', ' Reptile '); 73737 * 73738 * table.trim(); 73739 * print(table.getArray()); 73740 * } 73741 * 73742 * // prints: 73743 * // 0 "Lion" "Mamal" 73744 * // 1 "Snake" "Reptile" 73745 * </code></div> 73746 */ 73747 _main.default.Table.prototype.trim = function(column) { 73748 var regex = new RegExp(' ', 'g'); 73749 73750 if (typeof column === 'undefined') { 73751 for (var c = 0; c < this.columns.length; c++) { 73752 for (var d = 0; d < this.rows.length; d++) { 73753 var s = this.rows[d].arr[c]; 73754 s = s.replace(regex, ''); 73755 this.rows[d].arr[c] = s; 73756 this.rows[d].obj[this.columns[c]] = s; 73757 } 73758 } 73759 } else if (typeof column === 'string') { 73760 for (var j = 0; j < this.rows.length; j++) { 73761 var val = this.rows[j].obj[column]; 73762 val = val.replace(regex, ''); 73763 this.rows[j].obj[column] = val; 73764 var pos = this.columns.indexOf(column); 73765 this.rows[j].arr[pos] = val; 73766 } 73767 } else { 73768 for (var k = 0; k < this.rows.length; k++) { 73769 var str = this.rows[k].arr[column]; 73770 str = str.replace(regex, ''); 73771 this.rows[k].arr[column] = str; 73772 this.rows[k].obj[this.columns[column]] = str; 73773 } 73774 } 73775 }; 73776 73777 /** 73778 * Use <a href="#/p5/removeColumn">removeColumn()</a> to remove an existing column from a Table 73779 * object. The column to be removed may be identified by either 73780 * its title (a String) or its index value (an int). 73781 * removeColumn(0) would remove the first column, removeColumn(1) 73782 * would remove the second column, and so on. 73783 * 73784 * @method removeColumn 73785 * @param {String|Integer} column columnName (string) or ID (number) 73786 * 73787 * @example 73788 * <div class="norender"> 73789 * <code> 73790 * // Given the CSV file "mammals.csv" 73791 * // in the project's "assets" folder: 73792 * // 73793 * // id,species,name 73794 * // 0,Capra hircus,Goat 73795 * // 1,Panthera pardus,Leopard 73796 * // 2,Equus zebra,Zebra 73797 * 73798 * let table; 73799 * 73800 * function preload() { 73801 * //my table is comma separated value "csv" 73802 * //and has a header specifying the columns labels 73803 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 73804 * } 73805 * 73806 * function setup() { 73807 * table.removeColumn('id'); 73808 * print(table.getColumnCount()); 73809 * } 73810 * </code> 73811 * </div> 73812 * 73813 *@alt 73814 * no image displayed 73815 */ 73816 _main.default.Table.prototype.removeColumn = function(c) { 73817 var cString; 73818 var cNumber; 73819 if (typeof c === 'string') { 73820 // find the position of c in the columns 73821 cString = c; 73822 cNumber = this.columns.indexOf(c); 73823 } else { 73824 cNumber = c; 73825 cString = this.columns[c]; 73826 } 73827 73828 var chunk = this.columns.splice(cNumber + 1, this.columns.length); 73829 this.columns.pop(); 73830 this.columns = this.columns.concat(chunk); 73831 73832 for (var i = 0; i < this.rows.length; i++) { 73833 var tempR = this.rows[i].arr; 73834 var chip = tempR.splice(cNumber + 1, tempR.length); 73835 tempR.pop(); 73836 this.rows[i].arr = tempR.concat(chip); 73837 delete this.rows[i].obj[cString]; 73838 } 73839 }; 73840 73841 /** 73842 * Stores a value in the Table's specified row and column. 73843 * The row is specified by its ID, while the column may be specified 73844 * by either its ID or title. 73845 * 73846 * @method set 73847 * @param {Integer} row row ID 73848 * @param {String|Integer} column column ID (Number) 73849 * or title (String) 73850 * @param {String|Number} value value to assign 73851 * 73852 * @example 73853 * <div class="norender"> 73854 * <code> 73855 * // Given the CSV file "mammals.csv" 73856 * // in the project's "assets" folder: 73857 * // 73858 * // id,species,name 73859 * // 0,Capra hircus,Goat 73860 * // 1,Panthera pardus,Leopard 73861 * // 2,Equus zebra,Zebra 73862 * 73863 * let table; 73864 * 73865 * function preload() { 73866 * //my table is comma separated value "csv" 73867 * //and has a header specifying the columns labels 73868 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 73869 * } 73870 * 73871 * function setup() { 73872 * table.set(0, 'species', 'Canis Lupus'); 73873 * table.set(0, 'name', 'Wolf'); 73874 * 73875 * //print the results 73876 * for (let r = 0; r < table.getRowCount(); r++) 73877 * for (let c = 0; c < table.getColumnCount(); c++) 73878 * print(table.getString(r, c)); 73879 * } 73880 * </code> 73881 * </div> 73882 * 73883 *@alt 73884 * no image displayed 73885 */ 73886 _main.default.Table.prototype.set = function(row, column, value) { 73887 this.rows[row].set(column, value); 73888 }; 73889 73890 /** 73891 * Stores a Float value in the Table's specified row and column. 73892 * The row is specified by its ID, while the column may be specified 73893 * by either its ID or title. 73894 * 73895 * @method setNum 73896 * @param {Integer} row row ID 73897 * @param {String|Integer} column column ID (Number) 73898 * or title (String) 73899 * @param {Number} value value to assign 73900 * 73901 * @example 73902 * <div class="norender"> 73903 * <code> 73904 * // Given the CSV file "mammals.csv" 73905 * // in the project's "assets" folder: 73906 * // 73907 * // id,species,name 73908 * // 0,Capra hircus,Goat 73909 * // 1,Panthera pardus,Leopard 73910 * // 2,Equus zebra,Zebra 73911 * 73912 * let table; 73913 * 73914 * function preload() { 73915 * //my table is comma separated value "csv" 73916 * //and has a header specifying the columns labels 73917 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 73918 * } 73919 * 73920 * function setup() { 73921 * table.setNum(1, 'id', 1); 73922 * 73923 * print(table.getColumn(0)); 73924 * //["0", 1, "2"] 73925 * } 73926 * </code> 73927 * </div> 73928 * 73929 *@alt 73930 * no image displayed 73931 */ 73932 _main.default.Table.prototype.setNum = function(row, column, value) { 73933 this.rows[row].setNum(column, value); 73934 }; 73935 73936 /** 73937 * Stores a String value in the Table's specified row and column. 73938 * The row is specified by its ID, while the column may be specified 73939 * by either its ID or title. 73940 * 73941 * @method setString 73942 * @param {Integer} row row ID 73943 * @param {String|Integer} column column ID (Number) 73944 * or title (String) 73945 * @param {String} value value to assign 73946 * @example 73947 * <div class="norender"><code> 73948 * // Given the CSV file "mammals.csv" in the project's "assets" folder: 73949 * // 73950 * // id,species,name 73951 * // 0,Capra hircus,Goat 73952 * // 1,Panthera pardus,Leopard 73953 * // 2,Equus zebra,Zebra 73954 * 73955 * let table; 73956 * 73957 * function preload() { 73958 * //my table is comma separated value "csv" 73959 * //and has a header specifying the columns labels 73960 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 73961 * } 73962 * 73963 * function setup() { 73964 * //add a row 73965 * let newRow = table.addRow(); 73966 * newRow.setString('id', table.getRowCount() - 1); 73967 * newRow.setString('species', 'Canis Lupus'); 73968 * newRow.setString('name', 'Wolf'); 73969 * 73970 * print(table.getArray()); 73971 * } 73972 * </code></div> 73973 * 73974 * @alt 73975 * no image displayed 73976 */ 73977 _main.default.Table.prototype.setString = function(row, column, value) { 73978 this.rows[row].setString(column, value); 73979 }; 73980 73981 /** 73982 * Retrieves a value from the Table's specified row and column. 73983 * The row is specified by its ID, while the column may be specified by 73984 * either its ID or title. 73985 * 73986 * @method get 73987 * @param {Integer} row row ID 73988 * @param {String|Integer} column columnName (string) or 73989 * ID (number) 73990 * @return {String|Number} 73991 * 73992 * @example 73993 * <div class="norender"> 73994 * <code> 73995 * // Given the CSV file "mammals.csv" 73996 * // in the project's "assets" folder: 73997 * // 73998 * // id,species,name 73999 * // 0,Capra hircus,Goat 74000 * // 1,Panthera pardus,Leopard 74001 * // 2,Equus zebra,Zebra 74002 * 74003 * let table; 74004 * 74005 * function preload() { 74006 * //my table is comma separated value "csv" 74007 * //and has a header specifying the columns labels 74008 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 74009 * } 74010 * 74011 * function setup() { 74012 * print(table.get(0, 1)); 74013 * //Capra hircus 74014 * print(table.get(0, 'species')); 74015 * //Capra hircus 74016 * } 74017 * </code> 74018 * </div> 74019 * 74020 *@alt 74021 * no image displayed 74022 */ 74023 _main.default.Table.prototype.get = function(row, column) { 74024 return this.rows[row].get(column); 74025 }; 74026 74027 /** 74028 * Retrieves a Float value from the Table's specified row and column. 74029 * The row is specified by its ID, while the column may be specified by 74030 * either its ID or title. 74031 * 74032 * @method getNum 74033 * @param {Integer} row row ID 74034 * @param {String|Integer} column columnName (string) or 74035 * ID (number) 74036 * @return {Number} 74037 * 74038 * @example 74039 * <div class="norender"> 74040 * <code> 74041 * // Given the CSV file "mammals.csv" 74042 * // in the project's "assets" folder: 74043 * // 74044 * // id,species,name 74045 * // 0,Capra hircus,Goat 74046 * // 1,Panthera pardus,Leopard 74047 * // 2,Equus zebra,Zebra 74048 * 74049 * let table; 74050 * 74051 * function preload() { 74052 * //my table is comma separated value "csv" 74053 * //and has a header specifying the columns labels 74054 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 74055 * } 74056 * 74057 * function setup() { 74058 * print(table.getNum(1, 0) + 100); 74059 * //id 1 + 100 = 101 74060 * } 74061 * </code> 74062 * </div> 74063 * 74064 *@alt 74065 * no image displayed 74066 */ 74067 _main.default.Table.prototype.getNum = function(row, column) { 74068 return this.rows[row].getNum(column); 74069 }; 74070 74071 /** 74072 * Retrieves a String value from the Table's specified row and column. 74073 * The row is specified by its ID, while the column may be specified by 74074 * either its ID or title. 74075 * 74076 * @method getString 74077 * @param {Integer} row row ID 74078 * @param {String|Integer} column columnName (string) or 74079 * ID (number) 74080 * @return {String} 74081 * 74082 * @example 74083 * <div class="norender"> 74084 * <code> 74085 * // Given the CSV file "mammals.csv" 74086 * // in the project's "assets" folder: 74087 * // 74088 * // id,species,name 74089 * // 0,Capra hircus,Goat 74090 * // 1,Panthera pardus,Leopard 74091 * // 2,Equus zebra,Zebra 74092 * 74093 * let table; 74094 * 74095 * function preload() { 74096 * // table is comma separated value "CSV" 74097 * // and has specifiying header for column labels 74098 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 74099 * } 74100 * 74101 * function setup() { 74102 * print(table.getString(0, 0)); // 0 74103 * print(table.getString(0, 1)); // Capra hircus 74104 * print(table.getString(0, 2)); // Goat 74105 * print(table.getString(1, 0)); // 1 74106 * print(table.getString(1, 1)); // Panthera pardus 74107 * print(table.getString(1, 2)); // Leopard 74108 * print(table.getString(2, 0)); // 2 74109 * print(table.getString(2, 1)); // Equus zebra 74110 * print(table.getString(2, 2)); // Zebra 74111 * } 74112 * </code> 74113 * </div> 74114 * 74115 *@alt 74116 * no image displayed 74117 */ 74118 74119 _main.default.Table.prototype.getString = function(row, column) { 74120 return this.rows[row].getString(column); 74121 }; 74122 74123 /** 74124 * Retrieves all table data and returns as an object. If a column name is 74125 * passed in, each row object will be s
74125tored with that attribute as its 74126 * title. 74127 * 74128 * @method getObject 74129 * @param {String} [headerColumn] Name of the column which should be used to 74130 * title each row object (optional) 74131 * @return {Object} 74132 * 74133 * @example 74134 * <div class="norender"> 74135 * <code> 74136 * // Given the CSV file "mammals.csv" 74137 * // in the project's "assets" folder: 74138 * // 74139 * // id,species,name 74140 * // 0,Capra hircus,Goat 74141 * // 1,Panthera pardus,Leopard 74142 * // 2,Equus zebra,Zebra 74143 * 74144 * let table; 74145 * 74146 * function preload() { 74147 * //my table is comma separated value "csv" 74148 * //and has a header specifying the columns labels 74149 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 74150 * } 74151 * 74152 * function setup() { 74153 * let tableObject = table.getObject(); 74154 * 74155 * print(tableObject); 74156 * //outputs an object 74157 * } 74158 * </code> 74159 * </div> 74160 * 74161 *@alt 74162 * no image displayed 74163 */ 74164 _main.default.Table.prototype.getObject = function(headerColumn) { 74165 var tableObject = {}; 74166 var obj, cPos, index; 74167 74168 for (var i = 0; i < this.rows.length; i++) { 74169 obj = this.rows[i].obj; 74170 74171 if (typeof headerColumn === 'string') { 74172 cPos = this.columns.indexOf(headerColumn); // index of columnID 74173 if (cPos >= 0) { 74174 index = obj[headerColumn]; 74175 tableObject[index] = obj; 74176 } else { 74177 throw new Error( 74178 'This table has no column named "'.concat(headerColumn, '"') 74179 ); 74180 } 74181 } else { 74182 tableObject[i] = this.rows[i].obj; 74183 } 74184 } 74185 return tableObject; 74186 }; 74187 74188 /** 74189 * Retrieves all table data and returns it as a multidimensional array. 74190 * 74191 * @method getArray 74192 * @return {Array} 74193 * 74194 * @example 74195 * <div class="norender"> 74196 * <code> 74197 * // Given the CSV file "mammals.csv" 74198 * // in the project's "assets" folder 74199 * // 74200 * // id,species,name 74201 * // 0,Capra hircus,Goat 74202 * // 1,Panthera pardus,Leoperd 74203 * // 2,Equus zebra,Zebra 74204 * 74205 * let table; 74206 * 74207 * function preload() { 74208 * // table is comma separated value "CSV" 74209 * // and has specifiying header for column labels 74210 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 74211 * } 74212 * 74213 * function setup() { 74214 * let tableArray = table.getArray(); 74215 * for (let i = 0; i < tableArray.length; i++) { 74216 * print(tableArray[i]); 74217 * } 74218 * } 74219 * </code> 74220 * </div> 74221 * 74222 *@alt 74223 * no image displayed 74224 */ 74225 _main.default.Table.prototype.getArray = function() { 74226 var tableArray = []; 74227 for (var i = 0; i < this.rows.length; i++) { 74228 tableArray.push(this.rows[i].arr); 74229 } 74230 return tableArray; 74231 }; 74232 var _default = _main.default; 74233 exports.default = _default; 74234 }, 74235 { '../core/main': 59 } 74236 ], 74237 87: [ 74238 function(_dereq_, module, exports) { 74239 'use strict'; 74240 Object.defineProperty(exports, '__esModule', { value: true }); 74241 exports.default = void 0; 74242 74243 var _main = _interopRequireDefault(_dereq_('../core/main')); 74244 function _interopRequireDefault(obj) { 74245 return obj && obj.__esModule ? obj : { default: obj }; 74246 } 74247 /** 74248 * @module IO 74249 * @submodule Table 74250 * @requires core 74251 */ /** 74252 * A TableRow object represents a single row of data values, 74253 * stored in columns, from a table. 74254 * 74255 * A Table Row contains both an ordered array, and an unordered 74256 * JSON object. 74257 * 74258 * @class p5.TableRow 74259 * @constructor 74260 * @param {String} [str] optional: populate the row with a
74261 * string of values, separated by the 74262 * separator 74263 * @param {String} [separator] comma separated values (csv) by default 74264 */ _main.default.TableRow = function(str, separator) { 74265 var arr = []; 74266 var obj = {}; 74267 if (str) { 74268 separator = separator || ','; 74269 arr = str.split(separator); 74270 } 74271 for (var i = 0; i < arr.length; i++) { 74272 var key = i; 74273 var val = arr[i]; 74274 obj[key] = val; 74275 } 74276 this.arr = arr; 74277 this.obj = obj; 74278 this.table = null; 74279 }; 74280 74281 /** 74282 * Stores a value in the TableRow's specified column. 74283 * The column may be specified by either its ID or title. 74284 * 74285 * @method set 74286 * @param {String|Integer} column Column ID (Number) 74287 * or Title (String) 74288 * @param {String|Number} value The value to be stored 74289 * 74290 * @example 74291 * <div class="norender"><code> 74292 * // Given the CSV file "mammals.csv" in the project's "assets" folder: 74293 * // 74294 * // id,species,name 74295 * // 0,Capra hircus,Goat 74296 * // 1,Panthera pardus,Leopard 74297 * // 2,Equus zebra,Zebra 74298 * 74299 * let table; 74300 * 74301 * function preload() { 74302 * //my table is comma separated value "csv" 74303 * //and has a header specifying the columns labels 74304 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 74305 * } 74306 * 74307 * function setup() { 74308 * let rows = table.getRows(); 74309 * for (let r = 0; r < rows.length; r++) { 74310 * rows[r].set('name', 'Unicorn'); 74311 * } 74312 * 74313 * //print the results 74314 * print(table.getArray()); 74315 * } 74316 * </code></div> 74317 * 74318 * @alt 74319 * no image displayed 74320 */ 74321 _main.default.TableRow.prototype.set = function(column, value) { 74322 // if typeof column is string, use .obj 74323 if (typeof column === 'string') { 74324 var cPos = this.table.columns.indexOf(column); // index of columnID 74325 if (cPos >= 0) { 74326 this.obj[column] = value; 74327 this.arr[cPos] = value; 74328 } else { 74329 throw new Error('This table has no column named "'.concat(column, '"')); 74330 } 74331 } else { 74332 // if typeof column is number, use .arr 74333 if (column < this.table.columns.length) { 74334 this.arr[column] = value; 74335 var cTitle = this.table.columns[column]; 74336 this.obj[cTitle] = value; 74337 } else { 74338 throw new Error( 74339 'Column #'.concat(column, ' is out of the range of this table') 74340 ); 74341 } 74342 } 74343 }; 74344 74345 /** 74346 * Stores a Float value in the TableRow's specified column. 74347 * The column may be specified by either its ID or title. 74348 * 74349 * @method setNum 74350 * @param {String|Integer} column Column ID (Number) 74351 * or Title (String) 74352 * @param {Number|String} value The value to be stored 74353 * as a Float 74354 * @example 74355 * <div class="norender"><code> 74356 * // Given the CSV file "mammals.csv" in the project's "assets" folder: 74357 * // 74358 * // id,species,name 74359 * // 0,Capra hircus,Goat 74360 * // 1,Panthera pardus,Leopard 74361 * // 2,Equus zebra,Zebra 74362 * 74363 * let table; 74364 * 74365 * function preload() { 74366 * //my table is comma separated value "csv" 74367 * //and has a header specifying the columns labels 74368 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 74369 * } 74370 * 74371 * function setup() { 74372 * let rows = table.getRows(); 74373 * for (let r = 0; r < rows.length; r++) { 74374 * rows[r].setNum('id', r + 10); 74375 * } 74376 * 74377 * print(table.getArray()); 74378 * } 74379 * </code></div> 74380 * 74381 * @alt 74382 * no image displayed 74383 */ 74384 _main.default.TableRow.prototype.setNum = function(column, value) { 74385 var floatVal = parseFloat(value); 74386 this.set(column, floatVal); 74387 }; 74388 74389 /** 74390 * Stores a String value in the TableRow's specified column. 74391 * The column may be specified by either its ID or title. 74392 * 74393 * @method setString 74394 * @param {String|Integer} column Column ID (Number) 74395 * or Title (String) 74396 * @param {String|Number|Boolean|Object} value The value to be stored 74397 * as a String 74398 * @example 74399 * <div class="norender"><code> 74400 * // Given the CSV file "mammals.csv" in the project's "assets" folder: 74401 * // 74402 * // id,species,name 74403 * // 0,Capra hircus,Goat 74404 * // 1,Panthera pardus,Leopard 74405 * // 2,Equus zebra,Zebra 74406 * 74407 * let table; 74408 * 74409 * function preload() { 74410 * //my table is comma separated value "csv" 74411 * //and has a header specifying the columns labels 74412 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 74413 * } 74414 * 74415 * function setup() { 74416 * let rows = table.getRows(); 74417 * for (let r = 0; r < rows.length; r++) { 74418 * let name = rows[r].getString('name'); 74419 * rows[r].setString('name', 'A ' + name + ' named George'); 74420 * } 74421 * 74422 * print(table.getArray()); 74423 * } 74424 * </code></div> 74425 * 74426 * @alt 74427 * no image displayed 74428 */ 74429 _main.default.TableRow.prototype.setString = function(column, value) { 74430 var stringVal = value.toString(); 74431 this.set(column, stringVal); 74432 }; 74433 74434 /** 74435 * Retrieves a value from the TableRow's specified column. 74436 * The column may be specified by either its ID or title. 74437 * 74438 * @method get 74439 * @param {String|Integer} column columnName (string) or 74440 * ID (number) 74441 * @return {String|Number} 74442 * 74443 * @example 74444 * <div class="norender"><code> 74445 * // Given the CSV file "mammals.csv" in the project's "assets" folder: 74446 * // 74447 * // id,species,name 74448 * // 0,Capra hircus,Goat 74449 * // 1,Panthera pardus,Leopard 74450 * // 2,Equus zebra,Zebra 74451 * 74452 * let table; 74453 * 74454 * function preload() { 74455 * //my table is comma separated value "csv" 74456 * //and has a header specifying the columns labels 74457 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 74458 * } 74459 * 74460 * function setup() { 74461 * let names = []; 74462 * let rows = table.getRows(); 74463 * for (let r = 0; r < rows.length; r++) { 74464 * names.push(rows[r].get('name')); 74465 * } 74466 * 74467 * print(names); 74468 * } 74469 * </code></div> 74470 * 74471 * @alt 74472 * no image displayed 74473 */ 74474 _main.default.TableRow.prototype.get = function(column) { 74475 if (typeof column === 'string') { 74476 return this.obj[column]; 74477 } else { 74478 return this.arr[column]; 74479 } 74480 }; 74481 74482 /** 74483 * Retrieves a Float value from the TableRow's specified 74484 * column. The column may be specified by either its ID or 74485 * title. 74486 * 74487 * @method getNum 74488 * @param {String|Integer} column columnName (string) or 74489 * ID (number) 74490 * @return {Number} Float Floating point number 74491 * @example 74492 * <div class="norender"><code> 74493 * // Given the CSV file "mammals.csv" in the project's "assets" folder: 74494 * // 74495 * // id,species,name 74496 * // 0,Capra hircus,Goat 74497 * // 1,Panthera pardus,Leopard 74498 * // 2,Equus zebra,Zebra 74499 * 74500 * let table; 74501 * 74502 * function preload() { 74503 * //my table is comma separated value "csv" 74504 * //and has a header specifying the columns labels 74505 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 74506 * } 74507 * 74508 * function setup() { 74509 * let rows = table.getRows(); 74510 * let minId = Infinity; 74511 * let maxId = -Infinity; 74512 * for (let r = 0; r < rows.length; r++) { 74513 * let id = rows[r].getNum('id'); 74514 * minId = min(minId, id); 74515 * maxId = min(maxId, id); 74516 * } 74517 * print('minimum id = ' + minId + ', maximum id = ' + maxId); 74518 * } 74519 * </code></div> 74520 * 74521 * @alt 74522 * no image displayed 74523 */ 74524 _main.default.TableRow.prototype.getNum = function(column) { 74525 var ret; 74526 if (typeof column === 'string') { 74527 ret = parseFloat(this.obj[column]); 74528 } else { 74529 ret = parseFloat(this.arr[column]); 74530 } 74531 74532 if (ret.toString() === 'NaN') { 74533 throw 'Error: '.concat(this.obj[column], ' is NaN (Not a Number)'); 74534 } 74535 return ret; 74536 }; 74537 74538 /** 74539 * Retrieves an String value from the TableRow's specified 74540 * column. The column may be specified by either its ID or 74541 * title. 74542 * 74543 * @method getString 74544 * @param {String|Integer} column columnName (string) or 74545 * ID (number) 74546 * @return {String} String 74547 * @example 74548 * <div class="norender"><code> 74549 * // Given the CSV file "mammals.csv" in the project's "assets" folder: 74550 * // 74551 * // id,species,name 74552 * // 0,Capra hircus,Goat 74553 * // 1,Panthera pardus,Leopard 74554 * // 2,Equus zebra,Zebra 74555 * 74556 * let table; 74557 * 74558 * function preload() { 74559 * //my table is comma separated value "csv" 74560 * //and has a header specifying the columns labels 74561 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 74562 * } 74563 * 74564 * function setup() { 74565 * let rows = table.getRows(); 74566 * let longest = ''; 74567 * for (let r = 0; r < rows.length; r++) { 74568 * let species = rows[r].getString('species'); 74569 * if (longest.length < species.length) { 74570 * longest = species; 74571 * } 74572 * } 74573 * 74574 * print('longest: ' + longest); 74575 * } 74576 * </code></div> 74577 * 74578 * @alt 74579 * no image displayed 74580 */ 74581 _main.default.TableRow.prototype.getString = function(column) { 74582 if (typeof column === 'string') { 74583 return this.obj[column].toString(); 74584 } else { 74585 return this.arr[column].toString(); 74586 } 74587 }; 74588 var _default = _main.default; 74589 exports.default = _default; 74590 }, 74591 { '../core/main': 59 } 74592 ], 74593 88: [
74594 function(_dereq_, module, exports) { 74595 'use strict'; 74596 Object.defineProperty(exports, '__esModule', { value: true }); 74597 exports.default = void 0; 74598 74599 var _main = _interopRequireDefault(_dereq_('../core/main')); 74600 function _interopRequireDefault(obj) { 74601 return obj && obj.__esModule ? obj : { default: obj }; 74602 } 74603 /** 74604 * @module IO 74605 * @submodule Input 74606 * @requires core 74607 */ /** 74608 * XML is a representation of an XML object, able to parse XML code. Use 74609 * <a href="#/p5/loadXML">loadXML()</a> to load external XML files and create XML objects. 74610 * 74611 * @class p5.XML 74612 * @constructor 74613 * @example 74614 * <div class='norender'><code> 74615 * // The following short XML file called "mammals.xml" is parsed 74616 * // in the code below. 74617 * // 74618 * // <?xml version="1.0"?> 74619 * // <mammals> 74620 * // <animal id="0" species="Capra hircus">Goat</animal> 74621 * // <animal id="1" species="Panthera pardus">Leopard</animal> 74622 * // <animal id="2" species="Equus zebra">Zebra</animal> 74623 * // </mammals> 74624 * 74625 * let xml; 74626 * 74627 * function preload() { 74628 * xml = loadXML('assets/mammals.xml'); 74629 * } 74630 * 74631 * function setup() { 74632 * let children = xml.getChildren('animal'); 74633 * 74634 * for (let i = 0; i < children.length; i++) { 74635 * let id = children[i].getNum('id'); 74636 * let coloring = children[i].getString('species'); 74637 * let name = children[i].getContent(); 74638 * print(id + ', ' + coloring + ', ' + name); 74639 * } 74640 * } 74641 * 74642 * // Sketch prints: 74643 * // 0, Capra hircus, Goat 74644 * // 1, Panthera pardus, Leopard 74645 * // 2, Equus zebra, Zebra 74646 * </code></div> 74647 * 74648 * @alt 74649 * no image displayed 74650 */ _main.default.XML = function(DOM) { 74651 if (!DOM) { 74652 var xmlDoc = document.implementation.createDocument(null, 'doc'); 74653 this.DOM = xmlDoc.createElement('root'); 74654 } else { 74655 this.DOM = DOM; 74656 } 74657 }; 74658 74659 /** 74660 * Gets a copy of the element's parent. Returns the parent as another 74661 * <a href="#/p5.XML">p5.XML</a> object. 74662 * 74663 * @method getParent 74664 * @return {p5.XML} element parent 74665 * @example 74666 * <div class='norender'><code> 74667 * // The following short XML file called "mammals.xml" is parsed 74668 * // in the code below. 74669 * // 74670 * // <?xml version="1.0"?> 74671 * // <mammals> 74672 * // <animal id="0" species="Capra hircus">Goat</animal> 74673 * // <animal id="1" species="Panthera pardus">Leopard</animal> 74674 * // <animal id="2" species="Equus zebra">Zebra</animal> 74675 * // </mammals> 74676 * 74677 * let xml; 74678 * 74679 * function preload() { 74680 * xml = loadXML('assets/mammals.xml'); 74681 * } 74682 * 74683 * function setup() { 74684 * let children = xml.getChildren('animal'); 74685 * let parent = children[1].getParent(); 74686 * print(parent.getName()); 74687 * } 74688 * 74689 * // Sketch prints: 74690 * // mammals 74691 * </code></div> 74692 */ 74693 _main.default.XML.prototype.getParent = function() { 74694 return new _main.default.XML(this.DOM.parentElement); 74695 }; 74696 74697 /** 74698 * Gets the element's full name, which is returned as a String. 74699 * 74700 * @method getName 74701 * @return {String} the name of the node 74702 * @example<animal 74703 * <div class='norender'><code> 74704 * // The following short XML file called "mammals.xml" is parsed 74705 * // in the code below. 74706 * // 74707 * // <?xml version="1.0"?> 74708 * // <mammals> 74709 * // <animal id="0" species="Capra hircus">Goat</animal> 74710 * // <animal id="1" species="Panthera pardus">Leopard</animal> 74711 * // <animal id="2" species="Equus zebra">
74711Zebra</animal> 74712 * // </mammals> 74713 * 74714 * let xml; 74715 * 74716 * function preload() { 74717 * xml = loadXML('assets/mammals.xml'); 74718 * } 74719 * 74720 * function setup() { 74721 * print(xml.getName()); 74722 * } 74723 * 74724 * // Sketch prints: 74725 * // mammals 74726 * </code></div> 74727 */ 74728 _main.default.XML.prototype.getName = function() { 74729 return this.DOM.tagName; 74730 }; 74731 74732 /** 74733 * Sets the element's name, which is specified as a String. 74734 * 74735 * @method setName 74736 * @param {String} the new name of the node 74737 * @example<animal 74738 * <div class='norender'><code> 74739 * // The following short XML file called "mammals.xml" is parsed 74740 * // in the code below. 74741 * // 74742 * // <?xml version="1.0"?> 74743 * // <mammals> 74744 * // <animal id="0" species="Capra hircus">Goat</animal> 74745 * // <animal id="1" species="Panthera pardus">Leopard</animal> 74746 * // <animal id="2" species="Equus zebra">Zebra</animal> 74747 * // </mammals> 74748 * 74749 * let xml; 74750 * 74751 * function preload() { 74752 * xml = loadXML('assets/mammals.xml'); 74753 * } 74754 * 74755 * function setup() { 74756 * print(xml.getName()); 74757 * xml.setName('fish'); 74758 * print(xml.getName()); 74759 * } 74760 * 74761 * // Sketch prints: 74762 * // mammals 74763 * // fish 74764 * </code></div> 74765 */ 74766 _main.default.XML.prototype.setName = function(name) { 74767 var content = this.DOM.innerHTML; 74768 var attributes = this.DOM.attributes; 74769 var xmlDoc = document.implementation.createDocument(null, 'default'); 74770 var newDOM = xmlDoc.createElement(name); 74771 newDOM.innerHTML = content; 74772 for (var i = 0; i < attributes.length; i++) { 74773 newDOM.setAttribute(attributes[i].nodeName, attributes.nodeValue); 74774 } 74775 this.DOM = newDOM; 74776 }; 74777 74778 /** 74779 * Checks whether or not the element has any children, and returns the result 74780 * as a boolean. 74781 * 74782 * @method hasChildren 74783 * @return {boolean} 74784 * @example<animal 74785 * <div class='norender'><code> 74786 * // The following short XML file called "mammals.xml" is parsed 74787 * // in the code below. 74788 * // 74789 * // <?xml version="1.0"?> 74790 * // <mammals> 74791 * // <animal id="0" species="Capra hircus">Goat</animal> 74792 * // <animal id="1" species="Panthera pardus">Leopard</animal> 74793 * // <animal id="2" species="Equus zebra">Zebra</animal> 74794 * // </mammals> 74795 * 74796 * let xml; 74797 * 74798 * function preload() { 74799 * xml = loadXML('assets/mammals.xml'); 74800 * } 74801 * 74802 * function setup() { 74803 * print(xml.hasChildren()); 74804 * } 74805 * 74806 * // Sketch prints: 74807 * // true 74808 * </code></div> 74809 */ 74810 _main.default.XML.prototype.hasChildren = function() { 74811 return this.DOM.children.length > 0; 74812 }; 74813 74814 /** 74815 * Get the names of all of the element's children, and returns the names as an 74816 * array of Strings. This is the same as looping through and calling <a href="#/p5.XML/getName">getName()</a> 74817 * on each child element individually. 74818 * 74819 * @method listChildren 74820 * @return {String[]} names of the children of the element 74821 * @example<animal 74822 * <div class='norender'><code> 74823 * // The following short XML file called "mammals.xml" is parsed 74824 * // in the code below. 74825 * // 74826 * // <?xml version="1.0"?> 74827 * // <mammals> 74828 * // <animal id="0" species="Capra hircus">Goat</animal> 74829 * // <animal id="1" species="Panthera pardus">Leopard</animal> 74830 * // <animal id="2" species="Equus zebra">
74830Zebra</animal> 74831 * // </mammals> 74832 * 74833 * let xml; 74834 * 74835 * function preload() { 74836 * xml = loadXML('assets/mammals.xml'); 74837 * } 74838 * 74839 * function setup() { 74840 * print(xml.listChildren()); 74841 * } 74842 * 74843 * // Sketch prints: 74844 * // ["animal", "animal", "animal"] 74845 * </code></div> 74846 */ 74847 _main.default.XML.prototype.listChildren = function() { 74848 var arr = []; 74849 for (var i = 0; i < this.DOM.childNodes.length; i++) { 74850 arr.push(this.DOM.childNodes[i].nodeName); 74851 } 74852 return arr; 74853 }; 74854 74855 /** 74856 * Returns all of the element's children as an array of <a href="#/p5.XML">p5.XML</a> objects. When 74857 * the name parameter is specified, then it will return all children that match 74858 * that name. 74859 * 74860 * @method getChildren 74861 * @param {String} [name] element name 74862 * @return {p5.XML[]} children of the element 74863 * @example<animal 74864 * <div class='norender'><code> 74865 * // The following short XML file called "mammals.xml" is parsed 74866 * // in the code below. 74867 * // 74868 * // <?xml version="1.0"?> 74869 * // <mammals> 74870 * // <animal id="0" species="Capra hircus">Goat</animal> 74871 * // <animal id="1" species="Panthera pardus">Leopard</animal> 74872 * // <animal id="2" species="Equus zebra">Zebra</animal> 74873 * // </mammals> 74874 * 74875 * let xml; 74876 * 74877 * function preload() { 74878 * xml = loadXML('assets/mammals.xml'); 74879 * } 74880 * 74881 * function setup() { 74882 * let animals = xml.getChildren('animal'); 74883 * 74884 * for (let i = 0; i < animals.length; i++) { 74885 * print(animals[i].getContent()); 74886 * } 74887 * } 74888 * 74889 * // Sketch prints: 74890 * // "Goat" 74891 * // "Leopard" 74892 * // "Zebra" 74893 * </code></div> 74894 */ 74895 _main.default.XML.prototype.getChildren = function(param) { 74896 if (param) { 74897 return elementsToP5XML(this.DOM.getElementsByTagName(param)); 74898 } else { 74899 return elementsToP5XML(this.DOM.children); 74900 } 74901 }; 74902 74903 function elementsToP5XML(elements) { 74904 var arr = []; 74905 for (var i = 0; i < elements.length; i++) { 74906 arr.push(new _main.default.XML(elements[i])); 74907 } 74908 return arr; 74909 } 74910 74911 /** 74912 * Returns the first of the element's children that matches the name parameter 74913 * or the child of the given index.It returns undefined if no matching 74914 * child is found. 74915 * 74916 * @method getChild 74917 * @param {String|Integer} name element name or index 74918 * @return {p5.XML} 74919 * @example<animal 74920 * <div class='norender'><code> 74921 * // The following short XML file called "mammals.xml" is parsed 74922 * // in the code below. 74923 * // 74924 * // <?xml version="1.0"?> 74925 * // <mammals> 74926 * // <animal id="0" species="Capra hircus">Goat</animal> 74927 * // <animal id="1" species="Panthera pardus">Leopard</animal> 74928 * // <animal id="2" species="Equus zebra">Zebra</animal> 74929 * // </mammals> 74930 * 74931 * let xml; 74932 * 74933 * function preload() { 74934 * xml = loadXML('assets/mammals.xml'); 74935 * } 74936 * 74937 * function setup() { 74938 * let firstChild = xml.getChild('animal'); 74939 * print(firstChild.getContent()); 74940 * } 74941 * 74942 * // Sketch prints: 74943 * // "Goat" 74944 * </code></div> 74945 * <div class='norender'><code> 74946 * let xml; 74947 * 74948 * function preload() { 74949 * xml = loadXML('assets/mammals.xml'); 74950 * } 74951 * 74952 * function setup() { 74953 * let secondChild = xml.getChild(1); 74954 * print(secondChild.getContent()); 74955 * } 74956 * 74957 * // Sketch prints: 74958 * // "Leopard" 74959 * </code></div> 74960 */ 74961 _main.default.XML.prototype.getChild = function(param) { 74962 if (typeof param === 'string') { 74963 var _iteratorNormalCompletion = true; 74964 var _didIteratorError = false;
74965 var _iteratorError = undefined; 74966 try { 74967 for ( 74968 var _iterator = this.DOM.children[Symbol.iterator](), _step; 74969 !(_iteratorNormalCompletion = (_step = _iterator.next()).done); 74970 _iteratorNormalCompletion = true 74971 ) { 74972 var child = _step.value; 74973 if (child.tagName === param) return new _main.default.XML(child); 74974 } 74975 } catch (err) { 74976 _didIteratorError = true; 74977 _iteratorError = err; 74978 } finally { 74979 try { 74980 if (!_iteratorNormalCompletion && _iterator.return != null) { 74981 _iterator.return(); 74982 } 74983 } finally { 74984 if (_didIteratorError) { 74985 throw _iteratorError; 74986 } 74987 } 74988 } 74989 } else { 74990 return new _main.default.XML(this.DOM.children[param]); 74991 } 74992 }; 74993 74994 /** 74995 * Appends a new child to the element. The child can be specified with 74996 * either a String, which will be used as the new tag's name, or as a 74997 * reference to an existing <a href="#/p5.XML">p5.XML</a> object. 74998 * A reference to the newly created child is returned as an <a href="#/p5.XML">p5.XML</a> object. 74999 * 75000 * @method addChild 75001 * @param {p5.XML} node a <a href="#/p5.XML">p5.XML</a> Object which will be the child to be added 75002 * @example 75003 * <div class='norender'><code> 75004 * // The following short XML file called "mammals.xml" is parsed 75005 * // in the code below. 75006 * // 75007 * // <?xml version="1.0"?> 75008 * // <mammals> 75009 * // <animal id="0" species="Capra hircus">Goat</animal> 75010 * // <animal id="1" species="Panthera pardus">Leopard</animal> 75011 * // <animal id="2" species="Equus zebra">Zebra</animal> 75012 * // </mammals> 75013 * 75014 * let xml; 75015 * 75016 * function preload() { 75017 * xml = loadXML('assets/mammals.xml'); 75018 * } 75019 * 75020 * function setup() { 75021 * let child = new p5.XML(); 75022 * child.setName('animal'); 75023 * child.setAttribute('id', '3'); 75024 * child.setAttribute('species', 'Ornithorhynchus anatinus'); 75025 * child.setContent('Platypus'); 75026 * xml.addChild(child); 75027 * 75028 * let animals = xml.getChildren('animal'); 75029 * print(animals[animals.length - 1].getContent()); 75030 * } 75031 * 75032 * // Sketch prints: 75033 * // "Goat" 75034 * // "Leopard" 75035 * // "Zebra" 75036 * </code></div> 75037 */ 75038 _main.default.XML.prototype.addChild = function(node) { 75039 if (node instanceof _main.default.XML) { 75040 this.DOM.appendChild(node.DOM); 75041 } else { 75042 // PEND 75043 } 75044 }; 75045 75046 /** 75047 * Removes the element specified by name or index. 75048 * 75049 * @method removeChild 75050 * @param {String|Integer} name element name or index 75051 * @example 75052 * <div class='norender'><code> 75053 * // The following short XML file called "mammals.xml" is parsed 75054 * // in the code below. 75055 * // 75056 * // <?xml version="1.0"?> 75057 * // <mammals> 75058 * // <animal id="0" species="Capra hircus">Goat</animal> 75059 * // <animal id="1" species="Panthera pardus">Leopard</animal> 75060 * // <animal id="2" species="Equus zebra">Zebra</animal> 75061 * // </mammals> 75062 * 75063 * let xml; 75064 * 75065 * function preload() { 75066 * xml = loadXML('assets/mammals.xml'); 75067 * } 75068 * 75069 * function setup() { 75070 * xml.removeChild('animal'); 75071 * let children = xml.getChildren(); 75072 * for (let i = 0; i < children.length; i++) { 75073 * print(children[i].getContent()); 75074 * } 75075 * } 75076 * 75077 * // Sketch prints: 75078 * // "Leopard" 75079 * // "Zebra" 75080 * </code></div> 75081 * <div class='norender'><code> 75082 * let xml; 75083 * 75084 * function preload() { 75085 * xml = loadXML('assets/mammals.xml'); 75086 * } 75087 * 75088 * function setup() { 75089 * xml.removeChild(1); 75090 * let children = xml.getChildren(); 75091 * for (let i = 0; i < children.length; i++) { 75092 * print(children[i].getContent()); 75093 * } 75094 * } 75095 * 75096 * // Sketch prints: 75097 * // "Goat" 75098 * // "Zebra" 75099 * </code></div> 75100 */ 75101 _main.default.XML.prototype.removeChild = function(param) { 75102 var ind = -1; 75103 if (typeof param === 'string') { 75104 for (var i = 0; i < this.DOM.children.length; i++) { 75105 if (this.DOM.children[i].tagName === param) { 75106 ind = i; 75107 break; 75108 } 75109 } 75110 } else { 75111 ind = param; 75112 } 75113 if (ind !== -1) { 75114 this.DOM.removeChild(this.DOM.children[ind]); 75115 } 75116 }; 75117 75118 /** 75119 * Counts the specified element's number of attributes, returned as an Number. 75120 * 75121 * @method getAttributeCount 75122 * @return {Integer} 75123 * @example 75124 * <div class='norender'><code> 75125 * // The following short XML file called "mammals.xml" is parsed 75126 * // in the code below. 75127 * // 75128 * // <?xml version="1.0"?> 75129 * // <mammals> 75130 * // <animal id="0" species="Capra hircus">Goat</animal> 75131 * // <animal id="1" species="Panthera pardus">Leopard</animal> 75132 * // <animal id="2" species="Equus zebra">
75132Zebra</animal> 75133 * // </mammals> 75134 * 75135 * let xml; 75136 * 75137 * function preload() { 75138 * xml = loadXML('assets/mammals.xml'); 75139 * } 75140 * 75141 * function setup() { 75142 * let firstChild = xml.getChild('animal'); 75143 * print(firstChild.getAttributeCount()); 75144 * } 75145 * 75146 * // Sketch prints: 75147 * // 2 75148 * </code></div> 75149 */ 75150 _main.default.XML.prototype.getAttributeCount = function() { 75151 return this.DOM.attributes.length; 75152 }; 75153 75154 /** 75155 * Gets all of the specified element's attributes, and returns them as an 75156 * array of Strings. 75157 * 75158 * @method listAttributes 75159 * @return {String[]} an array of strings containing the names of attributes 75160 * @example 75161 * <div class='norender'><code> 75162 * // The following short XML file called "mammals.xml" is parsed 75163 * // in the code below. 75164 * // 75165 * // <?xml version="1.0"?> 75166 * // <mammals> 75167 * // <animal id="0" species="Capra hircus">Goat</animal> 75168 * // <animal id="1" species="Panthera pardus">Leopard</animal> 75169 * // <animal id="2" species="Equus zebra">Zebra</animal> 75170 * // </mammals> 75171 * 75172 * let xml; 75173 * 75174 * function preload() { 75175 * xml = loadXML('assets/mammals.xml'); 75176 * } 75177 * 75178 * function setup() { 75179 * let firstChild = xml.getChild('animal'); 75180 * print(firstChild.listAttributes()); 75181 * } 75182 * 75183 * // Sketch prints: 75184 * // ["id", "species"] 75185 * </code></div> 75186 */ 75187 _main.default.XML.prototype.listAttributes = function() { 75188 var arr = []; 75189 var _iteratorNormalCompletion2 = true; 75190 var _didIteratorError2 = false;
75191 var _iteratorError2 = undefined; 75192 try { 75193 for ( 75194 var _iterator2 = this.DOM.attributes[Symbol.iterator](), _step2; 75195 !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); 75196 _iteratorNormalCompletion2 = true 75197 ) { 75198 var attribute = _step2.value; 75199 arr.push(attribute.nodeName); 75200 } 75201 } catch (err) { 75202 _didIteratorError2 = true; 75203 _iteratorError2 = err; 75204 } finally { 75205 try { 75206 if (!_iteratorNormalCompletion2 && _iterator2.return != null) { 75207 _iterator2.return(); 75208 } 75209 } finally { 75210 if (_didIteratorError2) { 75211 throw _iteratorError2; 75212 } 75213 } 75214 } 75215 75216 return arr; 75217 }; 75218 75219 /** 75220 * Checks whether or not an element has the specified attribute. 75221 * 75222 * @method hasAttribute 75223 * @param {String} the attribute to be checked 75224 * @return {boolean} true if attribute found else false 75225 * @example 75226 * <div class='norender'><code> 75227 * // The following short XML file called "mammals.xml" is parsed 75228 * // in the code below. 75229 * // 75230 * // <?xml version="1.0"?> 75231 * // <mammals> 75232 * // <animal id="0" species="Capra hircus">Goat</animal> 75233 * // <animal id="1" species="Panthera pardus">Leopard</animal> 75234 * // <animal id="2" species="Equus zebra">Zebra</animal> 75235 * // </mammals> 75236 * 75237 * let xml; 75238 * 75239 * function preload() { 75240 * xml = loadXML('assets/mammals.xml'); 75241 * } 75242 * 75243 * function setup() { 75244 * let firstChild = xml.getChild('animal'); 75245 * print(firstChild.hasAttribute('species')); 75246 * print(firstChild.hasAttribute('color')); 75247 * } 75248 * 75249 * // Sketch prints: 75250 * // true 75251 * // false 75252 * </code></div> 75253 */ 75254 _main.default.XML.prototype.hasAttribute = function(name) { 75255 var obj = {}; 75256 var _iteratorNormalCompletion3 = true; 75257 var _didIteratorError3 = false; 75258 var _iteratorError3 = undefined; 75259 try { 75260 for ( 75261 var _iterator3 = this.DOM.attributes[Symbol.iterator](), _step3; 75262 !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); 75263 _iteratorNormalCompletion3 = true 75264 ) { 75265 var attribute = _step3.value; 75266 obj[attribute.nodeName] = attribute.nodeValue; 75267 } 75268 } catch (err) { 75269 _didIteratorError3 = true; 75270 _iteratorError3 = err; 75271 } finally { 75272 try { 75273 if (!_iteratorNormalCompletion3 && _iterator3.return != null) { 75274 _iterator3.return(); 75275 } 75276 } finally { 75277 if (_didIteratorError3) { 75278 throw _iteratorError3; 75279 } 75280 } 75281 } 75282 75283 return obj[name] ? true : false; 75284 }; 75285 75286 /** 75287 * Returns an attribute value of the element as an Number. If the defaultValue 75288 * parameter is specified and the attribute doesn't exist, then defaultValue 75289 * is returned. If no defaultValue is specified and the attribute doesn't 75290 * exist, the value 0 is returned. 75291 * 75292 * @method getNum 75293 * @param {String} name the non-null full name of the attribute 75294 * @param {Number} [defaultValue] the default value of the attribute 75295 * @return {Number} 75296 * @example 75297 * <div class='norender'><code> 75298 * // The following short XML file called "mammals.xml" is parsed 75299 * // in the code below. 75300 * // 75301 * // <?xml version="1.0"?> 75302 * // <mammals> 75303 * // <animal id="0" species="Capra hircus">Goat</animal> 75304 * // <animal id="1" species="Panthera pardus">Leopard</animal> 75305 * // <animal id="2" species="Equus zebra">
75305Zebra</animal> 75306 * // </mammals> 75307 * 75308 * let xml; 75309 * 75310 * function preload() { 75311 * xml = loadXML('assets/mammals.xml'); 75312 * } 75313 * 75314 * function setup() { 75315 * let firstChild = xml.getChild('animal'); 75316 * print(firstChild.getNum('id')); 75317 * } 75318 * 75319 * // Sketch prints: 75320 * // 0 75321 * </code></div> 75322 */ 75323 _main.default.XML.prototype.getNum = function(name, defaultValue) { 75324 var obj = {}; 75325 var _iteratorNormalCompletion4 = true; 75326 var _didIteratorError4 = false; 75327 var _iteratorError4 = undefined; 75328 try { 75329 for ( 75330 var _iterator4 = this.DOM.attributes[Symbol.iterator](), _step4; 75331 !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); 75332 _iteratorNormalCompletion4 = true 75333 ) { 75334 var attribute = _step4.value; 75335 obj[attribute.nodeName] = attribute.nodeValue; 75336 } 75337 } catch (err) { 75338 _didIteratorError4 = true; 75339 _iteratorError4 = err; 75340 } finally { 75341 try { 75342 if (!_iteratorNormalCompletion4 && _iterator4.return != null) { 75343 _iterator4.return(); 75344 } 75345 } finally { 75346 if (_didIteratorError4) { 75347 throw _iteratorError4; 75348 } 75349 } 75350 } 75351 75352 return Number(obj[name]) || defaultValue || 0; 75353 }; 75354 75355 /** 75356 * Returns an attribute value of the element as an String. If the defaultValue 75357 * parameter is specified and the attribute doesn't exist, then defaultValue 75358 * is returned. If no defaultValue is specified and the attribute doesn't 75359 * exist, null is returned. 75360 * 75361 * @method getString 75362 * @param {String} name the non-null full name of the attribute 75363 * @param {Number} [defaultValue] the default value of the attribute 75364 * @return {String} 75365 * @example 75366 * <div class='norender'><code> 75367 * // The following short XML file called "mammals.xml" is parsed 75368 * // in the code below. 75369 * // 75370 * // <?xml version="1.0"?> 75371 * // <mammals> 75372 * // <animal id="0" species="Capra hircus">Goat</animal> 75373 * // <animal id="1" species="Panthera pardus">Leopard</animal> 75374 * // <animal id="2" species="Equus zebra">Zebra</animal> 75375 * // </mammals> 75376 * 75377 * let xml; 75378 * 75379 * function preload() { 75380 * xml = loadXML('assets/mammals.xml'); 75381 * } 75382 * 75383 * function setup() { 75384 * let firstChild = xml.getChild('animal'); 75385 * print(firstChild.getString('species')); 75386 * } 75387 * 75388 * // Sketch prints: 75389 * // "Capra hircus" 75390 * </code></div> 75391 */ 75392 _main.default.XML.prototype.getString = function(name, defaultValue) { 75393 var obj = {}; 75394 var _iteratorNormalCompletion5 = true; 75395 var _didIteratorError5 = false; 75396 var _iteratorError5 = undefined; 75397 try { 75398 for ( 75399 var _iterator5 = this.DOM.attributes[Symbol.iterator](), _step5; 75400 !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); 75401 _iteratorNormalCompletion5 = true 75402 ) { 75403 var attribute = _step5.value; 75404 obj[attribute.nodeName] = attribute.nodeValue; 75405 } 75406 } catch (err) { 75407 _didIteratorError5 = true; 75408 _iteratorError5 = err; 75409 } finally { 75410 try { 75411 if (!_iteratorNormalCompletion5 && _iterator5.return != null) { 75412 _iterator5.return(); 75413 } 75414 } finally { 75415 if (_didIteratorError5) { 75416 throw _iteratorError5; 75417 } 75418 } 75419 } 75420 75421 return obj[name] ? String(obj[name]) : defaultValue || null; 75422 }; 75423 75424 /** 75425 * Sets the content of an element's attribute. The first parameter specifies 75426 * the attribute name, while the second specifies the new content. 75427 * 75428 * @method setAttribute 75429 * @param {String} name the full name of the attribute 75430 * @param {Number|String|Boolean} value the value of the attribute 75431 * @example 75432 * <div class='norender'><code> 75433 * // The following short XML file called "mammals.xml" is parsed 75434 * // in the code below. 75435 * // 75436 * // <?xml version="1.0"?> 75437 * // <mammals> 75438 * // <animal id="0" species="Capra hircus">Goat</animal> 75439 * // <animal id="1" species="Panthera pardus">Leopard</animal> 75440 * // <animal id="2" species="Equus zebra">
75440Zebra</animal> 75441 * // </mammals> 75442 * 75443 * let xml; 75444 * 75445 * function preload() { 75446 * xml = loadXML('assets/mammals.xml'); 75447 * } 75448 * 75449 * function setup() { 75450 * let firstChild = xml.getChild('animal'); 75451 * print(firstChild.getString('species')); 75452 * firstChild.setAttribute('species', 'Jamides zebra'); 75453 * print(firstChild.getString('species')); 75454 * } 75455 * 75456 * // Sketch prints: 75457 * // "Capra hircus" 75458 * // "Jamides zebra" 75459 * </code></div> 75460 */ 75461 _main.default.XML.prototype.setAttribute = function(name, value) { 75462 this.DOM.setAttribute(name, value); 75463 }; 75464 75465 /** 75466 * Returns the content of an element. If there is no such content, 75467 * defaultValue is returned if specified, otherwise null is returned. 75468 * 75469 * @method getContent 75470 * @param {String} [defaultValue] value returned if no content is found 75471 * @return {String} 75472 * @example 75473 * <div class='norender'><code> 75474 * // The following short XML file called "mammals.xml" is parsed 75475 * // in the code below. 75476 * // 75477 * // <?xml version="1.0"?> 75478 * // <mammals> 75479 * // <animal id="0" species="Capra hircus">Goat</animal> 75480 * // <animal id="1" species="Panthera pardus">Leopard</animal> 75481 * // <animal id="2" species="Equus zebra">Zebra</animal> 75482 * // </mammals> 75483 * 75484 * let xml; 75485 * 75486 * function preload() { 75487 * xml = loadXML('assets/mammals.xml'); 75488 * } 75489 * 75490 * function setup() { 75491 * let firstChild = xml.getChild('animal'); 75492 * print(firstChild.getContent()); 75493 * } 75494 * 75495 * // Sketch prints: 75496 * // "Goat" 75497 * </code></div> 75498 */ 75499 _main.default.XML.prototype.getContent = function(defaultValue) { 75500 var str; 75501 str = this.DOM.textContent; 75502 str = str.replace(/\s\s+/g, ','); 75503 return str || defaultValue || null; 75504 }; 75505 75506 /** 75507 * Sets the element's content. 75508 * 75509 * @method setContent 75510 * @param {String} text the new content 75511 * @example 75512 * <div class='norender'><code> 75513 * // The following short XML file called "mammals.xml" is parsed 75514 * // in the code below. 75515 * // 75516 * // <?xml version="1.0"?> 75517 * // <mammals> 75518 * // <animal id="0" species="Capra hircus">Goat</animal> 75519 * // <animal id="1" species="Panthera pardus">Leopard</animal> 75520 * // <animal id="2" species="Equus zebra">Zebra</animal> 75521 * // </mammals> 75522 * 75523 * let xml; 75524 * 75525 * function preload() { 75526 * xml = loadXML('assets/mammals.xml'); 75527 * } 75528 * 75529 * function setup() { 75530 * let firstChild = xml.getChild('animal'); 75531 * print(firstChild.getContent()); 75532 * firstChild.setContent('Mountain Goat'); 75533 * print(firstChild.getContent()); 75534 * } 75535 * 75536 * // Sketch prints: 75537 * // "Goat" 75538 * // "Mountain Goat" 75539 * </code></div> 75540 */ 75541 _main.default.XML.prototype.setContent = function(content) { 75542 if (!this.DOM.children.length) { 75543 this.DOM.textContent = content; 75544 } 75545 }; 75546 75547 /** 75548 * Serializes the element into a string. This function is useful for preparing 75549 * the content to be sent over a http request or saved to file. 75550 * 75551 * @method serialize 75552 * @return {String} Serialized string of the element 75553 * @example 75554 * <div class='norender'><code> 75555 * let xml; 75556 * 75557 * function preload() { 75558 * xml = loadXML('assets/mammals.xml'); 75559 * } 75560 * 75561 * function setup() { 75562 * print(xml.serialize()); 75563 * } 75564 * 75565 * // Sketch prints: 75566 * // <mammals> 75567 * // <animal id="0" species="Capra hircus">Goat</animal> 75568 * // <animal id="1" species="Panthera pardus">Leopard</animal> 75569 * // <animal id="2" species="Equus zebra">
75569Zebra</animal> 75570 * // </mammals> 75571 * </code></div> 75572 */ 75573 _main.default.XML.prototype.serialize = function() { 75574 var xmlSerializer = new XMLSerializer(); 75575 return xmlSerializer.serializeToString(this.DOM); 75576 }; 75577 var _default = _main.default; 75578 exports.default = _default; 75579 }, 75580 { '../core/main': 59 } 75581 ], 75582 89: [ 75583 function(_dereq_, module, exports) { 75584 'use strict'; 75585 Object.defineProperty(exports, '__esModule', { value: true }); 75586 exports.default = void 0; 75587 75588 var _main = _interopRequireDefault(_dereq_('../core/main')); 75589 function _interopRequireDefault(obj) { 75590 return obj && obj.__esModule ? obj : { default: obj }; 75591 } 75592 /** 75593 * @module Math 75594 * @submodule Calculation 75595 * @for p5 75596 * @requires core 75597 */ /** 75598 * Calculates the absolute value (magnitude) of a number. Maps to Math.abs(). 75599 * The absolute value of a number is always positive. 75600 * 75601 * @method abs 75602 * @param {Number} n number to compute 75603 * @return {Number} absolute value of given number 75604 * @example 75605 * <div class = "norender"><code> 75606 * function setup() { 75607 * let x = -3; 75608 * let y = abs(x); 75609 * 75610 * print(x); // -3 75611 * print(y); // 3 75612 * } 75613 * </code></div> 75614 * 75615 * @alt 75616 * no image displayed 75617 */ _main.default.prototype.abs = Math.abs; /** 75618 * Calculates the closest int value that is greater than or equal to the 75619 * value of the parameter. Maps to Math.ceil(). For example, ceil(9.03) 75620 * returns the value 10. 75621 * 75622 * @method ceil 75623 * @param {Number} n number to round up 75624 * @return {Integer} rounded up number 75625 * @example 75626 * <div><code> 75627 * function draw() { 75628 * background(200); 75629 * // map, mouseX between 0 and 5. 75630 * let ax = map(mouseX, 0, 100, 0, 5); 75631 * let ay = 66; 75632 * 75633 * //Get the ceiling of the mapped number. 75634 * let bx = ceil(map(mouseX, 0, 100, 0, 5)); 75635 * let by = 33; 75636 * 75637 * // Multiply the mapped numbers by 20 to more easily 75638 * // see the changes. 75639 * stroke(0); 75640 * fill(0); 75641 * line(0, ay, ax * 20, ay); 75642 * line(0, by, bx * 20, by); 75643 * 75644 * // Reformat the float returned by map and draw it. 75645 * noStroke(); 75646 * text(nfc(ax, 2), ax, ay - 5); 75647 * text(nfc(bx, 1), bx, by - 5); 75648 * } 75649 * </code></div> 75650 * 75651 * @alt 75652 * 2 horizontal lines & number sets. increase with mouse x. bottom to 2 decimals 75653 */ 75654 _main.default.prototype.ceil = Math.ceil; 75655 75656 /** 75657 * Constrains a value between a minimum and maximum value. 75658 * 75659 * @method constrain 75660 * @param {Number} n number to constrain 75661 * @param {Number} low minimum limit 75662 * @param {Number} high maximum limit 75663 * @return {Number} constrained number 75664 * @example 75665 * <div><code> 75666 * function draw() { 75667 * background(200); 75668 * 75669 * let leftWall = 25; 75670 * let rightWall = 75; 75671 * 75672 * // xm is just the mouseX, while 75673 * // xc is the mouseX, but constrained 75674 * // between the leftWall and rightWall! 75675 * let xm = mouseX; 75676 * let xc = constrain(mouseX, leftWall, rightWall); 75677 * 75678 * // Draw the walls. 75679 * stroke(150); 75680 * line(leftWall, 0, leftWall, height); 75681 * line(rightWall, 0, rightWall, height); 75682 * 75683 * // Draw xm and xc as circles. 75684 * noStroke(); 75685 * fill(150); 75686 * ellipse(xm, 33, 9, 9); // Not Constrained 75687 * fill(0); 75688 * ellipse(xc, 66, 9, 9); // Constrained 75689 * } 75690 * </code></div> 75691 * 75692 * @alt 75693 * 2 vertical lines. 2 ellipses move with mouse X 1 does not move passed lines 75694 */ 75695 _main.default.prototype.constrain = function(n, low, high) { 75696 _main.default._validateParameters('constrain', arguments); 75697 return Math.max(Math.min(n, high), low); 75698 }; 75699 75700 /** 75701 * Calculates the distance between two points, in either two or three dimensions. 75702 * 75703 * @method dist 75704 * @param {Number} x1 x-coordinate of the first point 75705 * @param {Number} y1 y-coordinate of the first point 75706 * @param {Number} x2 x-coordinate of the second point 75707 * @param {Number} y2 y-coordinate of the second point 75708 * @return {Number} distance between the two points 75709 * 75710 * @example 75711 * <div><code> 75712 * // Move your mouse inside the canvas to see the 75713 * // change in distance between two points! 75714 * function draw() { 75715 * background(200); 75716 * fill(0); 75717 * 75718 * let x1 = 10; 75719 * let y1 = 90; 75720 * let x2 = mouseX; 75721 * let y2 = mouseY; 75722 * 75723 * line(x1, y1, x2, y2); 75724 * ellipse(x1, y1, 7, 7); 75725 * ellipse(x2, y2, 7, 7); 75726 * 75727 * // d is the length of the line 75728 * // the distance from point 1 to point 2. 75729 * let d = dist(x1, y1, x2, y2); 75730 * 75731 * // Let's write d along the line we are drawing! 75732 * push(); 75733 * translate((x1 + x2) / 2, (y1 + y2) / 2); 75734 * rotate(atan2(y2 - y1, x2 - x1));
75735 * text(nfc(d, 1), 0, -5); 75736 * pop(); 75737 * // Fancy! 75738 * } 75739 * </code></div> 75740 * 75741 * @alt 75742 * 2 ellipses joined by line. 1 ellipse moves with mouse X&Y. Distance displayed. 75743 */ 75744 /** 75745 * @method dist 75746 * @param {Number} x1 75747 * @param {Number} y1 75748 * @param {Number} z1 z-coordinate of the first point 75749 * @param {Number} x2 75750 * @param {Number} y2 75751 * @param {Number} z2 z-coordinate of the second point 75752 * @return {Number} distance between the two points 75753 */ 75754 _main.default.prototype.dist = function() { 75755 for ( 75756 var _len = arguments.length, args = new Array(_len), _key = 0; 75757 _key < _len; 75758 _key++ 75759 ) { 75760 args[_key] = arguments[_key]; 75761 } 75762 _main.default._validateParameters('dist', args); 75763 if (args.length === 4) { 75764 //2D 75765 return hypot(args[2] - args[0], args[3] - args[1]); 75766 } else if (args.length === 6) { 75767 //3D 75768 return hypot(args[3] - args[0], args[4] - args[1], args[5] - args[2]); 75769 } 75770 }; 75771 75772 /** 75773 * Returns Euler's number e (2.71828...) raised to the power of the n 75774 * parameter. Maps to Math.exp(). 75775 * 75776 * @method exp 75777 * @param {Number} n exponent to raise 75778 * @return {Number} e^n 75779 * @example 75780 * <div><code> 75781 * function draw() { 75782 * background(200); 75783 * 75784 * // Compute the exp() function with a value between 0 and 2 75785 * let xValue = map(mouseX, 0, width, 0, 2); 75786 * let yValue = exp(xValue); 75787 * 75788 * let y = map(yValue, 0, 8, height, 0); 75789 * 75790 * let legend = 'exp (' + nfc(xValue, 3) + ')\n= ' + nf(yValue, 1, 4); 75791 * stroke(150); 75792 * line(mouseX, y, mouseX, height); 75793 * fill(0); 75794 * text(legend, 5, 15); 75795 * noStroke(); 75796 * ellipse(mouseX, y, 7, 7); 75797 * 75798 * // Draw the exp(x) curve, 75799 * // over the domain of x from 0 to 2 75800 * noFill(); 75801 * stroke(0); 75802 * beginShape(); 75803 * for (let x = 0; x < width; x++) { 75804 * xValue = map(x, 0, width, 0, 2); 75805 * yValue = exp(xValue); 75806 * y = map(yValue, 0, 8, height, 0); 75807 * vertex(x, y); 75808 * } 75809 * 75810 * endShape(); 75811 * line(0, 0, 0, height); 75812 * line(0, height - 1, width, height - 1); 75813 * } 75814 * </code></div> 75815 * 75816 * @alt 75817 * ellipse moves along a curve with mouse x. e^n displayed. 75818 */ 75819 _main.default.prototype.exp = Math.exp; 75820 75821 /** 75822 * Calculates the closest int value that is less than or equal to the 75823 * value of the parameter. Maps to Math.floor(). 75824 * 75825 * @method floor 75826 * @param {Number} n number to round down 75827 * @return {Integer} rounded down number 75828 * @example 75829 * <div><code> 75830 * function draw() { 75831 * background(200); 75832 * //map, mouseX between 0 and 5. 75833 * let ax = map(mouseX, 0, 100, 0, 5); 75834 * let ay = 66; 75835 * 75836 * //Get the floor of the mapped number. 75837 * let bx = floor(map(mouseX, 0, 100, 0, 5)); 75838 * let by = 33; 75839 * 75840 * // Multiply the mapped numbers by 20 to more easily 75841 * // see the changes. 75842 * stroke(0); 75843 * fill(0); 75844 * line(0, ay, ax * 20, ay); 75845 * line(0, by, bx * 20, by); 75846 * 75847 * // Reformat the float returned by map and draw it. 75848 * noStroke(); 75849 * text(nfc(ax, 2), ax, ay - 5); 75850 * text(nfc(bx, 1), bx, by - 5); 75851 * } 75852 * </code></div> 75853 * 75854 * @alt 75855 * 2 horizontal lines & number sets. increase with mouse x. bottom to 2 decimals 75856 */ 75857 _main.default.prototype.floor = Math.floor; 75858 75859 /** 75860 * Calculates a number between two numbers at a specific increment. The amt 75861 * parameter is the amount to interpolate between the two values where 0.0 75862 * equal to the first point, 0.1 is very near the first point, 0.5 is 75863 * half-way in between, and 1.0 is equal to the second point. If the 75864 * value of amt is more than 1.0 or less than 0.0, the number will be 75865 * calculated accordingly in the ratio of the two given numbers. The lerp 75866 * function is convenient for creating motion along a straight 75867 * path and for drawing dotted lines. 75868 * 75869 * @method lerp 75870 * @param {Number} start first value 75871 * @param {Number} stop second value 75872 * @param {Number} amt number 75873 * @return {Number} lerped value 75874 * @example 75875 * <div><code> 75876 * function setup() { 75877 * background(200); 75878 * let a = 20; 75879 * let b = 80; 75880 * let c = lerp(a, b, 0.2); 75881 * let d = lerp(a, b, 0.5); 75882 * let e = lerp(a, b, 0.8); 75883 * 75884 * let y = 50; 75885 * 75886 * strokeWeight(5); 75887 * stroke(0); // Draw the original points in black 75888 * point(a, y); 75889 * point(b, y); 75890 * 75891 * stroke(100); // Draw the lerp points in gray 75892 * point(c, y); 75893 * point(d, y); 75894 * point(e, y); 75895 * } 75896 * </code></div> 75897 * 75898 * @alt 75899 * 5 points horizontally staggered mid-canvas. mid 3 are grey, outer black 75900 */ 75901 _main.default.prototype.lerp = function(start, stop, amt) { 75902 _main.default._validateParameters('lerp', arguments); 75903 return amt * (stop - start) + start; 75904 }; 75905 75906 /** 75907 * Calculates the natural logarithm (the base-e logarithm) of a number. This 75908 * function expects the n parameter to be a value greater than 0.0. Maps to 75909 * Math.log(). 75910 * 75911 * @method log 75912 * @param {Number} n number greater than 0 75913 * @return {Number} natural logarithm of n 75914 * @example 75915 * <div><code> 75916 * function draw() { 75917 * background(200); 75918 * let maxX = 2.8; 75919 * let maxY = 1.5; 75920 * 75921 * // Compute the natural log of a value between 0 and maxX 75922 * let xValue = map(mouseX, 0, width, 0, maxX); 75923 * let yValue, y; 75924 * if (xValue > 0) { 75925 // Cannot take the log of a negative number. 75926 * yValue = log(xValue); 75927 * y = map(yValue, -maxY, maxY, height, 0); 75928 * 75929 * // Display the calculation occurring. 75930 * let legend = 'log(' + nf(xValue, 1, 2) + ')\n= ' + nf(yValue, 1, 3); 75931 * stroke(150); 75932 * line(mouseX, y, mouseX, height); 75933 * fill(0); 75934 * text(legend, 5, 15); 75935 * noStroke(); 75936 * ellipse(mouseX, y, 7, 7); 75937 * } 75938 * 75939 * // Draw the log(x) curve, 75940 * // over the domain of x from 0 to maxX 75941 * noFill(); 75942 * stroke(0); 75943 * beginShape(); 75944 * for (let x = 0; x < width; x++) { 75945 * xValue = map(x, 0, width, 0, maxX); 75946 * yValue = log(xValue); 75947 * y = map(yValue, -maxY, maxY, height, 0); 75948 * vertex(x, y); 75949 * } 75950 * endShape(); 75951 * line(0, 0, 0, height); 75952 * line(0, height / 2, width, height / 2); 75953 * } 75954 * </code></div> 75955 * 75956 * @alt 75957 * ellipse moves along a curve with mouse x. natural logarithm of n displayed. 75958 */ 75959 _main.default.prototype.log = Math.log; 75960 75961 /** 75962 * Calculates the magnitude (or length) of a vector. A vector is a direction 75963 * in space commonly used in computer graphics and linear algebra. Because it 75964 * has no "start" position, the magnitude of a vector can be thought of as 75965 * the distance from the coordinate 0,0 to its x,y value. Therefore, <a href="#/p5/mag">mag()</a> is 75966 * a shortcut for writing dist(0, 0, x, y). 75967 * 75968 * @method mag 75969 * @param {Number} a first value 75970 * @param {Number} b second value 75971 * @return {Number} magnitude of vector from (0,0) to (a,b) 75972 * @example 75973 * <div><code> 75974 * function setup() { 75975 * let x1 = 20; 75976 * let x2 = 80; 75977 * let y1 = 30; 75978 * let y2 = 70; 75979 * 75980 * line(0, 0, x1, y1); 75981 * print(mag(x1, y1)); // Prints "36.05551275463989" 75982 * line(0, 0, x2, y1); 75983 * print(mag(x2, y1)); // Prints "85.44003745317531" 75984 * line(0, 0, x1, y2); 75985 * print(mag(x1, y2)); // Prints "72.80109889280519" 75986 * line(0, 0, x2, y2); 75987 * print(mag(x2, y2)); // Prints "106.3014581273465" 75988 * } 75989 * </code></div> 75990 * 75991 * @alt 75992 * 4 lines of different length radiate from top left of canvas. 75993 */ 75994 _main.default.prototype.mag = function(x, y) { 75995 _main.default._validateParameters('mag', arguments); 75996 return hypot(x, y); 75997 }; 75998 75999 /** 76000 * Re-maps a number from one range to another. 76001 * 76002 * In the first example above, the number 25 is converted from a value in the 76003 * range of 0 to 100 into a value that ranges from the left edge of the 76004 * window (0) to the right edge (width). 76005 * 76006 * @method map 76007 * @param {Number} value the incoming value to be converted 76008 * @param {Number} start1 lower bound of the value's current range 76009 * @param {Number} stop1 upper bound of the value's current range 76010 * @param {Number} start2 lower bound of the value's target range 76011 * @param {Number} stop2 upper bound of the value's target range 76012 * @param {Boolean} [withinBounds] constrain the value to the newly mapped range 76013 * @return {Number} remapped number 76014 * @example 76015 * <div><code> 76016 * let value = 25; 76017 * let m = map(value, 0, 100, 0, width); 76018 * ellipse(m, 50, 10, 10); 76019 </code></div> 76020 * 76021 * <div><code> 76022 * function setup() { 76023 * noStroke(); 76024 * } 76025 * 76026 * function draw() { 76027 * background(204); 76028 * let x1 = map(mouseX, 0, width, 25, 75); 76029 * ellipse(x1, 25, 25, 25); 76030 * //This ellipse is constrained to the 0-100 range 76031 * //after setting withinBounds to true 76032 * let x2 = map(mouseX, 0, width, 0, 100, true); 76033 * ellipse(x2, 75, 25, 25); 76034 * } 76035 </code></div> 76036 * 76037 * @alt 76038 * 10 by 10 white ellipse with in mid left canvas 76039 * 2 25 by 25 white ellipses move with mouse x. Bottom has more range from X 76040 */ 76041 _main.default.prototype.map = function( 76042 n, 76043 start1, 76044 stop1, 76045 start2, 76046 stop2, 76047 withinBounds 76048 ) { 76049 _main.default._validateParameters('map', arguments); 76050 var newval = (n - start1) / (stop1 - start1) * (stop2 - start2) + start2; 76051 if (!withinBounds) { 76052 return newval; 76053 } 76054 if (start2 < stop2) { 76055 return this.constrain(newval, start2, stop2); 76056 } else { 76057 return this.constrain(newval, stop2, start2); 76058 } 76059 }; 76060 76061 /** 76062 * Determines the largest value in a sequence of numbers, and then returns 76063 * that value. <a href="#/p5/max">max()</a> accepts any number of Number parameters, or an Array 76064 * of any length. 76065 * 76066 * @method max 76067 * @param {Number} n0 Number to compare 76068 * @param {Number} n1 Number to compare 76069 * @return {Number} maximum Number 76070 * @example 76071 * <div><code> 76072 * function setup() { 76073 * // Change the elements in the array and run the sketch 76074 * // to show how max() works! 76075 * let numArray = [2, 1, 5, 4, 8, 9]; 76076 * fill(0); 76077 * noStroke(); 76078 * text('Array Elements', 0, 10); 76079 * // Draw all numbers in the array 76080 * let spacing = 15; 76081 * let elemsY = 25; 76082 * for (let i = 0; i < numArray.length; i++) { 76083 * text(numArray[i], i * spacing, elemsY); 76084 * } 76085 * let maxX = 33; 76086 * let maxY = 80; 76087 * // Draw the Maximum value in the array. 76088 * textSize(32); 76089 * text(max(numArray), maxX, maxY); 76090 * } 76091 * </code></div> 76092 * 76093 * @alt 76094 * Small text at top reads: Array Elements 2 1 5 4 8 9. Large text at center: 9 76095 */ 76096 /** 76097 * @method max 76098 * @param {Number[]} nums Numbers to compare 76099 * @return {Number} 76100 */ 76101 _main.default.prototype.max = function() { 76102 for ( 76103 var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; 76104 _key2 < _len2; 76105 _key2++ 76106 ) { 76107 args[_key2] = arguments[_key2]; 76108 } 76109 if (args[0] instanceof Array) { 76110 return Math.max.apply(null, args[0]); 76111 } else {
76112 return Math.max.apply(null, args); 76113 } 76114 }; 76115 76116 /** 76117 * Determines the smallest value in a sequence of numbers, and then returns 76118 * that value. <a href="#/p5/min">min()</a> accepts any number of Number parameters, or an Array 76119 * of any length. 76120 * 76121 * @method min 76122 * @param {Number} n0 Number to compare 76123 * @param {Number} n1 Number to compare 76124 * @return {Number} minimum Number 76125 * @example 76126 * <div><code> 76127 * function setup() { 76128 * // Change the elements in the array and run the sketch 76129 * // to show how min() works! 76130 * let numArray = [2, 1, 5, 4, 8, 9]; 76131 * fill(0); 76132 * noStroke(); 76133 * text('Array Elements', 0, 10); 76134 * // Draw all numbers in the array 76135 * let spacing = 15; 76136 * let elemsY = 25; 76137 * for (let i = 0; i < numArray.length; i++) { 76138 * text(numArray[i], i * spacing, elemsY); 76139 * } 76140 * let maxX = 33; 76141 * let maxY = 80; 76142 * // Draw the Minimum value in the array. 76143 * textSize(32); 76144 * text(min(numArray), maxX, maxY); 76145 * } 76146 * </code></div> 76147 * 76148 * @alt 76149 * Small text at top reads: Array Elements 2 1 5 4 8 9. Large text at center: 1 76150 */ 76151 /** 76152 * @method min 76153 * @param {Number[]} nums Numbers to compare 76154 * @return {Number} 76155 */ 76156 _main.default.prototype.min = function() { 76157 for ( 76158 var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; 76159 _key3 < _len3; 76160 _key3++ 76161 ) { 76162 args[_key3] = arguments[_key3]; 76163 } 76164 if (args[0] instanceof Array) { 76165 return Math.min.apply(null, args[0]); 76166 } else { 76167 return Math.min.apply(null, args); 76168 } 76169 }; 76170 76171 /** 76172 * Normalizes a number from another range into a value between 0 and 1. 76173 * Identical to map(value, low, high, 0, 1). 76174 * Numbers outside of the range are not clamped to 0 and 1, because 76175 * out-of-range values are often intentional and useful. (See the example above.) 76176 * 76177 * @method norm 76178 * @param {Number} value incoming value to be normalized 76179 * @param {Number} start lower bound of the value's current range 76180 * @param {Number} stop upper bound of the value's current range 76181 * @return {Number} normalized number 76182 * @example 76183 * <div><code> 76184 * function draw() { 76185 * background(200); 76186 * let currentNum = mouseX; 76187 * let lowerBound = 0; 76188 * let upperBound = width; //100; 76189 * let normalized = norm(currentNum, lowerBound, upperBound); 76190 * let lineY = 70; 76191 * stroke(3); 76192 * line(0, lineY, width, lineY); 76193 * //Draw an ellipse mapped to the non-normalized value. 76194 * noStroke(); 76195 * fill(50); 76196 * let s = 7; // ellipse size 76197 * ellipse(currentNum, lineY, s, s); 76198 * 76199 * // Draw the guide 76200 * let guideY = lineY + 15; 76201 * text('0', 0, guideY); 76202 * textAlign(RIGHT); 76203 * text('100', width, guideY); 76204 * 76205 * // Draw the normalized value 76206 * textAlign(LEFT); 76207 * fill(0); 76208 * textSize(32); 76209 * let normalY = 40; 76210 * let normalX = 20; 76211 * text(normalized, normalX, normalY); 76212 * } 76213 * </code></div> 76214 * 76215 * @alt 76216 * ellipse moves with mouse. 0 shown left & 100 right and updating values center 76217 */ 76218 _main.default.prototype.norm = function(n, start, stop) { 76219 _main.default._validateParameters('norm', arguments); 76220 return this.map(n, start, stop, 0, 1); 76221 }; 76222 76223 /** 76224 * Facilitates exponential expressions. The <a href="#/p5/pow">pow()</a>
76224 function is an efficient 76225 * way of multiplying numbers by themselves (or their reciprocals) in large 76226 * quantities. For example, pow(3, 5) is equivalent to the expression 76227 * 3 × 3 × 3 × 3 × 3 and pow(3, -5) is equivalent to 1 / 76228 * 3 × 3 × 3 × 3 × 3. Maps to 76229 * Math.pow(). 76230 * 76231 * @method pow 76232 * @param {Number} n base of the exponential expression 76233 * @param {Number} e power by which to raise the base 76234 * @return {Number} n^e 76235 * @example 76236 * <div><code> 76237 * function setup() { 76238 * //Exponentially increase the size of an ellipse. 76239 * let eSize = 3; // Original Size 76240 * let eLoc = 10; // Original Location 76241 * 76242 * ellipse(eLoc, eLoc, eSize, eSize); 76243 * 76244 * ellipse(eLoc * 2, eLoc * 2, pow(eSize, 2), pow(eSize, 2)); 76245 * 76246 * ellipse(eLoc * 4, eLoc * 4, pow(eSize, 3), pow(eSize, 3)); 76247 * 76248 * ellipse(eLoc * 8, eLoc * 8, pow(eSize, 4), pow(eSize, 4)); 76249 * } 76250 * </code></div> 76251 * 76252 * @alt 76253 * small to large ellipses radiating from top left of canvas 76254 */ 76255 _main.default.prototype.pow = Math.pow; 76256 76257 /** 76258 * Calculates the integer closest to the n parameter. For example, 76259 * round(133.8) returns the value 134. Maps to Math.round(). 76260 * 76261 * @method round 76262 * @param {Number} n number to round 76263 * @param {Number} [decimals] number of decimal places to round to, default is 0 76264 * @return {Integer} rounded number 76265 * @example 76266 * <div><code> 76267 * let x = round(3.7); 76268 * text(x, width / 2, height / 2); 76269 * </code></div> 76270 * <div><code> 76271 * let x = round(12.782383, 2); 76272 * text(x, width / 2, height / 2); 76273 * </code></div> 76274 * <div><code> 76275 * function draw() { 76276 * background(200); 76277 * //map, mouseX between 0 and 5. 76278 * let ax = map(mouseX, 0, 100, 0, 5); 76279 * let ay = 66; 76280 * 76281 * // Round the mapped number. 76282 * let bx = round(map(mouseX, 0, 100, 0, 5)); 76283 * let by = 33; 76284 * 76285 * // Multiply the mapped numbers by 20 to more easily 76286 * // see the changes. 76287 * stroke(0); 76288 * fill(0); 76289 * line(0, ay, ax * 20, ay); 76290 * line(0, by, bx * 20, by); 76291 * 76292 * // Reformat the float returned by map and draw it. 76293 * noStroke(); 76294 * text(nfc(ax, 2), ax, ay - 5); 76295 * text(nfc(bx, 1), bx, by - 5); 76296 * } 76297 * </code></div> 76298 * 76299 * @alt 76300 * "3" written in middle of canvas 76301 * "12.78" written in middle of canvas 76302 * horizontal center line squared values displayed on top and regular on bottom. 76303 */ 76304 _main.default.prototype.round = function(n, decimals) { 76305 if (!decimals) { 76306 return Math.round(n); 76307 } 76308 return Number(Math.round(n + 'e' + decimals) + 'e-' + decimals); 76309 }; 76310 76311 /** 76312 * Squares a number (multiplies a number by itself). The result is always a 76313 * positive number, as multiplying two negative numbers always yields a 76314 * positive result. For example, -1 * -1 = 1. 76315 * 76316 * @method sq 76317 * @param {Number} n number to square 76318 * @return {Number} squared number 76319 * @example 76320 * <div><code> 76321 * function draw() { 76322 * background(200); 76323 * let eSize = 7; 76324 * let x1 = map(mouseX, 0, width, 0, 10); 76325 * let y1 = 80; 76326 * let x2 = sq(x1); 76327 * let y2 = 20; 76328 * 76329 * // Draw the non-squared. 76330 * line(0, y1, width, y1); 76331 * ellipse(x1, y1, eSize, eSize); 76332 * 76333 * // Draw the squared. 76334 * line(0, y2, width, y2); 76335 * ellipse(x2, y2, eSize, eSize); 76336 * 76337 * // Draw dividing line. 76338 * stroke(100); 76339 * line(0, height / 2, width, height / 2); 76340 * 76341 * // Draw text. 76342 * let spacing = 15; 76343 * noStroke(); 76344 * fill(0); 76345 * text('x = ' + x1, 0, y1 + spacing); 76346 * text('sq(x) = ' + x2, 0, y2 + spacing); 76347 * } 76348 * </code></div> 76349 * 76350 * @alt 76351 * horizontal center line squared values displayed on top and regular on bottom. 76352 */ 76353 _main.default.prototype.sq = function(n) { 76354 return n * n; 76355 }; 76356 76357 /** 76358 * Calculates the square root of a number. The square root of a number is 76359 * always positive, even though there may be a valid negative root. The 76360 * square root s of number a is such that s*s = a. It is the opposite of 76361 * squaring. Maps to Math.sqrt(). 76362 * 76363 * @method sqrt 76364 * @param {Number} n non-negative number to square root 76365 * @return {Number} square root of number 76366 * @example 76367 * <div><code> 76368 * function draw() { 76369 * background(200); 76370 * let eSize = 7; 76371 * let x1 = mouseX; 76372 * let y1 = 80; 76373 * let x2 = sqrt(x1); 76374 * let y2 = 20; 76375 * 76376 * // Draw the non-squared. 76377 * line(0, y1, width, y1); 76378 * ellipse(x1, y1, eSize, eSize); 76379 * 76380 * // Draw the squared. 76381 * line(0, y2, width, y2); 76382 * ellipse(x2, y2, eSize, eSize); 76383 * 76384 * // Draw dividing line. 76385 * stroke(100); 76386 * line(0, height / 2, width, height / 2); 76387 * 76388 * // Draw text. 76389 * noStroke(); 76390 * fill(0); 76391 * let spacing = 15; 76392 * text('x = ' + x1, 0, y1 + spacing); 76393 * text('sqrt(x) = ' + x2, 0, y2 + spacing); 76394 * } 76395 * </code></div> 76396 * 76397 * @alt 76398 * horizontal center line squareroot values displayed on top and regular on bottom. 76399 */ 76400 _main.default.prototype.sqrt = Math.sqrt; 76401 76402 // Calculate the length of the hypotenuse of a right triangle 76403 // This won't under- or overflow in intermediate steps 76404 // https://en.wikipedia.org/wiki/Hypot 76405 function hypot(x, y, z) { 76406 // Use the native implementation if it's available 76407 if (typeof Math.hypot === 'function') { 76408 return Math.hypot.apply(null, arguments); 76409 } 76410 76411 // Otherwise use the V8 implementation 76412 // https://github.com/v8/v8/blob/8cd3cf297287e581a49e487067f5cbd991b27123/src/js/math.js#L217 76413 var length = arguments.length; 76414 var args = []; 76415 var max = 0; 76416 for (var i = 0; i < length; i++) { 76417 var n = arguments[i]; 76418 n = +n; 76419 if (n === Infinity || n === -Infinity) { 76420 return Infinity; 76421 } 76422 n = Math.abs(n); 76423 if (n > max) { 76424 max = n; 76425 } 76426 args[i] = n; 76427 } 76428 76429 if (max === 0) { 76430 max = 1; 76431 } 76432 var sum = 0; 76433 var compensation = 0; 76434 for (var j = 0; j < length; j++) { 76435 var m = args[j] / max; 76436 var summand = m * m - compensation; 76437 var preliminary = sum + summand; 76438 compensation = preliminary - sum - summand; 76439 sum = preliminary; 76440 } 76441 return Math.sqrt(sum) * max; 76442 } 76443 76444 /** 76445 * Calculates the fractional part of a number. 76446 * 76447 * @method fract 76448 * @param {Number} num Number whose fractional part needs to be found out 76449 * @returns {Number} fractional part of x, i.e, {x} 76450 * @example 76451 * <div> 76452 * <code> 76453 * function setup() { 76454 * createCanvas(windowWidth, windowHeight); 76455 * fill(0); 76456 * text(7345.73472742, 0, 50); 76457 * text(fract(7345.73472742), 0, 100); 76458 * text(1.4215e-15, 150, 50); 76459 * text(fract(1.4215e-15), 150, 100); 76460 * } 76461 * </code> 76462 * </div> 76463 * @alt 76464 * 2 rows of numbers, the first row having 8 numbers and the second having the fractional parts of those numbers. 76465 */ 76466 _main.default.prototype.fract = function(toConvert) { 76467 _main.default._validateParameters('fract', arguments); 76468 var sign = 0; 76469 var num = Number(toConvert); 76470 if (isNaN(num) || Math.abs(num) === Infinity) { 76471 return num; 76472 } else if (num < 0) { 76473 num = -num; 76474 sign = 1; 76475 } 76476 if (String(num).includes('.') && !String(num).includes('e')) { 76477 var toFract = String(num); 76478 toFract = Number('0' + toFract.slice(toFract.indexOf('.'))); 76479 return Math.abs(sign - toFract); 76480 } else if (num < 1) { 76481 return Math.abs(sign - num); 76482 } else { 76483 return 0; 76484 } 76485 }; 76486 var _default = _main.default; 76487 exports.default = _default; 76488 }, 76489 { '../core/main': 59 } 76490 ], 76491 90: [
76492 function(_dereq_, module, exports) { 76493 'use strict'; 76494 Object.defineProperty(exports, '__esModule', { value: true }); 76495 exports.default = void 0; 76496 76497 var _main = _interopRequireDefault(_dereq_('../core/main')); 76498 function _interopRequireDefault(obj) { 76499 return obj && obj.__esModule ? obj : { default: obj }; 76500 } 76501 /** 76502 * @module Math 76503 * @submodule Vector 76504 * @for p5 76505 * @requires core 76506 */ /** 76507 * Creates a new <a href="#/p5.Vector">p5.Vector</a> (the datatype for storing vectors). This provides a 76508 * two or three dimensional vector, specifically a Euclidean (also known as 76509 * geometric) vector. A vector is an entity that has both magnitude and 76510 * direction. 76511 * 76512 * @method createVector 76513 * @param {Number} [x] x component of the vector 76514 * @param {Number} [y] y component of the vector 76515 * @param {Number} [z] z component of the vector 76516 * @return {p5.Vector} 76517 * @example 76518 * <div><code> 76519 * let v1; 76520 * function setup() { 76521 * createCanvas(100, 100); 76522 * stroke(255, 0, 255); 76523 * v1 = createVector(width / 2, height / 2); 76524 * } 76525 * 76526 * function draw() { 76527 * background(255); 76528 * line(v1.x, v1.y, mouseX, mouseY); 76529 * } 76530 * </code></div> 76531 * 76532 * @alt 76533 * draws a line from center of canvas to mouse pointer position. 76534 */ _main.default.prototype.createVector = function(x, y, z) { 76535 if (this instanceof _main.default) { 76536 return new _main.default.Vector(this, arguments); 76537 } else { 76538 return new _main.default.Vector(x, y, z); 76539 } 76540 }; 76541 var _default = _main.default; 76542 exports.default = _default; 76543 }, 76544 { '../core/main': 59 } 76545 ], 76546 91: [ 76547 function(_dereq_, module, exports) { 76548 'use strict'; 76549 Object.defineProperty(exports, '__esModule', { value: true }); 76550 exports.default = void 0; 76551 76552 var _main = _interopRequireDefault(_dereq_('../core/main')); 76553 function _interopRequireDefault(obj) { 76554 return obj && obj.__esModule ? obj : { default: obj }; 76555 } ////////////////////////////////////////////////////////////// 76556 // http://mrl.nyu.edu/~perlin/noise/ 76557 // Adapting from PApplet.java 76558 // which was adapted from toxi 76559 // which was adapted from the german demo group farbrausch 76560 // as used in their demo "art": http://www.farb-rausch.de/fr010src.zip 76561 // someday we might consider using "improved noise" 76562 // http://mrl.nyu.edu/~perlin/paper445.pdf 76563 // See: https://github.com/shiffman/The-Nature-of-Code-Examples-p5.js/ 76564 // blob/main/introduction/Noise1D/noise.js 76565 /** 76566 * @module Math 76567 * @submodule Noise 76568 * @for p5 76569 * @requires core 76570 */ var PERLIN_YWRAPB = 4; 76571 var PERLIN_YWRAP = 1 << PERLIN_YWRAPB; 76572 var PERLIN_ZWRAPB = 8; 76573 var PERLIN_ZWRAP = 1 << PERLIN_ZWRAPB; 76574 var PERLIN_SIZE = 4095; 76575 var perlin_octaves = 4; // default to medium smooth 76576 var perlin_amp_falloff = 0.5; // 50% reduction/octave 76577 var scaled_cosine = function scaled_cosine(i) { 76578 return 0.5 * (1.0 - Math.cos(i * Math.PI)); 76579 }; 76580 var perlin; // will be initialized lazily by noise() or noiseSeed() 76581 /** 76582 * Returns the Perlin noise value at specified coordinates. Perlin noise is 76583 * a random sequence generator producing a more naturally ordered, harmonic 76584 * succession of numbers compared to the standard <b>random()</b> function. 76585 * It was invented by Ken Perlin in the 1980s and been used since in 76586 * graphical applications to produce procedural textures, natural motion, 76587 * shapes, terrains etc.<br /><br /> The main difference to the 76588 * <b>random()</b> function is that Perlin noise is defined in an infinite 76589 * n-dimensional space where each pair of coordinates corresponds to a 76590 * fixed semi-random value (fixed only for the lifespan of the program; see 76591 * the <a href="#/p5/noiseSeed">noiseSeed()</a> function). p5.js can compute 1D, 2D and 3D noise, 76592 * depending on the number of coordinates given. The resulting value will 76593 * always be between 0.0 and 1.0. The noise value can be animated by moving 76594 * through the noise space as demonstrated in the example above. The 2nd 76595 * and 3rd dimension can also be interpreted as time.<br /><br />The actual 76596 * noise is structured similar to an audio signal, in respect to the 76597 * function's use of frequencies. Similar to the concept of harmonics in 76598 * physics, perlin noise is computed over several octaves which are added 76599 * together for the final result. <br /><br />Another way to adjust the 76600 * character of the resulting sequence is the scale of the input 76601 * coordinates. As the function works within an infinite space the value of 76602 * the coordinates doesn't matter as such, only the distance between 76603 * successive coordinates does (eg. when using <b>noise()</b> within a 76604 * loop). As a general rule the smaller the difference between coordinates, 76605 * the smoother the resulting noise sequence will be. Steps of 0.005-0.03 76606 * work best for most applications, but this will differ depending on use. 76607 * 76608 * @method noise 76609 * @param {Number} x x-coordinate in noise space 76610 * @param {Number} [y] y-coordinate in noise space 76611 * @param {Number} [z] z-coordinate in noise space 76612 * @return {Number} Perlin noise value (between 0 and 1) at specified 76613 * coordinates 76614 * @example 76615 * <div> 76616 * <code> 76617 * let xoff = 0.0; 76618 * 76619 * function draw() { 76620 * background(204); 76621 * xoff = xoff + 0.01; 76622 * let n = noise(xoff) * width; 76623 * line(n, 0, n, height); 76624 * } 76625 * </code> 76626 * </div> 76627 * <div> 76628 * <code>let noiseScale=0.02; 76629 * 76630 * function draw() { 76631 * background(0); 76632 * for (let x=0; x < width; x++) { 76633 * let noiseVal = noise((mouseX+x)*noiseScale, mouseY*noiseScale); 76634 * stroke(noiseVal*255); 76635 * line(x, mouseY+noiseVal*80, x, height); 76636 * } 76637 * } 76638 * </code> 76639 * </div> 76640 * 76641 * @alt 76642 * vertical line moves left to right with updating noise values. 76643 * horizontal wave pattern effected by mouse x-position & updating noise values. 76644 */ _main.default.prototype.noise = function(x) { 76645 var y = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; 76646 var z = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; 76647 if (perlin == null) { 76648 perlin = new Array(PERLIN_SIZE + 1); 76649 for (var i = 0; i < PERLIN_SIZE + 1; i++) { 76650 perlin[i] = Math.random(); 76651 } 76652 } 76653 76654 if (x < 0) { 76655 x = -x; 76656 } 76657 if (y < 0) { 76658 y = -y; 76659 } 76660 if (z < 0) { 76661 z = -z; 76662 } 76663 76664 var xi = Math.floor(x), 76665 yi = Math.floor(y), 76666 zi = Math.floor(z); 76667 var xf = x - xi; 76668 var yf = y - yi; 76669 var zf = z - zi; 76670 var rxf, ryf; 76671 76672 var r = 0; 76673 var ampl = 0.5; 76674 76675 var n1, n2, n3; 76676 76677 for (var o = 0; o < perlin_octaves; o++) { 76678 var of = xi + (yi << PERLIN_YWRAPB) + (zi << PERLIN_ZWRAPB); 76679 76680 rxf = scaled_cosine(xf); 76681 ryf = scaled_cosine(yf); 76682 76683 n1 = perlin[of & PERLIN_SIZE]; 76684 n1 += rxf * (perlin[(of + 1) & PERLIN_SIZE] - n1); 76685 n2 = perlin[(of + PERLIN_YWRAP) & PERLIN_SIZE]; 76686 n2 += rxf * (perlin[(of + PERLIN_YWRAP + 1) & PERLIN_SIZE] - n2); 76687 n1 += ryf * (n2 - n1); 76688 76689 of += PERLIN_ZWRAP; 76690 n2 = perlin[of & PERLIN_SIZE]; 76691 n2 += rxf * (perlin[(of + 1) & PERLIN_SIZE] - n2); 76692 n3 = perlin[(of + PERLIN_YWRAP) & PERLIN_SIZE]; 76693 n3 += rxf * (perlin[(of + PERLIN_YWRAP + 1) & PERLIN_SIZE] - n3); 76694 n2 += ryf * (n3 - n2); 76695 76696 n1 += scaled_cosine(zf) * (n2 - n1); 76697 76698 r += n1 * ampl; 76699 ampl *= perlin_amp_falloff; 76700 xi <<= 1; 76701 xf *= 2; 76702 yi <<= 1; 76703 yf *= 2; 76704 zi <<= 1; 76705 zf *= 2; 76706 76707 if (xf >= 1.0) { 76708 xi++; 76709 xf--; 76710 } 76711 if (yf >= 1.0) { 76712 yi++; 76713 yf--; 76714 } 76715 if (zf >= 1.0) { 76716 zi++; 76717 zf--; 76718 } 76719 } 76720 return r; 76721 }; 76722 76723 /** 76724 * 76725 * Adjusts the character and level of detail produced by the Perlin noise 76726 * function. Similar to harmonics in physics, noise is computed over 76727 * several octaves. Lower octaves contribute more to the output signal and 76728 * as such define the overall intensity of the noise, whereas higher octaves 76729 * create finer grained details in the noise sequence. 76730 * 76731 * By default, noise is computed over 4 octaves with each octave contributing 76732 * exactly half than its predecessor, starting at 50% strength for the 1st 76733 * octave. This falloff amount can be changed by adding an additional function 76734 * parameter. Eg. a falloff factor of 0.75 means each octave will now have 76735 * 75% impact (25% less) of the previous lower octave. Any value between 76736 * 0.0 and 1.0 is valid, however note that values greater than 0.5 might 76737 * result in greater than 1.0 values returned by <b>noise()</b>. 76738 * 76739 * By changing these parameters, the signal created by the <b>noise()</b> 76740 * function can be adapted to fit very specific needs and characteristics. 76741 * 76742 * @method noiseDetail 76743 * @param {Number} lod number of octaves to be used by the noise 76744 * @param {Number} falloff falloff factor for each octave 76745 * @example 76746 * <div> 76747 * <code> 76748 * let noiseVal; 76749 * let noiseScale = 0.02; 76750 * 76751 * function setup() { 76752 * createCanvas(100, 100); 76753 * } 76754 * 76755 * function draw() { 76756 * background(0); 76757 * for (let y = 0; y < height; y++) { 76758 * for (let x = 0; x < width / 2; x++) { 76759 * noiseDetail(2, 0.2); 76760 * noiseVal = noise((mouseX + x) * noiseScale, (mouseY + y) * noiseScale); 76761 * stroke(noiseVal * 255); 76762 * point(x, y); 76763 * noiseDetail(8, 0.65); 76764 * noiseVal = noise( 76765 * (mouseX + x + width / 2) * noiseScale, 76766 * (mouseY + y) * noiseScale 76767 * ); 76768 * stroke(noiseVal * 255); 76769 * point(x + width / 2, y); 76770 * } 76771 * } 76772 * } 76773 * </code> 76774 * </div> 76775 * 76776 * @alt 76777 * 2 vertical grey smokey patterns affected my mouse x-position and noise. 76778 */ 76779 _main.default.prototype.noiseDetail = function(lod, falloff) { 76780 if (lod > 0) { 76781 perlin_octaves = lod; 76782 } 76783 if (falloff > 0) { 76784 perlin_amp_falloff = falloff; 76785 } 76786 }; 76787 76788 /** 76789 * Sets the seed value for <b>noise()</b>. By default, <b>noise()</b> 76790 * produces different results each time the program is run. Set the 76791 * <b>value</b> parameter to a constant to return the same pseudo-random
76792 * numbers each time the software is run. 76793 * 76794 * @method noiseSeed 76795 * @param {Number} seed the seed value 76796 * @example 76797 * <div> 76798 * <code>let xoff = 0.0; 76799 * 76800 * function setup() { 76801 * noiseSeed(99); 76802 * stroke(0, 10); 76803 * } 76804 * 76805 * function draw() { 76806 * xoff = xoff + .01; 76807 * let n = noise(xoff) * width; 76808 * line(n, 0, n, height); 76809 * } 76810 * </code> 76811 * </div> 76812 * 76813 * @alt 76814 * vertical grey lines drawing in pattern affected by noise. 76815 */ 76816 _main.default.prototype.noiseSeed = function(seed) { 76817 // Linear Congruential Generator 76818 // Variant of a Lehman Generator 76819 var lcg = (function() { 76820 // Set to values from http://en.wikipedia.org/wiki/Numerical_Recipes 76821 // m is basically chosen to be large (as it is the max period) 76822 // and for its relationships to a and c 76823 var m = 4294967296; 76824 // a - 1 should be divisible by m's prime factors 76825 var a = 1664525; 76826 // c and m should be co-prime 76827 var c = 1013904223; 76828 var seed, z; 76829 return { 76830 setSeed: function setSeed(val) { 76831 // pick a random seed if val is undefined or null 76832 // the >>> 0 casts the seed to an unsigned 32-bit integer 76833 z = seed = (val == null ? Math.random() * m : val) >>> 0; 76834 }, 76835 getSeed: function getSeed() { 76836 return seed; 76837 }, 76838 rand: function rand() { 76839 // define the recurrence relationship 76840 z = (a * z + c) % m; 76841 // return a float in [0, 1) 76842 // if z = m then z / m = 0 therefore (z % m) / m < 1 always 76843 return z / m; 76844 } 76845 }; 76846 })(); 76847 76848 lcg.setSeed(seed); 76849 perlin = new Array(PERLIN_SIZE + 1); 76850 for (var i = 0; i < PERLIN_SIZE + 1; i++) { 76851 perlin[i] = lcg.rand(); 76852 } 76853 }; 76854 var _default = _main.default; 76855 exports.default = _default; 76856 }, 76857 { '../core/main': 59 } 76858 ], 76859 92: [ 76860 function(_dereq_, module, exports) { 76861 'use strict'; 76862 function _typeof(obj) { 76863 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') { 76864 _typeof = function _typeof(obj) { 76865 return typeof obj; 76866 }; 76867 } else { 76868 _typeof = function _typeof(obj) { 76869 return obj && 76870 typeof Symbol === 'function' && 76871 obj.constructor === Symbol && 76872 obj !== Symbol.prototype 76873 ? 'symbol' 76874 : typeof obj; 76875 }; 76876 } 76877 return _typeof(obj); 76878 } 76879 Object.defineProperty(exports, '__esModule', { value: true }); 76880 exports.default = void 0; 76881 76882 var _main = _interopRequireDefault(_dereq_('../core/main')); 76883 var constants = _interopRequireWildcard(_dereq_('../core/constants')); 76884 function _getRequireWildcardCache() { 76885 if (typeof WeakMap !== 'function') return null; 76886 var cache = new WeakMap(); 76887 _getRequireWildcardCache = function _getRequireWildcardCache() { 76888 return cache; 76889 }; 76890 return cache; 76891 } 76892 function _interopRequireWildcard(obj) { 76893 if (obj && obj.__esModule) { 76894 return obj; 76895 } 76896 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) { 76897 return { default: obj }; 76898 } 76899 var cache = _getRequireWildcardCache(); 76900 if (cache && cache.has(obj)) { 76901 return cache.get(obj); 76902 } 76903 var newObj = {}; 76904 var hasPropertyDescriptor = 76905 Object.defineProperty && Object.getOwnPropertyDescriptor; 76906 for (var key in obj) { 76907 if (Object.prototype.hasOwnProperty.call(obj, key)) { 76908 var desc = hasPropertyDescriptor 76909 ? Object.getOwnPropertyDescriptor(obj, key) 76910 : null; 76911 if (desc && (desc.get || desc.set)) { 76912 Object.defineProperty(newObj, key, desc); 76913 } else { 76914 newObj[key] = obj[key]; 76915 } 76916 } 76917 } 76918 newObj.default = obj; 76919 if (cache) { 76920 cache.set(obj, newObj); 76921 } 76922 return newObj; 76923 } 76924 function _interopRequireDefault(obj) { 76925 return obj && obj.__esModule ? obj : { default: obj }; 76926 } 76927 /** 76928 * @module Math 76929 * @submodule Vector 76930 * @requires constants 76931 */ /** 76932 * A class to describe a two or three dimensional vector, specifically 76933 * a Euclidean (also known as geometric) vector. A vector is an entity 76934 * that has both magnitude and direction. The datatype, however, stores 76935 * the components of the vector (x, y for 2D, and x, y, z for 3D). The magnitude 76936 * and direction can be accessed via the methods <a href="#/p5.Vector/mag">mag()</a> and <a href="#/p5.Vector/heading">heading()</a>. 76937 * 76938 * In many of the p5.js examples, you will see <a href="#/p5.Vector">p5.Vector</a> used to describe a 76939 * position, velocity, or acceleration. For example, if you consider a rectangle 76940 * moving across the screen, at any given instant it has a position (a vector 76941 * that points from the origin to its location), a velocity (the rate at which 76942 * the object's position changes per time unit, expressed as a vector), and 76943 * acceleration (the rate at which the object's velocity changes per time 76944 * unit, expressed as a vector). 76945 * 76946 * Since vectors represent groupings of values, we cannot simply use 76947 * traditional addition/multiplication/etc. Instead, we'll need to do some 76948 * "vector" math, which is made easy by the methods inside the <a href="#/p5.Vector">p5.Vector</a> class. 76949 * 76950 * @class p5.Vector 76951 * @constructor 76952 * @param {Number} [x] x component of the vector 76953 * @param {Number} [y] y component of the vector 76954 * @param {Number} [z] z component of the vector 76955 * @example 76956 * <div> 76957 * <code> 76958 * let v1 = createVector(40, 50); 76959 * let v2 = createVector(40, 50); 76960 * 76961 * ellipse(v1.x, v1.y, 50, 50); 76962 * ellipse(v2.x, v2.y, 50, 50); 76963 * v1.add(v2); 76964 * ellipse(v1.x, v1.y, 50, 50); 76965 * </code> 76966 * </div> 76967 * 76968 * @alt 76969 * 2 white ellipses. One center-left the other bottom right and off canvas 76970 */ _main.default.Vector = function Vector() { 76971 var x, y, z; 76972 // This is how it comes in with createVector() 76973 if (arguments[0] instanceof _main.default) { 76974 // save reference to p5 if passed in 76975 this.p5 = arguments[0]; 76976 x = arguments[1][0] || 0; 76977 y = arguments[1][1] || 0; 76978 z = arguments[1][2] || 0; 76979 // This is what we'll get with new p5.Vector() 76980 } else { 76981 x = arguments[0] || 0; 76982 y = arguments[1] || 0; 76983 z = arguments[2] || 0; 76984 } 76985 /** 76986 * The x component of the vector 76987 * @property x {Number} 76988 */ 76989 this.x = x; 76990 /** 76991 * The y component of the vector 76992 * @property y {Number} 76993 */ 76994 this.y = y; 76995 /** 76996 * The z component of the vector 76997 * @property z {Number} 76998 */ 76999 this.z = z; 77000 }; 77001 77002 /** 77003 * Returns a string representation of a vector v by calling String(v) 77004 * or v.toString(). This method is useful for logging vectors in the 77005 * console. 77006 * @method toString 77007 * @return {String} 77008 * @example 77009 * <div class = "norender"> 77010 * <code> 77011 * function setup() { 77012 * let v = createVector(20, 30); 77013 * print(String(v)); // prints "p5.Vector Object : [20, 30, 0]" 77014 * } 77015 * </code> 77016 * </div> 77017 * 77018 * <div> 77019 * <code> 77020 * function draw() { 77021 * background(240); 77022 * 77023 * let v0 = createVector(0, 0); 77024 * let v1 = createVector(mouseX, mouseY); 77025 * drawArrow(v0, v1, 'black'); 77026 * 77027 * noStroke(); 77028 * text(v1.toString(), 10, 25, 90, 75); 77029 * } 77030 * 77031 * // draw an arrow for a vector at a given base position 77032 * function drawArrow(base, vec, myColor) { 77033 * push(); 77034 * stroke(myColor); 77035 * strokeWeight(3); 77036 * fill(myColor); 77037 * translate(base.x, base.y); 77038 * line(0, 0, vec.x, vec.y); 77039 * rotate(vec.heading()); 77040 * let arrowSize = 7; 77041 * translate(vec.mag() - arrowSize, 0); 77042 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0); 77043 * pop(); 77044 * } 77045 * </code> 77046 * </div> 77047 */ 77048 _main.default.Vector.prototype.toString = function p5VectorToString() { 77049 return 'p5.Vector Object : [' 77050 .concat(this.x, ', ') 77051 .concat(this.y, ', ') 77052 .concat(this.z, ']'); 77053 }; 77054 77055 /** 77056 * Sets the x, y, and z component of the vector using two or three separate 77057 * variables, the data from a <a href="#/p5.Vector">p5.Vector</a>, or the values from a float array. 77058 * @method set 77059 * @param {Number} [x] the x component of the vector 77060 * @param {Number} [y] the y component of the vector 77061 * @param {Number} [z] the z component of the vector 77062 * @chainable 77063 * @example 77064 * <div class="norender"> 77065 * <code> 77066 * function setup() { 77067 * let v = createVector(1, 2, 3);
77068 * v.set(4, 5, 6); // Sets vector to [4, 5, 6] 77069 * 77070 * let v1 = createVector(0, 0, 0); 77071 * let arr = [1, 2, 3]; 77072 * v1.set(arr); // Sets vector to [1, 2, 3] 77073 * } 77074 * </code> 77075 * </div> 77076 * 77077 * <div> 77078 * <code> 77079 * let v0, v1; 77080 * function setup() { 77081 * createCanvas(100, 100); 77082 * 77083 * v0 = createVector(0, 0); 77084 * v1 = createVector(50, 50); 77085 * } 77086 * 77087 * function draw() { 77088 * background(240); 77089 * 77090 * drawArrow(v0, v1, 'black'); 77091 * v1.set(v1.x + random(-1, 1), v1.y + random(-1, 1)); 77092 * 77093 * noStroke(); 77094 * text('x: ' + round(v1.x) + ' y: ' + round(v1.y), 20, 90); 77095 * } 77096 * 77097 * // draw an arrow for a vector at a given base position 77098 * function drawArrow(base, vec, myColor) { 77099 * push(); 77100 * stroke(myColor); 77101 * strokeWeight(3); 77102 * fill(myColor); 77103 * translate(base.x, base.y); 77104 * line(0, 0, vec.x, vec.y); 77105 * rotate(vec.heading()); 77106 * let arrowSize = 7; 77107 * translate(vec.mag() - arrowSize, 0); 77108 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0); 77109 * pop(); 77110 * } 77111 * </code> 77112 * </div> 77113 */ 77114 /** 77115 * @method set 77116 * @param {p5.Vector|Number[]} value the vector to set 77117 * @chainable 77118 */ 77119 _main.default.Vector.prototype.set = function set(x, y, z) { 77120 if (x instanceof _main.default.Vector) { 77121 this.x = x.x || 0; 77122 this.y = x.y || 0; 77123 this.z = x.z || 0; 77124 return this; 77125 } 77126 if (x instanceof Array) { 77127 this.x = x[0] || 0; 77128 this.y = x[1] || 0; 77129 this.z = x[2] || 0; 77130 return this; 77131 } 77132 this.x = x || 0; 77133 this.y = y || 0; 77134 this.z = z || 0; 77135 return this; 77136 }; 77137 77138 /** 77139 * Gets a copy of the vector, returns a <a href="#/p5.Vector">p5.Vector</a> object. 77140 * 77141 * @method copy 77142 * @return {p5.Vector} the copy of the <a href="#/p5.Vector">p5.Vector</a> object 77143 * @example 77144 * <div class="norender"> 77145 * <code> 77146 * let v1 = createVector(1, 2, 3); 77147 * let v2 = v1.copy(); 77148 * print(v1.x === v2.x && v1.y === v2.y && v1.z === v2.z); 77149 * // Prints "true" 77150 * </code> 77151 * </div> 77152 */ 77153 _main.default.Vector.prototype.copy = function copy() { 77154 if (this.p5) { 77155 return new _main.default.Vector(this.p5, [this.x, this.y, this.z]); 77156 } else { 77157 return new _main.default.Vector(this.x, this.y, this.z); 77158 } 77159 }; 77160 77161 /** 77162 * Adds x, y, and z components to a vector, adds one vector to another, or 77163 * adds two independent vectors together. The version of the method that adds 77164 * two vectors together is a static method and returns a <a href="#/p5.Vector">p5.Vector</a>, the others 77165 * acts directly on the vector. Additionally, you may provide arguments to this function as an array. 77166 * See the examples for more context. 77167 * 77168 * @method add 77169 * @param {Number} x the x component of the vector to be added 77170 * @param {Number} [y] the y component of the vector to be added 77171 * @param {Number} [z] the z component of the vector to be added 77172 * @chainable 77173 * @example 77174 * <div class="norender"> 77175 * <code> 77176 * let v = createVector(1, 2, 3); 77177 * v.add(4, 5, 6); 77178 * // v's components are set to [5, 7, 9] 77179 * </code> 77180 * </div> 77181 * 77182 * <div class="norender"> 77183 * <code> 77184 * let v = createVector(1, 2, 3); 77185 * // Provide arguments as an array 77186 * let arr = [4, 5, 6]; 77187 * v.add(arr); 77188 * // v's components are set to [5, 7, 9] 77189 * </code> 77190 * </div> 77191 * 77192 * <div class="norender"> 77193 * <code> 77194 * // Static method 77195 * let v1 = createVector(1, 2, 3); 77196 * let v2 = createVector(2, 3, 4); 77197 * 77198 * let v3 = p5.Vector.add(v1, v2); 77199 * // v3 has components [3, 5, 7] 77200 * print(v3); 77201 * </code> 77202 * </div> 77203 * 77204 * <div> 77205 * <code> 77206 * // red vector + blue vector = purple vector 77207 * function draw() { 77208 * background(240); 77209 * 77210 * let v0 = createVector(0, 0); 77211 * let v1 = createVector(mouseX, mouseY); 77212 * drawArrow(v0, v1, 'red'); 77213 * 77214 * let v2 = createVector(-30, 20); 77215 * drawArrow(v1, v2, 'blue'); 77216 * 77217 * let v3 = p5.Vector.add(v1, v2); 77218 * drawArrow(v0, v3, 'purple'); 77219 * } 77220 * 77221 * // draw an arrow for a vector at a given base position 77222 * function drawArrow(base, vec, myColor) { 77223 * push(); 77224 * stroke(myColor); 77225 * strokeWeight(3); 77226 * fill(myColor); 77227 * translate(base.x, base.y); 77228 * line(0, 0, vec.x, vec.y); 77229 * rotate(vec.heading()); 77230 * let arrowSize = 7; 77231 * translate(vec.mag() - arrowSize, 0); 77232 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0); 77233 * pop(); 77234 * } 77235 * </code> 77236 * </div> 77237 */ 77238 /** 77239 * @method add 77240 * @param {p5.Vector|Number[]} value the vector to add 77241 * @chainable 77242 */ 77243 _main.default.Vector.prototype.add = function add(x, y, z) { 77244 if (x instanceof _main.default.Vector) { 77245 this.x += x.x || 0; 77246 this.y += x.y || 0; 77247 this.z += x.z || 0; 77248 return this; 77249 } 77250 if (x instanceof Array) { 77251 this.x += x[0] || 0; 77252 this.y += x[1] || 0; 77253 this.z += x[2] || 0; 77254 return this; 77255 } 77256 this.x += x || 0; 77257 this.y += y || 0; 77258 this.z += z || 0; 77259 return this; 77260 }; 77261 77262 /// HELPERS FOR REMAINDER METHOD 77263 var calculateRemainder2D = function calculateRemainder2D(xComponent, yComponent) { 77264 if (xComponent !== 0) { 77265 this.x = this.x % xComponent; 77266 } 77267 if (yComponent !== 0) { 77268 this.y = this.y % yComponent; 77269 } 77270 return this; 77271 }; 77272 77273 var calculateRemainder3D = function calculateRemainder3D( 77274 xComponent, 77275 yComponent, 77276 zComponent 77277 ) { 77278 if (xComponent !== 0) { 77279 this.x = this.x % xComponent; 77280 } 77281 if (yComponent !== 0) { 77282 this.y = this.y % yComponent; 77283 }
77284 if (zComponent !== 0) { 77285 this.z = this.z % zComponent; 77286 } 77287 return this; 77288 }; 77289 /** 77290 * Gives remainder of a vector when it is divided by another vector. 77291 * See examples for more context. 77292 * 77293 * @method rem 77294 * @param {Number} x the x component of divisor vector 77295 * @param {Number} y the y component of divisor vector 77296 * @param {Number} z the z component of divisor vector 77297 * @chainable 77298 * @example 77299 * <div class='norender'> 77300 * <code> 77301 * let v = createVector(3, 4, 5); 77302 * v.rem(2, 3, 4); 77303 * // v's components are set to [1, 1, 1] 77304 * </code> 77305 * </div> 77306 * <div class="norender"> 77307 * <code> 77308 * // Static method 77309 * let v1 = createVector(3, 4, 5); 77310 * let v2 = createVector(2, 3, 4); 77311 * 77312 * let v3 = p5.Vector.rem(v1, v2); 77313 * // v3 has components [1, 1, 1] 77314 * print(v3); 77315 * </code> 77316 * </div> 77317 */ 77318 /** 77319 * @method rem 77320 * @param {p5.Vector | Number[]} value divisor vector 77321 * @chainable 77322 */ 77323 _main.default.Vector.prototype.rem = function rem(x, y, z) { 77324 if (x instanceof _main.default.Vector) { 77325 if (Number.isFinite(x.x) && Number.isFinite(x.y) && Number.isFinite(x.z)) { 77326 var xComponent = parseFloat(x.x); 77327 var yComponent = parseFloat(x.y); 77328 var zComponent = parseFloat(x.z); 77329 calculateRemainder3D.call(this, xComponent, yComponent, zComponent); 77330 } 77331 } else if (x instanceof Array) { 77332 if ( 77333 x.every(function(element) { 77334 return Number.isFinite(element); 77335 }) 77336 ) { 77337 if (x.length === 2) { 77338 calculateRemainder2D.call(this, x[0], x[1]); 77339 } 77340 if (x.length === 3) { 77341 calculateRemainder3D.call(this, x[0], x[1], x[2]); 77342 } 77343 } 77344 } else if (arguments.length === 1) { 77345 if (Number.isFinite(arguments[0]) && arguments[0] !== 0) { 77346 this.x = this.x % arguments[0]; 77347 this.y = this.y % arguments[0]; 77348 this.z = this.z % arguments[0]; 77349 return this; 77350 } 77351 } else if (arguments.length === 2) { 77352 var vectorComponents = Array.prototype.slice.call(arguments); 77353 if ( 77354 vectorComponents.every(function(element) { 77355 return Number.isFinite(element); 77356 }) 77357 ) { 77358 if (vectorComponents.length === 2) { 77359 calculateRemainder2D.call(this, vectorComponents[0], vectorComponents[1]); 77360 } 77361 } 77362 } else if (arguments.length === 3) { 77363 var _vectorComponents = Array.prototype.slice.call(arguments); 77364 if ( 77365 _vectorComponents.every(function(element) { 77366 return Number.isFinite(element); 77367 }) 77368 ) { 77369 if (_vectorComponents.length === 3) { 77370 calculateRemainder3D.call( 77371 this, 77372 _vectorComponents[0], 77373 _vectorComponents[1], 77374 _vectorComponents[2] 77375 ); 77376 } 77377 } 77378 } 77379 }; 77380 77381 /** 77382 * Subtracts x, y, and z components from a vector, subtracts one vector from 77383 * another, or subtracts two independent vectors. The version of the method 77384 * that subtracts two vectors is a static method and returns a <a href="#/p5.Vector">p5.Vector</a>, the 77385 * other acts directly on the vector. Additionally, you may provide arguments to this function as an array. 77386 * See the examples for more context. 77387 * 77388 * @method sub 77389 * @param {Number} x the x component of the vector to subtract 77390 * @param {Number} [y] the y component of the vector to subtract 77391 * @param {Number} [z] the z component of the vector to subtract 77392 * @chainable 77393 * @example 77394 * <div class="norender"> 77395 * <code>
77396 * let v = createVector(4, 5, 6); 77397 * v.sub(1, 1, 1); 77398 * // v's components are set to [3, 4, 5] 77399 * </code> 77400 * </div> 77401 * 77402 * <div class="norender"> 77403 * <code> 77404 * let v = createVector(4, 5, 6); 77405 * // Provide arguments as an array 77406 * let arr = [1, 1, 1]; 77407 * v.sub(arr); 77408 * // v's components are set to [3, 4, 5] 77409 * </code> 77410 * </div> 77411 * 77412 * <div class="norender"> 77413 * <code> 77414 * // Static method 77415 * let v1 = createVector(2, 3, 4); 77416 * let v2 = createVector(1, 2, 3); 77417 * 77418 * let v3 = p5.Vector.sub(v1, v2); 77419 * // v3 has components [1, 1, 1] 77420 * print(v3); 77421 * </code> 77422 * </div> 77423 * 77424 * <div> 77425 * <code> 77426 * // red vector - blue vector = purple vector 77427 * function draw() { 77428 * background(240); 77429 * 77430 * let v0 = createVector(0, 0); 77431 * let v1 = createVector(70, 50); 77432 * drawArrow(v0, v1, 'red'); 77433 * 77434 * let v2 = createVector(mouseX, mouseY); 77435 * drawArrow(v0, v2, 'blue'); 77436 * 77437 * let v3 = p5.Vector.sub(v1, v2); 77438 * drawArrow(v2, v3, 'purple'); 77439 * } 77440 * 77441 * // draw an arrow for a vector at a given base position 77442 * function drawArrow(base, vec, myColor) { 77443 * push(); 77444 * stroke(myColor); 77445 * strokeWeight(3); 77446 * fill(myColor); 77447 * translate(base.x, base.y); 77448 * line(0, 0, vec.x, vec.y); 77449 * rotate(vec.heading()); 77450 * let arrowSize = 7; 77451 * translate(vec.mag() - arrowSize, 0); 77452 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0); 77453 * pop(); 77454 * } 77455 * </code> 77456 * </div> 77457 */ 77458 /** 77459 * @method sub 77460 * @param {p5.Vector|Number[]} value the vector to subtract 77461 * @chainable 77462 */ 77463 _main.default.Vector.prototype.sub = function sub(x, y, z) { 77464 if (x instanceof _main.default.Vector) { 77465 this.x -= x.x || 0; 77466 this.y -= x.y || 0; 77467 this.z -= x.z || 0; 77468 return this; 77469 } 77470 if (x instanceof Array) { 77471 this.x -= x[0] || 0; 77472 this.y -= x[1] || 0; 77473 this.z -= x[2] || 0; 77474 return this; 77475 } 77476 this.x -= x || 0; 77477 this.y -= y || 0; 77478 this.z -= z || 0; 77479 return this; 77480 }; 77481 77482 /** 77483 * Multiplies the vector by a scalar, multiplies the x, y, and z components from a vector, or multiplies 77484 * the x, y, and z components of two independent vectors. When multiplying a vector by a scalar, the x, y, 77485 * and z components of the vector are all multiplied by the scalar. When multiplying a vector by a vector, 77486 * the x, y, z components of both vectors are multiplied by each other 77487 * (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 77488 * creates a new <a href="#/p5.Vector">p5.Vector</a> while the non static version acts on the vector 77489 * directly. Additionally, you may provide arguments to this function as an array. 77490 * See the examples for more context. 77491 * 77492 * @method mult 77493 * @param {Number} n The number to multiply with the vector 77494 * @chainable 77495 * @example 77496 * <div class="norender"> 77497 * <code> 77498 * let v = createVector(1, 2, 3); 77499 * v.mult(2); 77500 * // v's components are set to [2, 4, 6] 77501 * </code> 77502 * </div> 77503 * 77504 * <div class="norender"> 77505 * <code> 77506 * let v0 = createVector(1, 2, 3); 77507 * let v1 = createVector(2, 3, 4); 77508 * v0.mult(v1); // v0's components are set to [2, 6, 12] 77509 * </code> 77510 * </div> 77511 * 77512 * <div class="norender"> 77513 * <code> 77514 * let v0 = createVector(1, 2, 3); 77515 * // Provide arguments as an array 77516 * let arr = [2, 3, 4]; 77517 * v0.mult(arr); // v0's components are set to [2, 6, 12] 77518 * </code> 77519 * </div> 77520 * 77521 * <div class="norender"> 77522 * <code> 77523 * let v0 = createVector(1, 2, 3); 77524 * let v1 = createVector(2, 3, 4); 77525 * const result = p5.Vector.mult(v0, v1); 77526 * print(result); // result's components are set to [2, 6, 12] 77527 * </code> 77528 * </div> 77529 * 77530 * <div class="norender"> 77531 * <code> 77532 * // Static method 77533 * let v1 = createVector(1, 2, 3); 77534 * let v2 = p5.Vector.mult(v1, 2); 77535 * // v2 has components [2, 4, 6] 77536 * print(v2); 77537 * </code> 77538 * </div> 77539 * 77540 * <div> 77541 * <code> 77542 * function draw() { 77543 * background(240); 77544 * 77545 * let v0 = createVector(50, 50); 77546 * let v1 = createVector(25, -25); 77547 * drawArrow(v0, v1, 'red'); 77548 * 77549 * let num = map(mouseX, 0, width, -2, 2, true); 77550 * let v2 = p5.Vector.mult(v1, num); 77551 * drawArrow(v0, v2, 'blue'); 77552 * 77553 * noStroke(); 77554 * text('multiplied by ' + num.toFixed(2), 5, 90); 77555 * } 77556 * 77557 * // draw an arrow for a vector at a given base position 77558 * function drawArrow(base, vec, myColor) { 77559 * push(); 77560 * stroke(myColor); 77561 * strokeWeight(3); 77562 * fill(myColor); 77563 * translate(base.x, base.y); 77564 * line(0, 0, vec.x, vec.y); 77565 * rotate(vec.heading()); 77566 * let arrowSize = 7; 77567 * translate(vec.mag() - arrowSize, 0); 77568 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0); 77569 * pop(); 77570 * } 77571 * </code> 77572 * </div> 77573 */ 77574 77575 /** 77576 * @method mult 77577 * @param {Number} x The number to multiply with the x component of the vector 77578 * @param {Number} y The number to multiply with the y component of the vector 77579 * @param {Number} [z] The number to multiply with the z component of the vector 77580 * @chainable 77581 */ 77582 77583 /** 77584 * @method mult 77585 * @param {Number[]} arr The array to multiply with the components of the vector 77586 * @chainable 77587 */ 77588 77589 /** 77590 * @method mult 77591 * @param {p5.Vector} v The vector to multiply with the components of the original vector 77592 * @chainable 77593 */ 77594 77595 _main.default.Vector.prototype.mult = function mult(x, y, z) { 77596 if (x instanceof _main.default.Vector) { 77597 // new p5.Vector will check that values are valid upon construction but it's possible 77598 // that someone could change the value of a component after creation, which is why we still 77599 // perform this check 77600 if ( 77601 Number.isFinite(x.x) && 77602 Number.isFinite(x.y) && 77603 Number.isFinite(x.z) && 77604 typeof x.x === 'number' && 77605 typeof x.y === 'number' && 77606 typeof x.z === 'number' 77607 ) { 77608 this.x *= x.x; 77609 this.y *= x.y; 77610 this.z *= x.z; 77611 } else { 77612 console.warn( 77613 'p5.Vector.prototype.mult:', 77614 'x contains components that are either undefined or not finite numbers' 77615 ); 77616 } 77617 return this; 77618 } 77619 if (x instanceof Array) { 77620 if ( 77621 x.every(function(element) { 77622 return Number.isFinite(element); 77623 }) && 77624 x.every(function(element) { 77625 return typeof element === 'number'; 77626 }) 77627 ) { 77628 if (x.length === 1) { 77629 this.x *= x[0]; 77630 this.y *= x[0]; 77631 this.z *= x[0]; 77632 } else if (x.length === 2) { 77633 this.x *= x[0]; 77634 this.y *= x[1]; 77635 } else if (x.length === 3) { 77636 this.x *= x[0]; 77637 this.y *= x[1]; 77638 this.z *= x[2]; 77639 } 77640 } else { 77641 console.warn( 77642 'p5.Vector.prototype.mult:', 77643 'x contains elements that are either undefined or not finite numbers' 77644 ); 77645 } 77646 return this; 77647 } 77648 77649 var vectorComponents = Array.prototype.slice.call(arguments); 77650 if ( 77651 vectorComponents.every(function(element) { 77652 return Number.isFinite(element); 77653 }) && 77654 vectorComponents.every(function(element) { 77655 return typeof element === 'number'; 77656 }) 77657 ) { 77658 if (arguments.length === 1) { 77659 this.x *= x; 77660 this.y *= x; 77661 this.z *= x; 77662 } 77663 if (arguments.length === 2) { 77664 this.x *= x; 77665 this.y *= y; 77666 } 77667 if (arguments.length === 3) { 77668 this.x *= x; 77669 this.y *= y; 77670 this.z *= z; 77671 } 77672 } else { 77673 console.warn( 77674 'p5.Vector.prototype.mult:', 77675 'x, y, or z arguments are either undefined or not a finite number' 77676 ); 77677 } 77678 77679 return this; 77680 }; 77681 77682 /** 77683 * Divides the vector by a scalar, divides a vector by the x, y, and z arguments, or divides the x, y, and 77684 * z components of two vectors against each other. When dividing a vector by a scalar, the x, y, 77685 * and z components of the vector are all divided by the scalar. When dividing a vector by a vector, 77686 * the x, y, z components of the source vector are treated as the dividend, and the x, y, z components 77687 * 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). 77688 * The static version of this method creates a 77689 * new <a href="#/p5.Vector">p5.Vector</a> while the non static version acts on the vector directly. 77690 * Additionally, you may provide arguments to this function as an array.
77691 * See the examples for more context. 77692 * 77693 * @method div 77694 * @param {number} n The number to divide the vector by 77695 * @chainable 77696 * @example 77697 * <div class="norender"> 77698 * <code> 77699 * let v = createVector(6, 4, 2); 77700 * v.div(2); //v's components are set to [3, 2, 1] 77701 * </code> 77702 * </div> 77703 * 77704 * <div class="norender"> 77705 * <code> 77706 * let v0 = createVector(9, 4, 2); 77707 * let v1 = createVector(3, 2, 4); 77708 * v0.div(v1); // v0's components are set to [3, 2, 0.5] 77709 * </code> 77710 * </div> 77711 * 77712 * <div class="norender"> 77713 * <code> 77714 * let v0 = createVector(9, 4, 2); 77715 * // Provide arguments as an array 77716 * let arr = [3, 2, 4]; 77717 * v0.div(arr); // v0's components are set to [3, 2, 0.5] 77718 * </code> 77719 * </div> 77720 * 77721 * <div class="norender"> 77722 * <code> 77723 * let v0 = createVector(9, 4, 2); 77724 * let v1 = createVector(3, 2, 4); 77725 * let result = p5.Vector.div(v0, v1); 77726 * print(result); // result's components are set to [3, 2, 0.5] 77727 * </code> 77728 * </div> 77729 * 77730 * <div class="norender"> 77731 * <code> 77732 * // Static method 77733 * let v1 = createVector(6, 4, 2); 77734 * let v2 = p5.Vector.div(v1, 2); 77735 * // v2 has components [3, 2, 1] 77736 * print(v2); 77737 * </code> 77738 * </div> 77739 * 77740 * <div> 77741 * <code> 77742 * function draw() { 77743 * background(240); 77744 * 77745 * let v0 = createVector(0, 100); 77746 * let v1 = createVector(50, -50); 77747 * drawArrow(v0, v1, 'red'); 77748 * 77749 * let num = map(mouseX, 0, width, 10, 0.5, true); 77750 * let v2 = p5.Vector.div(v1, num); 77751 * drawArrow(v0, v2, 'blue'); 77752 * 77753 * noStroke(); 77754 * text('divided by ' + num.toFixed(2), 10, 90); 77755 * } 77756 * 77757 * // draw an arrow for a vector at a given base position 77758 * function drawArrow(base, vec, myColor) { 77759 * push(); 77760 * stroke(myColor); 77761 * strokeWeight(3); 77762 * fill(myColor); 77763 * translate(base.x, base.y); 77764 * line(0, 0, vec.x, vec.y); 77765 * rotate(vec.heading()); 77766 * let arrowSize = 7; 77767 * translate(vec.mag() - arrowSize, 0); 77768 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0); 77769 * pop(); 77770 * } 77771 * </code> 77772 * </div> 77773 */ 77774 77775 /** 77776 * @method div 77777 * @param {Number} x The number to divide with the x component of the vector 77778 * @param {Number} y The number to divide with the y component of the vector 77779 * @param {Number} [z] The number to divide with the z component of the vector 77780 * @chainable 77781 */ 77782 77783 /** 77784 * @method div 77785 * @param {Number[]} arr The array to divide the components of the vector by 77786 * @chainable 77787 */ 77788 77789 /** 77790 * @method div 77791 * @param {p5.Vector} v The vector to divide the components of the original vector by 77792 * @chainable 77793 */ 77794 _main.default.Vector.prototype.div = function div(x, y, z) { 77795 if (x instanceof _main.default.Vector) { 77796 // new p5.Vector will check that values are valid upon construction but it's possible 77797 // that someone could change the value of a component after creation, which is why we still 77798 // perform this check 77799 if ( 77800 Number.isFinite(x.x) && 77801 Number.isFinite(x.y) && 77802 Number.isFinite(x.z) && 77803 typeof x.x === 'number' && 77804 typeof x.y === 'number' && 77805 typeof x.z === 'number' 77806 ) { 77807 if (x.x === 0 || x.y === 0 || x.z === 0) { 77808 console.warn('p5.Vector.prototype.div:', 'divi
77808de by 0'); 77809 return this; 77810 } 77811 this.x /= x.x; 77812 this.y /= x.y; 77813 this.z /= x.z; 77814 } else { 77815 console.warn( 77816 'p5.Vector.prototype.div:', 77817 'x contains components that are either undefined or not finite numbers' 77818 ); 77819 } 77820 return this; 77821 } 77822 if (x instanceof Array) { 77823 if ( 77824 x.every(function(element) { 77825 return Number.isFinite(element); 77826 }) && 77827 x.every(function(element) { 77828 return typeof element === 'number'; 77829 }) 77830 ) { 77831 if ( 77832 x.some(function(element) { 77833 return element === 0; 77834 }) 77835 ) { 77836 console.warn('p5.Vector.prototype.div:', 'divide by 0'); 77837 return this; 77838 } 77839 77840 if (x.length === 1) { 77841 this.x /= x[0]; 77842 this.y /= x[0]; 77843 this.z /= x[0]; 77844 } else if (x.length === 2) { 77845 this.x /= x[0]; 77846 this.y /= x[1]; 77847 } else if (x.length === 3) { 77848 this.x /= x[0]; 77849 this.y /= x[1]; 77850 this.z /= x[2]; 77851 } 77852 } else { 77853 console.warn( 77854 'p5.Vector.prototype.div:', 77855 'x contains components that are either undefined or not finite numbers' 77856 ); 77857 } 77858 77859 return this; 77860 } 77861 77862 var vectorComponents = Array.prototype.slice.call(arguments); 77863 if ( 77864 vectorComponents.every(function(element) { 77865 return Number.isFinite(element); 77866 }) && 77867 vectorComponents.every(function(element) { 77868 return typeof element === 'number'; 77869 }) 77870 ) { 77871 if ( 77872 vectorComponents.some(function(element) { 77873 return element === 0; 77874 }) 77875 ) { 77876 console.warn('p5.Vector.prototype.div:', 'divide by 0'); 77877 return this; 77878 } 77879 77880 if (arguments.length === 1) { 77881 this.x /= x; 77882 this.y /= x; 77883 this.z /= x; 77884 } 77885 if (arguments.length === 2) { 77886 this.x /= x; 77887 this.y /= y; 77888 } 77889 if (arguments.length === 3) { 77890 this.x /= x; 77891 this.y /= y; 77892 this.z /= z; 77893 } 77894 } else { 77895 console.warn( 77896 'p5.Vector.prototype.div:', 77897 'x, y, or z arguments are either undefined or not a finite number' 77898 ); 77899 } 77900 77901 return this; 77902 }; 77903 /** 77904 * Calculates the magnitude (length) of the vector and returns the result as 77905 * a float (this is simply the equation sqrt(x\*x + y\*y + z\*z).) 77906 * 77907 * @method mag 77908 * @return {Number} magnitude of the vector 77909 * @example 77910 * <div> 77911 * <code> 77912 * function draw() { 77913 * background(240); 77914 * 77915 * let v0 = createVector(0, 0); 77916 * let v1 = createVector(mouseX, mouseY); 77917 * drawArrow(v0, v1, 'black'); 77918 * 77919 * noStroke(); 77920 * text('vector length: ' + v1.mag().toFixed(2), 10, 70, 90, 30); 77921 * } 77922 * 77923 * // draw an arrow for a vector at a given base position 77924 * function drawArrow(base, vec, myColor) { 77925 * push(); 77926 * stroke(myColor); 77927 * strokeWeight(3); 77928 * fill(myColor); 77929 * translate(base.x, base.y); 77930 * line(0, 0, vec.x, vec.y); 77931 * rotate(vec.heading()); 77932 * let arrowSize = 7; 77933 * translate(vec.mag() - arrowSize, 0); 77934 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0); 77935 * pop(); 77936 * } 77937 * </code> 77938 * </div> 77939 * <div class="norender"> 77940 * <code> 77941 * let v = createVector(20.0, 30.0, 40.0); 77942 * let m = v.mag(); 77943 * print(m); // Prints "53.85164807134504" 77944 * </code> 77945 * </div> 77946 */ 77947 _main.default.Vector.prototype.mag = function mag() { 77948 return Math.sqrt(this.magSq()); 77949 }; 77950 77951 /** 77952 * Calculates the squared magnitude of the vector and returns the result 77953 * as a float (this is simply the equation <em>(x\*x + y\*y + z\*z)</em>.) 77954 * Faster if the real length is not required in the 77955 * case of comparing vectors, etc. 77956 * 77957 * @method magSq 77958 * @return {number} squared magnitude of the vector 77959 * @example 77960 * <div class="norender"> 77961 * <code> 77962 * // Static method 77963 * let v1 = createVector(6, 4, 2); 77964 * print(v1.magSq()); // Prints "56" 77965 * </code> 77966 * </div> 77967 * 77968 * <div> 77969 * <code> 77970 * function draw() { 77971 * background(240); 77972 * 77973 * let v0 = createVector(0, 0); 77974 * let v1 = createVector(mouseX, mouseY); 77975 * drawArrow(v0, v1, 'black'); 77976 * 77977 * noStroke();
77978 * text('vector length squared: ' + v1.magSq().toFixed(2), 10, 45, 90, 55); 77979 * } 77980 * 77981 * // draw an arrow for a vector at a given base position 77982 * function drawArrow(base, vec, myColor) { 77983 * push(); 77984 * stroke(myColor); 77985 * strokeWeight(3); 77986 * fill(myColor); 77987 * translate(base.x, base.y); 77988 * line(0, 0, vec.x, vec.y); 77989 * rotate(vec.heading()); 77990 * let arrowSize = 7; 77991 * translate(vec.mag() - arrowSize, 0); 77992 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0); 77993 * pop(); 77994 * } 77995 * </code> 77996 * </div> 77997 */ 77998 _main.default.Vector.prototype.magSq = function magSq() { 77999 var x = this.x; 78000 var y = this.y; 78001 var z = this.z; 78002 return x * x + y * y + z * z; 78003 }; 78004 78005 /** 78006 * Calculates the dot product of two vectors. The version of the method 78007 * that computes the dot product of two independent vectors is a static 78008 * method. See the examples for more context. 78009 * 78010 * @method dot 78011 * @param {Number} x x component of the vector 78012 * @param {Number} [y] y component of the vector 78013 * @param {Number} [z] z component of the vector 78014 * @return {Number} the dot product 78015 * 78016 * @example 78017 * <div class="norender"> 78018 * <code> 78019 * let v1 = createVector(1, 2, 3); 78020 * let v2 = createVector(2, 3, 4); 78021 * 78022 * print(v1.dot(v2)); // Prints "20" 78023 * </code> 78024 * </div> 78025 * 78026 * <div class="norender"> 78027 * <code> 78028 * //Static method 78029 * let v1 = createVector(1, 2, 3); 78030 * let v2 = createVector(3, 2, 1); 78031 * print(p5.Vector.dot(v1, v2)); // Prints "10" 78032 * </code> 78033 * </div> 78034 */ 78035 /** 78036 * @method dot 78037 * @param {p5.Vector} value value component of the vector or a <a href="#/p5.Vector">p5.Vector</a> 78038 * @return {Number} 78039 */ 78040 _main.default.Vector.prototype.dot = function dot(x, y, z) { 78041 if (x instanceof _main.default.Vector) { 78042 return this.dot(x.x, x.y, x.z); 78043 } 78044 return this.x * (x || 0) + this.y * (y || 0) + this.z * (z || 0); 78045 }; 78046 78047 /** 78048 * Calculates and returns a vector composed of the cross product between 78049 * two vectors. Both the static and non static methods return a new <a href="#/p5.Vector">p5.Vector</a>. 78050 * See the examples for more context. 78051 * 78052 * @method cross 78053 * @param {p5.Vector} v <a href="#/p5.Vector">p5.Vector</a> to be crossed 78054 * @return {p5.Vector} <a href="#/p5.Vector">p5.Vector</a> composed of cross product 78055 * @example 78056 * <div class="norender"> 78057 * <code> 78058 * let v1 = createVector(1, 2, 3); 78059 * let v2 = createVector(1, 2, 3); 78060 * 78061 * let v = v1.cross(v2); // v's components are [0, 0, 0] 78062 * print(v); 78063 * </code> 78064 * </div> 78065 * 78066 * <div class="norender"> 78067 * <code> 78068 * // Static method 78069 * let v1 = createVector(1, 0, 0); 78070 * let v2 = createVector(0, 1, 0); 78071 * 78072 * let crossProduct = p5.Vector.cross(v1, v2); 78073 * // crossProduct has components [0, 0, 1] 78074 * print(crossProduct); 78075 * </code> 78076 * </div> 78077 */ 78078 _main.default.Vector.prototype.cross = function cross(v) { 78079 var x = this.y * v.z - this.z * v.y; 78080 var y = this.z * v.x - this.x * v.z; 78081 var z = this.x * v.y - this.y * v.x; 78082 if (this.p5) { 78083 return new _main.default.Vector(this.p5, [x, y, z]); 78084 } else { 78085 return new _main.default.Vector(x, y, z); 78086 } 78087 }; 78088 78089 /** 78090 * Calculates the Euclidean distance between two points (considering a 78091 * point as a vector object). 78092 * 78093 * @method dist 78094 * @param {p5.Vector} v the x, y, and z coordinates of a <a href="#/p5.Vector">p5.Vector</a> 78095 * @return {Number} the distance 78096 * @example 78097 * <div class="norender"> 78098 * <code> 78099 * let v1 = createVector(1, 0, 0); 78100 * let v2 = createVector(0, 1, 0); 78101 * 78102 * let distance = v1.dist(v2); // distance is 1.4142... 78103 * print(distance); 78104 * </code> 78105 * </div> 78106 * 78107 * <div class="norender"> 78108 * <code> 78109 * // Static method 78110 * let v1 = createVector(1, 0, 0); 78111 * let v2 = createVector(0, 1, 0); 78112 * 78113 * let distance = p5.Vector.dist(v1, v2); 78114 * // distance is 1.4142... 78115 * print(distance); 78116 * </code> 78117 * </div> 78118 * 78119 * <div> 78120 * <code> 78121 * function draw() { 78122 * background(240); 78123 * 78124 * let v0 = createVector(0, 0); 78125 * 78126 * let v1 = createVector(70, 50); 78127 * drawArrow(v0, v1, 'red'); 78128 * 78129 * let v2 = createVector(mouseX, mouseY); 78130 * drawArrow(v0, v2, 'blue'); 78131 * 78132 * noStroke(); 78133 * text('distance between vectors: ' + v2.dist(v1).toFixed(2), 5, 50, 95, 50); 78134 * } 78135 * 78136 * // draw an arrow for a vector at a given base position 78137 * function drawArrow(base, vec, myColor) { 78138 * push(); 78139 * stroke(myColor); 78140 * strokeWeight(3); 78141 * fill(myColor); 78142 * translate(base.x, base.y); 78143 * line(0, 0, vec.x, vec.y); 78144 * rotate(vec.heading()); 78145 * let arrowSize = 7; 78146 * translate(vec.mag() - arrowSize, 0); 78147 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0); 78148 * pop(); 78149 * } 78150 * </code> 78151 * </div> 78152 */ 78153 _main.default.Vector.prototype.dist = function dist(v) { 78154 return v 78155 .copy() 78156 .sub(this) 78157 .mag(); 78158 }; 78159 78160 /** 78161 * Normalize the vector to length 1 (make it a unit vector). 78162 * 78163 * @method normalize 78164 * @return {p5.Vector} normalized <a href="#/p5.Vector">p5.Vector</a> 78165 * @example 78166 * <div class="norender"> 78167 * <code> 78168 * let v = createVector(10, 20, 2); 78169 * // v has components [10.0, 20.0, 2.0] 78170 * v.normalize(); 78171 * // v's components are set to 78172 * // [0.4454354, 0.8908708, 0.089087084] 78173 * </code> 78174 * </div> 78175 * <div> 78176 * <code> 78177 * function draw() { 78178 * background(240); 78179 * 78180 * let v0 = createVector(50, 50); 78181 * let v1 = createVector(mouseX - 50, mouseY - 50); 78182 * 78183 * drawArrow(v0, v1, 'red'); 78184 * v1.normalize(); 78185 * drawArrow(v0, v1.mult(35), 'blue'); 78186 * 78187 * noFill(); 78188 * ellipse(50, 50, 35 * 2); 78189 * } 78190 * 78191 * // draw an arrow for a vector at a given base position 78192 * function drawArrow(base, vec, myColor) { 78193 * push(); 78194 * stroke(myColor); 78195 * strokeWeight(3); 78196 * fill(myColor); 78197 * translate(base.x, base.y); 78198 * line(0, 0, vec.x, vec.y); 78199 * rotate(vec.heading()); 78200 * let arrowSize = 7; 78201 * translate(vec.mag() - arrowSize, 0); 78202 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0); 78203 * pop(); 78204 * } 78205 * </code> 78206 * </div> 78207 */ 78208 _main.default.Vector.prototype.normalize = function normalize() { 78209 var len = this.mag(); 78210 // here we multiply by the reciprocal instead of calling 'div()' 78211 // since div duplicates this zero check. 78212 if (len !== 0) this.mult(1 / len); 78213 return this; 78214 }; 78215 78216 /** 78217 * Limit the magnitude of this vector to the value used for the <b>max</b> 78218 * parameter. 78219 * 78220 * @method limit 78221 * @param {Number} max the maximum magnitude for the vector 78222 * @chainable 78223 * @example 78224 * <div class="norender"> 78225 * <code> 78226 * let v = createVector(10, 20, 2); 78227 * // v has components [10.0, 20.0, 2.0] 78228 * v.limit(5); 78229 * // v's components are set to 78230 * // [2.2271771, 4.4543543, 0.4454354] 78231 * </code> 78232 * </div> 78233 * <div> 78234 * <code> 78235 * function draw() { 78236 * background(240); 78237 * 78238 * let v0 = createVector(50, 50); 78239 * let v1 = createVector(mouseX - 50, mouseY - 50); 78240 * 78241 * drawArrow(v0, v1, 'red'); 78242 * drawArrow(v0, v1.limit(35), 'blue'); 78243 * 78244 * noFill(); 78245 * ellipse(50, 50, 35 * 2); 78246 * } 78247 * 78248 * // draw an arrow for a vector at a given base position 78249 * function drawArrow(base, vec, myColor) { 78250 * push(); 78251 * stroke(myColor); 78252 * strokeWeight(3); 78253 * fill(myColor); 78254 * translate(base.x, base.y); 78255 * line(0, 0, vec.x, vec.y); 78256 * rotate(vec.heading()); 78257 * let arrowSize = 7; 78258 * translate(vec.mag() - arrowSize, 0); 78259 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0); 78260 * pop(); 78261 * } 78262 * </code> 78263 * </div> 78264 */ 78265 _main.default.Vector.prototype.limit = function limit(max) { 78266 var mSq = this.magSq(); 78267 if (mSq > max * max) { 78268 this.div(Math.sqrt(mSq)) //normalize it 78269 .mult(max); 78270 } 78271 return this; 78272 }; 78273 78274 /** 78275 * Set the magnitude of this vector to the value used for the <b>len</b> 78276 * parameter. 78277 * 78278 * @method setMag 78279 * @param {number} len the new length for this vector 78280 * @chainable 78281 * @example 78282 * <div class="norender"> 78283 * <code> 78284 * let v = createVector(10, 20, 2); 78285 * // v has components [10.0, 20.0, 2.0] 78286 * v.setMag(10); 78287 * // v's components are set to [6.0, 8.0, 0.0] 78288 * </code> 78289 * </div> 78290 * 78291 * <div> 78292 * <code> 78293 * function draw() { 78294 * background(240); 78295 * 78296 * let v0 = createVector(0, 0); 78297 * let v1 = createVector(50, 50); 78298 * 78299 * drawArrow(v0, v1, 'red'); 78300 * 78301 * let length = map(mouseX, 0, width, 0, 141, true); 78302 * v1.setMag(length); 78303 * drawArrow(v0, v1, 'blue'); 78304 * 78305 * noStroke(); 78306 * text('magnitude set to: ' + length.toFixed(2), 10, 70, 90, 30); 78307 * } 78308 * 78309 * // draw an arrow for a vector at a given base position 78310 * function drawArrow(base, vec, myColor) { 78311 * push(); 78312 * stroke(myColor); 78313 * strokeWeight(3); 78314 * fill(myColor); 78315 * translate(base.x, base.y); 78316 * line(0, 0, vec.x, vec.y); 78317 * rotate(vec.heading()); 78318 * let arrowSize = 7; 78319 * translate(vec.mag() - arrowSize, 0); 78320 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0); 78321 * pop(); 78322 * } 78323 * </code> 78324 * </div> 78325 */ 78326 _main.default.Vector.prototype.setMag = function setMag(n) { 78327 return this.normalize().mult(n); 78328 }; 78329 78330 /** 78331 * Calculate the angle of rotation for this vector(only 2D vectors). 78332 * p5.Vectors created using <a src="#/p5/createVector">createVector()</a> 78333 * will take the current <a = src="#/p5/angleMode">angleMode</a> into consideration, and give the angle 78334 * in radians or degree accordingly. 78335 * 78336 * @method heading 78337 * @return {Number} the angle of rotation 78338 * @example 78339 * <div class = "norender"> 78340 * <code> 78341 * function setup() { 78342 * let v1 = createVector(30, 50); 78343 * print(v1.heading()); // 1.0303768265243125 78344 * 78345 * v1 = createVector(40, 50); 78346 * print(v1.heading());
78346 // 0.8960553845713439 78347 * 78348 * v1 = createVector(30, 70); 78349 * print(v1.heading()); // 1.1659045405098132 78350 * } 78351 * </code> 78352 * </div> 78353 * 78354 * <div> 78355 * <code> 78356 * function draw() { 78357 * background(240); 78358 * 78359 * let v0 = createVector(50, 50); 78360 * let v1 = createVector(mouseX - 50, mouseY - 50); 78361 * 78362 * drawArrow(v0, v1, 'black'); 78363 * 78364 * let myHeading = v1.heading(); 78365 * noStroke(); 78366 * text( 78367 * 'vector heading: ' + 78368 * myHeading.toFixed(2) + 78369 * ' radians or ' + 78370 * degrees(myHeading).toFixed(2) + 78371 * ' degrees', 78372 * 10, 78373 * 50, 78374 * 90, 78375 * 50 78376 * ); 78377 * } 78378 * 78379 * // draw an arrow for a vector at a given base position 78380 * function drawArrow(base, vec, myColor) { 78381 * push(); 78382 * stroke(myColor); 78383 * strokeWeight(3); 78384 * fill(myColor); 78385 * translate(base.x, base.y); 78386 * line(0, 0, vec.x, vec.y); 78387 * rotate(vec.heading()); 78388 * let arrowSize = 7; 78389 * translate(vec.mag() - arrowSize, 0); 78390 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0); 78391 * pop(); 78392 * } 78393 * </code> 78394 * </div> 78395 */ 78396 _main.default.Vector.prototype.heading = function heading() { 78397 var h = Math.atan2(this.y, this.x); 78398 if (this.p5) return this.p5._fromRadians(h); 78399 return h; 78400 }; 78401 78402 /** 78403 * Rotate the vector to a specific angle (only 2D vectors), magnitude remains the 78404 * same 78405 * 78406 * @method setHeading 78407 * @param {number} angle the angle of rotation 78408 * @chainable 78409 * @example 78410 * <div class="norender"> 78411 * <code> 78412 * let v = createVector(10.0, 20.0); 78413 * // result of v.heading() is 1.1071487177940904 78414 * v.setHeading(Math.PI); 78415 * // result of v.heading() is now 3.141592653589793 78416 * </code> 78417 * </div> 78418 */ 78419 78420 _main.default.Vector.prototype.setHeading = function setHeading(a) { 78421 var m = this.mag(); 78422 this.x = m * Math.cos(a); 78423 this.y = m * Math.sin(a); 78424 return this; 78425 }; 78426 78427 /** 78428 * Rotate the vector by an angle (only 2D vectors), magnitude remains the 78429 * same 78430 * 78431 * @method rotate 78432 * @param {number} angle the angle of rotation 78433 * @chainable 78434 * @example 78435 * <div class="norender"> 78436 * <code> 78437 * let v = createVector(10.0, 20.0); 78438 * // v has components [10.0, 20.0, 0.0] 78439 * v.rotate(HALF_PI); 78440 * // v's components are set to [-20.0, 9.999999, 0.0] 78441 * </code> 78442 * </div> 78443 * 78444 * <div> 78445 * <code> 78446 * let angle = 0; 78447 * function draw() { 78448 * background(240); 78449 * 78450 * let v0 = createVector(50, 50); 78451 * let v1 = createVector(50, 0); 78452 * 78453 * drawArrow(v0, v1.rotate(angle), 'black'); 78454 * angle += 0.01; 78455 * } 78456 * 78457 * // draw an arrow for a vector at a given base position 78458 * function drawArrow(base, vec, myColor) { 78459 * push(); 78460 * stroke(myColor); 78461 * strokeWeight(3); 78462 * fill(myColor); 78463 * translate(base.x, base.y); 78464 * line(0, 0, vec.x, vec.y); 78465 * rotate(vec.heading()); 78466 * let arrowSize = 7; 78467 * translate(vec.mag() - arrowSize, 0); 78468 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0); 78469 * pop(); 78470 * } 78471 * </code> 78472 * </div> 78473 */ 78474 _main.default.Vector.prototype.rotate = function rotate(a) { 78475 var newHeading = this.heading() + a; 78476 if (this.p5) newHeading = this.p5._toRadians(newHeading); 78477 var mag = this.mag(); 78478 this.x = Math.cos(newHeading) * mag; 78479 this.y = Math.sin(newHeading) * mag; 78480 return this; 78481 }; 78482 78483 /** 78484 * Calculates and returns the angle (in radians) between two vectors. 78485 * @method angleBetween 78486 * @param {p5.Vector} value the x, y, and z components of a <a href="#/p5.Vector">p5.Vector</a> 78487 * @return {Number} the angle between (in radians) 78488 * @example 78489 * <div class="norender"> 78490 * <code> 78491 * let v1 = createVector(1, 0, 0); 78492 * let v2 = createVector(0, 1, 0); 78493 * 78494 * let angle = v1.angleBetween(v2); 78495 * // angle is PI/2 78496 * print(angle); 78497 * </code> 78498 * </div> 78499 * 78500 * <div> 78501 * <code> 78502 * function draw() { 78503 * background(240); 78504 * let v0 = createVector(50, 50); 78505 * 78506 * let v1 = createVector(50, 0); 78507 * drawArrow(v0, v1, 'red'); 78508 * 78509 * let v2 = createVector(mouseX - 50, mouseY - 50); 78510 * drawArrow(v0, v2, 'blue'); 78511 * 78512 * let angleBetween = v1.angleBetween(v2); 78513 * noStroke(); 78514 * text( 78515 * 'angle between: ' + 78516 * angleBetween.toFixed(2) + 78517 * ' radians or ' + 78518 * degrees(angleBetween).toFixed(2) + 78519 * ' degrees', 78520 * 10, 78521 * 50, 78522 * 90, 78523 * 50 78524 * ); 78525 * } 78526 * 78527 * // draw an arrow for a vector at a given base position 78528 * function drawArrow(base, vec, myColor) { 78529 * push(); 78530 * stroke(myColor); 78531 * strokeWeight(3); 78532 * fill(myColor); 78533 * translate(base.x, base.y); 78534 * line(0, 0, vec.x, vec.y); 78535 * rotate(vec.heading()); 78536 * let arrowSize = 7; 78537 * translate(vec.mag() - arrowSize, 0); 78538 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0); 78539 * pop(); 78540 * } 78541 * </code> 78542 * </div> 78543 */ 78544 78545 _main.default.Vector.prototype.angleBetween = function angleBetween(v) { 78546 var dotmagmag = this.dot(v) / (this.mag() * v.mag()); 78547 // Mathematically speaking: the dotmagmag variable will be between -1 and 1 78548 // inclusive. Practically though it could be slightly outside this range due 78549 // to floating-point rounding issues. This can make Math.acos return NaN. 78550 // 78551 // Solution: we'll clamp the value to the -1,1 range 78552 var angle; 78553 angle = Math.acos(Math.min(1, Math.max(-1, dotmagmag))); 78554 angle = angle * Math.sign(this.cross(v).z || 1); 78555 if (this.p5) { 78556 angle = this.p5._fromRadians(angle); 78557 } 78558 return angle; 78559 }; 78560 /** 78561 * Linear interpolate the vector to another vector 78562 * 78563 * @method lerp 78564 * @param {Number} x the x component 78565 * @param {Number} y the y component 78566 * @param {Number} z the z component 78567 * @param {Number} amt the amount of interpolation; some value between 0.0 78568 * (old vector) and 1.0 (new vector). 0.9 is very near 78569 * the new vector. 0.5 is halfway in between. 78570 * @chainable 78571 * 78572 * @example 78573 * <div class="norender"> 78574 * <code> 78575 * let v = createVector(1, 1, 0); 78576 * 78577 * v.lerp(3, 3, 0, 0.5); // v now has components [2,2,0] 78578 * </code> 78579 * </div> 78580 * 78581 * <div class="norender"> 78582 * <code> 78583 * let v1 = createVector(0, 0, 0); 78584 * let v2 = createVector(100, 100, 0); 78585 * 78586 * let v3 = p5.Vector.lerp(v1, v2, 0.5); 78587 * // v3 has components [50,50,0] 78588 * print(v3); 78589 * </code> 78590 * </div> 78591 * 78592 * <div> 78593 * <code> 78594 * let step = 0.01; 78595 * let amount = 0; 78596 * 78597 * function draw() { 78598 * background(240); 78599 * let v0 = createVector(0, 0); 78600 * 78601 * let v1 = createVector(mouseX, mouseY); 78602 * drawArrow(v0, v1, 'red'); 78603 * 78604 * let v2 = createVector(90, 90); 78605 * drawArrow(v0, v2, 'blue'); 78606 * 78607 * if (amount > 1 || amount < 0) { 78608 * step *= -1; 78609 * } 78610 * amount += step; 78611 * let v3 = p5.Vector.lerp(v1, v2, amount); 78612 * 78613 * drawArrow(v0, v3, 'purple'); 78614 * } 78615 * 78616 * // draw an arrow for a vector at a given base position 78617 * function drawArrow(base, vec, myColor) { 78618 * push(); 78619 * stroke(myColor); 78620 * strokeWeight(3); 78621 * fill(myColor); 78622 * translate(base.x, base.y); 78623 * line(0, 0, vec.x, vec.y); 78624 * rotate(vec.heading()); 78625 * let arrowSize = 7; 78626 * translate(vec.mag() - arrowSize, 0); 78627 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0); 78628 * pop(); 78629 * } 78630 * </code> 78631 * </div> 78632 */ 78633 /** 78634 * @method lerp 78635 * @param {p5.Vector} v the <a href="#/p5.Vector">p5.Vector</a> to lerp to 78636 * @param {Number} amt 78637 * @chainable 78638 */ 78639 _main.default.Vector.prototype.lerp = function lerp(x, y, z, amt) { 78640 if (x instanceof _main.default.Vector) { 78641 return this.lerp(x.x, x.y, x.z, y); 78642 } 78643 this.x += (x - this.x) * amt || 0; 78644 this.y += (y - this.y) * amt || 0; 78645 this.z += (z - this.z) * amt || 0; 78646 return this; 78647 }; 78648 78649 /** 78650 * Reflect the incoming vector about a normal to a line in 2D, or about a normal to a plane in 3D 78651 * This method acts on the vector directly 78652 * 78653 * @method reflect 78654 * @param {p5.Vector} surfaceNormal the <a href="#/p5.Vector">p5.Vector</a> to reflect about, will be normalized by this method 78655 * @chainable 78656 * @example 78657 * <div class="norender"> 78658 * <code> 78659 * let v = createVector(4, 6); // incoming vector, this example vector is heading to the right and downward 78660 * let n = createVector(0, -1); // surface normal to a plane (this example normal points directly upwards) 78661 * v.reflect(n); // v is reflected about the surface normal n. v's components are now set to [4, -6] 78662 * </code> 78663 * </div> 78664 * 78665 * <div> 78666 * <code> 78667 * function draw() { 78668 * background(240); 78669 * 78670 * let v0 = createVector(0, 0); 78671 * let v1 = createVector(mouseX, mouseY); 78672 * drawArrow(v0, v1, 'red'); 78673 * 78674 * let n = createVector(0, -30); 78675 * drawArrow(v1, n, 'blue'); 78676 * 78677 * let r = v1.copy(); 78678 * r.reflect(n); 78679 * drawArrow(v1, r, 'purple'); 78680 * } 78681 * 78682 * // draw an arrow for a vector at a given base position 78683 * function drawArrow(base, vec, myColor) { 78684 * push(); 78685 * stroke(myColor); 78686 * strokeWeight(3); 78687 * fill(myColor); 78688 * translate(base.x, base.y); 78689 * line(0, 0, vec.x, vec.y); 78690 * rotate(vec.heading()); 78691 * let arrowSize = 7; 78692 * translate(vec.mag() - arrowSize, 0); 78693 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0); 78694 * pop(); 78695 * } 78696 * </code> 78697 * </div> 78698 */ 78699 _main.default.Vector.prototype.reflect = function reflect(surfaceNormal) { 78700 surfaceNormal.normalize(); 78701 return this.sub(surfaceNormal.mult(2 * this.dot(surfaceNormal))); 78702 }; 78703 78704 /** 78705 * Return a representation of this vector as a float array. This is only 78706 * for temporary use. If used in any other fashion, the contents should be 78707 * copied by using the <b>p5.Vector.<a href="#/p5.Vector/copy">copy()</a></b> method to copy into your own 78708 * array.
78709 * 78710 * @method array 78711 * @return {Number[]} an Array with the 3 values 78712 * @example 78713 * <div class = "norender"> 78714 * <code> 78715 * function setup() { 78716 * let v = createVector(20, 30); 78717 * print(v.array()); // Prints : Array [20, 30, 0] 78718 * } 78719 * </code> 78720 * </div> 78721 * 78722 * <div class="norender"> 78723 * <code> 78724 * let v = createVector(10.0, 20.0, 30.0); 78725 * let f = v.array(); 78726 * print(f[0]); // Prints "10.0" 78727 * print(f[1]); // Prints "20.0" 78728 * print(f[2]); // Prints "30.0" 78729 * </code> 78730 * </div> 78731 */ 78732 _main.default.Vector.prototype.array = function array() { 78733 return [this.x || 0, this.y || 0, this.z || 0]; 78734 }; 78735 78736 /** 78737 * Equality check against a <a href="#/p5.Vector">p5.Vector</a> 78738 * 78739 * @method equals 78740 * @param {Number} [x] the x component of the vector 78741 * @param {Number} [y] the y component of the vector 78742 * @param {Number} [z] the z component of the vector 78743 * @return {Boolean} whether the vectors are equals 78744 * @example 78745 * <div class = "norender"> 78746 * <code> 78747 * let v1 = createVector(5, 10, 20); 78748 * let v2 = createVector(5, 10, 20); 78749 * let v3 = createVector(13, 10, 19); 78750 * 78751 * print(v1.equals(v2.x, v2.y, v2.z)); // true 78752 * print(v1.equals(v3.x, v3.y, v3.z)); // false 78753 * </code> 78754 * </div> 78755 * 78756 * <div class="norender"> 78757 * <code> 78758 * let v1 = createVector(10.0, 20.0, 30.0); 78759 * let v2 = createVector(10.0, 20.0, 30.0); 78760 * let v3 = createVector(0.0, 0.0, 0.0); 78761 * print(v1.equals(v2)); // true 78762 * print(v1.equals(v3)); // false 78763 * </code> 78764 * </div> 78765 */ 78766 /** 78767 * @method equals 78768 * @param {p5.Vector|Array} value the vector to compare 78769 * @return {Boolean} 78770 */ 78771 _main.default.Vector.prototype.equals = function equals(x, y, z) { 78772 var a, b, c; 78773 if (x instanceof _main.default.Vector) { 78774 a = x.x || 0; 78775 b = x.y || 0; 78776 c = x.z || 0; 78777 } else if (x instanceof Array) { 78778 a = x[0] || 0; 78779 b = x[1] || 0; 78780 c = x[2] || 0; 78781 } else { 78782 a = x || 0; 78783 b = y || 0; 78784 c = z || 0; 78785 } 78786 return this.x === a && this.y === b && this.z === c; 78787 }; 78788 78789 // Static Methods 78790 78791 /** 78792 * Make a new 2D vector from an angle 78793 * 78794 * @method fromAngle 78795 * @static 78796 * @param {Number} angle the desired angle, in radians (unaffected by <a href="#/p5/angleMode">angleMode</a>) 78797 * @param {Number} [length] the length of the new vector (defaults to 1) 78798 * @return {p5.Vector} the new <a href="#/p5.Vector">p5.Vector</a> object 78799 * @example 78800 * <div> 78801 * <code> 78802 * function draw() { 78803 * background(200); 78804 * 78805 * // Create a variable, proportional to the mouseX, 78806 * // varying from 0-360, to represent an angle in degrees. 78807 * let myDegrees = map(mouseX, 0, width, 0, 360); 78808 * 78809 * // Display that variable in an onscreen text. 78810 * // (Note the nfc() function to truncate additional decimal places, 78811 * // and the "\xB0" character for the degree symbol.) 78812 * let readout = 'angle = ' + nfc(myDegrees, 1) + '\xB0'; 78813 * noStroke(); 78814 * fill(0); 78815 * text(readout, 5, 15); 78816 * 78817 * // Create a p5.Vector using the fromAngle function, 78818 * // and extract its x and y components. 78819 * let v = p5.Vector.fromAngle(radians(myDegrees), 30); 78820 * let vx = v.x; 78821 * let vy = v.y; 78822 * 78823 * push(); 78824 * translate(width / 2, height / 2); 78825 * noFill(); 78826 * stroke(150); 78827 * line(0, 0, 30, 0); 78828 * stroke(0); 78829 * line(0, 0, vx, vy); 78830 * pop(); 78831 * } 78832 * </code> 78833 * </div> 78834 */ 78835 _main.default.Vector.fromAngle = function fromAngle(angle, length) { 78836 if (typeof length === 'undefined') { 78837 length = 1; 78838 } 78839 return new _main.default.Vector( 78840 length * Math.cos(angle), 78841 length * Math.sin(angle), 78842 0 78843 ); 78844 }; 78845 78846 /** 78847 * Make a new 3D vector from a pair of ISO spherical angles 78848 * 78849 * @method fromAngles 78850 * @static 78851 * @param {Number} theta the polar angle, in radians (zero is up) 78852 * @param {Number} phi the azimuthal angle, in radians 78853 * (zero is out of the screen) 78854 * @param {Number} [length] the length of the new vector (defaults to 1) 78855 * @return {p5.Vector} the new <a href="#/p5.Vector">p5.Vector</a> object 78856 * @example 78857 * <div modernizr='webgl'> 78858 * <code> 78859 * function setup() { 78860 * createCanvas(100, 100, WEBGL); 78861 * fill(255); 78862 * noStroke(); 78863 * } 78864 * function draw() { 78865 * background(255); 78866 * 78867 * let t = millis() / 1000; 78868 * 78869 * // add three point lights 78870 * pointLight(color('#f00'), p5.Vector.fromAngles(t * 1.0, t * 1.3, 100)); 78871 * pointLight(color('#0f0'), p5.Vector.fromAngles(t * 1.1, t * 1.2, 100)); 78872 * pointLight(color('#00f'), p5.Vector.fromAngles(t * 1.2, t * 1.1, 100)); 78873 * 78874 * sphere(35); 78875 * } 78876 * </code> 78877 * </div> 78878 */ 78879 _main.default.Vector.fromAngles = function(theta, phi, length) { 78880 if (typeof length === 'undefined') { 78881 length = 1; 78882 } 78883 var cosPhi = Math.cos(phi);
78884 var sinPhi = Math.sin(phi); 78885 var cosTheta = Math.cos(theta); 78886 var sinTheta = Math.sin(theta); 78887 78888 return new _main.default.Vector( 78889 length * sinTheta * sinPhi, 78890 -length * cosTheta, 78891 length * sinTheta * cosPhi 78892 ); 78893 }; 78894 78895 /** 78896 * Make a new 2D unit vector from a random angle 78897 * 78898 * @method random2D 78899 * @static 78900 * @return {p5.Vector} the new <a href="#/p5.Vector">p5.Vector</a> object 78901 * @example 78902 * <div class="norender"> 78903 * <code> 78904 * let v = p5.Vector.random2D(); 78905 * // May make v's attributes something like: 78906 * // [0.61554617, -0.51195765, 0.0] or 78907 * // [-0.4695841, -0.14366731, 0.0] or 78908 * // [0.6091097, -0.22805278, 0.0] 78909 * print(v); 78910 * </code> 78911 * </div> 78912 * 78913 * <div> 78914 * <code> 78915 * function setup() { 78916 * frameRate(1); 78917 * } 78918 * 78919 * function draw() { 78920 * background(240); 78921 * 78922 * let v0 = createVector(50, 50); 78923 * let v1 = p5.Vector.random2D(); 78924 * drawArrow(v0, v1.mult(50), 'black'); 78925 * } 78926 * 78927 * // draw an arrow for a vector at a given base position 78928 * function drawArrow(base, vec, myColor) { 78929 * push(); 78930 * stroke(myColor); 78931 * strokeWeight(3); 78932 * fill(myColor); 78933 * translate(base.x, base.y); 78934 * line(0, 0, vec.x, vec.y); 78935 * rotate(vec.heading()); 78936 * let arrowSize = 7; 78937 * translate(vec.mag() - arrowSize, 0); 78938 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0); 78939 * pop(); 78940 * } 78941 * </code> 78942 * </div> 78943 */ 78944 _main.default.Vector.random2D = function random2D() { 78945 return this.fromAngle(Math.random() * constants.TWO_PI); 78946 }; 78947 78948 /** 78949 * Make a new random 3D unit vector. 78950 * 78951 * @method random3D 78952 * @static 78953 * @return {p5.Vector} the new <a href="#/p5.Vector">p5.Vector</a> object 78954 * @example 78955 * <div class="norender"> 78956 * <code> 78957 * let v = p5.Vector.random3D(); 78958 * // May make v's attributes something like: 78959 * // [0.61554617, -0.51195765, 0.599168] or 78960 * // [-0.4695841, -0.14366731, -0.8711202] or 78961 * // [0.6091097, -0.22805278, -0.7595902] 78962 * print(v); 78963 * </code> 78964 * </div> 78965 */ 78966 _main.default.Vector.random3D = function random3D() { 78967 var angle = Math.random() * constants.TWO_PI; 78968 var vz = Math.random() * 2 - 1; 78969 var vzBase = Math.sqrt(1 - vz * vz); 78970 var vx = vzBase * Math.cos(angle); 78971 var vy = vzBase * Math.sin(angle); 78972 return new _main.default.Vector(vx, vy, vz); 78973 }; 78974 78975 // Adds two vectors together and returns a new one. 78976 /** 78977 * @method add 78978 * @static 78979 * @param {p5.Vector} v1 a <a href="#/p5.Vector">p5.Vector</a> to add 78980 * @param {p5.Vector} v2 a <a href="#/p5.Vector">p5.Vector</a> to add 78981 * @param {p5.Vector} [target] the vector to receive the result (Optional) 78982 * @return {p5.Vector} the resulting <a href="#/p5.Vector">p5.Vector</a> 78983 */ 78984 78985 _main.default.Vector.add = function add(v1, v2, target) { 78986 if (!target) { 78987 target = v1.copy(); 78988 if (arguments.length === 3) { 78989 _main.default._friendlyError( 78990 'The target parameter is undefined, it should be of type p5.Vector', 78991 'p5.Vector.add' 78992 ); 78993 } 78994 } else { 78995 target.set(v1); 78996 } 78997 target.add(v2); 78998 return target; 78999 }; 79000 79001 // Returns a vector remainder when it is divided by another vector 79002 /** 79003 * @method rem 79004 * @static 79005 * @param {p5.Vector} v1 dividend <a href="#/p5.Vector">p5.Vector</a> 79006 * @param {p5.Vector} v2 divisor <a href="#/p5.Vector">p5.Vector</a> 79007 */ 79008 /** 79009 * @method rem 79010 * @static 79011 * @param {p5.Vector} v1 79012 * @param {p5.Vector} v2 79013 * @return {p5.Vector} the resulting <a href="#/p5.Vector">p5.Vector</a> 79014 */ 79015 _main.default.Vector.rem = function rem(v1, v2) { 79016 if (v1 instanceof _main.default.Vector && v2 instanceof _main.default.Vector) { 79017 var target = v1.copy(); 79018 target.rem(v2); 79019 return target; 79020 } 79021 }; 79022 79023 /* 79024 * Subtracts one <a href="#/p5.Vector">p5.Vector</a> from another and returns a new one. The second 79025 * vector (v2) is subtracted from the first (v1), resulting in v1-v2. 79026 */ 79027 /** 79028 * @method sub 79029 * @static 79030 * @param {p5.Vector} v1 a <a href="#/p5.Vector">p5.Vector</a> to subtract from 79031 * @param {p5.Vector} v2 a <a href="#/p5.Vector">p5.Vector</a> to subtract 79032 * @param {p5.Vector} [target] the vector to receive the result (Optional) 79033 * @return {p5.Vector} the resulting <a href="#/p5.Vector">p5.Vector</a> 79034 */ 79035 79036 _main.default.Vector.sub = function sub(v1, v2, target) { 79037 if (!target) { 79038 target = v1.copy(); 79039 if (arguments.length === 3) { 79040 _main.default._friendlyError( 79041 'The target parameter is undefined, it should be of type p5.Vector', 79042 'p5.Vector.sub' 79043 ); 79044 } 79045 } else { 79046 target.set(v1); 79047 } 79048 target.sub(v2); 79049 return target; 79050 }; 79051 79052 /** 79053 * Multiplies a vector by a scalar and returns a new vector. 79054 */ 79055 79056 /** 79057 * @method mult 79058 * @static 79059 * @param {Number} x 79060 * @param {Number} y 79061 * @param {Number} [z] 79062 * @return {p5.Vector} The resulting new <a href="#/p5.Vector">p5.Vector</a> 79063 */ 79064 79065 /** 79066 * @method mult 79067 * @static 79068 * @param {p5.Vector} v 79069 * @param {Number} n 79070 * @param {p5.Vector} [target] the vector to receive the result (Optional) 79071 */ 79072 79073 /** 79074 * @method mult 79075 * @static 79076 * @param {p5.Vector} v0 79077 * @param {p5.Vector} v1 79078 * @param {p5.Vector} [target] 79079 */ 79080 79081 /** 79082 * @method mult 79083 * @static 79084 * @param {p5.Vector} v0 79085 * @param {Number[]} arr 79086 * @param {p5.Vector} [target] 79087 */ 79088 _main.default.Vector.mult = function mult(v, n, target) { 79089 if (!target) { 79090 target = v.copy(); 79091 if (arguments.length === 3) { 79092 _main.default._friendlyError( 79093 'The target parameter is undefined, it should be of type p5.Vector', 79094 'p5.Vector.mult' 79095 ); 79096 } 79097 } else { 79098 target.set(v); 79099 } 79100 target.mult(n); 79101 return target; 79102 }; 79103 79104 /** 79105 * Divides a vector by a scalar and returns a new vector. 79106 */ 79107 79108 /** 79109 * @method div 79110 * @static 79111 * @param {Number} x 79112 * @param {Number} y 79113 * @param {Number} [z] 79114 * @return {p5.Vector} The resulting new <a href="#/p5.Vector">p5.Vector</a> 79115 */ 79116 79117 /** 79118 * @method div 79119 * @static 79120 * @param {p5.Vector} v 79121 * @param {Number} n 79122 * @param {p5.Vector} [target] the vector to receive the result (Optional) 79123 */ 79124 79125 /** 79126 * @method div 79127 * @static 79128 * @param {p5.Vector} v0 79129 * @param {p5.Vector} v1 79130 * @param {p5.Vector} [target] 79131 */ 79132 79133 /** 79134 * @method div 79135 * @static 79136 * @param {p5.Vector} v0 79137 * @param {Number[]} arr 79138 * @param {p5.Vector} [target] 79139 */ 79140 _main.default.Vector.div = function div(v, n, target) { 79141 if (!target) { 79142 target = v.copy(); 79143 79144 if (arguments.length === 3) { 79145 _main.default._friendlyError( 79146 'The target parameter is undefined, it should be of type p5.Vector', 79147 'p5.Vector.div' 79148 ); 79149 } 79150 } else { 79151 target.set(v); 79152 } 79153 target.div(n); 79154 return target; 79155 }; 79156 79157 /** 79158 * Calculates the dot product of two vectors. 79159 */ 79160 /** 79161 * @method dot 79162 * @static 79163 * @param {p5.Vector} v1 the first <a href="#/p5.Vector">p5.Vector</a> 79164 * @param {p5.Vector} v2 the second <a href="#/p5.Vector">p5.Vector</a> 79165 * @return {Number} the dot product 79166 */ 79167 _main.default.Vector.dot = function dot(v1, v2) { 79168 return v1.dot(v2); 79169 }; 79170 79171 /** 79172 * Calculates the cross product of two vectors. 79173 */ 79174 /** 79175 * @method cross 79176 * @static 79177 * @param {p5.Vector} v1 the first <a href="#/p5.Vector">p5.Vector</a> 79178 * @param {p5.Vector} v2 the second <a href="#/p5.Vector">p5.Vector</a> 79179 * @return {Number} the cross product 79180 */ 79181 _main.default.Vector.cross = function cross(v1, v2) { 79182 return v1.cross(v2); 79183 }; 79184 79185 /** 79186 * Calculates the Euclidean distance between two points (considering a 79187 * point as a vector object). 79188 */ 79189 /** 79190 * @method dist 79191 * @static 79192 * @param {p5.Vector} v1 the first <a href="#/p5.Vector">p5.Vector</a> 79193 * @param {p5.Vector} v2 the second <a href="#/p5.Vector">p5.Vector</a> 79194 * @return {Number} the distance 79195 */ 79196 _main.default.Vector.dist = function dist(v1, v2) { 79197 return v1.dist(v2); 79198 }; 79199 79200 /** 79201 * Linear interpolate a vector to another vector and return the result as a 79202 * new vector. 79203 */ 79204 /** 79205 * @method lerp 79206 * @static 79207 * @param {p5.Vector} v1 79208 * @param {p5.Vector} v2 79209 * @param {Number} amt 79210 * @param {p5.Vector} [target] the vector to receive the result (Optional) 79211 * @return {p5.Vector} the lerped value 79212 */ 79213 _main.default.Vector.lerp = function lerp(v1, v2, amt, target) { 79214 if (!target) { 79215 target = v1.copy(); 79216 if (arguments.length === 4) { 79217 _main.default._friendlyError( 79218 'The target parameter is undefined, it should be of type p5.Vector', 79219 'p5.Vector.lerp' 79220 ); 79221 } 79222 } else { 79223 target.set(v1); 79224 } 79225 target.lerp(v2, amt); 79226 return target; 79227 }; 79228 79229 /** 79230 * @method mag 79231 * @param {p5.Vector} vecT the vector to return the magnitude of 79232 * @return {Number} the magnitude of vecT 79233 * @static 79234 */ 79235 _main.default.Vector.mag = function mag(vecT) { 79236 var x = vecT.x, 79237 y = vecT.y, 79238 z = vecT.z; 79239 var magSq = x * x + y * y + z * z; 79240 return Math.sqrt(magSq); 79241 }; 79242 var _default = _main.default.Vector; 79243 exports.default = _default; 79244 }, 79245 { '../core/constants': 48, '../core/main': 59 } 79246 ], 79247 93: [
79248 function(_dereq_, module, exports) { 79249 'use strict'; 79250 Object.defineProperty(exports, '__esModule', { value: true }); 79251 exports.default = void 0; 79252 79253 var _main = _interopRequireDefault(_dereq_('../core/main')); 79254 function _interopRequireDefault(obj) { 79255 return obj && obj.__esModule ? obj : { default: obj }; 79256 } /** // variables used for random number generators 79257 * @module Math 79258 * @submodule Random 79259 * @for p5 79260 * @requires core 79261 */ 79262 var randomStateProp = '_lcg_random_state'; // Set to values from http://en.wikipedia.org/wiki/Numerical_Recipes 79263 // m is basically chosen to be large (as it is the max period) 79264 // and for its relationships to a and c 79265 var m = 4294967296; // a - 1 should be divisible by m's prime factors 79266 var a = 1664525; // c and m should be co-prime 79267 var c = 1013904223; 79268 var y2 = 0; 79269 79270 // Linear Congruential Generator that stores its state at instance[stateProperty] 79271 _main.default.prototype._lcg = function(stateProperty) { 79272 // define the recurrence relationship 79273 this[stateProperty] = (a * this[stateProperty] + c) % m; 79274 // return a float in [0, 1) 79275 // we've just used % m, so / m is always < 1 79276 return this[stateProperty] / m; 79277 }; 79278 79279 _main.default.prototype._lcgSetSeed = function(stateProperty, val) { 79280 // pick a random seed if val is undefined or null 79281 // the >>> 0 casts the seed to an unsigned 32-bit integer 79282 this[stateProperty] = (val == null ? Math.random() * m : val) >>> 0; 79283 }; 79284 79285 /** 79286 * Sets the seed value for <a href="#/p5/random">random()</a>. 79287 * 79288 * By default, <a href="#/p5/random">random()</a> produces different results each time the program 79289 * is run. Set the seed parameter to a constant to return the same 79290 * pseudo-random numbers each time the software is run. 79291 * 79292 * @method randomSeed 79293 * @param {Number} seed the seed value 79294 * @example 79295 * <div> 79296 * <code> 79297 * randomSeed(99); 79298 * for (let i = 0; i < 100; i++) { 79299 * let r = random(0, 255); 79300 * stroke(r); 79301 * line(i, 0, i, 100); 79302 * } 79303 * </code> 79304 * </div> 79305 * 79306 * @alt 79307 * many vertical lines drawn in white, black or grey. 79308 */ 79309 _main.default.prototype.randomSeed = function(seed) { 79310 this._lcgSetSeed(randomStateProp, seed); 79311 this._gaussian_previous = false; 79312 }; 79313 79314 /** 79315 * Return a random floating-point number. 79316 * 79317 * Takes either 0, 1 or 2 arguments. 79318 * 79319 * If no argument is given, returns a random number from 0 79320 * up to (but not including) 1. 79321 * 79322 * If one argument is given and it is a number, returns a random number from 0 79323 * up to (but not including) the number. 79324 * 79325 * If one argument is given and it is an array, returns a random element from 79326 * that array. 79327 * 79328 * If two arguments are given, returns a random number from the 79329 * first argument up to (but not including) the second argument. 79330 * 79331 * @method random 79332 * @param {Number} [min] the lower bound (inclusive) 79333 * @param {Number} [max] the upper bound (exclusive) 79334 * @return {Number} the random number 79335 * @example 79336 * <div> 79337 * <code> 79338 * for (let i = 0; i < 100; i++) { 79339 * let r = random(50); 79340 * stroke(r * 5); 79341 * line(50, i, 50 + r, i); 79342 * } 79343 * </code> 79344 * </div> 79345 * <div> 79346 * <code> 79347 * for (let i = 0; i < 100; i++) { 79348 * let r = random(-50, 50); 79349 * line(50, i, 50 + r, i); 79350 * } 79351 * </code> 79352 * </div> 79353 * <div> 79354 * <code> 79355 * // Get a random element from an array using the random(Array) syntax 79356 * let words = ['apple', 'bear', 'cat', 'dog']; 79357 * let word = random(words); // select random word 79358 * text(word, 10, 50); // draw the word 79359 * </code> 79360 * </div> 79361 * 79362 * @alt 79363 * 100 horizontal lines from center canvas to right. size+fill change each time 79364 * 100 horizontal lines from center of canvas. height & side change each render 79365 * word displayed at random. Either apple, bear, cat, or dog 79366 */ 79367 /** 79368 * @method random 79369 * @param {Array} choices the array to choose from 79370 * @return {*} the random element from the array 79371 * @example 79372 */ 79373 _main.default.prototype.random = function(min, max) { 79374 _main.default._validateParameters('random', arguments); 79375 var rand; 79376 79377 if (this[randomStateProp] != null) { 79378 rand = this._lcg(randomStateProp); 79379 } else { 79380 rand = Math.random(); 79381 } 79382 if (typeof min === 'undefined') { 79383 return rand; 79384 } else if (typeof max === 'undefined') { 79385 if (min instanceof Array) { 79386 return min[Math.floor(rand * min.length)]; 79387 } else { 79388 return rand * min; 79389 } 79390 } else { 79391 if (min > max) { 79392 var tmp = min; 79393 min = max; 79394 max = tmp; 79395 } 79396 79397 return rand * (max - min) + min; 79398 } 79399 }; 79400 79401 /** 79402 * 79403 * Returns a random number fitting a Gaussian, or 79404 * normal, distribution. There is theoretically no minimum or maximum 79405 * value that <a href="#/p5/randomGaussian">randomGaussian()</a> might return. Rather, there is 79406 * just a very low probability that values far from the mean will be 79407 * returned; and a higher probability that numbers near the mean will 79408 * be returned. 79409 * 79410 * Takes either 0, 1 or 2 arguments.<br> 79411 * If no args, returns a mean of 0 and standard deviation of 1.<br> 79412 * If one arg, that arg is the mean (standard deviation is 1).<br> 79413 * If two args, first is mean, second is standard deviation. 79414 * 79415 * @method randomGaussian 79416 * @param {Number} [mean] the mean 79417 * @param {Number} [sd] the standard deviation 79418 * @return {Number} the random number 79419 * @example 79420 * <div> 79421 * <code> 79422 * for (let y = 0; y < 100; y++) { 79423 * let x = randomGaussian(50, 15); 79424 * line(50, y, x, y); 79425 * } 79426 * </code> 79427 * </div> 79428 * <div> 79429 * <code> 79430 * let distribution = new Array(360); 79431 * 79432 * function setup() { 79433 * createCanvas(100, 100); 79434 * for (let i = 0; i < distribution.length; i++) { 79435 * distribution[i] = floor(randomGaussian(0, 15)); 79436 * } 79437 * } 79438 * 79439 * function draw() { 79440 * background(204); 79441 * 79442 * translate(width / 2, width / 2); 79443 * 79444 * for (let i = 0; i < distribution.length; i++) { 79445 * rotate(TWO_PI / distribution.length); 79446 * stroke(0); 79447 * let dist = abs(distribution[i]); 79448 * line(0, 0, dist, 0); 79449 * } 79450 * } 79451 * </code> 79452 * </div> 79453 * @alt 79454 * 100 horizontal lines from center of canvas. height & side change each render 79455 * black lines radiate from center of canvas. size determined each render 79456 */ 79457 _main.default.prototype.randomGaussian = function(mean) { 79458 var sd = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; 79459 var y1, x1, x2, w; 79460 if (this._gaussian_previous) { 79461 y1 = y2; 79462 this._gaussian_previous = false;
79463 } else { 79464 do { 79465 x1 = this.random(2) - 1; 79466 x2 = this.random(2) - 1; 79467 w = x1 * x1 + x2 * x2; 79468 } while (w >= 1); 79469 w = Math.sqrt(-2 * Math.log(w) / w); 79470 y1 = x1 * w; 79471 y2 = x2 * w; 79472 this._gaussian_previous = true; 79473 } 79474 79475 var m = mean || 0; 79476 return y1 * sd + m; 79477 }; 79478 var _default = _main.default; 79479 exports.default = _default; 79480 }, 79481 { '../core/main': 59 } 79482 ], 79483 94: [ 79484 function(_dereq_, module, exports) { 79485 'use strict'; 79486 function _typeof(obj) { 79487 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') { 79488 _typeof = function _typeof(obj) { 79489 return typeof obj; 79490 }; 79491 } else { 79492 _typeof = function _typeof(obj) { 79493 return obj && 79494 typeof Symbol === 'function' && 79495 obj.constructor === Symbol && 79496 obj !== Symbol.prototype 79497 ? 'symbol' 79498 : typeof obj; 79499 }; 79500 } 79501 return _typeof(obj); 79502 } 79503 Object.defineProperty(exports, '__esModule', { value: true }); 79504 exports.default = void 0; 79505 79506 var _main = _interopRequireDefault(_dereq_('../core/main')); 79507 var constants = _interopRequireWildcard(_dereq_('../core/constants')); 79508 function _getRequireWildcardCache() { 79509 if (typeof WeakMap !== 'function') return null; 79510 var cache = new WeakMap(); 79511 _getRequireWildcardCache = function _getRequireWildcardCache() { 79512 return cache; 79513 }; 79514 return cache; 79515 } 79516 function _interopRequireWildcard(obj) { 79517 if (obj && obj.__esModule) { 79518 return obj; 79519 } 79520 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) { 79521 return { default: obj }; 79522 } 79523 var cache = _getRequireWildcardCache(); 79524 if (cache && cache.has(obj)) { 79525 return cache.get(obj); 79526 } 79527 var newObj = {}; 79528 var hasPropertyDescriptor = 79529 Object.defineProperty && Object.getOwnPropertyDescriptor; 79530 for (var key in obj) { 79531 if (Object.prototype.hasOwnProperty.call(obj, key)) { 79532 var desc = hasPropertyDescriptor 79533 ? Object.getOwnPropertyDescriptor(obj, key) 79534 : null; 79535 if (desc && (desc.get || desc.set)) { 79536 Object.defineProperty(newObj, key, desc); 79537 } else { 79538 newObj[key] = obj[key]; 79539 } 79540 } 79541 } 79542 newObj.default = obj; 79543 if (cache) { 79544 cache.set(obj, newObj); 79545 } 79546 return newObj; 79547 } 79548 function _interopRequireDefault(obj) { 79549 return obj && obj.__esModule ? obj : { default: obj }; 79550 } 79551 /** 79552 * @module Math 79553 * @submodule Trigonometry 79554 * @for p5 79555 * @requires core 79556 * @requires constants 79557 */ /* 79558 * all DEGREES/RADIANS conversion should be done in the p5 instance 79559 * if possible, using the p5._toRadians(), p5._fromRadians() methods. 79560 */ _main.default.prototype._angleMode = 79561 constants.RADIANS; 79562 /** 79563 * The inverse of <a href="#/p5/cos">cos()</a>, returns the arc cosine of a value. 79564 * This function expects the values in the range of -1 to 1 and values are returned in 79565 * the range 0 to PI (3.1415927) if the angleMode is RADIANS or 0 to 180 if the 79566 * angle mode is DEGREES.
79567 * 79568 * @method acos 79569 * @param {Number} value the value whose arc cosine is to be returned 79570 * @return {Number} the arc cosine of the given value 79571 * 79572 * @example 79573 * <div class= ânorender"> 79574 * <code> 79575 * let a = PI; 79576 * let c = cos(a); 79577 * let ac = acos(c); 79578 * // Prints: "3.1415927 : -1.0 : 3.1415927" 79579 * print(a + ' : ' + c + ' : ' + ac); 79580 * </code> 79581 * </div> 79582 * 79583 * <div class= ânorender"> 79584 * <code> 79585 * let a = PI + PI / 4.0; 79586 * let c = cos(a); 79587 * let ac = acos(c); 79588 * // Prints: "3.926991 : -0.70710665 : 2.3561943" 79589 * print(a + ' : ' + c + ' : ' + ac); 79590 * </code> 79591 * </div> 79592 */ _main.default.prototype.acos = function(ratio) { 79593 return this._fromRadians(Math.acos(ratio)); 79594 }; 79595 79596 /** 79597 * The inverse of <a href="#/p5/sin">sin()</a>, returns the arc sine of a value. 79598 * This function expects the values in the range of -1 to 1 and values are returned 79599 * in the range -PI/2 to PI/2 if the angleMode is RADIANS or -90 to 90 if the angle 79600 * mode is DEGREES. 79601 * 79602 * @method asin 79603 * @param {Number} value the value whose arc sine is to be returned 79604 * @return {Number} the arc sine of the given value 79605 * 79606 * @example 79607 * <div class= ânorender"> 79608 * <code> 79609 * let a = PI / 3.0; 79610 * let s = sin(a); 79611 * let as = asin(s); 79612 * // Prints: "1.0471975 : 0.86602540 : 1.0471975" 79613 * print(a + ' : ' + s + ' : ' + as); 79614 * </code> 79615 * </div> 79616 * 79617 * <div class= ânorender"> 79618 * <code> 79619 * let a = PI + PI / 3.0; 79620 * let s = sin(a); 79621 * let as = asin(s); 79622 * // Prints: "4.1887902 : -0.86602540 : -1.0471975" 79623 * print(a + ' : ' + s + ' : ' + as); 79624 * </code> 79625 * </div> 79626 */ 79627 _main.default.prototype.asin = function(ratio) { 79628 return this._fromRadians(Math.asin(ratio)); 79629 }; 79630 79631 /** 79632 * The inverse of <a href="#/p5/tan">tan()</a>, returns the arc tangent of a value. 79633 * This function expects the values in the range of -Infinity to Infinity (exclusive) and 79634 * values are returned in the range -PI/2 to PI/2 if the angleMode is RADIANS or 79635 * -90 to 90 if the angle mode is DEGREES. 79636 * 79637 * @method atan 79638 * @param {Number} value the value whose arc tangent is to be returned 79639 * @return {Number} the arc tangent of the given value 79640 * 79641 * @example 79642 * <div class= ânorender"> 79643 * <code> 79644 * let a = PI / 3.0; 79645 * let t = tan(a); 79646 * let at = atan(t); 79647 * // Prints: "1.0471975 : 1.7320508 : 1.0471975" 79648 * print(a + ' : ' + t + ' : ' + at); 79649 * </code> 79650 * </div> 79651 * 79652 * <div class= ânorender"> 79653 * <code> 79654 * let a = PI + PI / 3.0; 79655 * let t = tan(a); 79656 * let at = atan(t); 79657 * // Prints: "4.1887902 : 1.7320508 : 1.0471975" 79658 * print(a + ' : ' + t + ' : ' + at); 79659 * </code> 79660 * </div> 79661 */ 79662 _main.default.prototype.atan = function(ratio) { 79663 return this._fromRadians(Math.atan(ratio)); 79664 }; 79665 79666 /** 79667 * Calculates the angle (in radians) from a specified point to the coordinate 79668 * origin as measured from the positive x-axis. Values are returned as a 79669 * float in the range from PI to -PI if the angleMode is RADIANS or 180 to 79670 * -180 if the angleMode is DEGREES. The atan2<a href="#/p5/">()</a> function is 79671 * most often used for orienting geometry to the position of the cursor. 79672 * 79673 * Note: The y-coordinate of the point is the first parameter, and the 79674 * x-coordinate is the second parameter, due the the structure of calculating 79675 * the tangent. 79676 * 79677 * @method atan2 79678 * @param {Number} y y-coordinate of the point 79679 * @param {Number} x x-coordinate of the point 79680 * @return {Number} the arc tangent of the given point 79681 * 79682 * @example 79683 * <div> 79684 * <code> 79685 * function draw() { 79686 * background(204); 79687 * translate(width / 2, height / 2);
79688 * let a = atan2(mouseY - height / 2, mouseX - width / 2); 79689 * rotate(a); 79690 * rect(-30, -5, 60, 10); 79691 * } 79692 * </code> 79693 * </div> 79694 * 79695 * @alt 79696 * 60 by 10 rect at center of canvas rotates with mouse movements 79697 */ 79698 _main.default.prototype.atan2 = function(y, x) { 79699 return this._fromRadians(Math.atan2(y, x)); 79700 }; 79701 79702 /** 79703 * Calculates the cosine of an angle. This function takes into account the 79704 * current <a href="#/p5/angleMode">angleMode</a>. Values are returned in the range -1 to 1. 79705 * 79706 * @method cos 79707 * @param {Number} angle the angle 79708 * @return {Number} the cosine of the angle 79709 * 79710 * @example 79711 * <div> 79712 * <code> 79713 * let a = 0.0; 79714 * let inc = TWO_PI / 25.0; 79715 * for (let i = 0; i < 25; i++) { 79716 * line(i * 4, 50, i * 4, 50 + cos(a) * 40.0); 79717 * a = a + inc; 79718 * } 79719 * </code> 79720 * </div> 79721 * 79722 * @alt 79723 * vertical black lines form wave patterns, extend-down on left and right side 79724 */ 79725 _main.default.prototype.cos = function(angle) { 79726 return Math.cos(this._toRadians(angle)); 79727 }; 79728 79729 /** 79730 * Calculates the sine of an angle. This function takes into account the 79731 * current <a href="#/p5/angleMode">angleMode</a>. Values are returned in the range -1 to 1. 79732 * 79733 * @method sin 79734 * @param {Number} angle the angle 79735 * @return {Number} the sine of the angle 79736 * 79737 * @example 79738 * <div> 79739 * <code> 79740 * let a = 0.0; 79741 * let inc = TWO_PI / 25.0; 79742 * for (let i = 0; i < 25; i++) { 79743 * line(i * 4, 50, i * 4, 50 + sin(a) * 40.0); 79744 * a = a + inc; 79745 * } 79746 * </code> 79747 * </div> 79748 * 79749 * @alt 79750 * vertical black lines extend down and up from center to form wave pattern 79751 */ 79752 _main.default.prototype.sin = function(angle) { 79753 return Math.sin(this._toRadians(angle)); 79754 }; 79755 79756 /** 79757 * Calculates the tangent of an angle. This function takes into account 79758 * the current <a href="#/p5/angleMode">angleMode</a>. Values are returned in the range of all real numbers. 79759 * 79760 * @method tan 79761 * @param {Number} angle the angle 79762 * @return {Number} the tangent of the angle 79763 * 79764 * @example 79765 * <div> 79766 * <code> 79767 * let a = 0.0; 79768 * let inc = TWO_PI / 50.0; 79769 * for (let i = 0; i < 100; i = i + 2) { 79770 * line(i, 50, i, 50 + tan(a) * 2.0); 79771 * a = a + inc; 79772 * } 79773 * </code> 79774 * 79775 * @alt 79776 * vertical black lines end down and up from center to form spike pattern 79777 */ 79778 _main.default.prototype.tan = function(angle) { 79779 return Math.tan(this._toRadians(angle)); 79780 }; 79781 79782 /** 79783 * Converts a radian measurement to its corresponding value in degrees. 79784 * Radians and degrees are two ways of measuring the same thing. There are 79785 * 360 degrees in a circle and 2*PI radians in a circle. For example, 79786 * 90° = PI/2 = 1.5707964. This function does not take into account the 79787 * current <a href="#/p5/angleMode">angleMode</a>. 79788 * 79789 * @method degrees 79790 * @param {Number} radians the radians value to convert to degrees 79791 * @return {Number} the converted angle 79792 * 79793 * @example 79794 * <div class= ânorender"> 79795 * <code> 79796 * let rad = PI / 4; 79797 * let deg = degrees(rad); 79798 * print(rad + ' radians is ' + deg + ' degrees'); 79799 * // Prints: 0.7853981633974483 radians is 45 degrees 79800 * </code> 79801 * </div> 79802 */ 79803 _main.default.prototype.degrees = function(angle) { 79804 return angle * constants.RAD_TO_DEG; 79805 }; 79806 79807 /** 79808 * Converts a degree measurement to its corresponding value in radians. 79809 * Radians and degrees are two ways of measuring the same thing. There are 79810 * 360 degrees in a circle and 2*PI radians in a circle. For example, 79811 * 90° = PI/2 = 1.5707964. This function does not take into account the 79812 * current <a href="#/p5/angleMode">angleMode</a>. 79813 * 79814 * @method radians 79815 * @param {Number} degrees the degree value to convert to radians 79816 * @return {Number} the converted angle 79817 * 79818 * @example 79819 * <div class= ânorender"> 79820 * <code> 79821 * let deg = 45.0; 79822 * let rad = radians(deg); 79823 * print(deg + ' degrees is ' + rad + ' radians'); 79824 * // Prints: 45 degrees is 0.7853981633974483 radians 79825 * </code> 79826 * </div> 79827 */ 79828 _main.default.prototype.radians = function(angle) { 79829 return angle * constants.DEG_TO_RAD; 79830 }; 79831 79832 /** 79833 * Sets the current mode of p5 to given mode. Default mode is RADIANS. 79834 * 79835 * @method angleMode 79836 * @param {Constant} mode either RADIANS or DEGREES 79837 * 79838 * @example 79839 * <div> 79840 * <code> 79841 * function draw() { 79842 * background(204); 79843 * angleMode(DEGREES); // Change the mode to DEGREES
79844 * let a = atan2(mouseY - height / 2, mouseX - width / 2); 79845 * translate(width / 2, height / 2); 79846 * push(); 79847 * rotate(a); 79848 * rect(-20, -5, 40, 10); // Larger rectangle is rotating in degrees 79849 * pop(); 79850 * angleMode(RADIANS); // Change the mode to RADIANS 79851 * rotate(a); // variable a stays the same 79852 * rect(-40, -5, 20, 10); // Smaller rectangle is rotating in radians 79853 * } 79854 * </code> 79855 * </div> 79856 * 79857 * @alt 79858 * 40 by 10 rect in center rotates with mouse moves. 20 by 10 rect moves faster. 79859 * 79860 */ 79861 _main.default.prototype.angleMode = function(mode) { 79862 if (mode === constants.DEGREES || mode === constants.RADIANS) { 79863 this._angleMode = mode; 79864 } 79865 }; 79866 79867 /** 79868 * converts angles from the current angleMode to RADIANS 79869 * 79870 * @method _toRadians 79871 * @private 79872 * @param {Number} angle 79873 * @returns {Number} 79874 */ 79875 _main.default.prototype._toRadians = function(angle) { 79876 if (this._angleMode === constants.DEGREES) { 79877 return angle * constants.DEG_TO_RAD; 79878 } 79879 return angle; 79880 }; 79881 79882 /** 79883 * converts angles from the current angleMode to DEGREES 79884 * 79885 * @method _toDegrees 79886 * @private 79887 * @param {Number} angle 79888 * @returns {Number} 79889 */ 79890 _main.default.prototype._toDegrees = function(angle) { 79891 if (this._angleMode === constants.RADIANS) { 79892 return angle * constants.RAD_TO_DEG; 79893 } 79894 return angle; 79895 }; 79896 79897 /** 79898 * converts angles from RADIANS into the current angleMode 79899 * 79900 * @method _fromRadians 79901 * @private 79902 * @param {Number} angle 79903 * @returns {Number} 79904 */ 79905 _main.default.prototype._fromRadians = function(angle) { 79906 if (this._angleMode === constants.DEGREES) { 79907 return angle * constants.RAD_TO_DEG; 79908 } 79909 return angle; 79910 }; 79911 var _default = _main.default; 79912 exports.default = _default; 79913 }, 79914 { '../core/constants': 48, '../core/main': 59 } 79915 ], 79916 95: [ 79917 function(_dereq_, module, exports) { 79918 'use strict'; 79919 Object.defineProperty(exports, '__esModule', { value: true }); 79920 exports.default = void 0; 79921 79922 var _main = _interopRequireDefault(_dereq_('../core/main')); 79923 function _interopRequireDefault(obj) { 79924 return obj && obj.__esModule ? obj : { default: obj }; 79925 } 79926 /** 79927 * @module Typography 79928 * @submodule Attributes 79929 * @for p5 79930 * @requires core 79931 * @requires constants 79932 */ /** 79933 * Sets the current alignment for drawing text. Accepts two 79934 * arguments: horizAlign (LEFT, CENTER, or RIGHT) and 79935 * vertAlign (TOP, BOTTOM, CENTER, or BASELINE). 79936 * 79937 * The horizAlign parameter is in reference to the x value 79938 * of the <a href="#/p5/text">text()</a> function, while the vertAlign parameter 79939 * is in reference to the y value. 79940 * 79941 * So if you write textAlign(LEFT), you are aligning the left 79942 * edge of your text to the x value you give in <a href="#/p5/text">text()</a>. 79943 * If you write textAlign(RIGHT, TOP), you are aligning the right edge 79944 * of your text to the x value and the top of edge of the text 79945 * to the y value. 79946 * 79947 * @method textAlign 79948 * @param {Constant} horizAlign horizontal alignment, either LEFT, 79949 * CENTER, or RIGHT 79950 * @param {Constant} [vertAlign] vertical alignment, either TOP, 79951 * BOTTOM, CENTER, or BASELINE 79952 * @chainable 79953 * @example 79954 * <div> 79955 * <code> 79956 * textSize(16); 79957 * textAlign(RIGHT); 79958 * text('ABCD', 50, 30); 79959 * textAlign(CENTER); 79960 * text('EFGH', 50, 50); 79961 * textAlign(LEFT); 79962 * text('IJKL', 50, 70); 79963 * </code> 79964 * </div> 79965 * 79966 * <div> 79967 * <code> 79968 * textSize(16); 79969 * strokeWeight(0.5); 79970 * 79971 * line(0, 12, width, 12); 79972 * textAlign(CENTER, TOP); 79973 * text('TOP', 0, 12, width); 79974 * 79975 * line(0, 37, width, 37); 79976 * textAlign(CENTER, CENTER); 79977 * text('CENTER', 0, 37, width); 79978 * 79979 * line(0, 62, width, 62); 79980 * textAlign(CENTER, BASELINE); 79981 * text('BASELINE', 0, 62, width); 79982 * 79983 * line(0, 87, width, 87); 79984 * textAlign(CENTER, BOTTOM); 79985 * text('BOTTOM', 0, 87, width); 79986 * </code> 79987 * </div> 79988 * 79989 * @alt 79990 * Letters ABCD displayed at top left, EFGH at center and IJKL at bottom right. 79991 * The names of the four vertical alignments (TOP, CENTER, BASELINE & BOTTOM) rendered each showing that alignment's placement relative to a horizontal line. 79992 */ /** 79993 * @method textAlign 79994 * @return {Object} 79995 */ _main.default.prototype.textAlign = function(horizAlign, vertAlign) { 79996 var _this$_renderer; 79997 _main.default._validateParameters('textAlign', arguments); 79998 return (_this$_renderer = this._renderer).textAlign.apply( 79999 _this$_renderer, 80000 arguments 80001 ); 80002 }; 80003 80004 /** 80005 * Sets/gets the spacing, in pixels, between lines of text. This setting will be 80006 * used in all subsequent calls to the <a href="#/p5/text">text()</a> function. 80007 * 80008 * @method textLeading 80009 * @param {Number} leading the size in pixels for spacing between lines 80010 * @chainable 80011 * 80012 * @example 80013 * <div> 80014 * <code> 80015 * let lines = 'L1\nL2\nL3'; // "\n" is a "new line" character 80016 * textSize(12); 80017 * 80018 * textLeading(10); 80019 * text(lines, 10, 25); 80020 * 80021 * textLeading(20); 80022 * text(lines, 40, 25); 80023 * 80024 * textLeading(30); 80025 * text(lines, 70, 25); 80026 * </code> 80027 * </div> 80028 * 80029 * @alt 80030 * A set of L1 L2 & L3 displayed vertically 3 times. spacing increases for each set 80031 */ 80032 /** 80033 * @method textLeading 80034 * @return {Number} 80035 */ 80036 _main.default.prototype.textLeading = function(theLeading) { 80037 var _this$_renderer2; 80038 _main.default._validateParameters('textLeading', arguments); 80039 return (_this$_renderer2 = this._renderer).textLeading.apply( 80040 _this$_renderer2, 80041 arguments 80042 ); 80043 }; 80044 80045 /** 80046 * Sets/gets the current font size. This size will be used in all subsequent 80047 * calls to the <a href="#/p5/text">text()</a> function. Font size is measured in pixels. 80048 * 80049 * @method textSize 80050 * @param {Number} theSize the size of the letters in units of pixels 80051 * @chainable 80052 * 80053 * @example 80054 * <div> 80055 * <code> 80056 * textSize(12); 80057 * text('Font Size 12', 10, 30); 80058 * textSize(14); 80059 * text('Font Size 14', 10, 60); 80060 * textSize(16); 80061 * text('Font Size 16', 10, 90); 80062 * </code> 80063 * </div> 80064 * 80065 * @alt 80066 * 'Font Size 12' displayed small, 'Font Size 14' medium & 'Font Size 16' large 80067 */ 80068 /** 80069 * @method textSize 80070 * @return {Number} 80071 */ 80072 _main.default.prototype.textSize = function(theSize) { 80073 var _this$_renderer3; 80074 _main.default._validateParameters('textSize', arguments); 80075 return (_this$_renderer3 = this._renderer).textSize.apply( 80076 _this$_renderer3, 80077 arguments 80078 ); 80079 }; 80080 80081 /** 80082 * Sets/gets the style of the text for system fonts to NORMAL, ITALIC, BOLD or BOLDITALIC. 80083 * Note: this may be is overridden by CSS styling. For non-system fonts 80084 * (opentype, truetype, etc.) please load styled fonts instead. 80085 * 80086 * @method textStyle 80087 * @param {Constant} theStyle styling for text, either NORMAL, 80088 * ITALIC, BOLD or BOLDITALIC 80089 * @chainable 80090 * @example 80091 * <div> 80092 * <code> 80093 * strokeWeight(0); 80094 * textSize(12); 80095 * textStyle(NORMAL); 80096 * text('Font Style Normal', 10, 15); 80097 * textStyle(ITALIC); 80098 * text('Font Style Italic', 10, 40); 80099 * textStyle(BOLD); 80100 * text('Font Style Bold', 10, 65); 80101 * textStyle(BOLDITALIC); 80102 * text('Font Style Bold Italic', 10, 90); 80103 * </code> 80104 * </div> 80105 * 80106 * @alt 80107 * Words Font Style Normal displayed normally, Italic in italic, bold in bold and bold italic in bold italics. 80108 */ 80109 /** 80110 * @method textStyle 80111 * @return {String} 80112 */ 80113 _main.default.prototype.textStyle = function(theStyle) { 80114 var _this$_renderer4; 80115 _main.default._validateParameters('textStyle', arguments); 80116 return (_this$_renderer4 = this._renderer).textStyle.apply( 80117 _this$_renderer4, 80118 arguments 80119 ); 80120 }; 80121 80122 /** 80123 * Calculates and returns the width of any character or text str
80123ing. 80124 * 80125 * @method textWidth 80126 * @param {String} theText the String of characters to measure 80127 * @return {Number} the calculated width 80128 * @example 80129 * <div> 80130 * <code> 80131 * textSize(28); 80132 * 80133 * let aChar = 'P'; 80134 * let cWidth = textWidth(aChar); 80135 * text(aChar, 0, 40); 80136 * line(cWidth, 0, cWidth, 50); 80137 * 80138 * let aString = 'p5.js'; 80139 * let sWidth = textWidth(aString); 80140 * text(aString, 0, 85); 80141 * line(sWidth, 50, sWidth, 100); 80142 * </code> 80143 * </div> 80144 * 80145 * @alt 80146 * Letter P and p5.js are displayed with vertical lines at end. 80147 */ 80148 _main.default.prototype.textWidth = function() { 80149 var _this$_renderer5; 80150 for ( 80151 var _len = arguments.length, args = new Array(_len), _key = 0; 80152 _key < _len; 80153 _key++ 80154 ) { 80155 args[_key] = arguments[_key]; 80156 } 80157 args[0] += ''; 80158 _main.default._validateParameters('textWidth', args); 80159 if (args[0].length === 0) { 80160 return 0; 80161 } 80162 return (_this$_renderer5 = this._renderer).textWidth.apply( 80163 _this$_renderer5, 80164 args 80165 ); 80166 }; 80167 80168 /** 80169 * Returns the ascent of the current font at its current size. The ascent 80170 * represents the distance, in pixels, of the tallest character above 80171 * the baseline. 80172 * @method textAscent 80173 * @return {Number} 80174 * @example 80175 * <div> 80176 * <code> 80177 * let base = height * 0.75; 80178 * let scalar = 0.8; // Different for each font 80179 * 80180 * textSize(32); // Set initial text size 80181 * let asc = textAscent() * scalar; // Calc ascent 80182 * line(0, base - asc, width, base - asc); 80183 * text('dp', 0, base); // Draw text on baseline 80184 * 80185 * textSize(64); // Increase text size 80186 * asc = textAscent() * scalar; // Recalc ascent 80187 * line(40, base - asc, width, base - asc); 80188 * text('dp', 40, base); // Draw text on baseline 80189 * </code> 80190 * </div> 80191 */ 80192 _main.default.prototype.textAscent = function() { 80193 for ( 80194 var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; 80195 _key2 < _len2; 80196 _key2++ 80197 ) { 80198 args[_key2] = arguments[_key2]; 80199 } 80200 _main.default._validateParameters('textAscent', args); 80201 return this._renderer.textAscent(); 80202 }; 80203 80204 /** 80205 * Returns the descent of the current font at its current size. The descent 80206 * represents the distance, in pixels, of the character with the longest 80207 * descender below the baseline. 80208 * @method textDescent 80209 * @return {Number} 80210 * @example 80211 * <div> 80212 * <code> 80213 * let base = height * 0.75; 80214 * let scalar = 0.8; // Different for each font 80215 * 80216 * textSize(32); // Set initial text size 80217 * let desc = textDescent() * scalar; // Calc ascent 80218 * line(0, base + desc, width, base + desc); 80219 * text('dp', 0, base); // Draw text on baseline 80220 * 80221 * textSize(64); // Increase text size 80222 * desc = textDescent() * scalar; // Recalc ascent 80223 * line(40, base + desc, width, base + desc); 80224 * text('dp', 40, base); // Draw text on baseline 80225 * </code> 80226 * </div> 80227 */ 80228 _main.default.prototype.textDescent = function() { 80229 for ( 80230 var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; 80231 _key3 < _len3; 80232 _key3++ 80233 ) { 80234 args[_key3] = arguments[_key3]; 80235 } 80236 _main.default._validateParameters('textDescent', args); 80237 return this._renderer.textDescent(); 80238 }; 80239 80240 /**
80241 * Helper function to measure ascent and descent. 80242 */ 80243 _main.default.prototype._updateTextMetrics = function() { 80244 return this._renderer._updateTextMetrics(); 80245 }; 80246 var _default = _main.default; 80247 exports.default = _default; 80248 }, 80249 { '../core/main': 59 } 80250 ], 80251 96: [ 80252 function(_dereq_, module, exports) { 80253 'use strict'; 80254 function _typeof(obj) { 80255 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') { 80256 _typeof = function _typeof(obj) { 80257 return typeof obj; 80258 }; 80259 } else { 80260 _typeof = function _typeof(obj) { 80261 return obj && 80262 typeof Symbol === 'function' && 80263 obj.constructor === Symbol && 80264 obj !== Symbol.prototype 80265 ? 'symbol' 80266 : typeof obj; 80267 }; 80268 } 80269 return _typeof(obj); 80270 } 80271 Object.defineProperty(exports, '__esModule', { value: true }); 80272 exports.default = void 0; 80273 80274 var _main = _interopRequireDefault(_dereq_('../core/main')); 80275 var constants = _interopRequireWildcard(_dereq_('../core/constants')); 80276 var opentype = _interopRequireWildcard(_dereq_('opentype.js')); 80277 80278 _dereq_('../core/friendly_errors/validate_params'); 80279 _dereq_('../core/friendly_errors/file_errors'); 80280 _dereq_('../core/friendly_errors/fes_core'); 80281 function _getRequireWildcardCache() { 80282 if (typeof WeakMap !== 'function') return null; 80283 var cache = new WeakMap(); 80284 _getRequireWildcardCache = function _getRequireWildcardCache() { 80285 return cache; 80286 }; 80287 return cache; 80288 } 80289 function _interopRequireWildcard(obj) { 80290 if (obj && obj.__esModule) { 80291 return obj; 80292 } 80293 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) { 80294 return { default: obj }; 80295 } 80296 var cache = _getRequireWildcardCache(); 80297 if (cache && cache.has(obj)) { 80298 return cache.get(obj); 80299 } 80300 var newObj = {}; 80301 var hasPropertyDescriptor = 80302 Object.defineProperty && Object.getOwnPropertyDescriptor; 80303 for (var key in obj) { 80304 if (Object.prototype.hasOwnProperty.call(obj, key)) { 80305 var desc = hasPropertyDescriptor 80306 ? Object.getOwnPropertyDescriptor(obj, key) 80307 : null; 80308 if (desc && (desc.get || desc.set)) { 80309 Object.defineProperty(newObj, key, desc); 80310 } else { 80311 newObj[key] = obj[key]; 80312 } 80313 } 80314 } 80315 newObj.default = obj; 80316 if (cache) { 80317 cache.set(obj, newObj); 80318 } 80319 return newObj; 80320 } 80321 function _interopRequireDefault(obj) { 80322 return obj && obj.__esModule ? obj : { default: obj }; 80323 } 80324 /** 80325 * @module Typography 80326 * @submodule Loading & Displaying 80327 * @for p5 80328 * @requires core 80329 */ /** 80330 * Loads an opentype font file (.otf, .ttf) from a file or a URL, 80331 * and returns a PFont Object. This method is asynchronous, 80332 * meaning it may not finish before the next line in your sketch 80333 * is executed. 80334 * 80335 * The path to the font should be relative to the HTML file 80336 * that links in your sketch. Loading fonts from a URL or other 80337 * remote location may be blocked due to your browser's built-in 80338 * security. 80339 * 80340 * @method loadFont 80341 * @param {String} path name of the file or url to load 80342 * @param {Function} [callback] function to be executed after 80343 * <a href="#/p5/loadFont">loadFont()</a> completes 80344 * @param {Function} [onError] function to be executed if 80345 * an error occurs 80346 * @return {p5.Font} <a href="#/p5.Font">p5.Font</a> object 80347 * @example 80348 * 80349 * Calling loadFont() inside <a href="#/p5/preload">preload()</a> guarantees 80350 * that the load operation will have completed before <a href="#/p5/setup">setup()</a> 80351 * and <a href="#/p5/draw">draw()</a> are called. 80352 * 80353 * <div><code> 80354 * let myFont; 80355 * function preload() { 80356 * myFont = loadFont('assets/inconsolata.otf'); 80357 * } 80358 * 80359 * function setup() {
80360 * fill('#ED225D'); 80361 * textFont(myFont); 80362 * textSize(36); 80363 * text('p5*js', 10, 50); 80364 * } 80365 * </code></div> 80366 * 80367 * Outside of <a href="#/p5/preload">preload()</a>, you may supply a 80368 * callback function to handle the object: 80369 * 80370 * <div><code> 80371 * function setup() { 80372 * loadFont('assets/inconsolata.otf', drawText); 80373 * } 80374 * 80375 * function drawText(font) { 80376 * fill('#ED225D'); 80377 * textFont(font, 36); 80378 * text('p5*js', 10, 50); 80379 * } 80380 * </code></div> 80381 * 80382 * You can also use the font filename string (without the file extension) to 80383 * style other HTML elements. 80384 * 80385 * <div><code> 80386 * function preload() { 80387 * loadFont('assets/inconsolata.otf'); 80388 * } 80389 * 80390 * function setup() { 80391 * let myDiv = createDiv('hello there'); 80392 * myDiv.style('font-family', 'Inconsolata'); 80393 * } 80394 * </code></div> 80395 * 80396 * @alt 80397 * p5*js in p5's theme dark pink 80398 * p5*js in p5's theme dark pink 80399 */ _main.default.prototype.loadFont = function(path, onSuccess, onError) { 80400 _main.default._validateParameters('loadFont', arguments); 80401 var p5Font = new _main.default.Font(this); 80402 80403 var self = this; 80404 opentype.load(path, function(err, font) { 80405 if (err) { 80406 _main.default._friendlyFileLoadError(4, path); 80407 if (typeof onError !== 'undefined') { 80408 return onError(err); 80409 } 80410 console.error(err, path); 80411 return; 80412 } 80413 80414 p5Font.font = font; 80415 80416 if (typeof onSuccess !== 'undefined') { 80417 onSuccess(p5Font); 80418 } 80419 80420 self._decrementPreload(); 80421 80422 // check that we have an acceptable font type 80423 var validFontTypes = ['ttf', 'otf', 'woff', 'woff2']; 80424 80425 var fileNoPath = path 80426 .split('\\') 80427 .pop() 80428 .split('/') 80429 .pop(); 80430 80431 var lastDotIdx = fileNoPath.lastIndexOf('.'); 80432 var fontFamily; 80433 var newStyle; 80434 var fileExt = lastDotIdx < 1 ? null : fileNoPath.substr(lastDotIdx + 1); 80435 80436 // if so, add it to the DOM (name-only) for use with DOM module 80437 if (validFontTypes.includes(fileExt)) { 80438 fontFamily = fileNoPath.substr(0, lastDotIdx); 80439 newStyle = document.createElement('style'); 80440 newStyle.appendChild( 80441 document.createTextNode( 80442 '\n@font-face {\nfont-family: ' 80443 .concat(fontFamily, ';\nsrc: url(') 80444 .concat(path, ');\n}\n') 80445 ) 80446 ); 80447 80448 document.head.appendChild(newStyle); 80449 } 80450 }); 80451 80452 return p5Font; 80453 }; 80454 80455 /** 80456 * Draws text to the screen. Displays the information specified in the first 80457 * parameter on the screen in the position specified by the additional 80458 * parameters. A default font will be used unless a font is set with the 80459 * <a href="#/p5/textFont">textFont()</a> function and a default size will be 80460 * used unless a font is set with <a href="#/p5/textSize">textSize()</a>. Change 80461 * the color of the text with the <a href="#/p5/fill">fill()</a> function. Change 80462 * the outline of the text with the <a href="#/p5/stroke">stroke()</a> and 80463 * <a href="#/p5/strokeWeight">
80463strokeWeight()</a> functions. 80464 * 80465 * The text displays in relation to the <a href="#/p5/textAlign">textAlign()</a> 80466 * function, which gives the option to draw to the left, right, and center of the 80467 * coordinates. 80468 * 80469 * The x2 and y2 parameters define a rectangular area to display within and 80470 * may only be used with string data. When these parameters are specified, 80471 * they are interpreted based on the current <a href="#/p5/rectMode">rectMode()</a> 80472 * setting. Text that does not fit completely within the rectangle specified will 80473 * not be drawn to the screen. If x2 and y2 are not specified, the baseline 80474 * alignment is the default, which means that the text will be drawn upwards 80475 * from x and y. 80476 * 80477 * <b>WEBGL</b>: Only opentype/truetype fonts are supported. You must load a font 80478 * using the <a href="#/p5/loadFont">loadFont()</a> method (see the example above). 80479 * <a href="#/p5/stroke">stroke()</a> currently has no effect in webgl mode. 80480 * 80481 * @method text 80482 * @param {String|Object|Array|Number|Boolean} str the alphanumeric 80483 * symbols to be displayed 80484 * @param {Number} x x-coordinate of text 80485 * @param {Number} y y-coordinate of text 80486 * @param {Number} [x2] by default, the width of the text box, 80487 * see <a href="#/p5/rectMode">rectMode()</a> for more info 80488 * @param {Number} [y2] by default, the height of the text box, 80489 * see <a href="#/p5/rectMode">rectMode()</a> for more info 80490 * @chainable 80491 * @example 80492 * <div> 80493 * <code> 80494 * textSize(32); 80495 * text('word', 10, 30); 80496 * fill(0, 102, 153); 80497 * text('word', 10, 60); 80498 * fill(0, 102, 153, 51); 80499 * text('word', 10, 90); 80500 * </code> 80501 * </div> 80502 * <div> 80503 * <code> 80504 * let s = 'The quick brown fox jumped over the lazy dog.'; 80505 * fill(50); 80506 * text(s, 10, 10, 70, 80); // Text wraps within text box 80507 * </code> 80508 * </div> 80509 * 80510 * <div modernizr='webgl'> 80511 * <code> 80512 * let inconsolata; 80513 * function preload() { 80514 * inconsolata = loadFont('assets/inconsolata.otf'); 80515 * } 80516 * function setup() { 80517 * createCanvas(100, 100, WEBGL); 80518 * textFont(inconsolata); 80519 * textSize(width / 3); 80520 * textAlign(CENTER, CENTER); 80521 * } 80522 * function draw() { 80523 * background(0); 80524 * let time = millis(); 80525 * rotateX(time / 1000); 80526 * rotateZ(time / 1234); 80527 * text('p5.js', 0, 0); 80528 * } 80529 * </code> 80530 * </div> 80531 * 80532 * @alt 80533 * 'word' displayed 3 times going from black, blue to translucent blue 80534 * The text 'The quick brown fox jumped over the lazy dog' displayed. 80535 * The text 'p5.js' spinning in 3d 80536 */ 80537 _main.default.prototype.text = function(str, x, y, maxWidth, maxHeight) { 80538 var _this$_renderer; 80539 _main.default._validateParameters('text', arguments); 80540 return !(this._renderer._doFill || this._renderer._doStroke) 80541 ? this 80542 : (_this$_renderer = this._renderer).text.apply(_this$_renderer, arguments); 80543 }; 80544 80545 /** 80546 * Sets the current font that will be drawn with the <a href="#/p5/text">text()</a> function. 80547 * 80548 * <b>WEBGL</b>: Only fonts loaded via <a href="#/p5/loadFont">loadFont()</a> are supported. 80549 * 80550 * @method textFont 80551 * @return {Object} the current font 80552 * 80553 * @example 80554 * <div> 80555 * <code> 80556 * fill(0); 80557 * textSize(12); 80558 * textFont('Georgia'); 80559 * text('Georgia', 12, 30); 80560 * textFont('Helvetica'); 80561 * text('Helvetica', 12, 60); 80562 * </code> 80563 * </div> 80564 * <div> 80565 * <code> 80566 * let fontRegular, fontItalic, fontBold; 80567 * function preload() { 80568 * fontRegular = loadFont('assets/Regular.otf'); 80569 * fontItalic = loadFont('assets/Italic.ttf'); 80570 * fontBold = loadFont('assets/Bold.ttf'); 80571 * } 80572 * function setup() { 80573 * background(210); 80574 * fill(0) 80575 .strokeWeight(0) 80576 .textSize(10); 80577 * textFont(fontRegular); 80578 * text('Font Style Normal', 10, 30); 80579 * textFont(fontItalic); 80580 * text('Font Style Italic', 10, 50); 80581 * textFont(fontBold); 80582 * text('Font Style Bold', 10, 70); 80583 * } 80584 * </code> 80585 * </div> 80586 * 80587 * @alt 80588 * word 'Georgia' displayed in font Georgia and 'Helvetica' in font Helvetica 80589 * words Font Style Normal displayed normally, Italic in italic and bold in bold 80590 */ 80591 /** 80592 * @method textFont 80593 * @param {Object|String} font a font loaded via <a href="#/p5/loadFont">loadFont()</a>, 80594 * or a String representing a <a href="https://mzl.la/2dOw8WD">web safe font</a> 80595 * (a font that is generally available across all systems) 80596 * @param {Number} [size] the font size to use 80597 * @chainable 80598 */ 80599 _main.default.prototype.textFont = function(theFont, theSize) { 80600 _main.default._validateParameters('textFont', arguments); 80601 if (arguments.length) { 80602 if (!theFont) { 80603 throw new Error('null font passed to textFont'); 80604 } 80605 80606 this._renderer._setProperty('_textFont', theFont); 80607 80608 if (theSize) { 80609 this._renderer._setProperty('_textSize', theSize); 80610 this._renderer._setProperty( 80611 '_textLeading', 80612 theSize * constants._DEFAULT_LEADMULT 80613 ); 80614 } 80615 80616 return this._renderer._applyTextProperties(); 80617 } 80618 80619 return this._renderer._textFont; 80620 }; 80621 var _default = _main.default; 80622 exports.default = _default; 80623 }, 80624 { 80625 '../core/constants': 48, 80626 '../core/friendly_errors/fes_core': 51, 80627 '../core/friendly_errors/file_errors': 52, 80628 '../core/friendly_errors/validate_params': 54, 80629 '../core/main': 59, 80630 'opentype.js': 34 80631 } 80632 ], 80633 97: [
80634 function(_dereq_, module, exports) { 80635 'use strict'; 80636 Object.defineProperty(exports, '__esModule', { value: true }); 80637 exports.default = void 0; 80638 80639 var _main = _interopRequireDefault(_dereq_('../core/main')); 80640 var constants = _interopRequireWildcard(_dereq_('../core/constants')); 80641 function _getRequireWildcardCache() { 80642 if (typeof WeakMap !== 'function') return null; 80643 var cache = new WeakMap(); 80644 _getRequireWildcardCache = function _getRequireWildcardCache() { 80645 return cache; 80646 }; 80647 return cache; 80648 } 80649 function _interopRequireWildcard(obj) { 80650 if (obj && obj.__esModule) { 80651 return obj; 80652 } 80653 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) { 80654 return { default: obj }; 80655 } 80656 var cache = _getRequireWildcardCache(); 80657 if (cache && cache.has(obj)) { 80658 return cache.get(obj); 80659 } 80660 var newObj = {}; 80661 var hasPropertyDescriptor = 80662 Object.defineProperty && Object.getOwnPropertyDescriptor; 80663 for (var key in obj) { 80664 if (Object.prototype.hasOwnProperty.call(obj, key)) { 80665 var desc = hasPropertyDescriptor 80666 ? Object.getOwnPropertyDescriptor(obj, key) 80667 : null; 80668 if (desc && (desc.get || desc.set)) { 80669 Object.defineProperty(newObj, key, desc); 80670 } else { 80671 newObj[key] = obj[key]; 80672 } 80673 } 80674 } 80675 newObj.default = obj; 80676 if (cache) { 80677 cache.set(obj, newObj); 80678 } 80679 return newObj; 80680 } 80681 function _interopRequireDefault(obj) { 80682 return obj && obj.__esModule ? obj : { default: obj }; 80683 } 80684 function _typeof(obj) { 80685 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') { 80686 _typeof = function _typeof(obj) { 80687 return typeof obj; 80688 }; 80689 } else { 80690 _typeof = function _typeof(obj) { 80691 return obj && 80692 typeof Symbol === 'function' && 80693 obj.constructor === Symbol && 80694 obj !== Symbol.prototype 80695 ? 'symbol' 80696 : typeof obj; 80697 }; 80698 } 80699 return _typeof(obj); 80700 } 80701 80702 /** 80703 * Base class for font handling 80704 * @class p5.Font 80705 * @constructor 80706 * @param {p5} [pInst] pointer to p5 instance 80707 */ 80708 _main.default.Font = function(p) { 80709 this.parent = p; 80710 80711 this.cache = {}; 80712 80713 /** 80714 * Underlying opentype font implementation 80715 * @property font 80716 */ 80717 this.font = undefined; 80718 }; 80719 80720 /** 80721 * Returns a tight bounding box for the given text string using this 80722 * font 80723 * 80724 * @method textBounds 80725 * @param {String} line a line of text 80726 * @param {Number} x x-position 80727 * @param {Number} y y-position 80728 * @param {Number} [fontSize] font size to use (optional) Default is 12. 80729 * @param {Object} [options] opentype options (optional) 80730 * opentype fonts contains alignment and baseline options. 80731 * Default is 'LEFT' and 'alphabetic' 80732 * 80733 * @return {Object} a rectangle object with properties: x, y, w, h 80734 * 80735 * @example 80736 * <div> 80737 * <code> 80738 * let font; 80739 * let textString = 'Lorem ipsum dolor sit amet.'; 80740 * function preload() { 80741 * font = loadFont('./assets/Regular.otf'); 80742 * } 80743 * function setup() { 80744 * background(210); 80745 * 80746 * let bbox = font.textBounds(textString, 10, 30, 12); 80747 * fill(255); 80748 * stroke(0); 80749 * rect(bbox.x, bbox.y, bbox.w, bbox.h); 80750 * fill(0); 80751 * noStroke(); 80752 * 80753 * textFont(font); 80754 * textSize(12); 80755 * text(textString, 10, 30); 80756 * } 80757 * </code> 80758 * </div> 80759 * 80760 * @alt 80761 *words Lorem ipsum dol go off canvas and contained by white bounding box 80762 */ 80763 _main.default.Font.prototype.textBounds = function(str) { 80764 var x = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; 80765 var y = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; 80766 var fontSize = arguments.length > 3 ? arguments[3] : undefined; 80767 var opts = arguments.length > 4 ? arguments[4] : undefined; 80768 // Check cache for existing bounds. Take into consideration the text alignment 80769 // settings. Default alignment should match opentype's origin: left-aligned & 80770 // alphabetic baseline. 80771 var p = (opts && opts.renderer && opts.renderer._pInst) || this.parent; 80772 80773 var ctx = p._renderer.drawingContext; 80774 var alignment = ctx.textAlign || constants.LEFT; 80775 var baseline = ctx.textBaseline || constants.BASELINE; 80776 var cacheResults = false;
80777 var result; 80778 var key; 80779 80780 fontSize = fontSize || p._renderer._textSize; 80781 80782 // NOTE: cache disabled for now pending further discussion of #3436 80783 if (cacheResults) { 80784 key = cacheKey('textBounds', str, x, y, fontSize, alignment, baseline); 80785 result = this.cache[key]; 80786 } 80787 80788 if (!result) { 80789 var minX = []; 80790 var minY; 80791 var maxX = []; 80792 var maxY; 80793 var pos; 80794 var xCoords = []; 80795 xCoords[0] = []; 80796 var yCoords = []; 80797 var scale = this._scale(fontSize); 80798 var lineHeight = p._renderer.textLeading(); 80799 var lineCount = 0; 80800 80801 this.font.forEachGlyph(str, x, y, fontSize, opts, function( 80802 glyph, 80803 gX, 80804 gY, 80805 gFontSize 80806 ) { 80807 var gm = glyph.getMetrics(); 80808 if (glyph.index === 0 || glyph.index === 10) { 80809 lineCount += 1; 80810 xCoords[lineCount] = []; 80811 } else { 80812 xCoords[lineCount].push(gX + gm.xMin * scale); 80813 xCoords[lineCount].push(gX + gm.xMax * scale); 80814 yCoords.push(gY + lineCount * lineHeight + -gm.yMin * scale); 80815 yCoords.push(gY + lineCount * lineHeight + -gm.yMax * scale); 80816 } 80817 }); 80818 80819 if (xCoords[lineCount].length > 0) { 80820 minX[lineCount] = Math.min.apply(null, xCoords[lineCount]); 80821 maxX[lineCount] = Math.max.apply(null, xCoords[lineCount]); 80822 } 80823 80824 var finalMaxX = 0; 80825 for (var i = 0; i <= lineCount; i++) { 80826 minX[i] = Math.min.apply(null, xCoords[i]); 80827 maxX[i] = Math.max.apply(null, xCoords[i]); 80828 var lineLength = maxX[i] - minX[i]; 80829 if (lineLength > finalMaxX) { 80830 finalMaxX = lineLength; 80831 } 80832 } 80833 80834 var finalMinX = Math.min.apply(null, minX); 80835 minY = Math.min.apply(null, yCoords); 80836 maxY = Math.max.apply(null, yCoords); 80837 80838 result = { 80839 x: finalMinX, 80840 y: minY, 80841 h: maxY - minY, 80842 w: finalMaxX, 80843 advance: finalMinX - x 80844 }; 80845 80846 // Bounds are now calculated, so shift the x & y to match alignment settings 80847 pos = this._handleAlignment( 80848 p._renderer, 80849 str, 80850 result.x, 80851 result.y, 80852 result.w + result.advance 80853 ); 80854 80855 result.x = pos.x; 80856 result.y = pos.y; 80857 80858 if (cacheResults) { 80859 this.cache[key] = result; 80860 } 80861 } 80862 80863 return result; 80864 }; 80865 80866 /** 80867 * Computes an array of points following the path for specified text 80868 * 80869 * @method textToPoints 80870 * @param {String} txt a line of text 80871 * @param {Number} x x-position 80872 * @param {Number} y y-position 80873 * @param {Number} fontSize font size to use (optional) 80874 * @param {Object} [options] an (optional) object that can contain: 80875 * 80876 * <br>sampleFactor - the ratio of path-length to number of samples 80877 * (default=.1); higher values yield more points and are therefore 80878 * more precise 80879 * 80880 * <br>simplifyThreshold - if set to a non-zero value, collinear points will be 80881 * be removed from the polygon; the value represents the threshold angle to use 80882 * when determining whether two edges are collinear 80883 * 80884 * @return {Array} an array of points, each with x, y, alpha (the path angle) 80885 * @example 80886 * <div> 80887 * <code> 80888 * let font; 80889 * function preload() { 80890 * font = loadFont('assets/inconsolata.otf'); 80891 * } 80892 * 80893 * let points; 80894 * let bounds; 80895 * function setup() { 80896 * createCanvas(100, 100); 80897 * stroke(0); 80898 * fill(255, 104, 204); 80899 * 80900 * points = font.textToPoints('p5', 0, 0, 10, { 80901 * sampleFactor: 5, 80902 * simplifyThreshold: 0 80903 * }); 80904 * bounds = font.textBounds(' p5 ', 0, 0, 10); 80905 * } 80906 * 80907 * function draw() { 80908 * background(255); 80909 * beginShape(); 80910 * translate(-bounds.x * width / bounds.w, -bounds.y * height / bounds.h); 80911 * for (let i = 0; i < points.length; i++) { 80912 * let p = points[i]; 80913 * vertex( 80914 * p.x * width / bounds.w +
80915 * sin(20 * p.y / bounds.h + millis() / 1000) * width / 30, 80916 * p.y * height / bounds.h 80917 * ); 80918 * } 80919 * endShape(CLOSE); 80920 * } 80921 * </code> 80922 * </div> 80923 */ 80924 _main.default.Font.prototype.textToPoints = function( 80925 txt, 80926 x, 80927 y, 80928 fontSize, 80929 options 80930 ) { 80931 var xoff = 0; 80932 var result = []; 80933 var glyphs = this._getGlyphs(txt); 80934 80935 function isSpace(i) { 80936 return ( 80937 (glyphs[i].name && glyphs[i].name === 'space') || 80938 (txt.length === glyphs.length && txt[i] === ' ') || 80939 (glyphs[i].index && glyphs[i].index === 3) 80940 ); 80941 } 80942 80943 fontSize = fontSize || this.parent._renderer._textSize; 80944 80945 for (var i = 0; i < glyphs.length; i++) { 80946 if (!isSpace(i)) { 80947 // fix to #1817, #2069 80948 80949 var gpath = glyphs[i].getPath(x, y, fontSize), 80950 paths = splitPaths(gpath.commands); 80951 80952 for (var j = 0; j < paths.length; j++) { 80953 var pts = pathToPoints(paths[j], options); 80954 80955 for (var k = 0; k < pts.length; k++) { 80956 pts[k].x += xoff; 80957 result.push(pts[k]); 80958 } 80959 } 80960 } 80961 80962 xoff += glyphs[i].advanceWidth * this._scale(fontSize); 80963 } 80964 80965 return result; 80966 }; 80967 80968 // ----------------------------- End API ------------------------------ 80969 80970 /** 80971 * Returns the set of opentype glyphs for the supplied string. 80972 * 80973 * Note that there is not a strict one-to-one mapping between characters 80974 * and glyphs, so the list of returned glyphs can be larger or smaller 80975 * than the length of the given string. 80976 * 80977 * @private 80978 * @param {String} str the string to be converted 80979 * @return {Array} the opentype glyphs 80980 */ 80981 _main.default.Font.prototype._getGlyphs = function(str) { 80982 return this.font.stringToGlyphs(str); 80983 }; 80984 80985 /** 80986 * Returns an opentype path for the supplied string and position. 80987 * 80988 * @private 80989 * @param {String} line a line of text 80990 * @param {Number} x x-position 80991 * @param {Number} y y-position 80992 * @param {Object} options opentype options (optional) 80993 * @return {Object} the opentype path 80994 */ 80995 _main.default.Font.prototype._getPath = function(line, x, y, options) { 80996 var p = (options && options.renderer && options.renderer._pInst) || this.parent, 80997 renderer = p._renderer, 80998 pos = this._handleAlignment(renderer, line, x, y); 80999 81000 return this.font.getPath(line, pos.x, pos.y, renderer._textSize, options); 81001 }; 81002 81003 /* 81004 * Creates an SVG-formatted path-data string 81005 * (See http://www.w3.org/TR/SVG/paths.html#PathData) 81006 * from the given opentype path or string/position 81007 * 81008 * @param {Object} path an opentype path, OR the following: 81009 * 81010 * @param {String} line a line of text 81011 * @param {Number} x x-position 81012 * @param {Number} y y-position 81013 * @param {Object} options opentype options (optional), set options.decimals 81014 * to set the decimal precision of the path-data 81015 * 81016 * @return {Object} this p5.Font object 81017 */ 81018 _main.default.Font.prototype._getPathData = function(line, x, y, options) { 81019 var decimals = 3; 81020 81021 // create path from string/position 81022 if (typeof line === 'string' && arguments.length > 2) { 81023 line = this._getPath(line, x, y, options); 81024 } else if (_typeof(x) === 'object') { 81025 // handle options specified in 2nd arg 81026 options = x; 81027 } 81028 81029 // handle svg arguments 81030 if (options && typeof options.decimals === 'number') { 81031 decimals = options.decimals; 81032 } 81033 81034 return line.toPathData(decimals); 81035 }; 81036 81037 /* 81038 * Creates an SVG <path> element, as a string, 81039 * from the given opentype path or string/position 81040 * 81041 * @param {Object} path an opentype path, OR the following: 81042 * 81043 * @param {String} line a line of text 81044 * @param {Number} x x-position 81045 * @param {Number} y y-position 81046 * @param {Object} options opentype options (optional), set options.decimals 81047 * to set the decimal precision of the path-data in the <path> element, 81048 * options.fill to set the fill color for the <path> element, 81049 * options.stroke to set the stroke color for the <path> element, 81050 * options.strokeWidth to set the strokeWidth for the <path> element. 81051 * 81052 * @return {Object} this p5.Font object 81053 */ 81054 _main.default.Font.prototype._getSVG = function(line, x, y, options) { 81055 var decimals = 3; 81056 81057 // create path from string/position 81058 if (typeof line === 'string' && arguments.length > 2) { 81059 line = this._getPath(line, x, y, options); 81060 } else if (_typeof(x) === 'object') { 81061 // handle options specified in 2nd arg 81062 options = x; 81063 } 81064 81065 // handle svg arguments 81066 if (options) { 81067 if (typeof options.decimals === 'number') { 81068 decimals = options.decimals; 81069 } 81070 if (typeof options.strokeWidth === 'number') { 81071 line.strokeWidth = options.strokeWidth; 81072 } 81073 if (typeof options.fill !== 'undefined') { 81074 line.fill = options.fill; 81075 } 81076 if (typeof options.stroke !== 'undefined') { 81077 line.stroke = options.stroke; 81078 } 81079 } 81080 81081 return line.toSVG(decimals); 81082 }; 81083 81084 /* 81085 * Renders an opentype path or string/position 81086 * to the current graphics context 81087 * 81088 * @param {Object} path an opentype path, OR the following: 81089 * 81090 * @param {String} line a line of text 81091 * @param {Number} x x-position 81092 * @param {Number} y y-position 81093 * @param {Object} options opentype options (optional) 81094 * 81095 * @return {p5.Font} this p5.Font object 81096 */ 81097 _main.default.Font.prototype._renderPath = function(line, x, y, options) { 81098 var pdata; 81099 var pg = (options && options.renderer) || this.parent._renderer; 81100 var ctx = pg.drawingContext; 81101 81102 if (_typeof(line) === 'object' && line.commands) { 81103 pdata = line.commands; 81104 } else { 81105 //pos = handleAlignment(p, ctx, line, x, y); 81106 pdata = this._getPath(line, x, y, options).commands; 81107 } 81108 81109 ctx.beginPath(); 81110 var _iteratorNormalCompletion = true; 81111 var _didIteratorError = false;
81112 var _iteratorError = undefined; 81113 try { 81114 for ( 81115 var _iterator = pdata[Symbol.iterator](), _step; 81116 !(_iteratorNormalCompletion = (_step = _iterator.next()).done); 81117 _iteratorNormalCompletion = true 81118 ) { 81119 var cmd = _step.value; 81120 if (cmd.type === 'M') { 81121 ctx.moveTo(cmd.x, cmd.y); 81122 } else if (cmd.type === 'L') { 81123 ctx.lineTo(cmd.x, cmd.y); 81124 } else if (cmd.type === 'C') { 81125 ctx.bezierCurveTo(cmd.x1, cmd.y1, cmd.x2, cmd.y2, cmd.x, cmd.y); 81126 } else if (cmd.type === 'Q') { 81127 ctx.quadraticCurveTo(cmd.x1, cmd.y1, cmd.x, cmd.y); 81128 } else if (cmd.type === 'Z') { 81129 ctx.closePath(); 81130 } 81131 } 81132 81133 // only draw stroke if manually set by user 81134 } catch (err) { 81135 _didIteratorError = true; 81136 _iteratorError = err; 81137 } finally { 81138 try { 81139 if (!_iteratorNormalCompletion && _iterator.return != null) { 81140 _iterator.return(); 81141 } 81142 } finally { 81143 if (_didIteratorError) { 81144 throw _iteratorError; 81145 } 81146 } 81147 } 81148 if (pg._doStroke && pg._strokeSet) { 81149 ctx.stroke(); 81150 } 81151 81152 if (pg._doFill) { 81153 // if fill hasn't been set by user, use default-text-fill 81154 if (!pg._fillSet) { 81155 pg._setFill(constants._DEFAULT_TEXT_FILL); 81156 } 81157 ctx.fill(); 81158 } 81159 81160 return this; 81161 }; 81162 81163 _main.default.Font.prototype._textWidth = function(str, fontSize) { 81164 return this.font.getAdvanceWidth(str, fontSize); 81165 }; 81166 81167 _main.default.Font.prototype._textAscent = function(fontSize) { 81168 return this.font.ascender * this._scale(fontSize); 81169 }; 81170 81171 _main.default.Font.prototype._textDescent = function(fontSize) { 81172 return -this.font.descender * this._scale(fontSize); 81173 }; 81174 81175 _main.default.Font.prototype._scale = function(fontSize) { 81176 return 1 / this.font.unitsPerEm * (fontSize || this.parent._renderer._textSize); 81177 }; 81178 81179 _main.default.Font.prototype._handleAlignment = function( 81180 renderer, 81181 line, 81182 x, 81183 y, 81184 textWidth 81185 ) { 81186 var fontSize = renderer._textSize; 81187 81188 if (typeof textWidth === 'undefined') { 81189 textWidth = this._textWidth(line, fontSize); 81190 } 81191 81192 switch (renderer._textAlign) { 81193 case constants.CENTER: 81194 x -= textWidth / 2; 81195 break; 81196 case constants.RIGHT: 81197 x -= textWidth; 81198 break; 81199 } 81200 81201 switch (renderer._textBaseline) { 81202 case constants.TOP: 81203 y += this._textAscent(fontSize); 81204 break; 81205 case constants.CENTER: 81206 y += this._textAscent(fontSize) / 2; 81207 break; 81208 case constants.BOTTOM: 81209 y -= this._textDescent(fontSize); 81210 break; 81211 } 81212 81213 return { x: x, y: y }; 81214 }; 81215 81216 // path-utils 81217 81218 function pathToPoints(cmds, options) { 81219 var opts = parseOpts(options, { 81220 sampleFactor: 0.1, 81221 simplifyThreshold: 0 81222 }); 81223 81224 var // total-length 81225 len = pointAtLength(cmds, 0, 1), 81226 t = len / (len * opts.sampleFactor), 81227 pts = []; 81228 81229 for (var i = 0; i < len; i += t) { 81230 pts.push(pointAtLength(cmds, i)); 81231 } 81232 81233 if (opts.simplifyThreshold) { 81234 simplify(pts, opts.simplifyThreshold); 81235 } 81236 81237 return pts; 81238 } 81239 81240 function simplify(pts) { 81241 var angle = 81242 arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; 81243 var num = 0; 81244 for (var i = pts.length - 1; pts.length > 3 && i >= 0; --i) { 81245 if (collinear(at(pts, i - 1), at(pts, i), at(pts, i + 1), angle)) { 81246 // Remove the middle point 81247 pts.splice(i % pts.length, 1); 81248 num++; 81249 } 81250 } 81251 return num; 81252 } 81253 81254 function splitPaths(cmds) { 81255 var paths = []; 81256 var current; 81257 for (var i = 0; i < cmds.length; i++) { 81258 if (cmds[i].type === 'M') { 81259 if (current) { 81260 paths.push(current); 81261 } 81262 current = []; 81263 } 81264 current.push(cmdToArr(cmds[i])); 81265 } 81266 paths.push(current); 81267 81268 return paths; 81269 } 81270 81271 function cmdToArr(cmd) { 81272 var arr = [cmd.type]; 81273 if (cmd.type === 'M' || cmd.type === 'L') { 81274 // moveto or lineto 81275 arr.push(cmd.x, cmd.y); 81276 } else if (cmd.type === 'C') { 81277 arr.push(cmd.x1, cmd.y1, cmd.x2, cmd.y2, cmd.x, cmd.y); 81278 } else if (cmd.type === 'Q') { 81279 arr.push(cmd.x1, cmd.y1, cmd.x, cmd.y); 81280 } 81281 // else if (cmd.type === 'Z') { /* no-op */ } 81282 return arr; 81283 } 81284 81285 function parseOpts(options, defaults) { 81286 if (_typeof(options) !== 'object') { 81287 options = defaults; 81288 } else { 81289 for (var key in defaults) { 81290 if (typeof options[key] === 'undefined') { 81291 options[key] = defaults[key]; 81292 } 81293 } 81294 } 81295 return options; 81296 } 81297
81298 //////////////////////// Helpers //////////////////////////// 81299 81300 function at(v, i) { 81301 var s = v.length; 81302 return v[i < 0 ? i % s + s : i % s]; 81303 } 81304 81305 function collinear(a, b, c, thresholdAngle) { 81306 if (!thresholdAngle) { 81307 return areaTriangle(a, b, c) === 0; 81308 } 81309 81310 if (typeof collinear.tmpPoint1 === 'undefined') { 81311 collinear.tmpPoint1 = []; 81312 collinear.tmpPoint2 = []; 81313 } 81314 81315 var ab = collinear.tmpPoint1, 81316 bc = collinear.tmpPoint2; 81317 ab.x = b.x - a.x; 81318 ab.y = b.y - a.y; 81319 bc.x = c.x - b.x; 81320 bc.y = c.y - b.y; 81321 81322 var dot = ab.x * bc.x + ab.y * bc.y, 81323 magA = Math.sqrt(ab.x * ab.x + ab.y * ab.y), 81324 magB = Math.sqrt(bc.x * bc.x + bc.y * bc.y), 81325 angle = Math.acos(dot / (magA * magB)); 81326 81327 return angle < thresholdAngle; 81328 } 81329 81330 function areaTriangle(a, b, c) { 81331 return (b[0] - a[0]) * (c[1] - a[1]) - (c[0] - a[0]) * (b[1] - a[1]); 81332 } 81333 81334 // Portions of below code copyright 2008 Dmitry Baranovskiy (via MIT license) 81335 81336 function findDotsAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) { 81337 var t1 = 1 - t; 81338 var t13 = Math.pow(t1, 3); 81339 var t12 = Math.pow(t1, 2); 81340 var t2 = t * t; 81341 var t3 = t2 * t; 81342 var x = t13 * p1x + t12 * 3 * t * c1x + t1 * 3 * t * t * c2x + t3 * p2x; 81343 var y = t13 * p1y + t12 * 3 * t * c1y + t1 * 3 * t * t * c2y + t3 * p2y; 81344 var mx = p1x + 2 * t * (c1x - p1x) + t2 * (c2x - 2 * c1x + p1x); 81345 var my = p1y + 2 * t * (c1y - p1y) + t2 * (c2y - 2 * c1y + p1y); 81346 var nx = c1x + 2 * t * (c2x - c1x) + t2 * (p2x - 2 * c2x + c1x); 81347 var ny = c1y + 2 * t * (c2y - c1y) + t2 * (p2y - 2 * c2y + c1y); 81348 var ax = t1 * p1x + t * c1x; 81349 var ay = t1 * p1y + t * c1y; 81350 var cx = t1 * c2x + t * p2x; 81351 var cy = t1 * c2y + t * p2y; 81352 var alpha = 90 - Math.atan2(mx - nx, my - ny) * 180 / Math.PI; 81353 81354 if (mx > nx || my < ny) { 81355 alpha += 180; 81356 } 81357 81358 return { 81359 x: x, 81360 y: y, 81361 m: { x: mx, y: my }, 81362 n: { x: nx, y: ny }, 81363 start: { x: ax, y: ay }, 81364 end: { x: cx, y: cy }, 81365 alpha: alpha 81366 }; 81367 } 81368 81369 function getPointAtSegmentLength(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, length) { 81370 return length == null 81371 ? bezlen(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) 81372 : findDotsAtSegment( 81373 p1x, 81374 p1y, 81375 c1x, 81376 c1y, 81377 c2x, 81378 c2y, 81379 p2x, 81380 p2y, 81381 getTatLen(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, length) 81382 ); 81383 } 81384 81385 function pointAtLength(path, length, istotal) { 81386 path = path2curve(path); 81387 var x; 81388 var y; 81389 var p; 81390 var l; 81391 var sp = ''; 81392 var subpaths = {}; 81393 var point; 81394 var len = 0; 81395 for (var i = 0, ii = path.length; i < ii; i++) { 81396 p = path[i]; 81397 if (p[0] === 'M') { 81398 x = +p[1]; 81399 y = +p[2]; 81400 } else { 81401 l = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6]); 81402 if (len + l > length) { 81403 if (!istotal) { 81404 point = getPointAtSegmentLength( 81405 x, 81406 y, 81407 p[1], 81408 p[2], 81409 p[3], 81410 p[4], 81411 p[5], 81412 p[6], 81413 length - len 81414 ); 81415 81416 return { x: point.x, y: point.y, alpha: point.alpha }; 81417 } 81418 } 81419 len += l; 81420 x = +p[5]; 81421 y = +p[6]; 81422 } 81423 sp += p.shift() + p; 81424 } 81425 subpaths.end = sp; 81426 81427 point = istotal 81428 ? len 81429 : findDotsAtSegment(x, y, p[0], p[1], p[2], p[3], p[4], p[5], 1); 81430 81431 if (point.alpha) {
81432 point = { x: point.x, y: point.y, alpha: point.alpha }; 81433 } 81434 81435 return point; 81436 } 81437 81438 function pathToAbsolute(pathArray) { 81439 var res = [], 81440 x = 0, 81441 y = 0, 81442 mx = 0, 81443 my = 0, 81444 start = 0; 81445 if (!pathArray) { 81446 // console.warn("Unexpected state: undefined pathArray"); // shouldn't happen 81447 return res; 81448 } 81449 if (pathArray[0][0] === 'M') { 81450 x = +pathArray[0][1]; 81451 y = +pathArray[0][2]; 81452 mx = x; 81453 my = y; 81454 start++; 81455 res[0] = ['M', x, y]; 81456 } 81457 81458 var dots; 81459 81460 var crz = 81461 pathArray.length === 3 && 81462 pathArray[0][0] === 'M' && 81463 pathArray[1][0].toUpperCase() === 'R' && 81464 pathArray[2][0].toUpperCase() === 'Z'; 81465 81466 for (var r, pa, i = start, ii = pathArray.length; i < ii; i++) { 81467 res.push((r = [])); 81468 pa = pathArray[i]; 81469 if (pa[0] !== String.prototype.toUpperCase.call(pa[0])) { 81470 r[0] = String.prototype.toUpperCase.call(pa[0]); 81471 switch (r[0]) { 81472 case 'A': 81473 r[1] = pa[1]; 81474 r[2] = pa[2]; 81475 r[3] = pa[3]; 81476 r[4] = pa[4]; 81477 r[5] = pa[5]; 81478 r[6] = +(pa[6] + x); 81479 r[7] = +(pa[7] + y); 81480 break; 81481 case 'V': 81482 r[1] = +pa[1] + y; 81483 break; 81484 case 'H': 81485 r[1] = +pa[1] + x; 81486 break; 81487 case 'R': 81488 dots = [x, y].concat(pa.slice(1)); 81489 for (var j = 2, jj = dots.length; j < jj; j++) { 81490 dots[j] = +dots[j] + x; 81491 dots[++j] = +dots[j] + y; 81492 } 81493 res.pop(); 81494 res = res.concat(catmullRom2bezier(dots, crz)); 81495 break; 81496 case 'M': 81497 mx = +pa[1] + x; 81498 my = +pa[2] + y; 81499 break; 81500 default: 81501 for (var _j = 1, _jj = pa.length; _j < _jj; _j++) { 81502 r[_j] = +pa[_j] + (_j % 2 ? x : y); 81503 } 81504 } 81505 } else if (pa[0] === 'R') { 81506 dots = [x, y].concat(pa.slice(1)); 81507 res.pop(); 81508 res = res.concat(catmullRom2bezier(dots, crz)); 81509 r = ['R'].concat(pa.slice(-2)); 81510 } else { 81511 for (var k = 0, kk = pa.length; k < kk; k++) { 81512 r[k] = pa[k]; 81513 } 81514 } 81515 switch (r[0]) { 81516 case 'Z': 81517 x = mx; 81518 y = my; 81519 break; 81520 case 'H': 81521 x = r[1]; 81522 break; 81523 case 'V': 81524 y = r[1]; 81525 break; 81526 case 'M': 81527 mx = r[r.length - 2]; 81528 my = r[r.length - 1]; 81529 break; 81530 default: 81531 x = r[r.length - 2]; 81532 y = r[r.length - 1]; 81533 } 81534 } 81535 return res; 81536 } 81537 81538 function path2curve(path, path2) { 81539 var p = pathToAbsolute(path), 81540 p2 = path2 && pathToAbsolute(path2); 81541 var attrs = { x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null }; 81542 var attrs2 = { x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null }; 81543 var pcoms1 = []; // path commands of original path p 81544 var pcoms2 = []; // path commands of original path p2 81545 var ii; 81546 81547 var processPath = function processPath(path, d, pcom) { 81548 var nx; 81549 var ny; 81550 var tq = { T: 1, Q: 1 }; 81551 if (!path) { 81552 return ['C', d.x, d.y, d.x, d.y, d.x, d.y]; 81553 } 81554 if (!(path[0] in tq)) { 81555 d.qx = d.qy = null; 81556 } 81557 switch (path[0]) { 81558 case 'M': 81559 d.X = path[1]; 81560 d.Y = path[2]; 81561 break; 81562 case 'A': 81563 path = ['C'].concat(a2c.apply(0, [d.x, d.y].concat(path.slice(1)))); 81564 break; 81565 case 'S': 81566 if (pcom === 'C' || pcom === 'S') { 81567 nx = d.x * 2 - d.bx; 81568 ny = d.y * 2 - d.by; 81569 } else { 81570 nx = d.x; 81571 ny = d.y; 81572 } 81573 path = ['C', nx, ny].concat(path.slice(1)); 81574 break; 81575 case 'T': 81576 if (pcom === 'Q' || pcom === 'T') { 81577 d.qx = d.x * 2 - d.qx; 81578 d.qy = d.y * 2 - d.qy; 81579 } else { 81580 d.qx = d.x; 81581 d.qy = d.y; 81582 } 81583 path = ['C'].concat(q2c(d.x, d.y, d.qx, d.qy, path[1], path[2])); 81584 break; 81585 case 'Q': 81586 d.qx = path[1]; 81587 d.qy = path[2]; 81588 path = ['C'].concat(q2c(d.x, d.y, path[1], path[2], path[3], path[4])); 81589 81590 break; 81591 case 'L': 81592 path = ['C'].concat(l2c(d.x, d.y, path[1], path[2])); 81593 break; 81594 case 'H': 81595 path = ['C'].concat(l2c(d.x, d.y, path[1], d.y)); 81596 break; 81597 case 'V': 81598 path = ['C'].concat(l2c(d.x, d.y, d.x, path[1])); 81599 break; 81600 case 'Z': 81601 path = ['C'].concat(l2c(d.x, d.y, d.X, d.Y)); 81602 break; 81603 } 81604 81605 return path; 81606 }, 81607 fixArc = function fixArc(pp, i) { 81608 if (pp[i].length > 7) { 81609 pp[i].shift(); 81610 var pi = pp[i]; 81611 while (pi.length) { 81612 pcoms1[i] = 'A'; 81613 if (p2) { 81614 pcoms2[i] = 'A'; 81615 } 81616 pp.splice(i++, 0, ['C'].concat(pi.splice(0, 6))); 81617 } 81618 pp.splice(i, 1); 81619 ii = Math.max(p.length, (p2 && p2.length) || 0); 81620 } 81621 }, 81622 fixM = function fixM(path1, path2, a1, a2, i) { 81623 if (path1 && path2 && path1[i][0] === 'M' && path2[i][0] !== 'M') { 81624 path2.splice(i, 0, ['M', a2.x, a2.y]); 81625 a1.bx = 0; 81626 a1.by = 0; 81627 a1.x = path1[i][1]; 81628 a1.y = path1[i][2]; 81629 ii = Math.max(p.length, (p2 && p2.length) || 0); 81630 } 81631 }; 81632 81633 var pfirst = ''; // temporary holder for original path command 81634 var pcom = ''; // holder for previous path command of original path 81635 81636 ii = Math.max(p.length, (p2 && p2.length) || 0); 81637 for (var i = 0; i < ii; i++) { 81638 if (p[i]) { 81639 pfirst = p[i][0]; 81640 } // save current path command 81641 81642 if (pfirst !== 'C') { 81643 pcoms1[i] = pfirst; // Save current path command 81644 if (i) { 81645 pcom = pcoms1[i - 1]; 81646 } // Get previous path command pcom 81647 } 81648 p[i] = processPath(p[i], attrs, pcom); 81649 81650 if (pcoms1[i] !== 'A' && pfirst === 'C') { 81651 pcoms1[i] = 'C'; 81652 } 81653 81654 fixArc(p, i);
81654 // fixArc adds also the right amount of A:s to pcoms1 81655 81656 if (p2) { 81657 // the same procedures is done to p2 81658 if (p2[i]) { 81659 pfirst = p2[i][0]; 81660 } 81661 if (pfirst !== 'C') { 81662 pcoms2[i] = pfirst; 81663 if (i) { 81664 pcom = pcoms2[i - 1]; 81665 } 81666 } 81667 p2[i] = processPath(p2[i], attrs2, pcom); 81668 81669 if (pcoms2[i] !== 'A' && pfirst === 'C') { 81670 pcoms2[i] = 'C'; 81671 } 81672 81673 fixArc(p2, i); 81674 } 81675 fixM(p, p2, attrs, attrs2, i); 81676 fixM(p2, p, attrs2, attrs, i); 81677 var seg = p[i], 81678 seg2 = p2 && p2[i], 81679 seglen = seg.length, 81680 seg2len = p2 && seg2.length; 81681 attrs.x = seg[seglen - 2]; 81682 attrs.y = seg[seglen - 1]; 81683 attrs.bx = parseFloat(seg[seglen - 4]) || attrs.x; 81684 attrs.by = parseFloat(seg[seglen - 3]) || attrs.y; 81685 attrs2.bx = p2 && (parseFloat(seg2[seg2len - 4]) || attrs2.x); 81686 attrs2.by = p2 && (parseFloat(seg2[seg2len - 3]) || attrs2.y); 81687 attrs2.x = p2 && seg2[seg2len - 2]; 81688 attrs2.y = p2 && seg2[seg2len - 1]; 81689 } 81690 81691 return p2 ? [p, p2] : p; 81692 } 81693 81694 function a2c(x1, y1, rx, ry, angle, lac, sweep_flag, x2, y2, recursive) { 81695 // for more information of where this Math came from visit: 81696 // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes 81697 var PI = Math.PI; 81698 81699 var _120 = PI * 120 / 180; 81700 var f1; 81701 var f2; 81702 var cx; 81703 var cy; 81704 var rad = PI / 180 * (+angle || 0); 81705 var res = []; 81706 var xy; 81707 81708 var rotate = function rotate(x, y, rad) { 81709 var X = x * Math.cos(rad) - y * Math.sin(rad), 81710 Y = x * Math.sin(rad) + y * Math.cos(rad); 81711 return { x: X, y: Y }; 81712 }; 81713 81714 if (!recursive) { 81715 xy = rotate(x1, y1, -rad); 81716 x1 = xy.x; 81717 y1 = xy.y; 81718 xy = rotate(x2, y2, -rad); 81719 x2 = xy.x; 81720 y2 = xy.y; 81721 var x = (x1 - x2) / 2; 81722 var y = (y1 - y2) / 2; 81723 var h = x * x / (rx * rx) + y * y / (ry * ry); 81724 if (h > 1) { 81725 h = Math.sqrt(h); 81726 rx = h * rx; 81727 ry = h * ry; 81728 } 81729 var rx2 = rx * rx, 81730 ry2 = ry * ry; 81731 var k = 81732 (lac === sweep_flag ? -1 : 1) * 81733 Math.sqrt( 81734 Math.abs( 81735 (rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x) 81736 ) 81737 ); 81738 81739 cx = k * rx * y / ry + (x1 + x2) / 2; 81740 cy = k * -ry * x / rx + (y1 + y2) / 2; 81741 f1 = Math.asin(((y1 - cy) / ry).toFixed(9)); 81742 f2 = Math.asin(((y2 - cy) / ry).toFixed(9)); 81743 81744 f1 = x1 < cx ? PI - f1 : f1; 81745 f2 = x2 < cx ? PI - f2 : f2; 81746 81747 if (f1 < 0) { 81748 f1 = PI * 2 + f1; 81749 } 81750 if (f2 < 0) { 81751 f2 = PI * 2 + f2; 81752 } 81753 81754 if (sweep_flag && f1 > f2) { 81755 f1 = f1 - PI * 2; 81756 } 81757 if (!sweep_flag && f2 > f1) { 81758 f2 = f2 - PI * 2; 81759 } 81760 } else { 81761 f1 = recursive[0]; 81762 f2 = recursive[1]; 81763 cx = recursive[2]; 81764 cy = recursive[3]; 81765 } 81766 var df = f2 - f1; 81767 if (Math.abs(df) > _120) { 81768 var f2old = f2, 81769 x2old = x2, 81770 y2old = y2; 81771 f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1); 81772 x2 = cx + rx * Math.cos(f2); 81773 y2 = cy + ry * Math.sin(f2); 81774 res = a2c(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old, [ 81775 f2, 81776 f2old, 81777 cx, 81778 cy 81779 ]); 81780 } 81781 df = f2 - f1; 81782 var c1 = Math.cos(f1), 81783 s1 = Math.sin(f1),
81784 c2 = Math.cos(f2), 81785 s2 = Math.sin(f2), 81786 t = Math.tan(df / 4), 81787 hx = 4 / 3 * rx * t, 81788 hy = 4 / 3 * ry * t, 81789 m1 = [x1, y1], 81790 m2 = [x1 + hx * s1, y1 - hy * c1], 81791 m3 = [x2 + hx * s2, y2 - hy * c2], 81792 m4 = [x2, y2]; 81793 m2[0] = 2 * m1[0] - m2[0]; 81794 m2[1] = 2 * m1[1] - m2[1]; 81795 if (recursive) { 81796 return [m2, m3, m4].concat(res); 81797 } else { 81798 res = [m2, m3, m4] 81799 .concat(res) 81800 .join() 81801 .split(','); 81802 var newres = []; 81803 for (var i = 0, ii = res.length; i < ii; i++) { 81804 newres[i] = 81805 i % 2 81806 ? rotate(res[i - 1], res[i], rad).y 81807 : rotate(res[i], res[i + 1], rad).x; 81808 } 81809 return newres; 81810 } 81811 } 81812 81813 // http://schepers.cc/getting-to-the-point 81814 function catmullRom2bezier(crp, z) { 81815 var d = []; 81816 for (var i = 0, iLen = crp.length; iLen - 2 * !z > i; i += 2) { 81817 var p = [ 81818 { 81819 x: +crp[i - 2], 81820 y: +crp[i - 1] 81821 }, 81822 81823 { 81824 x: +crp[i], 81825 y: +crp[i + 1] 81826 }, 81827 81828 { 81829 x: +crp[i + 2], 81830 y: +crp[i + 3] 81831 }, 81832 81833 { 81834 x: +crp[i + 4], 81835 y: +crp[i + 5] 81836 } 81837 ]; 81838 81839 if (z) { 81840 if (!i) { 81841 p[0] = { 81842 x: +crp[iLen - 2], 81843 y: +crp[iLen - 1] 81844 }; 81845 } else if (iLen - 4 === i) { 81846 p[3] = { 81847 x: +crp[0], 81848 y: +crp[1] 81849 }; 81850 } else if (iLen - 2 === i) { 81851 p[2] = { 81852 x: +crp[0], 81853 y: +crp[1] 81854 }; 81855 81856 p[3] = { 81857 x: +crp[2], 81858 y: +crp[3] 81859 }; 81860 } 81861 } else { 81862 if (iLen - 4 === i) { 81863 p[3] = p[2]; 81864 } else if (!i) { 81865 p[0] = { 81866 x: +crp[i], 81867 y: +crp[i + 1] 81868 }; 81869 } 81870 } 81871 d.push([ 81872 'C', 81873 (-p[0].x + 6 * p[1].x + p[2].x) / 6, 81874 (-p[0].y + 6 * p[1].y + p[2].y) / 6, 81875 (p[1].x + 6 * p[2].x - p[3].x) / 6, 81876 (p[1].y + 6 * p[2].y - p[3].y) / 6, 81877 p[2].x, 81878 p[2].y 81879 ]); 81880 } 81881 81882 return d; 81883 } 81884 81885 function l2c(x1, y1, x2, y2) { 81886 return [x1, y1, x2, y2, x2, y2]; 81887 } 81888 81889 function q2c(x1, y1, ax, ay, x2, y2) { 81890 var _13 = 1 / 3, 81891 _23 = 2 / 3; 81892 return [ 81893 _13 * x1 + _23 * ax, 81894 _13 * y1 + _23 * ay, 81895 _13 * x2 + _23 * ax, 81896 _13 * y2 + _23 * ay, 81897 x2, 81898 y2 81899 ]; 81900 } 81901 81902 function bezlen(x1, y1, x2, y2, x3, y3, x4, y4, z) { 81903 if (z == null) { 81904 z = 1; 81905 } 81906 z = z > 1 ? 1 : z < 0 ? 0 : z; 81907 var z2 = z / 2; 81908 var n = 12; 81909 var Tvalues = [ 81910 -0.1252, 81911 0.1252, 81912 -0.3678, 81913 0.3678, 81914 -0.5873, 81915 0.5873, 81916 -0.7699, 81917 0.7699, 81918 -0.9041, 81919 0.9041, 81920 -0.9816, 81921 0.9816 81922 ]; 81923 81924 var sum = 0; 81925 var Cvalues = [ 81926 0.2491, 81927 0.2491, 81928 0.2335, 81929 0.2335, 81930 0.2032, 81931 0.2032, 81932 0.1601, 81933 0.1601, 81934 0.1069, 81935 0.1069, 81936 0.0472, 81937 0.0472 81938 ]; 81939 81940 for (var i = 0; i < n; i++) { 81941 var ct = z2 * Tvalues[i] + z2, 81942 xbase = base3(ct, x1, x2, x3, x4), 81943 ybase = base3(ct, y1, y2, y3, y4), 81944 comb = xbase * xbase + ybase * ybase; 81945 sum += Cvalues[i] * Math.sqrt(comb); 81946 } 81947 return z2 * sum; 81948 } 81949 81950 function getTatLen(x1, y1, x2, y2, x3, y3, x4, y4, ll) { 81951 if (ll < 0 || bezlen(x1, y1, x2, y2, x3, y3, x4, y4) < ll) { 81952 return; 81953 } 81954 var t = 1; 81955 var step = t / 2; 81956 var t2 = t - step; 81957 var l; 81958 var e = 0.01; 81959 l = bezlen(x1, y1, x2, y2, x3, y3, x4, y4, t2); 81960 while (Math.abs(l - ll) > e) { 81961 step /= 2; 81962 t2 += (l < ll ? 1 : -1) * step; 81963 l = bezlen(x1, y1, x2, y2, x3, y3, x4, y4, t2); 81964 } 81965 return t2; 81966 } 81967 81968 function base3(t, p1, p2, p3, p4) { 81969 var t1 = -3 * p1 + 9 * p2 - 9 * p3 + 3 * p4, 81970 t2 = t * t1 + 6 * p1 - 12 * p2 + 6 * p3; 81971 return t * t2 - 3 * p1 + 3 * p2; 81972 } 81973 81974 function cacheKey() { 81975 var hash = ''; 81976 for (var i = arguments.length - 1; i >= 0; --i) { 81977 hash += '\uFF1F'.concat( 81978 i < 0 || arguments.length <= i ? undefined : arguments[i] 81979 ); 81980 } 81981 return hash; 81982 } 81983 var _default = _main.default; 81984 exports.default = _default; 81985 }, 81986 { '../core/constants': 48, '../core/main': 59 } 81987 ], 81988 98: [
81989 function(_dereq_, module, exports) { 81990 'use strict'; 81991 Object.defineProperty(exports, '__esModule', { value: true }); 81992 exports.default = void 0; 81993 81994 var _main = _interopRequireDefault(_dereq_('../core/main')); 81995 function _interopRequireDefault(obj) { 81996 return obj && obj.__esModule ? obj : { default: obj }; 81997 } 81998 /** 81999 * @module Data 82000 * @submodule Array Functions 82001 * @for p5 82002 * @requires core 82003 */ /** 82004 * Adds a value to the end of an array. Extends the length of 82005 * the array by one. Maps to Array.push(). 82006 * 82007 * @method append 82008 * @deprecated Use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push">array.push(value)</a> instead. 82009 * @param {Array} array Array to append 82010 * @param {any} value to be added to the Array 82011 * @return {Array} the array that was appended to 82012 * @example 82013 * <div class='norender'><code> 82014 * function setup() { 82015 * let myArray = ['Mango', 'Apple', 'Papaya']; 82016 * print(myArray); // ['Mango', 'Apple', 'Papaya'] 82017 * 82018 * append(myArray, 'Peach'); 82019 * print(myArray); // ['Mango', 'Apple', 'Papaya', 'Peach'] 82020 * } 82021 * </code></div> 82022 */ _main.default.prototype.append = function(array, value) { 82023 array.push(value); 82024 return array; 82025 }; 82026 82027 /** 82028 * Copies an array (or part of an array) to another array. The src array is 82029 * copied to the dst array, beginning at the position specified by 82030 * srcPosition and into the position specified by dstPosition. The number of 82031 * elements to copy is determined by length. Note that copying values 82032 * overwrites existing values in the destination array. To append values 82033 * instead of overwriting them, use <a href="#/p5/concat">concat()</a>. 82034 * 82035 * The simplified version with only two arguments, arrayCopy(src, dst), 82036 * copies an entire array to another of the same size. It is equivalent to 82037 * arrayCopy(src, 0, dst, 0, src.length). 82038 * 82039 * Using this function is far more efficient for copying array data than 82040 * iterating through a for() loop and copying each element individually. 82041 * 82042 * @method arrayCopy 82043 * @deprecated Use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin">arr1.copyWithin(arr2)</a> instead. 82044 * @param {Array} src the source Array 82045 * @param {Integer} srcPosition starting position in the source Array 82046 * @param {Array} dst the destination Array 82047 * @param {Integer} dstPosition starting position in the destination Array 82048 * @param {Integer} length number of Array elements to be copied 82049 * 82050 * @example 82051 * <div class='norender'><code> 82052 * let src = ['A', 'B', 'C']; 82053 * let dst = [1, 2, 3]; 82054 * let srcPosition = 1; 82055 * let dstPosition = 0; 82056 * let length = 2; 82057 * 82058 * print(src); // ['A', 'B', 'C'] 82059 * print(dst); // [ 1 , 2 , 3 ] 82060 * 82061 * arrayCopy(src, srcPosition, dst, dstPosition, length); 82062 * print(dst); // ['B', 'C', 3] 82063 * </code></div> 82064 */ 82065 /** 82066 * @method arrayCopy 82067 * @deprecated Use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin">arr1.copyWithin(arr2)</a> instead. 82068 * @param {Array} src 82069 * @param {Array} dst 82070 * @param {Integer} [length] 82071 */ 82072 _main.default.prototype.arrayCopy = function( 82073 src, 82074 srcPosition, 82075 dst, 82076 dstPosition, 82077 length 82078 ) { 82079 // the index to begin splicing from dst array 82080 var start; 82081 var end; 82082 82083 if (typeof length !== 'undefined') { 82084 end = Math.min(length, src.length); 82085 start = dstPosition;
82086 src = src.slice(srcPosition, end + srcPosition); 82087 } else { 82088 if (typeof dst !== 'undefined') { 82089 // src, dst, length 82090 // rename so we don't get confused 82091 end = dst; 82092 end = Math.min(end, src.length); 82093 } else { 82094 // src, dst 82095 end = src.length; 82096 } 82097 82098 start = 0; 82099 // rename so we don't get confused 82100 dst = srcPosition; 82101 src = src.slice(0, end); 82102 } 82103 82104 // Since we are not returning the array and JavaScript is pass by reference 82105 // we must modify the actual values of the array 82106 // instead of reassigning arrays 82107 Array.prototype.splice.apply(dst, [start, end].concat(src)); 82108 }; 82109 82110 /** 82111 * Concatenates two arrays, maps to Array.concat(). Does not modify the 82112 * input arrays. 82113 * 82114 * @method concat 82115 * @deprecated Use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat">arr1.concat(arr2)</a> instead. 82116 * @param {Array} a first Array to concatenate 82117 * @param {Array} b second Array to concatenate 82118 * @return {Array} concatenated array 82119 * 82120 * @example 82121 * <div class = 'norender'><code> 82122 * function setup() { 82123 * let arr1 = ['A', 'B', 'C']; 82124 * let arr2 = [1, 2, 3]; 82125 * 82126 * print(arr1); // ['A','B','C'] 82127 * print(arr2); // [1,2,3] 82128 * 82129 * let arr3 = concat(arr1, arr2); 82130 * 82131 * print(arr1); // ['A','B','C'] 82132 * print(arr2); // [1, 2, 3] 82133 * print(arr3); // ['A','B','C', 1, 2, 3] 82134 * } 82135 * </code></div> 82136 */ 82137 _main.default.prototype.concat = function(list0, list1) { 82138 return list0.concat(list1); 82139 }; 82140 82141 /** 82142 * Reverses the order of an array, maps to Array.reverse() 82143 * 82144 * @method reverse 82145 * @deprecated Use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse">array.reverse()</a> instead. 82146 * @param {Array} list Array to reverse 82147 * @return {Array} the reversed list 82148 * @example 82149 * <div class='norender'><code> 82150 * function setup() { 82151 * let myArray = ['A', 'B', 'C']; 82152 * print(myArray); // ['A','B','C'] 82153 * 82154 * reverse(myArray); 82155 * print(myArray); // ['C','B','A'] 82156 * } 82157 * </code></div> 82158 */ 82159 _main.default.prototype.reverse = function(list) { 82160 return list.reverse(); 82161 }; 82162 82163 /** 82164 * Decreases an array by one element and returns the shortened array, 82165 * maps to Array.pop(). 82166 * 82167 * @method shorten 82168 * @deprecated Use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/pop">array.pop()</a> instead. 82169 * @param {Array} list Array to shorten 82170 * @return {Array} shortened Array 82171 * @example 82172 * <div class = 'norender'><code> 82173 * function setup() { 82174 * let myArray = ['A', 'B', 'C']; 82175 * print(myArray); // ['A', 'B', 'C'] 82176 * let newArray = shorten(myArray); 82177 * print(myArray); // ['A','B','C'] 82178 * print(newArray); // ['A','B'] 82179 * } 82180 * </code></div> 82181 */ 82182 _main.default.prototype.shorten = function(list) { 82183 list.pop(); 82184 return list; 82185 }; 82186 82187 /** 82188 * Randomizes the order of the elements of an array. Implements 82189 * <a href='http://Bost.Ocks.org/mike/shuffle/' target=_blank> 82190 * Fisher-Yates Shuffle Algorithm</a>. 82191 * 82192 * @method shuffle 82193 * @param {Array} array Array to shuffle 82194 * @param {Boolean} [bool] modify passed array 82195 * @return {Array} shuffled Array 82196 * @example 82197 * <div><code> 82198 * function setup() { 82199 * let regularArr = ['ABC', 'def', createVector(), TAU, Math.E]; 82200 * print(regularArr); 82201 * shuffle(regularArr, true); // force modifications to passed array 82202 * print(regularArr); 82203 * 82204 * // By default shuffle() returns a shuffled cloned array: 82205 * let newArr = shuffle(regularArr); 82206 * print(regularArr); 82207 * print(newArr); 82208 * } 82209 * </code></div> 82210 */ 82211 _main.default.prototype.shuffle = function(arr, bool) { 82212 var isView = ArrayBuffer && ArrayBuffer.isView && ArrayBuffer.isView(arr); 82213 arr = bool || isView ? arr : arr.slice(); 82214 82215 var rnd, 82216 tmp, 82217 idx = arr.length; 82218 while (idx > 1) { 82219 rnd = (this.random(0, 1) * idx) | 0; 82220 82221 tmp = arr[--idx]; 82222 arr[idx] = arr[rnd]; 82223 arr[rnd] = tmp; 82224 } 82225 82226 return arr; 82227 }; 82228 82229 /** 82230 * Sorts an array of numbers from smallest to largest, or puts an array of 82231 * words in alphabetical order. The original array is not modified; a 82232 * re-ordered array is returned. The count parameter states the number of 82233 * elements to sort. For example, if there are 12 elements in an array and 82234 * count is set to 5, only the first 5 elements in the array will be sorted. 82235 * 82236 * @method sort 82237 * @deprecated Use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort">array.sort()</a> instead. 82238 * @param {Array} list Array to sort 82239 * @param {Integer} [count] number of elements to sort, starting from 0 82240 * @return {Array} the sorted list 82241 * 82242 * @example 82243 * <div class = 'norender'><code> 82244 * function setup() { 82245 * let words = ['banana', 'apple', 'pear', 'lime']; 82246 * print(words); // ['banana', 'apple', 'pear', 'lime'] 82247 * let count = 4; // length of array 82248 * 82249 * words = sort(words, count); 82250 * print(words); // ['apple', 'banana', 'lime', 'pear'] 82251 * } 82252 * </code></div> 82253 * <div class = 'norender'><code> 82254 * function setup() { 82255 * let numbers = [2, 6, 1, 5, 14, 9, 8, 12]; 82256 * print(numbers); // [2, 6, 1, 5, 14, 9, 8, 12] 82257 * let count = 5; // Less than the length of the array 82258 * 82259 * numbers = sort(numbers, count); 82260 * print(numbers); // [1,2,5,6,14,9,8,12] 82261 * } 82262 * </code></div> 82263 */ 82264 _main.default.prototype.sort = function(list, count) { 82265 var arr = count ? list.slice(0, Math.min(count, list.length)) : list; 82266 var rest = count ? list.slice(Math.min(count, list.length)) : []; 82267 if (typeof arr[0] === 'string') { 82268 arr = arr.sort(); 82269 } else { 82270 arr = arr.sort(function(a, b) { 82271 return a - b; 82272 }); 82273 } 82274 return arr.concat(rest); 82275 }; 82276 82277 /** 82278 * Inserts a value or an array of values into an existing array. The first 82279 * parameter specifies the initial array to be modified, and the second 82280 * parameter defines the data to be inserted. The third parameter is an index 82281 * value which specifies the array position from which to insert data. 82282 * (Remember that array index numbering starts at zero, so the first position 82283 * is 0, the second position is 1, and so on.) 82284 * 82285 * @method splice 82286 * @deprecated Use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice">array.splice()</a> instead. 82287 * @param {Array} list Array to splice into 82288 * @param {any} value value to be spliced in 82289 * @param {Integer} position in the array from which to insert data 82290 * @return {Array} the list 82291 * 82292 * @example 82293 * <div class = 'norender'><code> 82294 * function setup() { 82295 * let myArray = [0, 1, 2, 3, 4]; 82296 * let insArray = ['A', 'B', 'C']; 82297 * print(myArray); // [0, 1, 2, 3, 4] 82298 * print(insArray); // ['A','B','C'] 82299 * 82300 * splice(myArray, insArray, 3); 82301 * print(myArray); // [0,1,2,'A','B','C',3,4] 82302 * } 82303 * </code></div> 82304 */ 82305 _main.default.prototype.splice = function(list, value, index) { 82306 // note that splice returns spliced elements and not an array 82307 Array.prototype.splice.apply(list, [index, 0].concat(value)); 82308 82309 return list; 82310 }; 82311 82312 /** 82313 * Extracts an array of elements from an existing array. The list parameter 82314 * defines the array from which the elements will be copied, and the start 82315 * and count parameters specify which elements to extract. If no count is 82316 * given, elements will be extracted from the start to the end of the array. 82317 * When specifying the start, remember that the first array element is 0. 82318 * This function does not change the source array. 82319 * 82320 * @method subset 82321 * @deprecated Use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice">array.slice()</a> instead. 82322 * @param {Array} list Array to extract from 82323 * @param {Integer} start position to begin 82324 * @param {Integer} [count] number of values to extract 82325 * @return {Array} Array of extracted elements 82326 * 82327 * @example 82328 * <div class = 'norender'><code> 82329 * function setup() { 82330 * let myArray = [1, 2, 3, 4, 5]; 82331 * print(myArray); // [1, 2, 3, 4, 5] 82332 * 82333 * let sub1 = subset(myArray, 0, 3); 82334 * let sub2 = subset(myArray, 2, 2); 82335 * print(sub1); // [1,2,3] 82336 * print(sub2); // [3,4] 82337 * } 82338 * </code></div> 82339 */ 82340 _main.default.prototype.subset = function(list, start, count) { 82341 if (typeof count !== 'undefined') { 82342 return list.slice(start, start + count); 82343 } else { 82344 return list.slice(start, list.length); 82345 } 82346 }; 82347 var _default = _main.default; 82348 exports.default = _default; 82349 }, 82350 { '../core/main': 59 } 82351 ], 82352 99: [
82353 function(_dereq_, module, exports) { 82354 'use strict'; 82355 Object.defineProperty(exports, '__esModule', { value: true }); 82356 exports.default = void 0; 82357 82358 var _main = _interopRequireDefault(_dereq_('../core/main')); 82359 function _interopRequireDefault(obj) { 82360 return obj && obj.__esModule ? obj : { default: obj }; 82361 } 82362 /** 82363 * @module Data 82364 * @submodule Conversion 82365 * @for p5 82366 * @requires core 82367 */ /** 82368 * Converts a string to its floating point representation. The contents of a 82369 * string must resemble a number, or NaN (not a number) will be returned. 82370 * For example, float("1234.56") evaluates to 1234.56, but float("giraffe") 82371 * will return NaN. 82372 * 82373 * When an array of values is passed in, then an array of floats of the same 82374 * length is returned. 82375 * 82376 * @method float 82377 * @param {String} str float string to parse 82378 * @return {Number} floating point representation of string 82379 * @example 82380 * <div><code> 82381 * let str = '20'; 82382 * let diameter = float(str); 82383 * ellipse(width / 2, height / 2, diameter, diameter); 82384 * </code></div> 82385 * <div class='norender'><code> 82386 * print(float('10.31')); // 10.31 82387 * print(float('Infinity')); // Infinity 82388 * print(float('-Infinity')); // -Infinity 82389 * </code></div> 82390 * 82391 * @alt 82392 * 20 by 20 white ellipse in the center of the canvas 82393 */ _main.default.prototype.float = function(str) { 82394 if (str instanceof Array) { 82395 return str.map(parseFloat); 82396 } 82397 return parseFloat(str); 82398 }; 82399 82400 /** 82401 * Converts a boolean, string, or float to its integer representation. 82402 * When an array of values is passed in, then an int array of the same length 82403 * is returned. 82404 * 82405 * @method int 82406 * @param {String|Boolean|Number} n value to parse 82407 * @param {Integer} [radix] the radix to convert to (default: 10) 82408 * @return {Number} integer representation of value 82409 * 82410 * @example 82411 * <div class='norender'><code> 82412 * print(int('10')); // 10 82413 * print(int(10.31)); // 10 82414 * print(int(-10)); // -10 82415 * print(int(true)); // 1 82416 * print(int(false)); // 0 82417 * print(int([false, true, '10.3', 9.8])); // [0, 1, 10, 9] 82418 * print(int(Infinity)); // Infinity 82419 * print(int('-Infinity')); // -Infinity 82420 * </code></div> 82421 */ 82422 /** 82423 * @method int 82424 * @param {Array} ns values to parse 82425 * @return {Number[]} integer representation of values 82426 */ 82427 _main.default.prototype.int = function(n) { 82428 var radix = 82429 arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 10; 82430 if (n === Infinity || n === 'Infinity') { 82431 return Infinity; 82432 } else if (n === -Infinity || n === '-Infinity') { 82433 return -Infinity; 82434 } else if (typeof n === 'string') { 82435 return parseInt(n, radix); 82436 } else if (typeof n === 'number') { 82437 return n | 0; 82438 } else if (typeof n === 'boolean') { 82439 return n ? 1 : 0; 82440 } else if (n instanceof Array) { 82441 return n.map(function(n) { 82442 return _main.default.prototype.int(n, radix); 82443 }); 82444 } 82445 }; 82446 82447 /** 82448 * Converts a boolean, string or number to its string representation. 82449 * When an array of values is passed in, then an array of strings of the same 82450 * length is returned. 82451 * 82452 * @method str 82453 * @param {String|Boolean|Number|Array} n value to parse 82454 * @return {String}
82454 string representation of value 82455 * @example 82456 * <div class='norender'><code> 82457 * print(str('10')); // "10" 82458 * print(str(10.31)); // "10.31" 82459 * print(str(-10)); // "-10" 82460 * print(str(true)); // "true" 82461 * print(str(false)); // "false" 82462 * print(str([true, '10.3', 9.8])); // [ "true", "10.3", "9.8" ] 82463 * </code></div> 82464 */ 82465 _main.default.prototype.str = function(n) { 82466 if (n instanceof Array) { 82467 return n.map(_main.default.prototype.str); 82468 } else { 82469 return String(n); 82470 } 82471 }; 82472 82473 /** 82474 * Converts a number or string to its boolean representation. 82475 * For a number, any non-zero value (positive or negative) evaluates to true, 82476 * while zero evaluates to false. For a string, the value "true" evaluates to 82477 * true, while any other value evaluates to false. When an array of number or 82478 * string values is passed in, then a array of booleans of the same length is 82479 * returned. 82480 * 82481 * @method boolean 82482 * @param {String|Boolean|Number|Array} n value to parse 82483 * @return {Boolean} boolean representation of value 82484 * @example 82485 * <div class='norender'><code> 82486 * print(boolean(0)); // false 82487 * print(boolean(1)); // true 82488 * print(boolean('true')); // true 82489 * print(boolean('abcd')); // false 82490 * print(boolean([0, 12, 'true'])); // [false, true, true] 82491 * </code></div> 82492 */ 82493 _main.default.prototype.boolean = function(n) { 82494 if (typeof n === 'number') { 82495 return n !== 0; 82496 } else if (typeof n === 'string') { 82497 return n.toLowerCase() === 'true'; 82498 } else if (typeof n === 'boolean') { 82499 return n; 82500 } else if (n instanceof Array) { 82501 return n.map(_main.default.prototype.boolean); 82502 } 82503 }; 82504 82505 /** 82506 * Converts a number, string representation of a number, or boolean to its byte 82507 * representation. A byte can be only a whole number between -128 and 127, so 82508 * when a value outside of this range is converted, it wraps around to the 82509 * corresponding byte representation. When an array of number, string or boolean 82510 * values is passed in, then an array of bytes the same length is returned. 82511 * 82512 * @method byte 82513 * @param {String|Boolean|Number} n value to parse 82514 * @return {Number} byte representation of value 82515 * 82516 * @example 82517 * <div class='norender'><code> 82518 * print(byte(127)); // 127 82519 * print(byte(128)); // -128 82520 * print(byte(23.4)); // 23 82521 * print(byte('23.4')); // 23 82522 * print(byte('hello')); // NaN 82523 * print(byte(true)); // 1 82524 * print(byte([0, 255, '100'])); // [0, -1, 100] 82525 * </code></div> 82526 */ 82527 /** 82528 * @method byte 82529 * @param {Array} ns values to parse 82530 * @return {Number[]} array of byte representation of values 82531 */ 82532 _main.default.prototype.byte = function(n) { 82533 var nn = _main.default.prototype.int(n, 10); 82534 if (typeof nn === 'number') { 82535 return (nn + 128) % 256 - 128; 82536 } else if (nn instanceof Array) { 82537 return nn.map(_main.default.prototype.byte); 82538 } 82539 }; 82540 82541 /** 82542 * Converts a number or string to its corresponding single-character 82543 * string representation. If a string parameter is provided, it is first 82544 * parsed as an integer and then translated into a single-character string. 82545 * When an array of number or string values is passed in, then an array of 82546 * single-character strings of the same length is returned. 82547 * 82548 * @method char 82549 * @param {String|Number} n value to parse 82550 * @return {String}
82550 string representation of value 82551 * 82552 * @example 82553 * <div class='norender'><code> 82554 * print(char(65)); // "A" 82555 * print(char('65')); // "A" 82556 * print(char([65, 66, 67])); // [ "A", "B", "C" ] 82557 * print(join(char([65, 66, 67]), '')); // "ABC" 82558 * </code></div> 82559 */ 82560 /** 82561 * @method char 82562 * @param {Array} ns values to parse 82563 * @return {String[]} array of string representation of values 82564 */ 82565 _main.default.prototype.char = function(n) { 82566 if (typeof n === 'number' && !isNaN(n)) { 82567 return String.fromCharCode(n); 82568 } else if (n instanceof Array) { 82569 return n.map(_main.default.prototype.char); 82570 } else if (typeof n === 'string') { 82571 return _main.default.prototype.char(parseInt(n, 10)); 82572 } 82573 }; 82574 82575 /** 82576 * Converts a single-character string to its corresponding integer 82577 * representation. When an array of single-character string values is passed 82578 * in, then an array of integers of the same length is returned. 82579 * 82580 * @method unchar 82581 * @param {String} n value to parse 82582 * @return {Number} integer representation of value 82583 * 82584 * @example 82585 * <div class='norender'><code> 82586 * print(unchar('A')); // 65 82587 * print(unchar(['A', 'B', 'C'])); // [ 65, 66, 67 ] 82588 * print(unchar(split('ABC', ''))); // [ 65, 66, 67 ] 82589 * </code></div> 82590 */ 82591 /** 82592 * @method unchar 82593 * @param {Array} ns values to parse 82594 * @return {Number[]} integer representation of values 82595 */ 82596 _main.default.prototype.unchar = function(n) { 82597 if (typeof n === 'string' && n.length === 1) { 82598 return n.charCodeAt(0); 82599 } else if (n instanceof Array) { 82600 return n.map(_main.default.prototype.unchar); 82601 } 82602 }; 82603 82604 /** 82605 * Converts a number to a string in its equivalent hexadecimal notation. If a 82606 * second parameter is passed, it is used to set the number of characters to 82607 * generate in the hexadecimal notation. When an array is passed in, an 82608 * array of strings in hexadecimal notation of the same length is returned. 82609 * 82610 * @method hex 82611 * @param {Number} n value to parse 82612 * @param {Number} [digits] 82613 * @return {String} hexadecimal string representation of value 82614 * 82615 * @example 82616 * <div class='norender'><code> 82617 * print(hex(255)); // "000000FF" 82618 * print(hex(255, 6)); // "0000FF" 82619 * print(hex([0, 127, 255], 6)); // [ "000000", "00007F", "0000FF" ] 82620 * print(Infinity); // "FFFFFFFF" 82621 * print(-Infinity); // "00000000" 82622 * </code></div> 82623 */ 82624 /** 82625 * @method hex 82626 * @param {Number[]} ns array of values to parse 82627 * @param {Number} [digits] 82628 * @return {String[]} hexadecimal string representation of values 82629 */ 82630 _main.default.prototype.hex = function(n, digits) { 82631 digits = digits === undefined || digits === null ? (digits = 8) : digits; 82632 if (n instanceof Array) { 82633 return n.map(function(n) { 82634 return _main.default.prototype.hex(n, digits); 82635 }); 82636 } else if (n === Infinity || n === -Infinity) { 82637 var c = n === Infinity ? 'F' : '0'; 82638 return c.repeat(digits); 82639 } else if (typeof n === 'number') { 82640 if (n < 0) { 82641 n = 0xffffffff + n + 1; 82642 } 82643 var hex = Number(n) 82644 .toString(16) 82645 .toUpperCase(); 82646 while (hex.length < digits) { 82647 hex = '0'.concat(hex); 82648 } 82649 if (hex.length >= digits) { 82650 hex = hex.substring(hex.length - digits, hex.length); 82651 } 82652 return hex; 82653 } 82654 }; 82655 82656 /** 82657 * Converts a string representation of a hexadecimal number to its equivalent
82658 * integer value. When an array of strings in hexadecimal notation is passed 82659 * in, an array of integers of the same length is returned. 82660 * 82661 * @method unhex 82662 * @param {String} n value to parse 82663 * @return {Number} integer representation of hexadecimal value 82664 * 82665 * @example 82666 * <div class='norender'><code> 82667 * print(unhex('A')); // 10 82668 * print(unhex('FF')); // 255 82669 * print(unhex(['FF', 'AA', '00'])); // [ 255, 170, 0 ] 82670 * </code></div> 82671 */ 82672 /** 82673 * @method unhex 82674 * @param {Array} ns values to parse 82675 * @return {Number[]} integer representations of hexadecimal value 82676 */ 82677 _main.default.prototype.unhex = function(n) { 82678 if (n instanceof Array) { 82679 return n.map(_main.default.prototype.unhex); 82680 } else { 82681 return parseInt('0x'.concat(n), 16); 82682 } 82683 }; 82684 var _default = _main.default; 82685 exports.default = _default; 82686 }, 82687 { '../core/main': 59 } 82688 ], 82689 100: [ 82690 function(_dereq_, module, exports) { 82691 'use strict'; 82692 Object.defineProperty(exports, '__esModule', { value: true }); 82693 exports.default = void 0; 82694 82695 var _main = _interopRequireDefault(_dereq_('../core/main')); 82696 _dereq_('../core/friendly_errors/validate_params'); 82697 _dereq_('../core/friendly_errors/file_errors'); 82698 _dereq_('../core/friendly_errors/fes_core'); 82699 function _interopRequireDefault(obj) { 82700 return obj && obj.__esModule ? obj : { default: obj }; 82701 } /** //return p5; //LM is this a mistake? 82702 * @module Data 82703 * @submodule String Functions 82704 * @for p5 82705 * @requires core 82706 */ 82707 /** 82708 * Combines an array of Strings into one String, each separated by the 82709 * character(s) used for the separator parameter. To join arrays of ints or 82710 * floats, it's necessary to first convert them to Strings using <a href="#/p5/nf">nf()</a> or 82711 * nfs(). 82712 * 82713 * @method join 82714 * @param {Array} list array of Strings to be joined 82715 * @param {String} separator String to be placed between each item 82716 * @return {String} joined String 82717 * @example 82718 * <div> 82719 * <code> 82720 * let array = ['Hello', 'world!']; 82721 * let separator = ' '; 82722 * let message = join(array, separator); 82723 * text(message, 5, 50); 82724 * </code> 82725 * </div> 82726 * 82727 * @alt 82728 * "hello world!" displayed middle left of canvas. 82729 */ _main.default.prototype.join = function(list, separator) { 82730 _main.default._validateParameters('join', arguments); 82731 return list.join(separator); 82732 }; 82733 82734 /** 82735 * This function is used to apply a regular expression to a piece of text, 82736 * and return matching groups (elements found inside parentheses) as a 82737 * String array. If there are no matches, a null value will be returned. 82738 * If no groups are specified in the regular expression, but the sequence 82739 * matches, an array of length 1 (with the matched text as the first element 82740 * of the array) will be returned. 82741 * 82742 * To use the function, first check to see if the result is null. If the 82743 * result is null, then the sequence did not match at all. If the sequence 82744 * did match, an array is returned. 82745 * 82746 * If there are groups (specified by sets of parentheses) in the regular 82747 * expression, then the contents of each will be returned in the array. 82748 * Element [0] of a regular expression match returns the entire matching 82749 * string, and the match groups start at element [1] (the first group is [1], 82750 * the second [2], and so on). 82751 * 82752 * @method match 82753 * @param {String} str the String to be searched 82754 * @param {String} regexp the regexp to be used for matching 82755 * @return {String[]} Array of Strings found 82756 * @example 82757 * <div> 82758 * <code> 82759 * let string = 'Hello p5js*!'; 82760 * let regexp = 'p5js\\*'; 82761 * let m = match(string, regexp); 82762 * text(m, 5, 50); 82763 * </code> 82764 * </div> 82765 * 82766 * @alt 82767 * "p5js*" displayed middle left of canvas. 82768 */ 82769 _main.default.prototype.match = function(str, reg) { 82770 _main.default._validateParameters('match', arguments); 82771 return str.match(reg); 82772 }; 82773 82774 /** 82775 * This function is used to apply a regular expression to a piece of text, 82776 * and return a list of matching groups (elements found inside parentheses)
82777 * as a two-dimensional String array. If there are no matches, a null value 82778 * will be returned. If no groups are specified in the regular expression, 82779 * but the sequence matches, a two dimensional array is still returned, but 82780 * the second dimension is only of length one. 82781 * 82782 * To use the function, first check to see if the result is null. If the 82783 * result is null, then the sequence did not match at all. If the sequence 82784 * did match, a 2D array is returned. 82785 * 82786 * If there are groups (specified by sets of parentheses) in the regular 82787 * expression, then the contents of each will be returned in the array. 82788 * Assuming a loop with counter variable i, element [i][0] of a regular 82789 * expression match returns the entire matching string, and the match groups 82790 * start at element [i][1] (the first group is [i][1], the second [i][2], 82791 * and so on). 82792 * 82793 * @method matchAll 82794 * @param {String} str the String to be searched 82795 * @param {String} regexp the regexp to be used for matching 82796 * @return {String[]} 2d Array of Strings found 82797 * @example 82798 * <div class="norender"> 82799 * <code> 82800 * let string = 'Hello p5js*! Hello world!'; 82801 * let regexp = 'Hello'; 82802 * matchAll(string, regexp); 82803 * </code> 82804 * </div> 82805 */ 82806 _main.default.prototype.matchAll = function(str, reg) { 82807 _main.default._validateParameters('matchAll', arguments); 82808 var re = new RegExp(reg, 'g'); 82809 var match = re.exec(str); 82810 var matches = []; 82811 while (match !== null) { 82812 matches.push(match); 82813 // matched text: match[0] 82814 // match start: match.index 82815 // capturing group n: match[n] 82816 match = re.exec(str); 82817 } 82818 return matches; 82819 }; 82820 82821 /** 82822 * Utility function for formatting numbers into strings. There are two 82823 * versions: one for formatting floats, and one for formatting ints. 82824 * The values for the digits, left, and right parameters should always 82825 * be positive integers. 82826 * (NOTE): Be cautious when using left and right parameters as it prepends numbers of 0's if the parameter 82827 * if greater than the current length of the number. 82828 * For example if number is 123.2 and left parameter passed is 4 which is greater than length of 123 82829 * (integer part) i.e 3 than result will be 0123.2. Same case for right parameter i.e. if right is 3 than 82830 * the result will be 123.200. 82831 * 82832 * @method nf 82833 * @param {Number|String} num the Number to format 82834 * @param {Integer|String} [left] number of digits to the left of the 82835 * decimal point 82836 * @param {Integer|String} [right] number of digits to the right of the 82837 * decimal point 82838 * @return {String} formatted String 82839 * 82840 * @example 82841 * <div> 82842 * <code> 82843 * let myFont; 82844 * function preload() { 82845 * myFont = loadFont('assets/fonts/inconsolata.ttf'); 82846 * } 82847 * function setup() { 82848 * background(200); 82849 * let num1 = 321; 82850 * let num2 = -1321; 82851 * 82852 * noStroke(); 82853 * fill(0); 82854 * textFont(myFont); 82855 * textSize(22); 82856 * 82857 * text(nf(num1, 4, 2), 10, 30); 82858 * text(nf(num2, 4, 2), 10, 80); 82859 * // Draw dividing line 82860 * stroke(120); 82861 * line(0, 50, width, 50); 82862 * } 82863 * </code> 82864 * </div> 82865 * 82866 * @alt 82867 * "0321.00" middle top, -1321.00" middle bottom canvas 82868 */ 82869 /** 82870 * @method nf 82871 * @param {Array} nums the Numbers to format 82872 * @param {Integer|String} [left] 82873 * @param {Integer|String} [right] 82874 * @return {String[]} formatted Strings 82875 */ 82876 _main.default.prototype.nf = function(nums, left, right) { 82877 _main.default._validateParameters('nf', arguments); 82878 if (nums instanceof Array) { 82879 return nums.map(function(x) { 82880 return doNf(x, left, right); 82881 }); 82882 } else { 82883 var typeOfFirst = Object.prototype.toString.call(nums); 82884 if (typeOfFirst === '[object Arguments]') { 82885 if (nums.length === 3) { 82886 return this.nf(nums[0], nums[1], nums[2]); 82887 } else if (nums.length === 2) { 82888 return this.nf(nums[0], nums[1]); 82889 } else { 82890 return this.nf(nums[0]); 82891 } 82892 } else { 82893 return doNf(nums, left, right); 82894 } 82895 } 82896 }; 82897 82898 function doNf(num, left, right) { 82899 var neg = num < 0; 82900 var n = neg ? num.toString().substring(1) : num.toString(); 82901 var decimalInd = n.indexOf('.'); 82902 var intPart = decimalInd !== -1 ? n.substring(0, decimalInd) : n; 82903 var decPart = decimalInd !== -1 ? n.substring(decimalInd + 1) : ''; 82904 var str = neg ? '-' : ''; 82905 if (typeof right !== 'undefined') { 82906 var decimal = ''; 82907 if (decimalInd !== -1 || right - decPart.length > 0) { 82908 decimal = '.'; 82909 } 82910 if (decPart.length > right) { 82911 decPart = decPart.substring(0, right); 82912 } 82913 for (var i = 0; i < left - intPart.length; i++) { 82914 str += '0'; 82915 } 82916 str += intPart; 82917 str += decimal; 82918 str += decPart; 82919 for (var j = 0; j < right - decPart.length; j++) { 82920 str += '0'; 82921 } 82922 return str; 82923 } else { 82924 for (var k = 0; k < Math.max(left - intPart.length, 0); k++) { 82925 str += '0'; 82926 } 82927 str += n; 82928 return str; 82929 } 82930 } 82931 82932 /** 82933 * Utility function for formatting numbers into strings and placing 82934 * appropriate commas to mark units of 1000. There are two versions: one 82935 * for formatting ints, and one for formatting an array of ints. The value 82936 * for the right parameter should always be a positive integer. 82937 * 82938 * @method nfc 82939 * @param {Number|String} num the Number to format 82940 * @param {Integer|String} [right] number of digits to the right of the 82941 * decimal point 82942 * @return {String} formatted String 82943 * 82944 * @example 82945 * <div> 82946 * <code> 82947 * function setup() { 82948 * background(200); 82949 * let num = 11253106.115; 82950 * let numArr = [1, 1, 2]; 82951 * 82952 * noStroke(); 82953 * fill(0); 82954 * textSize(12); 82955 * 82956 * // Draw formatted numbers 82957 * text(nfc(num, 4), 10, 30); 82958 * text(nfc(numArr, 2), 10, 80); 82959 * 82960 * // Draw dividing line 82961 * stroke(120); 82962 * line(0, 50, width, 50); 82963 * } 82964 * </code> 82965 * </div> 82966 * 82967 * @alt 82968 * "11,253,106.115" top middle and "1.00,1.00,2.00" displayed bottom mid 82969 */ 82970 /** 82971 * @method nfc 82972 * @param {Array} nums the Numbers to format 82973 * @param {Integer|String} [right] 82974 * @return {String[]} formatted Strings 82975 */ 82976 _main.default.prototype.nfc = function(num, right) { 82977 _main.default._validateParameters('nfc', arguments); 82978 if (num instanceof Array) { 82979 return num.map(function(x) { 82980 return doNfc(x, right); 82981 }); 82982 } else { 82983 return doNfc(num, right); 82984 } 82985 }; 82986 function doNfc(num, right) { 82987 num = num.toString(); 82988 var dec = num.indexOf('.'); 82989 var rem = dec !== -1 ? num.substring(dec) : ''; 82990 var n = dec !== -1 ? num.substring(0, dec) : num; 82991 n = n.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ','); 82992 if (right === 0) { 82993 rem = ''; 82994 } else if (typeof right !== 'undefined') { 82995 if (right > rem.length) { 82996 rem += dec === -1 ? '.' : ''; 82997 var len = right - rem.length + 1; 82998 for (var i = 0; i < len; i++) { 82999 rem += '0'; 83000 } 83001 } else { 83002 rem = rem.substring(0, right + 1); 83003 } 83004 } 83005 return n + rem; 83006 } 83007 83008 /** 83009 * Utility function for formatting numbers into strings. Similar to <a href="#/p5/nf">nf()</a> but 83010 * puts a "+" in front of positive numbers and a "-" in front of negative 83011 * numbers. There are two versions: one for formatting floats, and one for 83012 * formatting ints. The values for left, and right parameters 83013 * should always be positive integers. 83014 * 83015 * @method nfp 83016 * @param {Number} num the Number to format 83017 * @param {Integer} [left] number of digits to the left of the decimal 83018 * point 83019 * @param {Integer} [right] number of digits to the right of the 83020 * decimal point 83021 * @return {String} formatted String 83022 * 83023 * @example 83024 * <div> 83025 * <code> 83026 * function setup() { 83027 * background(200); 83028 * let num1 = 11253106.115; 83029 * let num2 = -11253106.115; 83030 * 83031 * noStroke(); 83032 * fill(0); 83033 * textSize(12); 83034 * 83035 * // Draw formatted numbers 83036 * text(nfp(num1, 4, 2), 10, 30); 83037 * text(nfp(num2, 4, 2), 10, 80); 83038 * 83039 * // Draw dividing line 83040 * stroke(120); 83041 * line(0, 50, width, 50); 83042 * } 83043 * </code> 83044 * </div> 83045 * 83046 * @alt 83047 * "+11253106.11" top middle and "-11253106.11" displayed bottom middle 83048 */ 83049 /** 83050 * @method nfp 83051 * @param {Number[]} nums the Numbers to format 83052 * @param {Integer} [left] 83053 * @param {Integer} [right] 83054 * @return {String[]} formatted Strings 83055 */ 83056 _main.default.prototype.nfp = function() { 83057 for ( 83058 var _len = arguments.length, args = new Array(_len), _key = 0; 83059 _key < _len; 83060 _key++ 83061 ) { 83062 args[_key] = arguments[_key]; 83063 }
83064 _main.default._validateParameters('nfp', args); 83065 var nfRes = _main.default.prototype.nf.apply(this, args); 83066 if (nfRes instanceof Array) { 83067 return nfRes.map(addNfp); 83068 } else { 83069 return addNfp(nfRes); 83070 } 83071 }; 83072 83073 function addNfp(num) { 83074 return parseFloat(num) > 0 ? '+'.concat(num.toString()) : num.toString(); 83075 } 83076 83077 /** 83078 * Utility function for formatting numbers into strings. Similar to <a href="#/p5/nf">nf()</a> but 83079 * puts an additional "_" (space) in front of positive numbers just in case to align it with negative 83080 * numbers which includes "-" (minus) sign. 83081 * The main usecase of nfs() can be seen when one wants to align the digits (place values) of a non-negative 83082 * number with some negative number (See the example to get a clear picture). 83083 * There are two versions: one for formatting float, and one for formatting int. 83084 * The values for the digits, left, and right parameters should always be positive integers. 83085 * (IMP): The result on the canvas basically the expected alignment can vary based on the typeface you are using. 83086 * (NOTE): Be cautious when using left and right parameters as it prepends numbers of 0's if the parameter 83087 * if greater than the current length of the number. 83088 * For example if number is 123.2 and left parameter passed is 4 which is greater than length of 123 83089 * (integer part) i.e 3 than result will be 0123.2. Same case for right parameter i.e. if right is 3 than 83090 * the result will be 123.200. 83091 * 83092 * @method nfs 83093 * @param {Number} num the Number to format 83094 * @param {Integer} [left] number of digits to the left of the decimal 83095 * point 83096 * @param {Integer} [right] number of digits to the right of the 83097 * decimal point 83098 * @return {String} formatted String 83099 * 83100 * @example 83101 * <div> 83102 * <code> 83103 * let myFont; 83104 * function preload() { 83105 * myFont = loadFont('assets/fonts/inconsolata.ttf'); 83106 * } 83107 * function setup() { 83108 * background(200); 83109 * let num1 = 321; 83110 * let num2 = -1321; 83111 * 83112 * noStroke(); 83113 * fill(0); 83114 * textFont(myFont); 83115 * textSize(22); 83116 * 83117 * // nfs() aligns num1 (positive number) with num2 (negative number) by 83118 * // adding a blank space in front of the num1 (positive number) 83119 * // [left = 4] in num1 add one 0 in front, to align the digits with num2 83120 * // [right = 2] in num1 and num2 adds two 0's after both numbers 83121 * // To see the differences check the example of nf() too. 83122 * text(nfs(num1, 4, 2), 10, 30); 83123 * text(nfs(num2, 4, 2), 10, 80); 83124 * // Draw dividing line 83125 * stroke(120); 83126 * line(0, 50, width, 50); 83127 * } 83128 * </code> 83129 * </div> 83130 * 83131 * @alt 83132 * "0321.00" top middle and "-1321.00" displayed bottom middle 83133 */ 83134 /** 83135 * @method nfs 83136 * @param {Array} nums the Numbers to format 83137 * @param {Integer} [left] 83138 * @param {Integer} [right] 83139 * @return {String[]} formatted Strings 83140 */ 83141 _main.default.prototype.nfs = function() { 83142 for ( 83143 var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; 83144 _key2 < _len2; 83145 _key2++ 83146 ) { 83147 args[_key2] = arguments[_key2]; 83148 } 83149 _main.default._validateParameters('nfs', args); 83150 var nfRes = _main.default.prototype.nf.apply(this, args); 83151 if (nfRes instanceof Array) { 83152 return nfRes.map(addNfs); 83153 } else { 83154 return addNfs(nfRes); 83155 } 83156 }; 83157 83158 function addNfs(num) { 83159 return parseFloat(num) >= 0 ? ' '.concat(num.toString()) : num.toString(); 83160 } 83161 83162 /** 83163 * The <a href="#/p5/split">split()</a> function maps to String.split(), it breaks a String into 83164 * pieces using a character or string as the delimiter. The delim parameter 83165 * specifies the character or characters that mark the boundaries between 83166 * each piece. A String[] array is returned that contains each of the pieces. 83167 * 83168 * The <a href="#/p5/splitTokens">splitTokens()</a> function works in a similar fashion, except that it 83169 * splits using a range of characters instead of a specific character or 83170 * sequence. 83171 * 83172 * @method split 83173 * @param {String} value the String to be split 83174 * @param {String} delim the String used to separate the data 83175 * @return {String[]} Array of Strings 83176 * @example 83177 * <div> 83178 * <code> 83179 * let names = 'Pat,Xio,Alex'; 83180 * let splitString = split(names, ',');
83181 * text(splitString[0], 5, 30); 83182 * text(splitString[1], 5, 50); 83183 * text(splitString[2], 5, 70); 83184 * </code> 83185 * </div> 83186 * 83187 * @alt 83188 * "pat" top left, "Xio" mid left and "Alex" displayed bottom left 83189 */ 83190 _main.default.prototype.split = function(str, delim) { 83191 _main.default._validateParameters('split', arguments); 83192 return str.split(delim); 83193 }; 83194 83195 /** 83196 * The <a href="#/p5/splitTokens">splitTokens()</a> function splits a String at one or many character 83197 * delimiters or "tokens." The delim parameter specifies the character or 83198 * characters to be used as a boundary. 83199 * 83200 * If no delim characters are specified, any whitespace character is used to 83201 * split. Whitespace characters include tab (\t), line feed (\n), carriage 83202 * return (\r), form feed (\f), and space. 83203 * 83204 * @method splitTokens 83205 * @param {String} value the String to be split 83206 * @param {String} [delim] list of individual Strings that will be used as 83207 * separators 83208 * @return {String[]} Array of Strings 83209 * @example 83210 * <div class = "norender"> 83211 * <code> 83212 * function setup() { 83213 * let myStr = 'Mango, Banana, Lime'; 83214 * let myStrArr = splitTokens(myStr, ','); 83215 * 83216 * print(myStrArr); // prints : ["Mango"," Banana"," Lime"] 83217 * } 83218 * </code> 83219 * </div> 83220 */ 83221 _main.default.prototype.splitTokens = function(value, delims) { 83222 _main.default._validateParameters('splitTokens', arguments); 83223 var d; 83224 if (typeof delims !== 'undefined') { 83225 var str = delims; 83226 var sqc = /\]/g.exec(str); 83227 var sqo = /\[/g.exec(str); 83228 if (sqo && sqc) { 83229 str = str.slice(0, sqc.index) + str.slice(sqc.index + 1); 83230 sqo = /\[/g.exec(str); 83231 str = str.slice(0, sqo.index) + str.slice(sqo.index + 1); 83232 d = new RegExp('[\\['.concat(str, '\\]]'), 'g'); 83233 } else if (sqc) { 83234 str = str.slice(0, sqc.index) + str.slice(sqc.index + 1); 83235 d = new RegExp('['.concat(str, '\\]]'), 'g'); 83236 } else if (sqo) { 83237 str = str.slice(0, sqo.index) + str.slice(sqo.index + 1); 83238 d = new RegExp('['.concat(str, '\\[]'), 'g'); 83239 } else { 83240 d = new RegExp('['.concat(str, ']'), 'g'); 83241 } 83242 } else { 83243 d = /\s/g; 83244 } 83245 return value.split(d).filter(function(n) { 83246 return n; 83247 }); 83248 }; 83249 83250 /** 83251 * Removes whitespace characters from the beginning and end of a String. In 83252 * addition to standard whitespace characters such as space, carriage return, 83253 * and tab, this function also removes the Unicode "nbsp" character. 83254 * 83255 * @method trim 83256 * @param {String} str a String to be trimmed 83257 * @return {String} a trimmed String 83258 * 83259 * @example 83260 * <div> 83261 * <code> 83262 * let string = trim(' No new lines\n '); 83263 * text(string + ' here', 2, 50); 83264 * </code> 83265 * </div> 83266 * 83267 * @alt 83268 * "No new lines here" displayed center canvas 83269 */ 83270 /** 83271 * @method trim 83272 * @param {Array} strs an Array of Strings to be trimmed 83273 * @return {String[]} an Array of trimmed Strings 83274 */ 83275 _main.default.prototype.trim = function(str) { 83276 _main.default._validateParameters('trim', arguments); 83277 if (str instanceof Array) { 83278 return str.map(this.trim); 83279 } else { 83280 return str.trim(); 83281 } 83282 }; 83283 var _default = _main.default; 83284 exports.default = _default; 83285 }, 83286 { 83287 '../core/friendly_errors/fes_core': 51, 83288 '../core/friendly_errors/file_errors': 52, 83289 '../core/friendly_errors/validate_params': 54, 83290 '../core/main': 59 83291 } 83292 ], 83293 101: [
83294 function(_dereq_, module, exports) { 83295 'use strict'; 83296 Object.defineProperty(exports, '__esModule', { value: true }); 83297 exports.default = void 0; 83298 83299 var _main = _interopRequireDefault(_dereq_('../core/main')); 83300 function _interopRequireDefault(obj) { 83301 return obj && obj.__esModule ? obj : { default: obj }; 83302 } 83303 /** 83304 * @module IO 83305 * @submodule Time & Date 83306 * @for p5 83307 * @requires core 83308 */ /** 83309 * p5.js communicates with the clock on your computer. The <a href="#/p5/day">day()</a> function 83310 * returns the current day as a value from 1 - 31. 83311 * 83312 * @method day 83313 * @return {Integer} the current day 83314 * @example 83315 * <div> 83316 * <code> 83317 * let d = day(); 83318 * text('Current day: \n' + d, 5, 50); 83319 * </code> 83320 * </div> 83321 * 83322 * @alt 83323 * Current day is displayed 83324 */ _main.default.prototype.day = function() { 83325 return new Date().getDate(); 83326 }; 83327 83328 /** 83329 * p5.js communicates with the clock on your computer. The <a href="#/p5/hour">hour()</a> function 83330 * returns the current hour as a value from 0 - 23. 83331 * 83332 * @method hour 83333 * @return {Integer} the current hour 83334 * @example 83335 * <div> 83336 * <code> 83337 * let h = hour(); 83338 * text('Current hour:\n' + h, 5, 50); 83339 * </code> 83340 * </div> 83341 * 83342 * @alt 83343 * Current hour is displayed 83344 */ 83345 _main.default.prototype.hour = function() { 83346 return new Date().getHours(); 83347 }; 83348 83349 /** 83350 * p5.js communicates with the clock on your computer. The <a href="#/p5/minute">minute()</a> function 83351 * returns the current minute as a value from 0 - 59. 83352 * 83353 * @method minute 83354 * @return {Integer} the current minute 83355 * @example 83356 * <div> 83357 * <code> 83358 * let m = minute(); 83359 * text('Current minute: \n' + m, 5, 50); 83360 * </code> 83361 * </div> 83362 * 83363 * @alt 83364 * Current minute is displayed 83365 */ 83366 _main.default.prototype.minute = function() { 83367 return new Date().getMinutes(); 83368 }; 83369 83370 /** 83371 * Returns the number of milliseconds (thousandths of a second) since 83372 * starting the sketch (when `setup()` is called). This information is often 83373 * used for timing events and animation sequences. 83374 * 83375 * @method millis 83376 * @return {Number} the number of milliseconds since starting the sketch 83377 * @example 83378 * <div> 83379 * <code> 83380 * let millisecond = millis(); 83381 * text('Milliseconds \nrunning: \n' + millisecond, 5, 40); 83382 * </code> 83383 * </div> 83384 * 83385 * @alt 83386 * number of milliseconds since sketch has started displayed 83387 */ 83388 _main.default.prototype.millis = function() { 83389 if (this._millisStart === -1) { 83390 // Sketch has not started 83391 return 0; 83392 } else { 83393 return window.performance.now() - this._millisStart; 83394 } 83395 }; 83396 83397 /** 83398 * p5.js communicates with the clock on your computer. The <a href="#/p5/month">month()</a> function 83399 * returns the current month as a value from 1 - 12. 83400 * 83401 * @method month 83402 * @return {Integer} the current month 83403 * @example 83404 * <div> 83405 * <code> 83406 * let m = month(); 83407 * text('Current month: \n' + m, 5, 50); 83408 * </code> 83409 * </div> 83410 * 83411 * @alt 83412 * Current month is displayed 83413 */ 83414 _main.default.prototype.month = function() { 83415 //January is 0! 83416 return new Date().getMonth() + 1; 83417 }; 83418 83419 /** 83420 * p5.js communicates with the clock on your computer. The <a href="#/p5/second">second()</a> function 83421 * returns the current second as a value from 0 - 59. 83422 * 83423 * @method second 83424 * @return {Integer} the current second 83425 * @example 83426 * <div> 83427 * <code> 83428 * let s = second(); 83429 * text('Current second: \n' + s, 5, 50); 83430 * </code> 83431 * </div> 83432 * 83433 * @alt 83434 * Current second is displayed 83435 */ 83436 _main.default.prototype.second = function() { 83437 return new Date().getSeconds(); 83438 }; 83439 83440 /** 83441 * p5.js communicates with the clock on your computer. The <a href="#/p5/year">year()</a> function 83442 * returns the current year as an integer (2014, 2015, 2016, etc). 83443 * 83444 * @method year 83445 * @return {Integer} the current year 83446 * @example 83447 * <div> 83448 * <code> 83449 * let y = year(); 83450 * text('Current year: \n' + y, 5, 50); 83451 * </code> 83452 * </div> 83453 * 83454 * @alt 83455 * Current year is displayed 83456 */ 83457 _main.default.prototype.year = function() { 83458 return new Date().getFullYear(); 83459 }; 83460 var _default = _main.default; 83461 exports.default = _default; 83462 }, 83463 { '../core/main': 59 } 83464 ], 83465 102: [
83466 function(_dereq_, module, exports) { 83467 'use strict'; 83468 function _typeof(obj) { 83469 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') { 83470 _typeof = function _typeof(obj) { 83471 return typeof obj; 83472 }; 83473 } else { 83474 _typeof = function _typeof(obj) { 83475 return obj && 83476 typeof Symbol === 'function' && 83477 obj.constructor === Symbol && 83478 obj !== Symbol.prototype 83479 ? 'symbol' 83480 : typeof obj; 83481 }; 83482 } 83483 return _typeof(obj); 83484 } 83485 Object.defineProperty(exports, '__esModule', { value: true }); 83486 exports.default = void 0; 83487 83488 var _main = _interopRequireDefault(_dereq_('../core/main')); 83489 _dereq_('./p5.Geometry'); 83490 var constants = _interopRequireWildcard(_dereq_('../core/constants')); 83491 function _getRequireWildcardCache() { 83492 if (typeof WeakMap !== 'function') return null; 83493 var cache = new WeakMap(); 83494 _getRequireWildcardCache = function _getRequireWildcardCache() { 83495 return cache; 83496 }; 83497 return cache; 83498 } 83499 function _interopRequireWildcard(obj) { 83500 if (obj && obj.__esModule) { 83501 return obj; 83502 } 83503 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) { 83504 return { default: obj }; 83505 } 83506 var cache = _getRequireWildcardCache(); 83507 if (cache && cache.has(obj)) { 83508 return cache.get(obj); 83509 } 83510 var newObj = {}; 83511 var hasPropertyDescriptor = 83512 Object.defineProperty && Object.getOwnPropertyDescriptor; 83513 for (var key in obj) { 83514 if (Object.prototype.hasOwnProperty.call(obj, key)) { 83515 var desc = hasPropertyDescriptor 83516 ? Object.getOwnPropertyDescriptor(obj, key) 83517 : null; 83518 if (desc && (desc.get || desc.set)) { 83519 Object.defineProperty(newObj, key, desc); 83520 } else { 83521 newObj[key] = obj[key]; 83522 } 83523 } 83524 } 83525 newObj.default = obj; 83526 if (cache) { 83527 cache.set(obj, newObj); 83528 } 83529 return newObj; 83530 } 83531 function _interopRequireDefault(obj) { 83532 return obj && obj.__esModule ? obj : { default: obj }; 83533 } 83534 /** 83535 * @module Shape 83536 * @submodule 3D Primitives 83537 * @for p5 83538 * @requires core 83539 * @requires p5.Geometry 83540 */ /** 83541 * Draw a plane with given a width and height 83542 * @method plane 83543 * @param {Number} [width] width of the plane 83544 * @param {Number} [height] height of the plane 83545 * @param {Integer} [detailX] Optional number of triangle 83546 * subdivisions in x-dimension 83547 * @param {Integer} [detailY] Optional number of triangle 83548 * subdivisions in y-dimension 83549 * @chainable 83550 * @example 83551 * <div> 83552 * <code> 83553 * // draw a plane 83554 * // with width 50 and height 50 83555 * function setup() { 83556 * createCanvas(100, 100, WEBGL); 83557 * } 83558 * 83559 * function draw() { 83560 * background(200); 83561 * plane(50, 50); 83562 * } 83563 * </code> 83564 * </div> 83565 * 83566 * @alt 83567 * Nothing displayed on canvas 83568 * Rotating interior view of a box with sides that change color. 83569 * 3d red and green gradient. 83570 * Rotating interior view of a cylinder with sides that change color. 83571 * Rotating view of a cylinder with sides that change color. 83572 * 3d red and green gradient. 83573 * rotating view of a multi-colored cylinder with concave sides. 83574 */ _main.default.prototype.plane = function(width, height, detailX, detailY) { 83575 this._assert3d('plane'); 83576 _main.default._validateParameters('plane', arguments); 83577 if (typeof width === 'undefined') { 83578 width = 50; 83579 } 83580 if (typeof height === 'undefined') { 83581 height = width; 83582 } 83583 83584 if (typeof detailX === 'undefined') { 83585 detailX = 1; 83586 } 83587 if (typeof detailY === 'undefined') { 83588 detailY = 1; 83589 } 83590 83591 var gId = 'plane|'.concat(detailX, '|').concat(detailY); 83592 83593 if (!this._renderer.geometryInHash(gId)) { 83594 var _plane = function _plane() { 83595 var u, v, p; 83596 for (var i = 0; i <= this.detailY; i++) { 83597 v = i / this.detailY; 83598 for (var j = 0; j <= this.detailX; j++) { 83599 u = j / this.detailX; 83600 p = new _main.default.Vector(u - 0.5, v - 0.5, 0); 83601 this.vertices.push(p); 83602 this.uvs.push(u, v); 83603 } 83604 } 83605 }; 83606 var planeGeom = new _main.default.Geometry(detailX, detailY, _plane); 83607 planeGeom.computeFaces().computeNormals(); 83608 if (detailX <= 1 && detailY <= 1) { 83609 planeGeom._makeTriangleEdges()._edgesToVertices(); 83610 } else if (this._renderer._doStroke) { 83611 console.log( 83612 'Cannot draw stroke on plane objects with more' + 83613 ' than 1 detailX or 1 detailY' 83614 ); 83615 } 83616 this._renderer.createBuffers(gId, planeGeom); 83617 } 83618 83619 this._renderer.drawBuffersScaled(gId, width, height, 1); 83620 return this; 83621 }; 83622 83623 /** 83624 * Draw a box with given width, height and depth 83625 * @method box 83626 * @param {Number} [width] width of the box 83627 * @param {Number} [Height] height of the box 83628 * @param {Number} [depth] depth of the box 83629 * @param {Integer} [detailX] Optional number of triangle 83630 * subdivisions in x-dimension 83631 * @param {Integer} [detailY] Optional number of triangle 83632 * subdivisions in y-dimension 83633 * @chainable 83634 * @example 83635 * <div> 83636 * <code> 83637 * // draw a spinning box 83638 * // with width, height and depth of 50 83639 * function setup() { 83640 * createCanvas(100, 100, WEBGL); 83641 * } 83642 * 83643 * function draw() { 83644 * background(200); 83645 * rotateX(frameCount * 0.01); 83646 * rotateY(frameCount * 0.01); 83647 * box(50); 83648 * } 83649 * </code> 83650 * </div> 83651 */ 83652 _main.default.prototype.box = function(width, height, depth, detailX, detailY) { 83653 this._assert3d('box'); 83654 _main.default._validateParameters('box', arguments); 83655 if (typeof width === 'undefined') { 83656 width = 50; 83657 } 83658 if (typeof height === 'undefined') { 83659 height = width; 83660 } 83661 if (typeof depth === 'undefined') { 83662 depth = height; 83663 } 83664 83665 var perPixelLighting = 83666 this._renderer.attributes && this._renderer.attributes.perPixelLighting; 83667 if (typeof detailX === 'undefined') { 83668 detailX = perPixelLighting ? 1 : 4; 83669 } 83670 if (typeof detailY === 'undefined') { 83671 detailY = perPixelLighting ? 1 : 4; 83672 } 83673 83674 var gId = 'box|'.concat(detailX, '|').concat(detailY); 83675 if (!this._renderer.geometryInHash(gId)) { 83676 var _box = function _box() { 83677 var cubeIndices = [ 83678 [0, 4, 2, 6], // -1, 0, 0],// -x 83679 [1, 3, 5, 7], // +1, 0, 0],// +x 83680 [0, 1, 4, 5], // 0, -1, 0],// -y 83681 [2, 6, 3, 7], // 0, +1, 0],// +y 83682 [0, 2, 1, 3], // 0, 0, -1],// -z 83683 [4, 5, 6, 7] // 0, 0, +1] // +z 83684 ]; 83685 //using strokeIndices instead of faces for strokes 83686 //to avoid diagonal stroke lines across face of box 83687 this.strokeIndices = [ 83688 [0, 1], 83689 [1, 3], 83690 [3, 2], 83691 [6, 7], 83692 [8, 9], 83693 [9, 11], 83694 [14, 15], 83695 [16, 17], 83696 [17, 19], 83697 [18, 19], 83698 [20, 21], 83699 [22, 23] 83700 ]; 83701 83702 for (var i = 0; i < cubeIndices.length; i++) { 83703 var cubeIndex = cubeIndices[i]; 83704 var v = i * 4; 83705 for (var j = 0; j < 4; j++) { 83706 var d = cubeIndex[j]; 83707 //inspired by lightgl: 83708 //https://github.com/evanw/lightgl.js 83709 //octants:https://en.wikipedia.org/wiki/Octant_(solid_geometry) 83710 var octant = new _main.default.Vector( 83711 ((d & 1) * 2 - 1) / 2, 83712 ((d & 2) - 1) / 2, 83713 ((d & 4) / 2 - 1) / 2 83714 ); 83715 83716 this.vertices.push(octant); 83717 this.uvs.push(j & 1, (j & 2) / 2); 83718 } 83719 this.faces.push([v, v + 1, v + 2]); 83720 this.faces.push([v + 2, v + 1, v + 3]); 83721 } 83722 }; 83723 var boxGeom = new _main.default.Geometry(detailX, detailY, _box); 83724 boxGeom.computeNormals(); 83725 if (detailX <= 4 && detailY <= 4) { 83726 boxGeom._makeTriangleEdges()._edgesToVertices(); 83727 } else if (this._renderer._doStroke) { 83728 console.log( 83729 'Cannot draw stroke on box objects with more' + 83730 ' than 4 detailX or 4 detailY' 83731 ); 83732 } 83733 //initialize our geometry buffer with 83734 //the key val pair: 83735 //geometry Id, Geom object 83736 this._renderer.createBuffers(gId, boxGeom); 83737 } 83738 this._renderer.drawBuffersScaled(gId, width, height, depth); 83739 83740 return this; 83741 }; 83742 83743 /** 83744 * Draw a sphere with given radius. 83745 * 83746 * DetailX and detailY determines the number of subdivisions in the x-dimension 83747 * and the y-dimension of a sphere. More subdivisions make the sphere seem 83748 * smoother. The recommended maximum values are both 24. Using a value greater 83749 * than 24 may cause a warning or slow down the browser. 83750 * @method sphere 83751 * @param {Number} [radius] radius of circle 83752 * @param {Integer} [detailX] optional number of subdivisions in x-dimension 83753 * @param {Integer} [detailY] optional number of subdivisions in y-dimension 83754 * 83755 * @chainable 83756 * @example 83757 * <div> 83758 * <code> 83759 * // draw a sphere with radius 40 83760 * function setup() { 83761 * createCanvas(100, 100, WEBGL); 83762 * } 83763 * 83764 * function draw() { 83765 * background(205, 102, 94); 83766 * sphere(40); 83767 * } 83768 * </code> 83769 * </div> 83770 * 83771 * @example 83772 * <div> 83773 * <code> 83774 * let detailX; 83775 * // slide to see how detailX works 83776 * function setup() { 83777 * createCanvas(100, 100, WEBGL); 83778 * detailX = createSlider(3, 24, 3); 83779 * detailX.position(10, height + 5); 83780 * detailX.style('width', '80px'); 83781 * } 83782 * 83783 * function draw() { 83784 * background(205, 105, 94); 83785 * rotateY(millis() / 1000);
83786 * sphere(40, detailX.value(), 16); 83787 * } 83788 * </code> 83789 * </div> 83790 * 83791 * @example 83792 * <div> 83793 * <code> 83794 * let detailY; 83795 * // slide to see how detailY works 83796 * function setup() { 83797 * createCanvas(100, 100, WEBGL); 83798 * detailY = createSlider(3, 16, 3); 83799 * detailY.position(10, height + 5); 83800 * detailY.style('width', '80px'); 83801 * } 83802 * 83803 * function draw() { 83804 * background(205, 105, 94); 83805 * rotateY(millis() / 1000); 83806 * sphere(40, 16, detailY.value()); 83807 * } 83808 * </code> 83809 * </div> 83810 */ 83811 _main.default.prototype.sphere = function(radius, detailX, detailY) { 83812 this._assert3d('sphere'); 83813 _main.default._validateParameters('sphere', arguments); 83814 if (typeof radius === 'undefined') { 83815 radius = 50; 83816 } 83817 if (typeof detailX === 'undefined') { 83818 detailX = 24; 83819 } 83820 if (typeof detailY === 'undefined') { 83821 detailY = 16; 83822 } 83823 83824 this.ellipsoid(radius, radius, radius, detailX, detailY); 83825 83826 return this; 83827 }; 83828 83829 /** 83830 * @private 83831 * Helper function for creating both cones and cylinders 83832 * Will only generate well-defined geometry when bottomRadius, height > 0 83833 * and topRadius >= 0 83834 * If topRadius == 0, topCap should be false 83835 */ 83836 var _truncatedCone = function _truncatedCone( 83837 bottomRadius, 83838 topRadius, 83839 height, 83840 detailX, 83841 detailY, 83842 bottomCap, 83843 topCap 83844 ) { 83845 bottomRadius = bottomRadius <= 0 ? 1 : bottomRadius; 83846 topRadius = topRadius < 0 ? 0 : topRadius; 83847 height = height <= 0 ? bottomRadius : height; 83848 detailX = detailX < 3 ? 3 : detailX; 83849 detailY = detailY < 1 ? 1 : detailY; 83850 bottomCap = bottomCap === undefined ? true : bottomCap; 83851 topCap = topCap === undefined ? topRadius !== 0 : topCap; 83852 var start = bottomCap ? -2 : 0; 83853 var end = detailY + (topCap ? 2 : 0); 83854 //ensure constant slant for interior vertex normals 83855 var slant = Math.atan2(bottomRadius - topRadius, height); 83856 var sinSlant = Math.sin(slant); 83857 var cosSlant = Math.cos(slant); 83858 var yy, ii, jj; 83859 for (yy = start; yy <= end; ++yy) { 83860 var v = yy / detailY; 83861 var y = height * v; 83862 var ringRadius = void 0; 83863 if (yy < 0) { 83864 //for the bottomCap edge 83865 y = 0; 83866 v = 0; 83867 ringRadius = bottomRadius; 83868 } else if (yy > detailY) { 83869 //for the topCap edge 83870 y = height; 83871 v = 1; 83872 ringRadius = topRadius; 83873 } else { 83874 //for the middle 83875 ringRadius = bottomRadius + (topRadius - bottomRadius) * v; 83876 } 83877 if (yy === -2 || yy === detailY + 2) { 83878 //center of bottom or top caps 83879 ringRadius = 0; 83880 } 83881 83882 y -= height / 2; //shift coordiate origin to the center of object 83883 for (ii = 0; ii < detailX; ++ii) { 83884 var u = ii / (detailX - 1); 83885 var ur = 2 * Math.PI * u; 83886 var sur = Math.sin(ur); 83887 var cur = Math.cos(ur); 83888 83889 //VERTICES 83890 this.vertices.push( 83891 new _main.default.Vector(sur * ringRadius, y, cur * ringRadius) 83892 ); 83893 83894 //VERTEX NORMALS 83895 var vertexNormal = void 0; 83896 if (yy < 0) { 83897 vertexNormal = new _main.default.Vector(0, -1, 0); 83898 } else if (yy > detailY && topRadius) { 83899 vertexNormal = new _main.default.Vector(0, 1, 0); 83900 } else { 83901 vertexNormal = new _main.default.Vector( 83902 sur * cosSlant, 83903 sinSlant, 83904 cur * cosSlant 83905 ); 83906 } 83907 this.vertexNormals.push(vertexNormal); 83908 //UVs 83909 this.uvs.push(u, v); 83910 } 83911 } 83912 83913 var startIndex = 0; 83914 if (bottomCap) { 83915 for (jj = 0; jj < detailX; ++jj) { 83916 var nextjj = (jj + 1) % detailX; 83917 this.faces.push([ 83918 startIndex + jj, 83919 startIndex + detailX + nextjj, 83920 startIndex + detailX + jj 83921 ]); 83922 } 83923 startIndex += detailX * 2; 83924 } 83925 for (yy = 0; yy < detailY; ++yy) { 83926 for (ii = 0; ii < detailX; ++ii) { 83927 var nextii = (ii + 1) % detailX; 83928 this.faces.push([ 83929 startIndex + ii, 83930 startIndex + nextii, 83931 startIndex + detailX + nextii 83932 ]); 83933 83934 this.faces.push([ 83935 startIndex + ii, 83936 startIndex + detailX + nextii, 83937 startIndex + detailX + ii 83938 ]); 83939 } 83940 startIndex += detailX; 83941 } 83942 if (topCap) { 83943 startIndex += detailX; 83944 for (ii = 0; ii < detailX; ++ii) { 83945 this.faces.push([ 83946 startIndex + ii, 83947 startIndex + (ii + 1) % detailX, 83948 startIndex + detailX 83949 ]); 83950 } 83951 } 83952 }; 83953 83954 /** 83955 * Draw a cylinder with given radius and height 83956 * 83957 * DetailX and detailY determines the number of subdivisions in the x-dimension 83958 * and the y-dimension of a cylinder. More subdivisions make the cylinder seem smoother. 83959 * The recommended maximum value for detailX is 24. Using a value greater than 24 83960 * may cause a warning or slow down the browser. 83961 * 83962 * @method cylinder 83963 * @param {Number} [radius] radius of the surface 83964 * @param {Number} [height] height of the cylinder 83965 * @param {Integer} [detailX] number of subdivisions in x-dimension; 83966 * default is 24 83967 * @param {Integer} [detailY] number of subdivisions in y-dimension; 83968 * default is 1 83969 * @param {Boolean} [bottomCap] whether to draw the bottom of the cylinder 83970 * @param {Boolean} [topCap] whether to draw the top of the cylinder 83971 * @chainable 83972 * @example 83973 * <div> 83974 * <code> 83975 * // draw a spinning cylinder 83976 * // with radius 20 and height 50 83977 * function setup() { 83978 * createCanvas(100, 100, WEBGL); 83979 * } 83980 * 83981 * function draw() { 83982 * background(205, 105, 94); 83983 * rotateX(frameCount * 0.01); 83984 * rotateZ(frameCount * 0.01); 83985 * cylinder(20, 50); 83986 * } 83987 * </code> 83988 * </div> 83989 * 83990 * @example 83991 * <div> 83992 * <code> 83993 * // slide to see how detailX works 83994 * let detailX; 83995 * function setup() { 83996 * createCanvas(100, 100, WEBGL); 83997 * detailX = createSlider(3, 24, 3); 83998 * detailX.position(10, height + 5); 83999 * detailX.style('width', '80px'); 84000 * } 84001 * 84002 * function draw() { 84003 * background(205, 105, 94); 84004 * rotateY(millis() / 1000);
84005 * cylinder(20, 75, detailX.value(), 1); 84006 * } 84007 * </code> 84008 * </div> 84009 * 84010 * @example 84011 * <div> 84012 * <code> 84013 * // slide to see how detailY works 84014 * let detailY; 84015 * function setup() { 84016 * createCanvas(100, 100, WEBGL); 84017 * detailY = createSlider(1, 16, 1); 84018 * detailY.position(10, height + 5); 84019 * detailY.style('width', '80px'); 84020 * } 84021 * 84022 * function draw() { 84023 * background(205, 105, 94); 84024 * rotateY(millis() / 1000); 84025 * cylinder(20, 75, 16, detailY.value()); 84026 * } 84027 * </code> 84028 * </div> 84029 */ 84030 _main.default.prototype.cylinder = function( 84031 radius, 84032 height, 84033 detailX, 84034 detailY, 84035 bottomCap, 84036 topCap 84037 ) { 84038 this._assert3d('cylinder'); 84039 _main.default._validateParameters('cylinder', arguments); 84040 if (typeof radius === 'undefined') { 84041 radius = 50; 84042 } 84043 if (typeof height === 'undefined') { 84044 height = radius; 84045 } 84046 if (typeof detailX === 'undefined') { 84047 detailX = 24; 84048 } 84049 if (typeof detailY === 'undefined') { 84050 detailY = 1; 84051 } 84052 if (typeof topCap === 'undefined') { 84053 topCap = true; 84054 } 84055 if (typeof bottomCap === 'undefined') { 84056 bottomCap = true; 84057 } 84058 84059 var gId = 'cylinder|' 84060 .concat(detailX, '|') 84061 .concat(detailY, '|') 84062 .concat(bottomCap, '|') 84063 .concat(topCap); 84064 if (!this._renderer.geometryInHash(gId)) { 84065 var cylinderGeom = new _main.default.Geometry(detailX, detailY); 84066 _truncatedCone.call( 84067 cylinderGeom, 84068 1, 84069 1, 84070 1, 84071 detailX, 84072 detailY, 84073 bottomCap, 84074 topCap 84075 ); 84076 84077 // normals are computed in call to _truncatedCone 84078 if (detailX <= 24 && detailY <= 16) { 84079 cylinderGeom._makeTriangleEdges()._edgesToVertices(); 84080 } else if (this._renderer._doStroke) { 84081 console.log( 84082 'Cannot draw stroke on cylinder objects with more' + 84083 ' than 24 detailX or 16 detailY' 84084 ); 84085 } 84086 this._renderer.createBuffers(gId, cylinderGeom); 84087 } 84088 84089 this._renderer.drawBuffersScaled(gId, radius, height, radius); 84090 84091 return this; 84092 }; 84093 84094 /** 84095 * Draw a cone with given radius and height 84096 * 84097 * DetailX and detailY determine the number of subdivisions in the x-dimension and 84098 * the y-dimension of a cone. More subdivisions make the cone seem smoother. The 84099 * recommended maximum value for detailX is 24. Using a value greater than 24 84100 * may cause a warning or slow down the browser. 84101 * @method cone 84102 * @param {Number} [radius] radius of the bottom surface 84103 * @param {Number} [height] height of the cone 84104 * @param {Integer} [detailX] number of segments, 84105 * the more segments the smoother geometry 84106 * default is 24 84107 * @param {Integer} [detailY] number of segments, 84108 * the more segments the smoother geometry 84109 * default is 1 84110 * @param {Boolean} [cap] whether to draw the base of the cone 84111 * @chainable 84112 * @example 84113 * <div> 84114 * <code> 84115 * // draw a spinning cone 84116 * // with radius 40 and height 70 84117 * function setup() { 84118 * createCanvas(100, 100, WEBGL); 84119 * } 84120 * 84121 * function draw() { 84122 * background(200); 84123 * rotateX(frameCount * 0.01); 84124 * rotateZ(frameCount * 0.01); 84125 * cone(40, 70); 84126 * } 84127 * </code> 84128 * </div> 84129 * 84130 * @example 84131 * <div> 84132 * <code> 84133 * // slide to see how detailx works 84134 * let detailX; 84135 * function setup() { 84136 * createCanvas(100, 100, WEBGL); 84137 * detailX = createSlider(3, 16, 3); 84138 * detailX.position(10, height + 5); 84139 * detailX.style('width', '80px'); 84140 * } 84141 * 84142 * function draw() { 84143 * background(205, 102, 94); 84144 * rotateY(millis() / 1000);
84145 * cone(30, 65, detailX.value(), 16); 84146 * } 84147 * </code> 84148 * </div> 84149 * 84150 * @example 84151 * <div> 84152 * <code> 84153 * // slide to see how detailY works 84154 * let detailY; 84155 * function setup() { 84156 * createCanvas(100, 100, WEBGL); 84157 * detailY = createSlider(3, 16, 3); 84158 * detailY.position(10, height + 5); 84159 * detailY.style('width', '80px'); 84160 * } 84161 * 84162 * function draw() { 84163 * background(205, 102, 94); 84164 * rotateY(millis() / 1000); 84165 * cone(30, 65, 16, detailY.value()); 84166 * } 84167 * </code> 84168 * </div> 84169 */ 84170 _main.default.prototype.cone = function(radius, height, detailX, detailY, cap) { 84171 this._assert3d('cone'); 84172 _main.default._validateParameters('cone', arguments); 84173 if (typeof radius === 'undefined') { 84174 radius = 50; 84175 } 84176 if (typeof height === 'undefined') { 84177 height = radius; 84178 } 84179 if (typeof detailX === 'undefined') { 84180 detailX = 24; 84181 } 84182 if (typeof detailY === 'undefined') { 84183 detailY = 1; 84184 } 84185 if (typeof cap === 'undefined') { 84186 cap = true; 84187 } 84188 84189 var gId = 'cone|' 84190 .concat(detailX, '|') 84191 .concat(detailY, '|') 84192 .concat(cap); 84193 if (!this._renderer.geometryInHash(gId)) { 84194 var coneGeom = new _main.default.Geometry(detailX, detailY); 84195 _truncatedCone.call(coneGeom, 1, 0, 1, detailX, detailY, cap, false); 84196 if (detailX <= 24 && detailY <= 16) { 84197 coneGeom._makeTriangleEdges()._edgesToVertices(); 84198 } else if (this._renderer._doStroke) { 84199 console.log( 84200 'Cannot draw stroke on cone objects with more' + 84201 ' than 24 detailX or 16 detailY' 84202 ); 84203 } 84204 this._renderer.createBuffers(gId, coneGeom); 84205 } 84206 84207 this._renderer.drawBuffersScaled(gId, radius, height, radius); 84208 84209 return this; 84210 }; 84211 84212 /** 84213 * Draw an ellipsoid with given radius 84214 * 84215 * DetailX and detailY determine the number of subdivisions in the x-dimension and 84216 * the y-dimension of a cone. More subdivisions make the ellipsoid appear to be smoother. 84217 * Avoid detail number above 150, it may crash the browser. 84218 * @method ellipsoid 84219 * @param {Number} [radiusx] x-radius of ellipsoid 84220 * @param {Number} [radiusy] y-radius of ellipsoid 84221 * @param {Number} [radiusz] z-radius of ellipsoid 84222 * @param {Integer} [detailX] number of segments, 84223 * the more segments the smoother geometry 84224 * default is 24. Avoid detail number above 84225 * 150, it may crash the browser. 84226 * @param {Integer} [detailY] number of segments, 84227 * the more segments the smoother geometry 84228 * default is 16. Avoid detail number above 84229 * 150, it may crash the browser. 84230 * @chainable 84231 * @example 84232 * <div> 84233 * <code> 84234 * // draw an ellipsoid 84235 * // with radius 30, 40 and 40. 84236 * function setup() { 84237 * createCanvas(100, 100, WEBGL); 84238 * } 84239 * 84240 * function draw() { 84241 * background(205, 105, 94); 84242 * ellipsoid(30, 40, 40); 84243 * } 84244 * </code> 84245 * </div> 84246 * 84247 * @example 84248 * <div> 84249 * <code> 84250 * // slide to see how detailX works 84251 * let detailX; 84252 * function setup() { 84253 * createCanvas(100, 100, WEBGL); 84254 * detailX = createSlider(2, 24, 12); 84255 * detailX.position(10, height + 5); 84256 * detailX.style('width', '80px'); 84257 * } 84258 * 84259 * function draw() { 84260 * background(205, 105, 94); 84261 * rotateY(millis() / 1000);
84262 * ellipsoid(30, 40, 40, detailX.value(), 8); 84263 * } 84264 * </code> 84265 * </div> 84266 * 84267 * @example 84268 * <div> 84269 * <code> 84270 * // slide to see how detailY works 84271 * let detailY; 84272 * function setup() { 84273 * createCanvas(100, 100, WEBGL); 84274 * detailY = createSlider(2, 24, 6); 84275 * detailY.position(10, height + 5); 84276 * detailY.style('width', '80px'); 84277 * } 84278 * 84279 * function draw() { 84280 * background(205, 105, 9); 84281 * rotateY(millis() / 1000); 84282 * ellipsoid(30, 40, 40, 12, detailY.value()); 84283 * } 84284 * </code> 84285 * </div> 84286 */ 84287 _main.default.prototype.ellipsoid = function( 84288 radiusX, 84289 radiusY, 84290 radiusZ, 84291 detailX, 84292 detailY 84293 ) { 84294 this._assert3d('ellipsoid'); 84295 _main.default._validateParameters('ellipsoid', arguments); 84296 if (typeof radiusX === 'undefined') { 84297 radiusX = 50; 84298 } 84299 if (typeof radiusY === 'undefined') { 84300 radiusY = radiusX; 84301 } 84302 if (typeof radiusZ === 'undefined') { 84303 radiusZ = radiusX; 84304 } 84305 84306 if (typeof detailX === 'undefined') { 84307 detailX = 24; 84308 } 84309 if (typeof detailY === 'undefined') { 84310 detailY = 16; 84311 } 84312 84313 var gId = 'ellipsoid|'.concat(detailX, '|').concat(detailY); 84314 84315 if (!this._renderer.geometryInHash(gId)) { 84316 var _ellipsoid = function _ellipsoid() { 84317 for (var i = 0; i <= this.detailY; i++) { 84318 var v = i / this.detailY; 84319 var phi = Math.PI * v - Math.PI / 2; 84320 var cosPhi = Math.cos(phi); 84321 var sinPhi = Math.sin(phi); 84322 84323 for (var j = 0; j <= this.detailX; j++) { 84324 var u = j / this.detailX; 84325 var theta = 2 * Math.PI * u; 84326 var cosTheta = Math.cos(theta); 84327 var sinTheta = Math.sin(theta); 84328 var p = new _main.default.Vector( 84329 cosPhi * sinTheta, 84330 sinPhi, 84331 cosPhi * cosTheta 84332 ); 84333 this.vertices.push(p); 84334 this.vertexNormals.push(p); 84335 this.uvs.push(u, v); 84336 } 84337 } 84338 }; 84339 var ellipsoidGeom = new _main.default.Geometry(detailX, detailY, _ellipsoid); 84340 ellipsoidGeom.computeFaces(); 84341 if (detailX <= 24 && detailY <= 24) { 84342 ellipsoidGeom._makeTriangleEdges()._edgesToVertices(); 84343 } else if (this._renderer._doStroke) { 84344 console.log( 84345 'Cannot draw stroke on ellipsoids with more' + 84346 ' than 24 detailX or 24 detailY' 84347 ); 84348 } 84349 this._renderer.createBuffers(gId, ellipsoidGeom); 84350 } 84351 84352 this._renderer.drawBuffersScaled(gId, radiusX, radiusY, radiusZ); 84353 84354 return this; 84355 }; 84356 84357 /** 84358 * Draw a torus with given radius and tube radius 84359 * 84360 * DetailX and detailY determine the number of subdivisions in the x-dimension and 84361 * the y-dimension of a torus. More subdivisions make the torus appear to be smoother. 84362 * The default and maximum values for detailX and detailY are 24 and 16, respectively. 84363 * Setting them to relatively small values like 4 and 6 allows you to create new 84364 * shapes other than a torus. 84365 * @method torus 84366 * @param {Number} [radius] radius of the whole ring 84367 * @param {Number} [tubeRadius] radius of the tube 84368 * @param {Integer} [detailX] number of segments in x-dimension, 84369 * the more segments the smoother geometry 84370 * default is 24 84371 * @param {Integer} [detailY] number of segments in y-dimension, 84372 * the more segments the smoother geometry 84373 * default is 16 84374 * @chainable 84375 * @example 84376 * <div> 84377 * <code> 84378 * // draw a spinning torus 84379 * // with ring radius 30 and tube radius 15 84380 * function setup() { 84381 * createCanvas(100, 100, WEBGL); 84382 * } 84383 * 84384 * function draw() { 84385 * background(205, 102, 94); 84386 * rotateX(frameCount * 0.01); 84387 * rotateY(frameCount * 0.01); 84388 * torus(30, 15); 84389 * } 84390 * </code> 84391 * </div> 84392 * 84393 * @example 84394 * <div> 84395 * <code> 84396 * // slide to see how detailX works 84397 * let detailX; 84398 * function setup() { 84399 * createCanvas(100, 100, WEBGL); 84400 * detailX = createSlider(3, 24, 3); 84401 * detailX.position(10, height + 5); 84402 * detailX.style('width', '80px'); 84403 * } 84404 * 84405 * function draw() { 84406 * background(205, 102, 94); 84407 * rotateY(millis() / 1000);
84408 * torus(30, 15, detailX.value(), 12); 84409 * } 84410 * </code> 84411 * </div> 84412 * 84413 * @example 84414 * <div> 84415 * <code> 84416 * // slide to see how detailY works 84417 * let detailY; 84418 * function setup() { 84419 * createCanvas(100, 100, WEBGL); 84420 * detailY = createSlider(3, 16, 3); 84421 * detailY.position(10, height + 5); 84422 * detailY.style('width', '80px'); 84423 * } 84424 * 84425 * function draw() { 84426 * background(205, 102, 94); 84427 * rotateY(millis() / 1000); 84428 * torus(30, 15, 16, detailY.value()); 84429 * } 84430 * </code> 84431 * </div> 84432 */ 84433 _main.default.prototype.torus = function(radius, tubeRadius, detailX, detailY) { 84434 this._assert3d('torus'); 84435 _main.default._validateParameters('torus', arguments); 84436 if (typeof radius === 'undefined') { 84437 radius = 50; 84438 } else if (!radius) { 84439 return; // nothing to draw 84440 } 84441 84442 if (typeof tubeRadius === 'undefined') { 84443 tubeRadius = 10; 84444 } else if (!tubeRadius) { 84445 return; // nothing to draw 84446 } 84447 84448 if (typeof detailX === 'undefined') { 84449 detailX = 24; 84450 } 84451 if (typeof detailY === 'undefined') { 84452 detailY = 16; 84453 } 84454 84455 var tubeRatio = (tubeRadius / radius).toPrecision(4); 84456 var gId = 'torus|' 84457 .concat(tubeRatio, '|') 84458 .concat(detailX, '|') 84459 .concat(detailY); 84460 84461 if (!this._renderer.geometryInHash(gId)) { 84462 var _torus = function _torus() { 84463 for (var i = 0; i <= this.detailY; i++) { 84464 var v = i / this.detailY; 84465 var phi = 2 * Math.PI * v; 84466 var cosPhi = Math.cos(phi); 84467 var sinPhi = Math.sin(phi); 84468 var r = 1 + tubeRatio * cosPhi; 84469 84470 for (var j = 0; j <= this.detailX; j++) { 84471 var u = j / this.detailX; 84472 var theta = 2 * Math.PI * u; 84473 var cosTheta = Math.cos(theta); 84474 var sinTheta = Math.sin(theta); 84475 84476 var p = new _main.default.Vector( 84477 r * cosTheta, 84478 r * sinTheta, 84479 tubeRatio * sinPhi 84480 ); 84481 84482 var n = new _main.default.Vector( 84483 cosPhi * cosTheta, 84484 cosPhi * sinTheta, 84485 sinPhi 84486 ); 84487 84488 this.vertices.push(p); 84489 this.vertexNormals.push(n); 84490 this.uvs.push(u, v); 84491 } 84492 } 84493 }; 84494 var torusGeom = new _main.default.Geometry(detailX, detailY, _torus); 84495 torusGeom.computeFaces(); 84496 if (detailX <= 24 && detailY <= 16) { 84497 torusGeom._makeTriangleEdges()._edgesToVertices(); 84498 } else if (this._renderer._doStroke) { 84499 console.log( 84500 'Cannot draw strokes on torus object with more' + 84501 ' than 24 detailX or 16 detailY' 84502 ); 84503 } 84504 this._renderer.createBuffers(gId, torusGeom); 84505 } 84506 this._renderer.drawBuffersScaled(gId, radius, radius, radius); 84507 84508 return this; 84509 }; 84510
84511 /////////////////////// 84512 /// 2D primitives 84513 ///////////////////////// 84514 84515 /** 84516 * Draws a point, a coordinate in space at the dimension of one pixel, 84517 * given x, y and z coordinates. The color of the point is determined 84518 * by the current stroke, while the point size is determined by current 84519 * stroke weight. 84520 * @private 84521 * @param {Number} x x-coordinate of point 84522 * @param {Number} y y-coordinate of point 84523 * @param {Number} z z-coordinate of point 84524 * @chainable 84525 * @example 84526 * <div> 84527 * <code> 84528 * function setup() { 84529 * createCanvas(100, 100, WEBGL); 84530 * } 84531 * 84532 * function draw() { 84533 * background(50); 84534 * stroke(255); 84535 * strokeWeight(4); 84536 * point(25, 0); 84537 * strokeWeight(3); 84538 * point(-25, 0); 84539 * strokeWeight(2); 84540 * point(0, 25); 84541 * strokeWeight(1); 84542 * point(0, -25); 84543 * } 84544 * </code> 84545 * </div> 84546 */ 84547 _main.default.RendererGL.prototype.point = function(x, y, z) { 84548 if (typeof z === 'undefined') { 84549 z = 0; 84550 } 84551 84552 var _vertex = []; 84553 _vertex.push(new _main.default.Vector(x, y, z)); 84554 this._drawPoints(_vertex, this.immediateMode.buffers.point); 84555 84556 return this; 84557 }; 84558 84559 _main.default.RendererGL.prototype.triangle = function(args) { 84560 var x1 = args[0], 84561 y1 = args[1]; 84562 var x2 = args[2], 84563 y2 = args[3]; 84564 var x3 = args[4], 84565 y3 = args[5]; 84566 84567 var gId = 'tri'; 84568 if (!this.geometryInHash(gId)) { 84569 var _triangle = function _triangle() { 84570 var vertices = []; 84571 vertices.push(new _main.default.Vector(0, 0, 0)); 84572 vertices.push(new _main.default.Vector(0, 1, 0)); 84573 vertices.push(new _main.default.Vector(1, 0, 0)); 84574 this.strokeIndices = [[0, 1], [1, 2], [2, 0]]; 84575 this.vertices = vertices; 84576 this.faces = [[0, 1, 2]]; 84577 this.uvs = [0, 0, 0, 1, 1, 1]; 84578 }; 84579 var triGeom = new _main.default.Geometry(1, 1, _triangle); 84580 triGeom._makeTriangleEdges()._edgesToVertices(); 84581 triGeom.computeNormals(); 84582 this.createBuffers(gId, triGeom); 84583 } 84584 84585 // only one triangle is cached, one point is at the origin, and the 84586 // two adjacent sides are tne unit vectors along the X & Y axes. 84587 // 84588 // this matrix multiplication transforms those two unit vectors 84589 // onto the required vector prior to rendering, and moves the 84590 // origin appropriately. 84591 var uMVMatrix = this.uMVMatrix.copy(); 84592 try { 84593 // prettier-ignore 84594 var mult = new _main.default.Matrix([ 84595 x2 - x1, y2 - y1, 0, 0, // the resulting unit X-axis 84596 x3 - x1, y3 - y1, 0, 0, // the resulting unit Y-axis 84597 0, 0, 1, 0, // the resulting unit Z-axis (unchanged) 84598 x1, y1, 0, 1 // the resulting origin 84599 ]).mult(this.uMVMatrix); 84600 84601 this.uMVMatrix = mult; 84602 84603 this.drawBuffers(gId); 84604 } finally { 84605 this.uMVMatrix = uMVMatrix; 84606 } 84607 84608 return this; 84609 }; 84610 84611 _main.default.RendererGL.prototype.ellipse = function(args) { 84612 this.arc( 84613 args[0], 84614 args[1], 84615 args[2], 84616 args[3], 84617 0, 84618 constants.TWO_PI, 84619 constants.OPEN, 84620 args[4] 84621 ); 84622 }; 84623 84624 _main.default.RendererGL.prototype.arc = function(args) { 84625 var x = arguments[0]; 84626 var y = arguments[1]; 84627 var width = arguments[2]; 84628 var height = arguments[3]; 84629 var start = arguments[4]; 84630 var stop = arguments[5]; 84631 var mode = arguments[6]; 84632 var detail = arguments[7] || 25; 84633 84634 var shape; 84635 var gId; 84636 84637 // check if it is an ellipse or an arc 84638 if (Math.abs(stop - start) >= constants.TWO_PI) { 84639 shape = 'ellipse'; 84640 gId = ''.concat(shape, '|').concat(detail, '|'); 84641 } else { 84642 shape = 'arc'; 84643 gId = '' 84644 .concat(shape, '|') 84645 .concat(start, '|') 84646 .concat(stop, '|') 84647 .concat(mode, '|') 84648 .concat(detail, '|'); 84649 } 84650 84651 if (!this.geometryInHash(gId)) { 84652 var _arc = function _arc() { 84653 this.strokeIndices = []; 84654 84655 // if the start and stop angles are not the same, push vertices to the array 84656 if (start.toFixed(10) !== stop.toFixed(10)) { 84657 // if the mode specified is PIE or null, push the mid point of the arc in vertices 84658 if (mode === constants.PIE || typeof mode === 'undefined') { 84659 this.vertices.push(new _main.default.Vector(0.5, 0.5, 0)); 84660 this.uvs.push([0.5, 0.5]); 84661 } 84662 84663 // vertices for the perimeter of the circle 84664 for (var i = 0; i <= detail; i++) { 84665 var u = i / detail; 84666 var theta = (stop - start) * u + start; 84667
84668 var _x = 0.5 + Math.cos(theta) / 2; 84669 var _y = 0.5 + Math.sin(theta) / 2; 84670 84671 this.vertices.push(new _main.default.Vector(_x, _y, 0)); 84672 this.uvs.push([_x, _y]); 84673 84674 if (i < detail - 1) { 84675 this.faces.push([0, i + 1, i + 2]); 84676 this.strokeIndices.push([i + 1, i + 2]); 84677 } 84678 } 84679 84680 // check the mode specified in order to push vertices and faces, different for each mode 84681 switch (mode) { 84682 case constants.PIE: 84683 this.faces.push([ 84684 0, 84685 this.vertices.length - 2, 84686 this.vertices.length - 1 84687 ]); 84688 84689 this.strokeIndices.push([0, 1]); 84690 this.strokeIndices.push([ 84691 this.vertices.length - 2, 84692 this.vertices.length - 1 84693 ]); 84694 84695 this.strokeIndices.push([0, this.vertices.length - 1]); 84696 break; 84697 84698 case constants.CHORD: 84699 this.strokeIndices.push([0, 1]); 84700 this.strokeIndices.push([0, this.vertices.length - 1]); 84701 break; 84702 84703 case constants.OPEN: 84704 this.strokeIndices.push([0, 1]); 84705 break; 84706 84707 default: 84708 this.faces.push([ 84709 0, 84710 this.vertices.length - 2, 84711 this.vertices.length - 1 84712 ]); 84713 84714 this.strokeIndices.push([ 84715 this.vertices.length - 2, 84716 this.vertices.length - 1 84717 ]); 84718 } 84719 } 84720 }; 84721 84722 var arcGeom = new _main.default.Geometry(detail, 1, _arc); 84723 arcGeom.computeNormals(); 84724 84725 if (detail <= 50) { 84726 arcGeom._makeTriangleEdges()._edgesToVertices(arcGeom); 84727 } else if (this._renderer._doStroke) { 84728 console.log('Cannot stroke ${shape} with more than 50 detail'); 84729 } 84730 84731 this.createBuffers(gId, arcGeom); 84732 } 84733 84734 var uMVMatrix = this.uMVMatrix.copy(); 84735 84736 try { 84737 this.uMVMatrix.translate([x, y, 0]); 84738 this.uMVMatrix.scale(width, height, 1); 84739 84740 this.drawBuffers(gId); 84741 } finally { 84742 this.uMVMatrix = uMVMatrix; 84743 } 84744 84745 return this; 84746 }; 84747 84748 _main.default.RendererGL.prototype.rect = function(args) { 84749 var perPixelLighting = this._pInst._glAttributes.perPixelLighting; 84750 var x = args[0]; 84751 var y = args[1]; 84752 var width = args[2]; 84753 var height = args[3]; 84754 var detailX = args[4] || (perPixelLighting ? 1 : 24); 84755 var detailY = args[5] || (perPixelLighting ? 1 : 16); 84756 var gId = 'rect|'.concat(detailX, '|').concat(detailY); 84757 if (!this.geometryInHash(gId)) { 84758 var _rect = function _rect() { 84759 for (var i = 0; i <= this.detailY; i++) { 84760 var v = i / this.detailY; 84761 for (var j = 0; j <= this.detailX; j++) { 84762 var u = j / this.detailX; 84763 var p = new _main.default.Vector(u, v, 0); 84764 this.vertices.push(p); 84765 this.uvs.push(u, v); 84766 } 84767 } 84768 // using stroke indices to avoid stroke over face(s) of rectangle 84769 if (detailX > 0 && detailY > 0) { 84770 this.strokeIndices = [ 84771 [0, detailX], 84772 [detailX, (detailX + 1) * (detailY + 1) - 1], 84773 [(detailX + 1) * (detailY + 1) - 1, (detailX + 1) * detailY], 84774 [(detailX + 1) * detailY, 0] 84775 ]; 84776 } 84777 }; 84778 var rectGeom = new _main.default.Geometry(detailX, detailY, _rect); 84779 rectGeom 84780 .computeFaces() 84781 .computeNormals() 84782 ._makeTriangleEdges() 84783 ._edgesToVertices(); 84784 this.createBuffers(gId, rectGeom); 84785 } 84786 84787 // only a single rectangle (of a given detail) is cached: a square with 84788 // opposite corners at (0,0) & (1,1). 84789 // 84790 // before rendering, this square is scaled & moved to the required location. 84791 var uMVMatrix = this.uMVMatrix.copy(); 84792 try { 84793 this.uMVMatrix.translate([x, y, 0]); 84794 this.uMVMatrix.scale(width, height, 1); 84795 84796 this.drawBuffers(gId); 84797 } finally { 84798 this.uMVMatrix = uMVMatrix; 84799 } 84800 return this; 84801 }; 84802 84803 // prettier-ignore 84804 _main.default.RendererGL.prototype.quad = function (x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4) { 84805 var gId = "quad|".concat( 84806 x1, "|").concat(y1, "|").concat(z1, "|").concat(x2, "|").concat(y2, "|").concat(z2, "|").concat(x3, "|").concat(y3, "|").concat(z3, "|").concat(x4, "|").concat(y4, "|").concat(z4); 84807 if (!this.geometryInHash(gId)) { 84808 var _quad = function _quad() { 84809 this.vertices.push(new _main.default.Vector(x1, y1, z1)); 84810 this.vertices.push(new _main.default.Vector(x2, y2, z2)); 84811 this.vertices.push(new _main.default.Vector(x3, y3, z3)); 84812 this.vertices.push(new _main.default.Vector(x4, y4, z4)); 84813 this.uvs.push(0, 0, 1, 0, 1, 1, 0, 1); 84814 this.strokeIndices = [[0, 1], [1, 2], [2, 3], [3, 0]]; 84815 }; 84816 var quadGeom = new _main.default.Geometry(2, 2, _quad); 84817 quadGeom. 84818 computeNormals(). 84819 _makeTriangleEdges(). 84820 _edgesToVertices(); 84821 quadGeom.faces = [[0, 1, 2], [2, 3, 0]]; 84822 this.createBuffers(gId, quadGeom); 84823 } 84824 this.drawBuffers(gId); 84825 return this; 84826}; 84827 84828 //this implementation of bezier curve 84829 //is based on Bernstein polynomial 84830 // pretier-ignore 84831 _main.default.RendererGL.prototype.bezier = function( 84832 x1, 84833 y1, 84834 z1, // x2 84835 x2, // y2 84836 y2, // x3 84837 z2, // y3 84838 x3, // x4 84839 y3, // y4 84840 z3, 84841 x4, 84842 y4, 84843 z4 84844 ) { 84845 if (arguments.length === 8) { 84846 y4 = y3; 84847 x4 = x3; 84848 y3 = z2; 84849 x3 = y2; 84850 y2 = x2; 84851 x2 = z1; 84852 z1 = z2 = z3 = z4 = 0; 84853 } 84854 var bezierDetail = this._pInst._bezierDetail || 20; //value of Bezier detail 84855 this.beginShape(); 84856 for (var i = 0; i <= bezierDetail; i++) { 84857 var c1 = Math.pow(1 - i / bezierDetail, 3); 84858 var c2 = 3 * (i / bezierDetail) * Math.pow(1 - i / bezierDetail, 2); 84859 var c3 = 3 * Math.pow(i / bezierDetail, 2) * (1 - i / bezierDetail); 84860 var c4 = Math.pow(i / bezierDetail, 3); 84861 this.vertex( 84862 x1 * c1 + x2 * c2 + x3 * c3 + x4 * c4, 84863 y1 * c1 + y2 * c2 + y3 * c3 + y4 * c4, 84864 z1 * c1 + z2 * c2 + z3 * c3 + z4 * c4 84865 ); 84866 } 84867 this.endShape(); 84868 return this; 84869 }; 84870 84871 // pretier-ignore 84872 _main.default.RendererGL.prototype.curve = function( 84873 x1, 84874 y1, 84875 z1, // x2 84876 x2, // y2 84877 y2, // x3 84878 z2, // y3 84879 x3, // x4 84880 y3, // y4 84881 z3, 84882 x4, 84883 y4, 84884 z4 84885 ) { 84886 if (arguments.length === 8) { 84887 x4 = x3; 84888 y4 = y3; 84889 x3 = y2; 84890 y3 = x2; 84891 x2 = z1; 84892 y2 = x2; 84893 z1 = z2 = z3 = z4 = 0; 84894 } 84895 var curveDetail = this._pInst._curveDetail; 84896 this.beginShape(); 84897 for (var i = 0; i <= curveDetail; i++) { 84898 var c1 = Math.pow(i / curveDetail, 3) * 0.5; 84899 var c2 = Math.pow(i / curveDetail, 2) * 0.5; 84900 var c3 = i / curveDetail * 0.5; 84901 var c4 = 0.5; 84902 var vx = 84903 c1 * (-x1 + 3 * x2 - 3 * x3 + x4) + 84904 c2 * (2 * x1 - 5 * x2 + 4 * x3 - x4) + 84905 c3 * (-x1 + x3) + 84906 c4 * (2 * x2); 84907 var vy = 84908 c1 * (-y1 + 3 * y2 - 3 * y3 + y4) + 84909 c2 * (2 * y1 - 5 * y2 + 4 * y3 - y4) + 84910 c3 * (-y1 + y3) + 84911 c4 * (2 * y2); 84912 var vz = 84913 c1 * (-z1 + 3 * z2 - 3 * z3 + z4) + 84914 c2 * (2 * z1 - 5 * z2 + 4 * z3 - z4) + 84915 c3 * (-z1 + z3) + 84916 c4 * (2 * z2); 84917 this.vertex(vx, vy, vz); 84918 } 84919 this.endShape(); 84920 return this; 84921 }; 84922 84923 /** 84924 * Draw a line given two points 84925 * @private 84926 * @param {Number} x0 x-coordinate of first vertex 84927 * @param {Number} y0 y-coordinate of first vertex 84928 * @param {Number} z0 z-coordinate of first vertex 84929 * @param {Number} x1 x-coordinate of second vertex 84930 * @param {Number} y1 y-coordinate of second vertex 84931 * @param {Number} z1 z-coordinate of second vertex 84932 * @chainable 84933 * @example 84934 * <div> 84935 * <code> 84936 * //draw a line 84937 * function setup() { 84938 * createCanvas(100, 100, WEBGL); 84939 * } 84940 * 84941 * function draw() { 84942 * background(200); 84943 * rotateX(frameCount * 0.01); 84944 * rotateY(frameCount * 0.01); 84945 * // Use fill instead of stroke to change the color of shape. 84946 * fill(255, 0, 0); 84947 * line(10, 10, 0, 60, 60, 20); 84948 * } 84949 * </code> 84950 * </div> 84951 */ 84952 _main.default.RendererGL.prototype.line = function() { 84953 if (arguments.length === 6) { 84954 this.beginShape(constants.LINES); 84955 this.vertex( 84956 arguments.length <= 0 ? undefined : arguments[0], 84957 arguments.length <= 1 ? undefined : arguments[1], 84958 arguments.length <= 2 ? undefined : arguments[2] 84959 ); 84960 this.vertex( 84961 arguments.length <= 3 ? undefined : arguments[3], 84962 arguments.length <= 4 ? undefined : arguments[4], 84963 arguments.length <= 5 ? undefined : arguments[5] 84964 ); 84965 this.endShape(); 84966 } else if (arguments.length === 4) { 84967 this.beginShape(constants.LINES); 84968 this.vertex( 84969 arguments.length <= 0 ? undefined : arguments[0], 84970 arguments.length <= 1 ? undefined : arguments[1], 84971 0 84972 ); 84973 this.vertex( 84974 arguments.length <= 2 ? undefined : arguments[2], 84975 arguments.length <= 3 ? undefined : arguments[3], 84976 0 84977 ); 84978 this.endShape(); 84979 } 84980 return this; 84981 }; 84982 84983 _main.default.RendererGL.prototype.bezierVertex = function() { 84984 if (this.immediateMode._bezierVertex.length === 0) { 84985 throw Error('vertex() must be used once before calling bezierVertex()'); 84986 } else { 84987 var w_x = [];
84988 var w_y = []; 84989 var w_z = []; 84990 var t, _x, _y, _z, i; 84991 var argLength = arguments.length; 84992 84993 t = 0; 84994 84995 if ( 84996 this._lookUpTableBezier.length === 0 || 84997 this._lutBezierDetail !== this._pInst._curveDetail 84998 ) { 84999 this._lookUpTableBezier = []; 85000 this._lutBezierDetail = this._pInst._curveDetail; 85001 var step = 1 / this._lutBezierDetail; 85002 var start = 0; 85003 var end = 1; 85004 var j = 0; 85005 while (start < 1) { 85006 t = parseFloat(start.toFixed(6)); 85007 this._lookUpTableBezier[j] = this._bezierCoefficients(t); 85008 if (end.toFixed(6) === step.toFixed(6)) { 85009 t = parseFloat(end.toFixed(6)) + parseFloat(start.toFixed(6)); 85010 ++j; 85011 this._lookUpTableBezier[j] = this._bezierCoefficients(t); 85012 break; 85013 } 85014 start += step; 85015 end -= step; 85016 ++j; 85017 } 85018 } 85019 85020 var LUTLength = this._lookUpTableBezier.length; 85021 85022 if (argLength === 6) { 85023 this.isBezier = true; 85024 85025 w_x = [ 85026 this.immediateMode._bezierVertex[0], 85027 arguments.length <= 0 ? undefined : arguments[0], 85028 arguments.length <= 2 ? undefined : arguments[2], 85029 arguments.length <= 4 ? undefined : arguments[4] 85030 ]; 85031 w_y = [ 85032 this.immediateMode._bezierVertex[1], 85033 arguments.length <= 1 ? undefined : arguments[1], 85034 arguments.length <= 3 ? undefined : arguments[3], 85035 arguments.length <= 5 ? undefined : arguments[5] 85036 ]; 85037 85038 for (i = 0; i < LUTLength; i++) { 85039 _x = 85040 w_x[0] * this._lookUpTableBezier[i][0] + 85041 w_x[1] * this._lookUpTableBezier[i][1] + 85042 w_x[2] * this._lookUpTableBezier[i][2] + 85043 w_x[3] * this._lookUpTableBezier[i][3]; 85044 _y = 85045 w_y[0] * this._lookUpTableBezier[i][0] + 85046 w_y[1] * this._lookUpTableBezier[i][1] + 85047 w_y[2] * this._lookUpTableBezier[i][2] + 85048 w_y[3] * this._lookUpTableBezier[i][3]; 85049 this.vertex(_x, _y); 85050 } 85051 this.immediateMode._bezierVertex[0] = 85052 arguments.length <= 4 ? undefined : arguments[4]; 85053 this.immediateMode._bezierVertex[1] = 85054 arguments.length <= 5 ? undefined : arguments[5]; 85055 } else if (argLength === 9) { 85056 this.isBezier = true; 85057 85058 w_x = [ 85059 this.immediateMode._bezierVertex[0], 85060 arguments.length <= 0 ? undefined : arguments[0], 85061 arguments.length <= 3 ? undefined : arguments[3], 85062 arguments.length <= 6 ? undefined : arguments[6] 85063 ]; 85064 w_y = [ 85065 this.immediateMode._bezierVertex[1], 85066 arguments.length <= 1 ? undefined : arguments[1], 85067 arguments.length <= 4 ? undefined : arguments[4], 85068 arguments.length <= 7 ? undefined : arguments[7] 85069 ]; 85070 w_z = [ 85071 this.immediateMode._bezierVertex[2], 85072 arguments.length <= 2 ? undefined : arguments[2], 85073 arguments.length <= 5 ? undefined : arguments[5], 85074 arguments.length <= 8 ? undefined : arguments[8] 85075 ]; 85076 for (i = 0; i < LUTLength; i++) { 85077 _x = 85078 w_x[0] * this._lookUpTableBezier[i][0] + 85079 w_x[1] * this._lookUpTableBezier[i][1] + 85080 w_x[2] * this._lookUpTableBezier[i][2] + 85081 w_x[3] * this._lookUpTableBezier[i][3]; 85082 _y = 85083 w_y[0] * this._lookUpTableBezier[i][0] + 85084 w_y[1] * this._lookUpTableBezier[i][1] + 85085 w_y[2] * this._lookUpTableBezier[i][2] + 85086 w_y[3] * this._lookUpTableBezier[i][3]; 85087 _z = 85088 w_z[0] * this._lookUpTableBezier[i][0] + 85089 w_z[1] * this._lookUpTableBezier[i][1] + 85090 w_z[2] * this._lookUpTableBezier[i][2] + 85091 w_z[3] * this._lookUpTableBezier[i][3]; 85092 this.vertex(_x, _y, _z); 85093 } 85094 this.immediateMode._bezierVertex[0] = 85095 arguments.length <= 6 ? undefined : arguments[6]; 85096 this.immediateMode._bezierVertex[1] = 85097 arguments.length <= 7 ? undefined : arguments[7]; 85098 this.immediateMode._bezierVertex[2] = 85099 arguments.length <= 8 ? undefined : arguments[8]; 85100 } 85101 } 85102 }; 85103 85104 _main.default.RendererGL.prototype.quadraticVertex = function() { 85105 if (this.immediateMode._quadraticVertex.length === 0) { 85106 throw Error('vertex() must be used once before calling quadraticVertex()'); 85107 } else { 85108 var w_x = [];
85109 var w_y = []; 85110 var w_z = []; 85111 var t, _x, _y, _z, i; 85112 var argLength = arguments.length; 85113 85114 t = 0; 85115 85116 if ( 85117 this._lookUpTableQuadratic.length === 0 || 85118 this._lutQuadraticDetail !== this._pInst._curveDetail 85119 ) { 85120 this._lookUpTableQuadratic = []; 85121 this._lutQuadraticDetail = this._pInst._curveDetail; 85122 var step = 1 / this._lutQuadraticDetail; 85123 var start = 0; 85124 var end = 1; 85125 var j = 0; 85126 while (start < 1) { 85127 t = parseFloat(start.toFixed(6)); 85128 this._lookUpTableQuadratic[j] = this._quadraticCoefficients(t); 85129 if (end.toFixed(6) === step.toFixed(6)) { 85130 t = parseFloat(end.toFixed(6)) + parseFloat(start.toFixed(6)); 85131 ++j; 85132 this._lookUpTableQuadratic[j] = this._quadraticCoefficients(t); 85133 break; 85134 } 85135 start += step; 85136 end -= step; 85137 ++j; 85138 } 85139 } 85140 85141 var LUTLength = this._lookUpTableQuadratic.length; 85142 85143 if (argLength === 4) { 85144 this.isQuadratic = true; 85145 85146 w_x = [ 85147 this.immediateMode._quadraticVertex[0], 85148 arguments.length <= 0 ? undefined : arguments[0], 85149 arguments.length <= 2 ? undefined : arguments[2] 85150 ]; 85151 w_y = [ 85152 this.immediateMode._quadraticVertex[1], 85153 arguments.length <= 1 ? undefined : arguments[1], 85154 arguments.length <= 3 ? undefined : arguments[3] 85155 ]; 85156 85157 for (i = 0; i < LUTLength; i++) { 85158 _x = 85159 w_x[0] * this._lookUpTableQuadratic[i][0] + 85160 w_x[1] * this._lookUpTableQuadratic[i][1] + 85161 w_x[2] * this._lookUpTableQuadratic[i][2]; 85162 _y = 85163 w_y[0] * this._lookUpTableQuadratic[i][0] + 85164 w_y[1] * this._lookUpTableQuadratic[i][1] + 85165 w_y[2] * this._lookUpTableQuadratic[i][2]; 85166 this.vertex(_x, _y); 85167 } 85168 85169 this.immediateMode._quadraticVertex[0] = 85170 arguments.length <= 2 ? undefined : arguments[2]; 85171 this.immediateMode._quadraticVertex[1] = 85172 arguments.length <= 3 ? undefined : arguments[3]; 85173 } else if (argLength === 6) { 85174 this.isQuadratic = true; 85175 85176 w_x = [ 85177 this.immediateMode._quadraticVertex[0], 85178 arguments.length <= 0 ? undefined : arguments[0], 85179 arguments.length <= 3 ? undefined : arguments[3] 85180 ]; 85181 w_y = [ 85182 this.immediateMode._quadraticVertex[1], 85183 arguments.length <= 1 ? undefined : arguments[1], 85184 arguments.length <= 4 ? undefined : arguments[4] 85185 ]; 85186 w_z = [ 85187 this.immediateMode._quadraticVertex[2], 85188 arguments.length <= 2 ? undefined : arguments[2], 85189 arguments.length <= 5 ? undefined : arguments[5] 85190 ]; 85191 85192 for (i = 0; i < LUTLength; i++) { 85193 _x = 85194 w_x[0] * this._lookUpTableQuadratic[i][0] + 85195 w_x[1] * this._lookUpTableQuadratic[i][1] + 85196 w_x[2] * this._lookUpTableQuadratic[i][2]; 85197 _y = 85198 w_y[0] * this._lookUpTableQuadratic[i][0] + 85199 w_y[1] * this._lookUpTableQuadratic[i][1] + 85200 w_y[2] * this._lookUpTableQuadratic[i][2]; 85201 _z = 85202 w_z[0] * this._lookUpTableQuadratic[i][0] + 85203 w_z[1] * this._lookUpTableQuadratic[i][1] + 85204 w_z[2] * this._lookUpTableQuadratic[i][2]; 85205 this.vertex(_x, _y, _z); 85206 } 85207 85208 this.immediateMode._quadraticVertex[0] = 85209 arguments.length <= 3 ? undefined : arguments[3]; 85210 this.immediateMode._quadraticVertex[1] = 85211 arguments.length <= 4 ? undefined : arguments[4]; 85212 this.immediateMode._quadraticVertex[2] = 85213 arguments.length <= 5 ? undefined : arguments[5]; 85214 } 85215 } 85216 }; 85217 85218 _main.default.RendererGL.prototype.curveVertex = function() { 85219 var w_x = [];
85220 var w_y = []; 85221 var w_z = []; 85222 var t, _x, _y, _z, i; 85223 t = 0; 85224 var argLength = arguments.length; 85225 85226 if ( 85227 this._lookUpTableBezier.length === 0 || 85228 this._lutBezierDetail !== this._pInst._curveDetail 85229 ) { 85230 this._lookUpTableBezier = []; 85231 this._lutBezierDetail = this._pInst._curveDetail; 85232 var step = 1 / this._lutBezierDetail; 85233 var start = 0; 85234 var end = 1; 85235 var j = 0; 85236 while (start < 1) { 85237 t = parseFloat(start.toFixed(6)); 85238 this._lookUpTableBezier[j] = this._bezierCoefficients(t); 85239 if (end.toFixed(6) === step.toFixed(6)) { 85240 t = parseFloat(end.toFixed(6)) + parseFloat(start.toFixed(6)); 85241 ++j; 85242 this._lookUpTableBezier[j] = this._bezierCoefficients(t); 85243 break; 85244 } 85245 start += step; 85246 end -= step; 85247 ++j; 85248 } 85249 } 85250 85251 var LUTLength = this._lookUpTableBezier.length; 85252 85253 if (argLength === 2) { 85254 this.immediateMode._curveVertex.push( 85255 arguments.length <= 0 ? undefined : arguments[0] 85256 ); 85257 this.immediateMode._curveVertex.push( 85258 arguments.length <= 1 ? undefined : arguments[1] 85259 ); 85260 if (this.immediateMode._curveVertex.length === 8) { 85261 this.isCurve = true; 85262 w_x = this._bezierToCatmull([ 85263 this.immediateMode._curveVertex[0], 85264 this.immediateMode._curveVertex[2], 85265 this.immediateMode._curveVertex[4], 85266 this.immediateMode._curveVertex[6] 85267 ]); 85268 85269 w_y = this._bezierToCatmull([ 85270 this.immediateMode._curveVertex[1], 85271 this.immediateMode._curveVertex[3], 85272 this.immediateMode._curveVertex[5], 85273 this.immediateMode._curveVertex[7] 85274 ]); 85275 85276 for (i = 0; i < LUTLength; i++) { 85277 _x = 85278 w_x[0] * this._lookUpTableBezier[i][0] + 85279 w_x[1] * this._lookUpTableBezier[i][1] + 85280 w_x[2] * this._lookUpTableBezier[i][2] + 85281 w_x[3] * this._lookUpTableBezier[i][3]; 85282 _y = 85283 w_y[0] * this._lookUpTableBezier[i][0] + 85284 w_y[1] * this._lookUpTableBezier[i][1] + 85285 w_y[2] * this._lookUpTableBezier[i][2] + 85286 w_y[3] * this._lookUpTableBezier[i][3]; 85287 this.vertex(_x, _y); 85288 } 85289 for (i = 0; i < argLength; i++) { 85290 this.immediateMode._curveVertex.shift(); 85291 } 85292 } 85293 } else if (argLength === 3) { 85294 this.immediateMode._curveVertex.push( 85295 arguments.length <= 0 ? undefined : arguments[0] 85296 ); 85297 this.immediateMode._curveVertex.push( 85298 arguments.length <= 1 ? undefined : arguments[1] 85299 ); 85300 this.immediateMode._curveVertex.push( 85301 arguments.length <= 2 ? undefined : arguments[2] 85302 ); 85303 if (this.immediateMode._curveVertex.length === 12) { 85304 this.isCurve = true; 85305 w_x = this._bezierToCatmull([ 85306 this.immediateMode._curveVertex[0], 85307 this.immediateMode._curveVertex[3], 85308 this.immediateMode._curveVertex[6], 85309 this.immediateMode._curveVertex[9] 85310 ]); 85311 85312 w_y = this._bezierToCatmull([ 85313 this.immediateMode._curveVertex[1], 85314 this.immediateMode._curveVertex[4], 85315 this.immediateMode._curveVertex[7], 85316 this.immediateMode._curveVertex[10] 85317 ]); 85318 85319 w_z = this._bezierToCatmull([ 85320 this.immediateMode._curveVertex[2], 85321 this.immediateMode._curveVertex[5], 85322 this.immediateMode._curveVertex[8], 85323 this.immediateMode._curveVertex[11] 85324 ]); 85325 85326 for (i = 0; i < LUTLength; i++) { 85327 _x = 85328 w_x[0] * this._lookUpTableBezier[i][0] + 85329 w_x[1] * this._lookUpTableBezier[i][1] + 85330 w_x[2] * this._lookUpTableBezier[i][2] + 85331 w_x[3] * this._lookUpTableBezier[i][3]; 85332 _y = 85333 w_y[0] * this._lookUpTableBezier[i][0] + 85334 w_y[1] * this._lookUpTableBezier[i][1] + 85335 w_y[2] * this._lookUpTableBezier[i][2] + 85336 w_y[3] * this._lookUpTableBezier[i][3]; 85337 _z = 85338 w_z[0] * this._lookUpTableBezier[i][0] + 85339 w_z[1] * this._lookUpTableBezier[i][1] + 85340 w_z[2] * this._lookUpTableBezier[i][2] + 85341 w_z[3] * this._lookUpTableBezier[i][3]; 85342 this.vertex(_x, _y, _z); 85343 } 85344 for (i = 0; i < argLength; i++) { 85345 this.immediateMode._curveVertex.shift(); 85346 } 85347 } 85348 } 85349 }; 85350 85351 _main.default.RendererGL.prototype.image = function( 85352 img, 85353 sx, 85354 sy, 85355 sWidth, 85356 sHeight, 85357 dx, 85358 dy, 85359 dWidth, 85360 dHeight 85361 ) { 85362 if (this._isErasing) { 85363 this.blendMode(this._cachedBlendMode); 85364 } 85365 85366 this._pInst.push(); 85367 85368 this._pInst.noLights(); 85369 85370 this._pInst.texture(img); 85371 this._pInst.textureMode(constants.NORMAL); 85372 85373 var u0 = 0; 85374 if (sx <= img.width) { 85375 u0 = sx / img.width; 85376 } 85377 85378 var u1 = 1; 85379 if (sx + sWidth <= img.width) { 85380 u1 = (sx + sWidth) / img.width; 85381 } 85382 85383 var v0 = 0; 85384 if (sy <= img.height) { 85385 v0 = sy / img.height; 85386 } 85387 85388 var v1 = 1; 85389 if (sy + sHeight <= img.height) { 85390 v1 = (sy + sHeight) / img.height; 85391 } 85392 85393 this.beginShape(); 85394 this.vertex(dx, dy, 0, u0, v0); 85395 this.vertex(dx + dWidth, dy, 0, u1, v0);
85396 this.vertex(dx + dWidth, dy + dHeight, 0, u1, v1); 85397 this.vertex(dx, dy + dHeight, 0, u0, v1); 85398 this.endShape(constants.CLOSE); 85399 85400 this._pInst.pop(); 85401 85402 if (this._isErasing) { 85403 this.blendMode(constants.REMOVE); 85404 } 85405 }; 85406 var _default = _main.default; 85407 exports.default = _default; 85408 }, 85409 { '../core/constants': 48, '../core/main': 59, './p5.Geometry': 108 } 85410 ], 85411 103: [ 85412 function(_dereq_, module, exports) { 85413 'use strict'; 85414 function _typeof(obj) { 85415 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') { 85416 _typeof = function _typeof(obj) { 85417 return typeof obj; 85418 }; 85419 } else { 85420 _typeof = function _typeof(obj) { 85421 return obj && 85422 typeof Symbol === 'function' && 85423 obj.constructor === Symbol && 85424 obj !== Symbol.prototype 85425 ? 'symbol' 85426 : typeof obj; 85427 }; 85428 } 85429 return _typeof(obj); 85430 } 85431 Object.defineProperty(exports, '__esModule', { value: true }); 85432 exports.default = void 0; 85433 85434 var _main = _interopRequireDefault(_dereq_('../core/main')); 85435 var constants = _interopRequireWildcard(_dereq_('../core/constants')); 85436 function _getRequireWildcardCache() { 85437 if (typeof WeakMap !== 'function') return null; 85438 var cache = new WeakMap(); 85439 _getRequireWildcardCache = function _getRequireWildcardCache() { 85440 return cache; 85441 }; 85442 return cache; 85443 } 85444 function _interopRequireWildcard(obj) { 85445 if (obj && obj.__esModule) { 85446 return obj; 85447 } 85448 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) { 85449 return { default: obj }; 85450 } 85451 var cache = _getRequireWildcardCache(); 85452 if (cache && cache.has(obj)) { 85453 return cache.get(obj); 85454 } 85455 var newObj = {}; 85456 var hasPropertyDescriptor = 85457 Object.defineProperty && Object.getOwnPropertyDescriptor; 85458 for (var key in obj) { 85459 if (Object.prototype.hasOwnProperty.call(obj, key)) { 85460 var desc = hasPropertyDescriptor 85461 ? Object.getOwnPropertyDescriptor(obj, key) 85462 : null; 85463 if (desc && (desc.get || desc.set)) { 85464 Object.defineProperty(newObj, key, desc); 85465 } else { 85466 newObj[key] = obj[key]; 85467 } 85468 } 85469 } 85470 newObj.default = obj; 85471 if (cache) { 85472 cache.set(obj, newObj); 85473 } 85474 return newObj; 85475 } 85476 function _interopRequireDefault(obj) { 85477 return obj && obj.__esModule ? obj : { default: obj }; 85478 } /** // implementation based on three.js 'orbitControls': 85479 * @module Lights, Camera 85480 * @submodule Interaction 85481 * @for p5 85482 * @requires core 85483 */ /** 85484 * Allows movement around a 3D sketch using a mouse or trackpad. Left-clicking 85485 * and dragging will rotate the camera position about the center of the sketch, 85486 * right-clicking and dragging will pan the camera position without rotation, 85487 * and using the mouse wheel (scrolling) will move the camera closer or further 85488 * from the center of the sketch. This function can be called with parameters 85489 * dictating sensitivity to mouse movement along the X and Y axes. Calling 85490 * this function without parameters is equivalent to calling orbitControl(1,1). 85491 * To reverse direction of movement in either axis, enter a negative number 85492 * for sensitivity. 85493 * @method orbitControl 85494 * @for p5 85495 * @param {Number} [sensitivityX] sensitivity to mouse movement along X axis 85496 * @param {Number} [sensitivityY] sensitivity to mouse movement along Y axis 85497 * @param {Number} [sensitivityZ] sensitivity to scroll movement along Z axis 85498 * @chainable 85499 * @example 85500 * <div> 85501 * <code> 85502 * function setup() { 85503 * createCanvas(100, 100, WEBGL); 85504 * normalMaterial(); 85505 * } 85506 * function draw() { 85507 * background(200); 85508 * orbitControl(); 85509 * rotateY(0.5); 85510 * box(30, 50); 85511 * } 85512 * </code> 85513 * </div> 85514 * 85515 * @alt 85516 * Camera orbits around a box when mouse is hold-clicked & then moved. 85517 */ 85518 // https://github.com/mrdoob/three.js/blob/dev/examples/js/control
85518s/OrbitControls.js 85519 _main.default.prototype.orbitControl = function( 85520 sensitivityX, 85521 sensitivityY, 85522 sensitivityZ 85523 ) { 85524 this._assert3d('orbitControl'); 85525 _main.default._validateParameters('orbitControl', arguments); 85526 85527 // If the mouse is not in bounds of the canvas, disable all behaviors: 85528 var mouseInCanvas = 85529 this.mouseX < this.width && 85530 this.mouseX > 0 && 85531 this.mouseY < this.height && 85532 this.mouseY > 0; 85533 if (!mouseInCanvas) return; 85534 85535 var cam = this._renderer._curCamera; 85536 85537 if (typeof sensitivityX === 'undefined') { 85538 sensitivityX = 1; 85539 } 85540 if (typeof sensitivityY === 'undefined') { 85541 sensitivityY = sensitivityX; 85542 } 85543 if (typeof sensitivityZ === 'undefined') { 85544 sensitivityZ = 0.5; 85545 } 85546 85547 // default right-mouse and mouse-wheel behaviors (context menu and scrolling, 85548 // respectively) are disabled here to allow use of those events for panning and 85549 // zooming 85550 85551 // disable context menu for canvas element and add 'contextMenuDisabled' 85552 // flag to p5 instance 85553 if (this.contextMenuDisabled !== true) { 85554 this.canvas.oncontextmenu = function() { 85555 return false; 85556 }; 85557 this._setProperty('contextMenuDisabled', true); 85558 } 85559 85560 // disable default scrolling behavior on the canvas element and add 85561 // 'wheelDefaultDisabled' flag to p5 instance 85562 if (this.wheelDefaultDisabled !== true) { 85563 this.canvas.onwheel = function() { 85564 return false; 85565 }; 85566 this._setProperty('wheelDefaultDisabled', true); 85567 } 85568 85569 var scaleFactor = this.height < this.width ? this.height : this.width; 85570 85571 // ZOOM if there is a change in mouseWheelDelta 85572 if (this._mouseWheelDeltaY !== this._pmouseWheelDeltaY) { 85573 // zoom according to direction of mouseWheelDeltaY rather than value 85574 if (this._mouseWheelDeltaY > 0) { 85575 this._renderer._curCamera._orbit(0, 0, sensitivityZ * scaleFactor); 85576 } else { 85577 this._renderer._curCamera._orbit(0, 0, -sensitivityZ * scaleFactor); 85578 } 85579 } 85580 85581 if (this.mouseIsPressed) { 85582 // ORBIT BEHAVIOR 85583 if (this.mouseButton === this.LEFT) { 85584 var deltaTheta = -sensitivityX * (this.mouseX - this.pmouseX) / scaleFactor; 85585 var deltaPhi = sensitivityY * (this.mouseY - this.pmouseY) / scaleFactor; 85586 this._renderer._curCamera._orbit(deltaTheta, deltaPhi, 0); 85587 } else if (this.mouseButton === this.RIGHT) { 85588 // PANNING BEHAVIOR along X/Z camera axes and restricted to X/Z plane 85589 // in world space 85590 var local = cam._getLocalAxes(); 85591 85592 // normalize portions along X/Z axes 85593 var xmag = Math.sqrt(local.x[0] * local.x[0] + local.x[2] * local.x[2]); 85594 if (xmag !== 0) { 85595 local.x[0] /= xmag; 85596 local.x[2] /= xmag; 85597 } 85598 85599 // normalize portions along X/Z axes 85600 var ymag = Math.sqrt(local.y[0] * local.y[0] + local.y[2] * local.y[2]); 85601 if (ymag !== 0) { 85602 local.y[0] /= ymag; 85603 local.y[2] /= ymag; 85604 } 85605 85606 // move along those vectors by amount controlled by mouseX, pmouseY 85607 var dx = -1 * sensitivityX * (this.mouseX - this.pmouseX); 85608 var dz = -1 * sensitivityY * (this.mouseY - this.pmouseY); 85609 85610 // restrict movement to XZ plane in world space 85611 cam.setPosition( 85612 cam.eyeX + dx * local.x[0] + dz * local.z[0], 85613 cam.eyeY, 85614 cam.eyeZ + dx * local.x[2] + dz * local.z[2] 85615 ); 85616 } 85617 } 85618 return this; 85619 }; 85620 85621 /** 85622 * debugMode() helps visualize 3D space by adding a grid to indicate where the 85623 * âgroundâ is in a sketch and an axes icon which indicates the +X, +Y, and +Z 85624 * directions. This function can be called without parameters to create a 85625 * default grid and axes icon, or it can be called according to the examples 85626 * above to customize the size and position of the grid and/or axes icon. The 85627 * grid is drawn using the most recently set stroke color and weight. To 85628 * specify these parameters, add a call to stroke() and strokeWeight(
85628) 85629 * just before the end of the draw() loop. 85630 * 85631 * By default, the grid will run through the origin (0,0,0) of the sketch 85632 * along the XZ plane 85633 * and the axes icon will be offset from the origin. Both the grid and axes 85634 * icon will be sized according to the current canvas size. Note that because the 85635 * grid runs parallel to the default camera view, it is often helpful to use 85636 * debugMode along with orbitControl to allow full view of the grid. 85637 * @method debugMode 85638 * @example 85639 * <div> 85640 * <code> 85641 * function setup() { 85642 * createCanvas(100, 100, WEBGL); 85643 * camera(0, -30, 100, 0, 0, 0, 0, 1, 0); 85644 * normalMaterial(); 85645 * debugMode(); 85646 * } 85647 * 85648 * function draw() { 85649 * background(200); 85650 * orbitControl(); 85651 * box(15, 30); 85652 * // Press the spacebar to turn debugMode off! 85653 * if (keyIsDown(32)) { 85654 * noDebugMode(); 85655 * } 85656 * } 85657 * </code> 85658 * </div> 85659 * @alt 85660 * a 3D box is centered on a grid in a 3D sketch. an icon 85661 * indicates the direction of each axis: a red line points +X, 85662 * a green line +Y, and a blue line +Z. the grid and icon disappear when the 85663 * spacebar is pressed. 85664 * 85665 * @example 85666 * <div> 85667 * <code> 85668 * function setup() { 85669 * createCanvas(100, 100, WEBGL); 85670 * camera(0, -30, 100, 0, 0, 0, 0, 1, 0); 85671 * normalMaterial(); 85672 * debugMode(GRID); 85673 * } 85674 * 85675 * function draw() { 85676 * background(200); 85677 * orbitControl(); 85678 * box(15, 30); 85679 * } 85680 * </code> 85681 * </div> 85682 * @alt 85683 * a 3D box is centered on a grid in a 3D sketch. 85684 * 85685 * @example 85686 * <div> 85687 * <code> 85688 * function setup() { 85689 * createCanvas(100, 100, WEBGL); 85690 * camera(0, -30, 100, 0, 0, 0, 0, 1, 0); 85691 * normalMaterial(); 85692 * debugMode(AXES); 85693 * } 85694 * 85695 * function draw() { 85696 * background(200); 85697 * orbitControl(); 85698 * box(15, 30); 85699 * } 85700 * </code> 85701 * </div> 85702 * @alt 85703 * a 3D box is centered in a 3D sketch. an icon 85704 * indicates the direction of each axis: a red line points +X, 85705 * a green line +Y, and a blue line +Z. 85706 * 85707 * @example 85708 * <div> 85709 * <code> 85710 * function setup() { 85711 * createCanvas(100, 100, WEBGL); 85712 * camera(0, -30, 100, 0, 0, 0, 0, 1, 0); 85713 * normalMaterial(); 85714 * debugMode(GRID, 100, 10, 0, 0, 0); 85715 * } 85716 * 85717 * function draw() { 85718 * background(200); 85719 * orbitControl(); 85720 * box(15, 30); 85721 * } 85722 * </code> 85723 * </div> 85724 * @alt 85725 * a 3D box is centered on a grid in a 3D sketch 85726 * 85727 * @example 85728 * <div> 85729 * <code> 85730 * function setup() { 85731 * createCanvas(100, 100, WEBGL); 85732 * camera(0, -30, 100, 0, 0, 0, 0, 1, 0); 85733 * normalMaterial(); 85734 * debugMode(100, 10, 0, 0, 0, 20, 0, -40, 0); 85735 * } 85736 * 85737 * function draw() { 85738 * noStroke(); 85739 * background(200); 85740 * orbitControl(); 85741 * box(15, 30); 85742 * // set the stroke color and weight for the grid! 85743 * stroke(255, 0, 150); 85744 * strokeWeight(0.8); 85745 * } 85746 * </code> 85747 * </div> 85748 * @alt 85749 * a 3D box is centered on a grid in a 3D sketch. an icon 85750 * indicates the direction of each axis: a red line points +X, 85751 * a green line +Y, and a blue line +Z. 85752 */ 85753 85754 /** 85755 * @method debugMode 85756 * @param {Constant} mode either GRID or AXES 85757 */ 85758 85759 /** 85760 * @method debugMode 85761 * @param {Constant} mode 85762 * @param {Number} [gridSize] size of one side of the grid 85763 * @param {Number} [gridDivisions] number of divisions in the grid 85764 * @param {Number} [xOff] X axis offset from origin (0,0,0) 85765 * @param {Number} [yOff] Y axis offset from origin (0,0,0) 85766 * @param {Number} [zOff] Z axis offset from origin (0,0,0) 85767 */ 85768 85769 /** 85770 * @method debugMode 85771 * @param {Constant} mode 85772 * @param {Number} [axesSize] size of axes icon 85773 * @param {Number} [xOff] 85774 * @param {Number} [yOff] 85775 * @param {Number} [zOff] 85776 */ 85777 85778 /** 85779 * @method debugMode 85780 * @param {Number} [gridSize] 85781 * @param {Number} [gridDivisions] 85782 * @param {Number} [gridXOff] 85783 * @param {Number} [gridYOff] 85784 * @param {Number} [gridZOff] 85785 * @param {Number} [axesSize] 85786 * @param {Number} [axesXOff] 85787 * @param {Number} [axesYOff] 85788 * @param {Number} [axesZOff] 85789 */ 85790 85791 _main.default.prototype.debugMode = function() { 85792 this._assert3d('debugMode'); 85793 for ( 85794 var _len = arguments.length, args = new Array(_len), _key = 0; 85795 _key < _len; 85796 _key++ 85797 ) { 85798 args[_key] = arguments[_key]; 85799 } 85800 _main.default._validateParameters('debugMode', args); 85801 85802 // start by removing existing 'post' registered debug methods 85803 for (var i = this._registeredMethods.post.length - 1; i >= 0; i--) { 85804 // test for equality... 85805 if ( 85806 this._registeredMethods.post[i].toString() === this._grid().toString() || 85807 this._registeredMethods.post[i].toString() === this._axesIcon().toString() 85808 ) { 85809 this._registeredMethods.post.splice(i, 1); 85810 } 85811 } 85812 85813 // then add new debugMode functions according to the argument list 85814 if (args[0] === constants.GRID) { 85815 this.registerMethod( 85816 'post', 85817 this._grid.call(this, args[1], args[2], args[3], args[4], args[5]) 85818 ); 85819 } else if (args[0] === constants.AXES) { 85820 this.registerMethod( 85821 'post', 85822 this._axesIcon.call(this, args[1], args[2], args[3], args[4]) 85823 ); 85824 } else { 85825 this.registerMethod( 85826 'post', 85827 this._grid.call(this, args[0], args[1], args[2], args[3], args[4]) 85828 ); 85829 85830 this.registerMethod( 85831 'post', 85832 this._axesIcon.call(this, args[5], args[6], args[7], args[8]) 85833 ); 85834 } 85835 }; 85836 85837 /** 85838 * Turns off debugMode() in a 3D sketch. 85839 * @method noDebugMode 85840 * @example 85841 * <div> 85842 * <code> 85843 * function setup() { 85844 * createCanvas(100, 100, WEBGL); 85845 * camera(0, -30, 100, 0, 0, 0, 0, 1, 0); 85846 * normalMaterial(); 85847 * debugMode(); 85848 * } 85849 * 85850 * function draw() { 85851 * background(200); 85852 * orbitControl(); 85853 * box(15, 30); 85854 * // Press the spacebar to turn debugMode off! 85855 * if (keyIsDown(32)) { 85856 * noDebugMode(); 85857 * } 85858 * } 85859 * </code> 85860 * </div> 85861 * @alt 85862 * a 3D box is centered on a grid in a 3D sketch. an icon 85863 * indicates the direction of each axis: a red line points +X, 85864 * a green line +Y, and a blue line +Z. the grid and icon disappear when the 85865 * spacebar is pressed. 85866 */ 85867 _main.default.prototype.noDebugMode = function() { 85868 this._assert3d('noDebugMode'); 85869 85870 // start by removing existing 'post' registered debug methods 85871 for (var i = this._registeredMethods.post.length - 1; i >= 0; i--) { 85872 // test for equality... 85873 if ( 85874 this._registeredMethods.post[i].toString() === this._grid().toString() || 85875 this._registeredMethods.post[i].toString() === this._axesIcon().toString() 85876 ) { 85877 this._registeredMethods.post.splice(i, 1); 85878 } 85879 } 85880 }; 85881 85882 /** 85883 * For use with debugMode 85884 * @private 85885 * @method _grid 85886 * @param {Number}
85886 [size] size of grid sides 85887 * @param {Number} [div] number of grid divisions 85888 * @param {Number} [xOff] offset of grid center from origin in X axis 85889 * @param {Number} [yOff] offset of grid center from origin in Y axis 85890 * @param {Number} [zOff] offset of grid center from origin in Z axis 85891 */ 85892 _main.default.prototype._grid = function(size, numDivs, xOff, yOff, zOff) { 85893 if (typeof size === 'undefined') { 85894 size = this.width / 2; 85895 } 85896 if (typeof numDivs === 'undefined') { 85897 // ensure at least 2 divisions 85898 numDivs = Math.round(size / 30) < 4 ? 4 : Math.round(size / 30); 85899 } 85900 if (typeof xOff === 'undefined') { 85901 xOff = 0; 85902 } 85903 if (typeof yOff === 'undefined') { 85904 yOff = 0; 85905 } 85906 if (typeof zOff === 'undefined') { 85907 zOff = 0; 85908 } 85909 85910 var spacing = size / numDivs; 85911 var halfSize = size / 2; 85912 85913 return function() { 85914 this.push(); 85915 this.stroke( 85916 this._renderer.curStrokeColor[0] * 255, 85917 this._renderer.curStrokeColor[1] * 255, 85918 this._renderer.curStrokeColor[2] * 255 85919 ); 85920 85921 this._renderer.uMVMatrix.set( 85922 this._renderer._curCamera.cameraMatrix.mat4[0], 85923 this._renderer._curCamera.cameraMatrix.mat4[1], 85924 this._renderer._curCamera.cameraMatrix.mat4[2], 85925 this._renderer._curCamera.cameraMatrix.mat4[3], 85926 this._renderer._curCamera.cameraMatrix.mat4[4], 85927 this._renderer._curCamera.cameraMatrix.mat4[5], 85928 this._renderer._curCamera.cameraMatrix.mat4[6], 85929 this._renderer._curCamera.cameraMatrix.mat4[7], 85930 this._renderer._curCamera.cameraMatrix.mat4[8], 85931 this._renderer._curCamera.cameraMatrix.mat4[9], 85932 this._renderer._curCamera.cameraMatrix.mat4[10], 85933 this._renderer._curCamera.cameraMatrix.mat4[11], 85934 this._renderer._curCamera.cameraMatrix.mat4[12], 85935 this._renderer._curCamera.cameraMatrix.mat4[13], 85936 this._renderer._curCamera.cameraMatrix.mat4[14], 85937 this._renderer._curCamera.cameraMatrix.mat4[15] 85938 ); 85939 85940 // Lines along X axis 85941 for (var q = 0; q <= numDivs; q++) { 85942 this.beginShape(this.LINES); 85943 this.vertex(-halfSize + xOff, yOff, q * spacing - halfSize + zOff); 85944 this.vertex(+halfSize + xOff, yOff, q * spacing - halfSize + zOff); 85945 this.endShape(); 85946 } 85947 85948 // Lines along Z axis 85949 for (var i = 0; i <= numDivs; i++) { 85950 this.beginShape(this.LINES); 85951 this.vertex(i * spacing - halfSize + xOff, yOff, -halfSize + zOff); 85952 this.vertex(i * spacing - halfSize + xOff, yOff, +halfSize + zOff); 85953 this.endShape(); 85954 } 85955 85956 this.pop(); 85957 }; 85958 }; 85959 85960 /** 85961 * For use with debugMode 85962 * @private 85963 * @method _axesIcon 85964 * @param {Number} [size] size of axes icon lines 85965 * @param {Number} [xOff] offset of icon from origin in X axis 85966 * @param {Number} [yOff] offset of icon from origin in Y axis 85967 * @param {Number} [zOff] offset of icon from origin in Z axis 85968 */ 85969 _main.default.prototype._axesIcon = function(size, xOff, yOff, zOff) { 85970 if (typeof size === 'undefined') { 85971 size = this.width / 20 > 40 ? this.width / 20 : 40; 85972 } 85973 if (typeof xOff === 'undefined') { 85974 xOff = -this.width / 4; 85975 } 85976 if (typeof yOff === 'undefined') { 85977 yOff = xOff; 85978 } 85979 if (typeof zOff === 'undefined') { 85980 zOff = xOff; 85981 } 85982 85983 return function() { 85984 this.push(); 85985 this._renderer.uMVMatrix.set( 85986 this._renderer._curCamera.cameraMatrix.mat4[0], 85987 this._renderer._curCamera.cameraMatrix.mat4[1], 85988 this._renderer._curCamera.cameraMatrix.mat4[2], 85989 this._renderer._curCamera.cameraMatrix.mat4[3], 85990 this._renderer._curCamera.cameraMatrix.mat4[4], 85991 this._renderer._curCamera.cameraMatrix.mat4[5], 85992 this._renderer._curCamera.cameraMatrix.mat4[6], 85993 this._renderer._curCamera.cameraMatrix.mat4[7], 85994 this._renderer._curCamera.cameraMatrix.mat4[8], 85995 this._renderer._curCamera.cameraMatrix.mat4[9], 85996 this._renderer._curCamera.cameraMatrix.mat4[10], 85997 this._renderer._curCamera.cameraMatrix.mat4[11], 85998 this._renderer._curCamera.cameraMatrix.mat4[12], 85999 this._renderer._curCamera.cameraMatrix.mat4[13], 86000 this._renderer._curCamera.cameraMatrix.mat4[14], 86001 this._renderer._curCamera.cameraMatrix.mat4[15] 86002 ); 86003 86004 // X axis 86005 this.strokeWeight(2); 86006 this.stroke(255, 0, 0); 86007 this.beginShape(this.LINES); 86008 this.vertex(xOff, yOff, zOff); 86009 this.vertex(xOff + size, yOff, zOff); 86010 this.endShape(); 86011 // Y axis 86012 this.stroke(0, 255, 0); 86013 this.beginShape(this.LINES); 86014 this.vertex(xOff, yOff, zOff); 86015 this.vertex(xOff, yOff + size, zOff); 86016 this.endShape(); 86017 // Z axis 86018 this.stroke(0, 0, 255); 86019 this.beginShape(this.LINES); 86020 this.vertex(xOff, yOff, zOff); 86021 this.vertex(xOff, yOff, zOff + size); 86022 this.endShape(); 86023 this.pop(); 86024 }; 86025 }; 86026 var _default = _main.default; 86027 exports.default = _default; 86028 }, 86029 { '../core/constants': 48, '../core/main': 59 } 86030 ], 86031 104: [
86032 function(_dereq_, module, exports) { 86033 'use strict'; 86034 Object.defineProperty(exports, '__esModule', { value: true }); 86035 exports.default = void 0; 86036 86037 var _main = _interopRequireDefault(_dereq_('../core/main')); 86038 function _interopRequireDefault(obj) { 86039 return obj && obj.__esModule ? obj : { default: obj }; 86040 } /** 86041 * @method ambientLight 86042 * @param {String} value a color string 86043 * @chainable 86044 */ /** 86045 * @module Lights, Camera 86046 * @submodule Lights 86047 * @for p5 86048 * @requires core 86049 */ /** 86050 * Creates an ambient light with a color. Ambient light is light that comes from everywhere on the canvas. 86051 * It has no particular source. 86052 * @method ambientLight 86053 * @param {Number} v1 red or hue value relative to 86054 * the current color range 86055 * @param {Number} v2 green or saturation value 86056 * relative to the current color range 86057 * @param {Number} v3 blue or brightness value 86058 * relative to the current color range 86059 * @param {Number} [alpha] the alpha value 86060 * @chainable 86061 * 86062 * @example 86063 * <div> 86064 * <code> 86065 * createCanvas(100, 100, WEBGL); 86066 * ambientLight(0); 86067 * ambientMaterial(250); 86068 * sphere(40); 86069 * </code> 86070 * </div> 86071 * <div> 86072 * <code> 86073 * function setup() { 86074 * createCanvas(100, 100, WEBGL); 86075 * } 86076 * function draw() { 86077 * background(51); 86078 * ambientLight(100); // white light 86079 * ambientMaterial(255, 102, 94); // magenta material 86080 * box(30); 86081 * } 86082 * </code> 86083 * </div> 86084 * @alt 86085 * evenly distributed light across a sphere 86086 * evenly distributed light across a rotating sphere 86087 */ 86088 /** 86089 * @method ambientLight 86090 * @param {Number} gray a gray value 86091 * @param {Number} [alpha] 86092 * @chainable 86093 */ 86094 86095 /** 86096 * @method ambientLight 86097 * @param {Number[]} values an array containing the red,green,blue & 86098 * and alpha components of the color 86099 * @chainable 86100 */ 86101 86102 /** 86103 * @method ambientLight 86104 * @param {p5.Color} color the ambient light color 86105 * @chainable 86106 */ 86107 _main.default.prototype.ambientLight = function(v1, v2, v3, a) { 86108 this._assert3d('ambientLight'); 86109 _main.default._validateParameters('ambientLight', arguments); 86110 var color = this.color.apply(this, arguments); 86111 86112 this._renderer.ambientLightColors.push( 86113 color._array[0], 86114 color._array[1], 86115 color._array[2] 86116 ); 86117 86118 this._renderer._enableLighting = true; 86119 86120 return this; 86121 }; 86122 86123 /** 86124 * Set's the color of the specular highlight when using a specular material and 86125 * specular light. 86126 * 86127 * This method can be combined with specularMaterial() and shininess() 86128 * functions to set specular highlights. The default color is white, ie 86129 * (255, 255, 255), which is used if this method is not called before 86130 * specularMaterial(). If this method is called without specularMaterial(), 86131 * There will be no effect. 86132 * 86133 * Note: specularColor is equivalent to the processing function 86134 * <a href="https://processing.org/reference/lightSpecular_.html">lightSpecular</a>. 86135 * 86136 * @method specularColor 86137 * @param {Number} v1 red or hue value relative to 86138 * the current color range 86139 * @param {Number} v2 green or saturation value 86140 * relative to the current color range 86141 * @param {Number} v3 blue or brightness value 86142 * relative to the current color range 86143 * @chainable 86144 * @example 86145 * <div> 86146 * <code> 86147 * function setup() { 86148 * createCanvas(100, 100, WEBGL); 86149 * noStroke(); 86150 * } 86151 * 86152 * function draw() { 86153 * background(0); 86154 * shininess(20); 86155 * ambientLight(50); 86156 * specularColor(255, 0, 0); 86157 * pointLight(255, 0, 0, 0, -50, 50); 86158 * specularColor(0, 255, 0); 86159 * pointLight(0, 255, 0, 0, 50, 50); 86160 * specularMaterial(255); 86161 * sphere(40); 86162 * } 86163 * </code> 86164 * </div> 86165 * 86166 * @alt 86167 * different specular light sources from top and bottom of canvas 86168 */ 86169 86170 /** 86171 * @method specularColor 86172 * @param {String} value a color string 86173 * @chainable 86174 */ 86175 86176 /** 86177 * @method specularColor 86178 * @param {Number} gray a gray value 86179 * @chainable 86180 */ 86181 86182 /** 86183 * @method specularColor 86184 * @param {Number[]} values an array containing the red,green,blue & 86185 * and alpha components of the color 86186 * @chainable 86187 */ 86188 86189 /** 86190 * @method specularColor 86191 * @param {p5.Color} color the ambient light color 86192 * @chainable 86193 */ 86194 _main.default.prototype.specularColor = function(v1, v2, v3) { 86195 this._assert3d('specularColor'); 86196 _main.default._validateParameters('specularColor', arguments); 86197 var color = this.color.apply(this, arguments); 86198 86199 this._renderer.specularColors = [ 86200 color._array[0], 86201 color._array[1], 86202 color._array[2] 86203 ]; 86204 86205 return this; 86206 }; 86207 86208 /** 86209 * Creates a directional light with a color and a direction 86210 * 86211 * A maximum of 5 directionalLight can be active at one time 86212 * @method directionalLight 86213 * @param {Number} v1 red or hue value (depending on the current 86214 * color mode), 86215 * @param {Number} v2 green or saturation value 86216 * @param {Number} v3 blue or brightness value 86217 * @param {p5.Vector} position the direction of the light 86218 * @chainable 86219 * @example 86220 * <div> 86221 * <code> 86222 * function setup() { 86223 * createCanvas(100, 100, WEBGL); 86224 * } 86225 * function draw() { 86226 * background(0); 86227 * //move your mouse to change light direction 86228 * let dirX = (mouseX / width - 0.5) * 2; 86229 * let dirY = (mouseY / height - 0.5) * 2; 86230 * directionalLight(250, 250, 250, -dirX, -dirY, -1); 86231 * noStroke(); 86232 * sphere(40); 86233 * } 86234 * </code> 86235 * </div> 86236 * 86237 * @alt 86238 * light source on canvas changeable with mouse position 86239 */ 86240 86241 /** 86242 * @method directionalLight 86243 * @param {Number[]|String|p5.Color} color color Array, CSS color string, 86244 * or <a href="#/p5.Color">p5.Color</a> value 86245 * @param {Number} x x axis direction 86246 * @param {Number} y y axis direction 86247 * @param {Number} z z axis direction 86248 * @chainable 86249 */ 86250 86251 /** 86252 * @method directionalLight 86253 * @param {Number[]|String|p5.Color} color 86254 * @param {p5.Vector} position 86255 * @chainable 86256 */ 86257 86258 /** 86259 * @method directionalLight 86260 * @param {Number} v1 86261 * @param {Number} v2 86262 * @param {Number} v3 86263 * @param {Number} x 86264 * @param {Number} y 86265 * @param {Number} z 86266 * @chainable 86267 */ 86268 _main.default.prototype.directionalLight = function(v1, v2, v3, x, y, z) { 86269 this._assert3d('directionalLight'); 86270 _main.default._validateParameters('directionalLight', arguments); 86271 86272 //@TODO: check parameters number 86273 var color; 86274 if (v1 instanceof _main.default.Color) { 86275 color = v1; 86276 } else { 86277 color = this.color(v1, v2, v3); 86278 } 86279 86280 var _x, _y, _z; 86281 var v = arguments[arguments.length - 1]; 86282 if (typeof v === 'number') { 86283 _x = arguments[arguments.length - 3]; 86284 _y = arguments[arguments.length - 2]; 86285 _z = arguments[arguments.length - 1]; 86286 } else { 86287 _x = v.x; 86288 _y = v.y; 86289 _z = v.z; 86290 } 86291 86292 // normalize direction 86293 var l = Math.sqrt(_x * _x + _y * _y + _z * _z); 86294 this._renderer.directionalLightDirections.push(_x / l, _y / l, _z / l); 86295 86296 this._renderer.directionalLightDiffuseColors.push( 86297 color._array[0], 86298 color._array[1], 86299 color._array[2] 86300 ); 86301 86302 Array.prototype.push.apply( 86303 this._renderer.directionalLightSpecularColors, 86304 this._renderer.specularColors 86305 ); 86306 86307 this._renderer._enableLighting = true; 86308 86309 return this; 86310 }; 86311 86312 /** 86313 * Creates a point light with a color and a light position 86314 * 86315 * A maximum of 5 pointLight can be active at one time 86316 * @method pointLight 86317 * @param {Number} v1 red or hue value (depending on the current 86318 * color mode), 86319 * @param {Number} v2 green or saturation value 86320 * @param {Number} v3 blue or brightness value 86321 * @param {Number} x x axis position 86322 * @param {Number} y y axis position 86323 * @param {Number} z z axis position 86324 * @chainable 86325 * @example 86326 * <div> 86327 * <code> 86328 * function setup() { 86329 * createCanvas(100, 100, WEBGL); 86330 * } 86331 * function draw() { 86332 * background(0); 86333 * //move your mouse to change light position 86334 * let locX = mouseX - width / 2;
86335 * let locY = mouseY - height / 2; 86336 * // to set the light position, 86337 * // think of the world's coordinate as: 86338 * // -width/2,-height/2 -------- width/2,-height/2 86339 * // | | 86340 * // | 0,0 | 86341 * // | | 86342 * // -width/2,height/2--------width/2,height/2 86343 * pointLight(250, 250, 250, locX, locY, 50); 86344 * noStroke(); 86345 * sphere(40); 86346 * } 86347 * </code> 86348 * </div> 86349 * 86350 * @alt 86351 * spot light on canvas changes position with mouse 86352 */ 86353 86354 /** 86355 * @method pointLight 86356 * @param {Number} v1 86357 * @param {Number} v2 86358 * @param {Number} v3 86359 * @param {p5.Vector} position the position of the light 86360 * @chainable 86361 */ 86362 86363 /** 86364 * @method pointLight 86365 * @param {Number[]|String|p5.Color} color color Array, CSS color string, 86366 * or <a href="#/p5.Color">p5.Color</a> value 86367 * @param {Number} x 86368 * @param {Number} y 86369 * @param {Number} z 86370 * @chainable 86371 */ 86372 86373 /** 86374 * @method pointLight 86375 * @param {Number[]|String|p5.Color} color 86376 * @param {p5.Vector} position 86377 * @chainable 86378 */ 86379 _main.default.prototype.pointLight = function(v1, v2, v3, x, y, z) { 86380 this._assert3d('pointLight'); 86381 _main.default._validateParameters('pointLight', arguments); 86382 86383 //@TODO: check parameters number 86384 var color; 86385 if (v1 instanceof _main.default.Color) { 86386 color = v1; 86387 } else { 86388 color = this.color(v1, v2, v3); 86389 } 86390 86391 var _x, _y, _z; 86392 var v = arguments[arguments.length - 1]; 86393 if (typeof v === 'number') { 86394 _x = arguments[arguments.length - 3]; 86395 _y = arguments[arguments.length - 2]; 86396 _z = arguments[arguments.length - 1]; 86397 } else { 86398 _x = v.x; 86399 _y = v.y; 86400 _z = v.z; 86401 } 86402 86403 this._renderer.pointLightPositions.push(_x, _y, _z); 86404 this._renderer.pointLightDiffuseColors.push( 86405 color._array[0], 86406 color._array[1], 86407 color._array[2] 86408 ); 86409 86410 Array.prototype.push.apply( 86411 this._renderer.pointLightSpecularColors, 86412 this._renderer.specularColors 86413 ); 86414 86415 this._renderer._enableLighting = true; 86416 86417 return this; 86418 }; 86419 86420 /** 86421 * 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. 86422 * @method lights 86423 * @chainable 86424 * @example 86425 * <div> 86426 * <code> 86427 * function setup() { 86428 * createCanvas(100, 100, WEBGL); 86429 * } 86430 * function draw() { 86431 * background(0); 86432 * lights(); 86433 * rotateX(millis() / 1000); 86434 * rotateY(millis() / 1000); 86435 * rotateZ(millis() / 1000); 86436 * box(); 86437 * } 86438 * </code> 86439 * </div> 86440 * 86441 * @alt 86442 * the light is partially ambient and partially directional 86443 */ 86444 _main.default.prototype.lights = function() { 86445 this._assert3d('lights'); 86446 this.ambientLight(128, 128, 128); 86447 this.directionalLight(128, 128, 128, 0, 0, -1); 86448 return this; 86449 }; 86450 86451 /** 86452 * Sets the falloff rates for point lights. It affects only the elements which are created after it in the code. 86453 * The default value is lightFalloff(1.0, 0.0, 0.0), and the parameters are used to calculate the falloff with the following equation: 86454 * 86455 * d = distance from light position to vertex position 86456 * 86457 * falloff = 1 / (CONSTANT + d \* LINEAR + ( d \* d ) \* QUADRATIC) 86458 * 86459 * @method lightFalloff 86460 * @param {Number} constant constant value for determining falloff 86461 * @param {Number} linear linear value for determining falloff 86462 * @param {Number} quadratic quadratic value for determining falloff 86463 * @chainable 86464 * @example 86465 * <div> 86466 * <code> 86467 * function setup() { 86468 * createCanvas(100, 100, WEBGL); 86469 * noStroke(); 86470 * } 86471 * function draw() { 86472 * background(0); 86473 * let locX = mouseX - width / 2;
86474 * let locY = mouseY - height / 2; 86475 * translate(-25, 0, 0); 86476 * lightFalloff(1, 0, 0); 86477 * pointLight(250, 250, 250, locX, locY, 50); 86478 * sphere(20); 86479 * translate(50, 0, 0); 86480 * lightFalloff(0.9, 0.01, 0); 86481 * pointLight(250, 250, 250, locX, locY, 50); 86482 * sphere(20); 86483 * } 86484 * </code> 86485 * </div> 86486 * 86487 * @alt 86488 * Two spheres with different falloff values show different intensity of light 86489 */ 86490 _main.default.prototype.lightFalloff = function( 86491 constantAttenuation, 86492 linearAttenuation, 86493 quadraticAttenuation 86494 ) { 86495 this._assert3d('lightFalloff'); 86496 _main.default._validateParameters('lightFalloff', arguments); 86497 86498 if (constantAttenuation < 0) { 86499 constantAttenuation = 0; 86500 console.warn( 86501 'Value of constant argument in lightFalloff() should be never be negative. Set to 0.' 86502 ); 86503 } 86504 86505 if (linearAttenuation < 0) { 86506 linearAttenuation = 0; 86507 console.warn( 86508 'Value of linear argument in lightFalloff() should be never be negative. Set to 0.' 86509 ); 86510 } 86511 86512 if (quadraticAttenuation < 0) { 86513 quadraticAttenuation = 0; 86514 console.warn( 86515 'Value of quadratic argument in lightFalloff() should be never be negative. Set to 0.' 86516 ); 86517 } 86518 86519 if ( 86520 constantAttenuation === 0 && 86521 linearAttenuation === 0 && 86522 quadraticAttenuation === 0 86523 ) { 86524 constantAttenuation = 1; 86525 console.warn( 86526 'Either one of the three arguments in lightFalloff() should be greater than zero. Set constant argument to 1.' 86527 ); 86528 } 86529 86530 this._renderer.constantAttenuation = constantAttenuation; 86531 this._renderer.linearAttenuation = linearAttenuation; 86532 this._renderer.quadraticAttenuation = quadraticAttenuation; 86533 86534 return this; 86535 }; 86536 86537 /** 86538 * Creates a spotlight with a given color, position, direction of light, 86539 * angle and concentration. Here, angle refers to the opening or aperture 86540 * of the cone of the spotlight, and concentration is used to focus the 86541 * light towards the center. Both angle and concentration are optional, but if 86542 * you want to provide concentration, you will also have to specify the angle. 86543 * 86544 * A maximum of 5 spotLight can be active at one time 86545 * @method spotLight 86546 * @param {Number} v1 red or hue value (depending on the current 86547 * color mode), 86548 * @param {Number} v2 green or saturation value 86549 * @param {Number} v3 blue or brightness value 86550 * @param {Number} x x axis position 86551 * @param {Number} y y axis position 86552 * @param {Number} z z axis position 86553 * @param {Number} rx x axis direction of light 86554 * @param {Number} ry y axis direction of light 86555 * @param {Number} rz z axis direction of light 86556 * @param {Number} [angle] optional parameter for angle. Defaults to PI/3 86557 * @param {Number} [conc] optional parameter for concentration. Defaults to 100 86558 * @chainable 86559 * 86560 * @example 86561 * <div> 86562 * <code> 86563 * function setup() { 86564 * createCanvas(100, 100, WEBGL); 86565 * } 86566 * function draw() { 86567 * background(0); 86568 * //move your mouse to change light position 86569 * let locX = mouseX - width / 2; 86570 * let locY = mouseY - height / 2; 86571 * // to set the light position, 86572 * // think of the world's coordinate as: 86573 * // -width/2,-height/2 -------- width/2,-height/2 86574 * // | | 86575 * // | 0,0 | 86576 * // | | 86577 * // -width/2,height/2--------width/2,height/2 86578 * ambientLight(50); 86579 * spotLight(0, 250, 0, locX, locY, 100, 0, 0, -1, Math.PI / 16); 86580 * noStroke(); 86581 * sphere(40); 86582 * } 86583 * </code> 86584 * </div> 86585 * 86586 * @alt 86587 * Spot light on a sphere which changes position with mouse 86588 */ 86589 /** 86590 * @method spotLight 86591 * @param {Number[]|String|p5.Color} color color Array, CSS color string, 86592 * or <a href="#/p5.Color">p5.Color</a> value 86593 * @param {p5.Vector} position the position of the light 86594 * @param {p5.Vector} direction the direction of the light 86595 * @param {Number} [angle] 86596 * @param {Number} [conc] 86597 */ 86598 /** 86599 * @method spotLight 86600 * @param {Number} v1 86601 * @param {Number} v2 86602 * @param {Number} v3 86603 * @param {p5.Vector} position 86604 * @param {p5.Vector} direction 86605 * @param {Number} [angle] 86606 * @param {Number} [conc] 86607 */ 86608 /** 86609 * @method spotLight 86610 * @param {Number[]|String|p5.Color} color 86611 * @param {Number} x 86612 * @param {Number} y 86613 * @param {Number} z 86614 * @param {p5.Vector} direction 86615 * @param {Number} [angle] 86616 * @param {Number} [conc] 86617 */ 86618 /** 86619 * @method spotLight 86620 * @param {Number[]|String|p5.Color} color 86621 * @param {p5.Vector} position 86622 * @param {Number} rx 86623 * @param {Number} ry 86624 * @param {Number} rz 86625 * @param {Number} [angle] 86626 * @param {Number} [conc] 86627 */ 86628 /** 86629 * @method spotLight 86630 * @param {Number} v1 86631 * @param {Number} v2 86632 * @param {Number} v3 86633 * @param {Number} x 86634 * @param {Number} y 86635 * @param {Number} z 86636 * @param {p5.Vector} direction 86637 * @param {Number} [angle] 86638 * @param {Number} [conc] 86639 */ 86640 /** 86641 * @method spotLight 86642 * @param {Number} v1 86643 * @param {Number} v2 86644 * @param {Number} v3 86645 * @param {p5.Vector} position 86646 * @param {Number} rx 86647 * @param {Number} ry 86648 * @param {Number} rz 86649 * @param {Number} [angle] 86650 * @param {Number} [conc] 86651 */ 86652 /** 86653 * @method spotLight 86654 * @param {Number[]|String|p5.Color} color 86655 * @param {Number} x 86656 * @param {Number} y 86657 * @param {Number} z 86658 * @param {Number} rx 86659 * @param {Number} ry 86660 * @param {Number} rz 86661 * @param {Number} [angle] 86662 * @param {Number} [conc] 86663 */ 86664 _main.default.prototype.spotLight = function( 86665 v1, 86666 v2, 86667 v3, 86668 x, 86669 y, 86670 z, 86671 nx, 86672 ny, 86673 nz, 86674 angle, 86675 concentration 86676 ) { 86677 this._assert3d('spotLight'); 86678 _main.default._validateParameters('spotLight', arguments); 86679 86680 var color, position, direction; 86681 var length = arguments.length; 86682 86683 switch (length) { 86684 case 11: 86685 case 10: 86686 color = this.color(v1, v2, v3); 86687 position = new _main.default.Vector(x, y, z); 86688 direction = new _main.default.Vector(nx, ny, nz); 86689 break; 86690 86691 case 9: 86692 if (v1 instanceof _main.default.Color) { 86693 color = v1; 86694 position = new _main.default.Vector(v2, v3, x); 86695 direction = new _main.default.Vector(y, z, nx); 86696 angle = ny; 86697 concentration = nz; 86698 } else if (x instanceof _main.default.Vector) { 86699 color = this.color(v1, v2, v3); 86700 position = x; 86701 direction = new _main.default.Vector(y, z, nx); 86702 angle = ny; 86703 concentration = nz; 86704 } else if (nx instanceof _main.default.Vector) { 86705 color = this.color(v1, v2, v3); 86706 position = new _main.default.Vector(x, y, z); 86707 direction = nx; 86708 angle = ny; 86709 concentration = nz; 86710 } else { 86711 color = this.color(v1, v2, v3); 86712 position = new _main.default.Vector(x, y, z); 86713 direction = new _main.default.Vector(nx, ny, nz); 86714 } 86715 break; 86716 86717 case 8: 86718 if (v1 instanceof _main.default.Color) { 86719 color = v1; 86720 position = new _main.default.Vector(v2, v3, x); 86721 direction = new _main.default.Vector(y, z, nx); 86722 angle = ny; 86723 } else if (x instanceof _main.default.Vector) { 86724 color = this.color(v1, v2, v3); 86725 position = x; 86726 direction = new _main.default.Vector(y, z, nx); 86727 angle = ny; 86728 } else { 86729 color = this.color(v1, v2, v3); 86730 position = new _main.default.Vector(x, y, z); 86731 direction = nx; 86732 angle = ny; 86733 } 86734 break; 86735 86736 case 7: 86737 if ( 86738 v1 instanceof _main.default.Color && 86739 v2 instanceof _main.default.Vector 86740 ) { 86741 color = v1; 86742 position = v2; 86743 direction = new _main.default.Vector(v3, x, y); 86744 angle = z; 86745 concentration = nx; 86746 } else if ( 86747 v1 instanceof _main.default.Color && 86748 y instanceof _main.default.Vector 86749 ) { 86750 color = v1; 86751 position = new _main.default.Vector(v2, v3, x); 86752 direction = y; 86753 angle = z; 86754 concentration = nx; 86755 } else if ( 86756 x instanceof _main.default.Vector && 86757 y instanceof _main.default.Vector 86758 ) { 86759 color = this.color(v1, v2, v3); 86760 position = x; 86761 direction = y; 86762 angle = z; 86763 concentration = nx; 86764 } else if (v1 instanceof _main.default.Color) { 86765 color = v1; 86766 position = new _main.default.Vector(v2, v3, x); 86767 direction = new _main.default.Vector(y, z, nx); 86768 } else if (x instanceof _main.default.Vector) { 86769 color = this.color(v1, v2, v3); 86770 position = x; 86771 direction = new _main.default.Vector(y, z, nx); 86772 } else { 86773 color = this.color(v1, v2, v3); 86774 position = new _main.default.Vector(x, y, z); 86775 direction = nx; 86776 } 86777 break; 86778 86779 case 6: 86780 if ( 86781 x instanceof _main.default.Vector && 86782 y instanceof _main.default.Vector 86783 ) { 86784 color = this.color(v1, v2, v3); 86785 position = x; 86786 direction = y; 86787 angle = z; 86788 } else if ( 86789 v1 instanceof _main.default.Color && 86790 y instanceof _main.default.Vector 86791 ) { 86792 color = v1; 86793 position = new _main.default.Vector(v2, v3, x); 86794 direction = y; 86795 angle = z; 86796 } else if ( 86797 v1 instanceof _main.default.Color && 86798 v2 instanceof _main.default.Vector 86799 ) { 86800 color = v1; 86801 position = v2; 86802 direction = new _main.default.Vector(v3, x, y); 86803 angle = z; 86804 } 86805 break; 86806 86807 case 5: 86808 if ( 86809 v1 instanceof _main.default.Color && 86810 v2 instanceof _main.default.Vector && 86811 v3 instanceof _main.default.Vector 86812 ) { 86813 color = v1; 86814 position = v2; 86815 direction = v3; 86816 angle = x; 86817 concentration = y; 86818 } else if ( 86819 x instanceof _main.default.Vector && 86820 y instanceof _main.default.Vector 86821 ) { 86822 color = this.color(v1, v2, v3); 86823 position = x; 86824 direction = y; 86825 } else if ( 86826 v1 instanceof _main.default.Color && 86827 y instanceof _main.default.Vector 86828 ) { 86829 color = v1; 86830 position = new _main.default.Vector(v2, v3, x); 86831 direction = y; 86832 } else if ( 86833 v1 instanceof _main.default.Color && 86834 v2 instanceof _main.default.Vector 86835 ) { 86836 color = v1; 86837 position = v2; 86838 direction = new _main.default.Vector(v3, x, y); 86839 } 86840 break; 86841 86842 case 4: 86843 color = v1; 86844 position = v2; 86845 direction = v3; 86846 angle = x; 86847 break; 86848 86849 case 3: 86850 color = v1; 86851 position = v2; 86852 direction = v3; 86853 break; 86854 86855 default: 86856 console.warn( 86857 'Sorry, input for spotlight() is not in prescribed format. Too '.concat( 86858 length < 3 ? 'few' : 'many', 86859 ' arguments were provided' 86860 ) 86861 ); 86862 86863 return this; 86864 } 86865 86866 this._renderer.spotLightDiffuseColors.push( 86867 color._array[0], 86868 color._array[1], 86869 color._array[2] 86870 ); 86871 86872 Array.prototype.push.apply( 86873 this._renderer.spotLightSpecularColors, 86874 this._renderer.specularColors 86875 ); 86876 86877 this._renderer.spotLightPositions.push(position.x, position.y, position.z); 86878 direction.normalize(); 86879 this._renderer.spotLightDirections.push(direction.x, direction.y, direction.z); 86880 86881 if (angle === undefined) { 86882 angle = Math.PI / 3; 86883 } 86884 86885 if (concentration !== undefined && concentration < 1) { 86886 concentration = 1; 86887 console.warn( 86888 'Value of concentration needs to be greater than 1. Setting it to 1' 86889 ); 86890 } else if (concentration === undefined) { 86891 concentration = 100; 86892 } 86893 86894 angle = this._renderer._pInst._toRadians(angle); 86895 this._renderer.spotLightAngle.push(Math.cos(angle)); 86896 this._renderer.spotLightConc.push(concentration); 86897 86898 this._renderer._enableLighting = true; 86899 86900 return this; 86901 }; 86902 86903 /** 86904 * This function will remove all the lights from the sketch for the 86905 * subsequent materials rendered. It affects all the subsequent methods. 86906 * Calls to lighting methods made after noLights() will re-enable
86906 lights 86907 * in the sketch. 86908 * @method noLights 86909 * @chainable 86910 * @example 86911 * <div> 86912 * <code> 86913 * function setup() { 86914 * createCanvas(100, 100, WEBGL); 86915 * } 86916 * function draw() { 86917 * background(0); 86918 * noStroke(); 86919 * 86920 * ambientLight(150, 0, 0); 86921 * translate(-25, 0, 0); 86922 * ambientMaterial(250); 86923 * sphere(20); 86924 * 86925 * noLights(); 86926 * ambientLight(0, 150, 0); 86927 * translate(50, 0, 0); 86928 * ambientMaterial(250); 86929 * sphere(20); 86930 * } 86931 * </code> 86932 * </div> 86933 * 86934 * @alt 86935 * Two spheres showing different colors 86936 */ 86937 _main.default.prototype.noLights = function() { 86938 this._assert3d('noLights'); 86939 _main.default._validateParameters('noLights', arguments); 86940 86941 this._renderer._enableLighting = false; 86942 86943 this._renderer.ambientLightColors.length = 0; 86944 this._renderer.specularColors = [1, 1, 1]; 86945 86946 this._renderer.directionalLightDirections.length = 0; 86947 this._renderer.directionalLightDiffuseColors.length = 0; 86948 this._renderer.directionalLightSpecularColors.length = 0; 86949 86950 this._renderer.pointLightPositions.length = 0; 86951 this._renderer.pointLightDiffuseColors.length = 0; 86952 this._renderer.pointLightSpecularColors.length = 0; 86953 86954 this._renderer.spotLightPositions.length = 0; 86955 this._renderer.spotLightDirections.length = 0; 86956 this._renderer.spotLightDiffuseColors.length = 0; 86957 this._renderer.spotLightSpecularColors.length = 0; 86958 this._renderer.spotLightAngle.length = 0; 86959 this._renderer.spotLightConc.length = 0; 86960 86961 this._renderer.constantAttenuation = 1; 86962 this._renderer.linearAttenuation = 0; 86963 this._renderer.quadraticAttenuation = 0; 86964 this._renderer._useShininess = 1; 86965 86966 return this; 86967 }; 86968 var _default = _main.default; 86969 exports.default = _default; 86970 }, 86971 { '../core/main': 59 } 86972 ], 86973 105: [ 86974 function(_dereq_, module, exports) { 86975 'use strict'; 86976 Object.defineProperty(exports, '__esModule', { value: true }); 86977 exports.default = void 0; 86978 86979 var _main = _interopRequireDefault(_dereq_('../core/main')); 86980 _dereq_('./p5.Geometry'); 86981 function _interopRequireDefault(obj) { 86982 return obj && obj.__esModule ? obj : { default: obj }; 86983 } 86984 /** 86985 * @module Shape 86986 * @submodule 3D Models 86987 * @for p5 86988 * @requires core 86989 * @requires p5.Geometry 86990 */ /** 86991 * Load a 3d model from an OBJ or STL file. 86992 * 86993 * <a href="#/p5/loadModel">loadModel()</a> should be placed inside of <a href="#/p5/preload">preload()</a>. 86994 * This allows the model to load fully before the rest of your code is run. 86995 * 86996 * One of the limitations of the OBJ and STL format is that it doesn't have a built-in 86997 * sense of scale. This means that models exported from different programs might 86998 * be very different sizes. If your model isn't displaying, try calling 86999 * <a href="#/p5/loadModel">loadModel()</a> with the normalized parameter set to true. This will resize the 87000 * model to a scale appropriate for p5. You can also make additional changes to 87001 * the final size of your model with the <a href="#/p5/scale">scale()</a> function. 87002 * 87003 * Also, the support for colored STL files is not present. STL files with color will be 87004 * rendered without color properties. 87005 * 87006 * @method loadModel 87007 * @param {String} path Path of the model to be loaded 87008 * @param {Boolean} normalize If true, scale the model to a 87009 * standardized size when loading 87010 * @param {function(p5.Geometry)} [successCallback] Function to be called 87011 * once the model is loaded. Will be passed 87012 * the 3D model object. 87013 * @param {function(Event)} [failureCallback] called with event error if 87014 * the model fails to load. 87015 * @param {String} [fileType] The file extension of the model 87016 * (<code>.stl</code>, <code>.obj</code>). 87017 * @return {p5.Geometry} the <a href="#/p5.Geometry">p5.Geometry</a> object 87018 * 87019 * @example 87020 * <div> 87021 * <code> 87022 * //draw a spinning octahedron 87023 * let octahedron; 87024 * 87025 * function preload() { 87026 * octahedron = loadModel('assets/octahedron.obj'); 87027 * } 87028 * 87029 * function setup() { 87030 * createCanvas(100, 100, WEBGL); 87031 * } 87032 * 87033 * function draw() { 87034 * background(200); 87035 * rotateX(frameCount * 0.01); 87036 * rotateY(frameCount * 0.01); 87037 * model(octahedron); 87038 * } 87039 * </code> 87040 * </div> 87041 * 87042 * @alt 87043 * Vertically rotating 3-d octahedron. 87044 * 87045 * @example 87046 * <div> 87047 * <code> 87048 * //draw a spinning teapot 87049 * let teapot; 87050 * 87051 * function preload() { 87052 * // Load model with normalise parameter set to true 87053 * teapot = loadModel('assets/teapot.obj', true); 87054 * } 87055 * 87056 * function setup() { 87057 * createCanvas(100, 100, WEBGL); 87058 * } 87059 * 87060 * function draw() { 87061 * background(200); 87062 * scale(0.4); // Scaled to make model fit into canvas 87063 * rotateX(frameCount * 0.01); 87064 * rotateY(frameCount * 0.01); 87065 * normalMaterial(); // For effect
87066 * model(teapot); 87067 * } 87068 * </code> 87069 * </div> 87070 * 87071 * @alt 87072 * Vertically rotating 3-d teapot with red, green and blue gradient. 87073 */ /** 87074 * @method loadModel 87075 * @param {String} path 87076 * @param {function(p5.Geometry)} [successCallback] 87077 * @param {function(Event)} [failureCallback] 87078 * @param {String} [fileType] 87079 * @return {p5.Geometry} the <a href="#/p5.Geometry">p5.Geometry</a> object 87080 */ _main.default.prototype.loadModel = function(path) { 87081 _main.default._validateParameters('loadModel', arguments); 87082 var normalize; 87083 var successCallback; 87084 var failureCallback; 87085 var fileType = path.slice(-4); 87086 if (typeof arguments[1] === 'boolean') { 87087 normalize = arguments[1]; 87088 successCallback = arguments[2]; 87089 failureCallback = arguments[3]; 87090 if (typeof arguments[4] !== 'undefined') { 87091 fileType = arguments[4]; 87092 } 87093 } else { 87094 normalize = false; 87095 successCallback = arguments[1]; 87096 failureCallback = arguments[2]; 87097 if (typeof arguments[3] !== 'undefined') { 87098 fileType = arguments[3]; 87099 } 87100 } 87101 87102 var model = new _main.default.Geometry(); 87103 model.gid = ''.concat(path, '|').concat(normalize); 87104 var self = this; 87105 87106 if (fileType.match(/\.stl$/i)) { 87107 this.httpDo( 87108 path, 87109 'GET', 87110 'arrayBuffer', 87111 function(arrayBuffer) { 87112 parseSTL(model, arrayBuffer); 87113 87114 if (normalize) { 87115 model.normalize(); 87116 } 87117 self._decrementPreload(); 87118 if (typeof successCallback === 'function') { 87119 successCallback(model); 87120 } 87121 }, 87122 failureCallback 87123 ); 87124 } else if (fileType.match(/\.obj$/i)) { 87125 this.loadStrings( 87126 path, 87127 function(strings) { 87128 parseObj(model, strings); 87129 87130 if (normalize) { 87131 model.normalize(); 87132 } 87133 87134 self._decrementPreload(); 87135 if (typeof successCallback === 'function') { 87136 successCallback(model); 87137 } 87138 }, 87139 failureCallback 87140 ); 87141 } else { 87142 _main.default._friendlyFileLoadError(3, path); 87143 87144 if (failureCallback) { 87145 failureCallback(); 87146 } else { 87147 console.error( 87148 'Sorry, the file type is invalid. Only OBJ and STL files are supported.' 87149 ); 87150 } 87151 } 87152 return model; 87153 }; 87154 87155 /** 87156 * Parse OBJ lines into model. For reference, this is what a simple model of a 87157 * square might look like: 87158 * 87159 * v -0.5 -0.5 0.5 87160 * v -0.5 -0.5 -0.5 87161 * v -0.5 0.5 -0.5 87162 * v -0.5 0.5 0.5 87163 * 87164 * f 4 3 2 1 87165 */ 87166 function parseObj(model, lines) { 87167 // OBJ allows a face to specify an index for a vertex (in the above example), 87168 // but it also allows you to specify a custom combination of vertex, UV 87169 // coordinate, and vertex normal. So, "3/4/3" would mean, "use vertex 3 with 87170 // UV coordinate 4 and vertex normal 3". In WebGL, every vertex with different 87171 // parameters must be a different vertex, so loadedVerts is used to 87172 // temporarily store the parsed vertices, normals, etc., and indexedVerts is 87173 // used to map a specific combination (keyed on, for example, the string 87174 // "3/4/3"), to the actual index of the newly created vertex in the final 87175 // object. 87176 var loadedVerts = { 87177 v: [], 87178 vt: [], 87179 vn: [] 87180 }; 87181 87182 var indexedVerts = {}; 87183 87184 for (var line = 0; line < lines.length; ++line) { 87185 // Each line is a separate object (vertex, face, vertex normal, etc) 87186 // For each line, split it into tokens on whitespace. The first token 87187 // describes the type. 87188 var tokens = lines[line].trim().split(/\b\s+/); 87189 87190 if (tokens.length > 0) { 87191 if (tokens[0] === 'v' || tokens[0] === 'vn') { 87192 // Check if this line describes a vertex or vertex normal. 87193 // It will have three numeric parameters. 87194 var vertex = new _main.default.Vector( 87195 parseFloat(tokens[1]), 87196 parseFloat(tokens[2]), 87197 parseFloat(tokens[3]) 87198 ); 87199 87200 loadedVerts[tokens[0]].push(vertex); 87201 } else if (tokens[0] === 'vt') { 87202 // Check if this line describes a texture coordinate. 87203 // It will have two numeric parameters. 87204 var texVertex = [parseFloat(tokens[1]), parseFloat(tokens[2])]; 87205 loadedVerts[tokens[0]].push(texVertex); 87206 } else if (tokens[0] === 'f') { 87207 // Check if this line describes a face. 87208 // OBJ faces can have more than three points. Triangulate points. 87209 for (var tri = 3; tri < tokens.length; ++tri) { 87210 var face = []; 87211 87212 var vertexTokens = [1, tri - 1, tri]; 87213 87214 for (var tokenInd = 0; tokenInd < vertexTokens.length; ++tokenInd) { 87215 // Now, convert the given token into an index 87216 var vertString = tokens[vertexTokens[tokenInd]]; 87217 var vertIndex = 0; 87218 87219 // TODO: Faces can technically use negative numbers to refer to the 87220 // previous nth vertex. I haven't seen this used in practice, but 87221 // it might be good to implement this in the future. 87222 87223 if (indexedVerts[vertString] !== undefined) { 87224 vertIndex = indexedVerts[vertString]; 87225 } else { 87226 var vertParts = vertString.split('/'); 87227 for (var i = 0; i < vertParts.length; i++) { 87228 vertParts[i] = parseInt(vertParts[i]) - 1; 87229 } 87230 87231 vertIndex = indexedVerts[vertString] = model.vertices.length; 87232 model.vertices.push(loadedVerts.v[vertParts[0]].copy()); 87233 if (loadedVerts.vt[vertParts[1]]) { 87234 model.uvs.push(loadedVerts.vt[vertParts[1]].slice()); 87235 } else { 87236 model.uvs.push([0, 0]); 87237 } 87238 87239 if (loadedVerts.vn[vertParts[2]]) { 87240 model.vertexNormals.push(loadedVerts.vn[vertParts[2]].copy()); 87241 } 87242 } 87243 87244 face.push(vertIndex); 87245 } 87246 87247 if (face[0] !== face[1] && face[0] !== face[2] && face[1] !== face[2]) { 87248 model.faces.push(face); 87249 } 87250 } 87251 } 87252 } 87253 } 87254 // If the model doesn't have normals, compute the normals 87255 if (model.vertexNormals.length === 0) { 87256 model.computeNormals(); 87257 } 87258 87259 return model; 87260 } 87261 87262 /** 87263 * STL files can be of two types, ASCII and Binary, 87264 * 87265 * We need to convert the arrayBuffer to an array of str
87265ings, 87266 * to parse it as an ASCII file. 87267 */ 87268 function parseSTL(model, buffer) { 87269 if (isBinary(buffer)) { 87270 parseBinarySTL(model, buffer); 87271 } else { 87272 var reader = new DataView(buffer); 87273 87274 if (!('TextDecoder' in window)) { 87275 console.warn( 87276 'Sorry, ASCII STL loading only works in browsers that support TextDecoder (https://caniuse.com/#feat=textencoder)' 87277 ); 87278 87279 return model; 87280 } 87281 87282 var decoder = new TextDecoder('utf-8'); 87283 var lines = decoder.decode(reader); 87284 var lineArray = lines.split('\n'); 87285 parseASCIISTL(model, lineArray); 87286 } 87287 return model; 87288 } 87289 87290 /** 87291 * This function checks if the file is in ASCII format or in Binary format 87292 * 87293 * It is done by searching keyword `solid` at the start of the file. 87294 * 87295 * An ASCII STL data must begin with `solid` as the first six bytes. 87296 * However, ASCII STLs lacking the SPACE after the `d` are known to be 87297 * plentiful. So, check the first 5 bytes for `solid`. 87298 * 87299 * Several encodings, such as UTF-8, precede the text with up to 5 bytes: 87300 * https://en.wikipedia.org/wiki/Byte_order_mark#Byte_order_marks_by_encoding 87301 * Search for `solid` to start anywhere after those prefixes. 87302 */ 87303 function isBinary(data) { 87304 var reader = new DataView(data); 87305 87306 // US-ASCII ordinal values for `s`, `o`, `l`, `i`, `d` 87307 var solid = [115, 111, 108, 105, 100]; 87308 for (var off = 0; off < 5; off++) { 87309 // If "solid" text is matched to the current offset, declare it to be an ASCII STL. 87310 if (matchDataViewAt(solid, reader, off)) return false; 87311 } 87312 87313 // Couldn't find "solid" text at the beginning; it is binary STL. 87314 return true; 87315 } 87316 87317 /** 87318 * This function matches the `query` at the provided `offset` 87319 */ 87320 function matchDataViewAt(query, reader, offset) { 87321 // Check if each byte in query matches the corresponding byte from the current offset 87322 for (var i = 0, il = query.length; i < il; i++) { 87323 if (query[i] !== reader.getUint8(offset + i, false)) return false; 87324 } 87325 87326 return true; 87327 } 87328 87329 /** 87330 * This function parses the Binary STL files. 87331 * https://en.wikipedia.org/wiki/STL_%28file_format%29#Binary_STL 87332 * 87333 * Currently there is no support for the colors provided in STL files. 87334 */ 87335 function parseBinarySTL(model, buffer) { 87336 var reader = new DataView(buffer); 87337 87338 // Number of faces is present following the header 87339 var faces = reader.getUint32(80, true); 87340 var r, 87341 g, 87342 b, 87343 hasColors = false, 87344 colors; 87345 var defaultR, defaultG, defaultB; 87346 87347 // Binary files contain 80-byte header, which is generally ignored. 87348 for (var index = 0; index < 80 - 10; index++) { 87349 // Check for `COLOR=` 87350 if ( 87351 reader.getUint32(index, false) === 0x434f4c4f /*COLO*/ && 87352 reader.getUint8(index + 4) === 0x52 /*'R'*/ && 87353 reader.getUint8(index + 5) === 0x3d /*'='*/ 87354 ) { 87355 hasColors = true; 87356 colors = []; 87357 87358 defaultR = reader.getUint8(index + 6) / 255; 87359 defaultG = reader.getUint8(index + 7) / 255; 87360 defaultB = reader.getUint8(index + 8) / 255; 87361 // To be used when color support is added 87362 // alpha = reader.getUint8(index + 9) / 255; 87363 } 87364 } 87365 var dataOffset = 84; 87366 var faceLength = 12 * 4 + 2; 87367 87368 // Iterate the faces 87369 for (var face = 0; face < faces; face++) { 87370 var start = dataOffset + face * faceLength; 87371 var normalX = reader.getFloat32(start, true); 87372 var normalY = reader.getFloat32(start + 4, true); 87373 var normalZ = reader.getFloat32(start + 8, true); 87374 87375 if (hasColors) { 87376 var packedColor = reader.getUint16(start + 48, true); 87377 87378 if ((packedColor & 0x8000) === 0) { 87379 // facet has its own unique color 87380 r = (packedColor & 0x1f) / 31; 87381 g = ((packedColor >> 5) & 0x1f) / 31; 87382 b = ((packedColor >> 10) & 0x1f) / 31; 87383 } else { 87384 r = defaultR; 87385 g = defaultG; 87386 b = defaultB; 87387 } 87388 } 87389 var newNormal = new _main.default.Vector(normalX, normalY, normalZ); 87390 87391 for (var i = 1; i <= 3; i++) { 87392 var vertexstart = start + i * 12; 87393 87394 var newVertex = new _main.default.Vector( 87395 reader.getFloat32(vertexstart, true), 87396 reader.getFloat32(vertexstart + 4, true), 87397 reader.getFloat32(vertexstart + 8, true) 87398 ); 87399 87400 model.vertices.push(newVertex); 87401 model.vertexNormals.push(newNormal); 87402 87403 if (hasColors) { 87404 colors.push(r, g, b); 87405 } 87406 } 87407 87408 model.faces.push([3 * face, 3 * face + 1, 3 * face + 2]); 87409 model.uvs.push([0, 0], [0, 0], [0, 0]); 87410 } 87411 if (hasColors) { 87412 // add support for colors here. 87413 } 87414 return model; 87415 } 87416 87417 /** 87418 * ASCII STL file starts with `solid 'nameOfFile'`
87419 * Then contain the normal of the face, starting with `facet normal` 87420 * Next contain a keyword indicating the start of face vertex, `outer loop` 87421 * Next comes the three vertex, starting with `vertex x y z` 87422 * Vertices ends with `endloop` 87423 * Face ends with `endfacet` 87424 * Next face starts with `facet normal` 87425 * The end of the file is indicated by `endsolid` 87426 */ 87427 function parseASCIISTL(model, lines) { 87428 var state = ''; 87429 var curVertexIndex = []; 87430 var newNormal, newVertex; 87431 87432 for (var iterator = 0; iterator < lines.length; ++iterator) { 87433 var line = lines[iterator].trim(); 87434 var parts = line.split(' '); 87435 87436 for (var partsiterator = 0; partsiterator < parts.length; ++partsiterator) { 87437 if (parts[partsiterator] === '') { 87438 // Ignoring multiple whitespaces 87439 parts.splice(partsiterator, 1); 87440 } 87441 } 87442 87443 if (parts.length === 0) { 87444 // Remove newline 87445 continue; 87446 } 87447 87448 switch (state) { 87449 case '': // First run 87450 if (parts[0] !== 'solid') { 87451 // Invalid state 87452 console.error(line); 87453 console.error( 87454 'Invalid state "'.concat(parts[0], '", should be "solid"') 87455 ); 87456 return; 87457 } else { 87458 state = 'solid'; 87459 } 87460 break; 87461 87462 case 'solid': // First face 87463 if (parts[0] !== 'facet' || parts[1] !== 'normal') { 87464 // Invalid state 87465 console.error(line); 87466 console.error( 87467 'Invalid state "'.concat(parts[0], '", should be "facet normal"') 87468 ); 87469 87470 return; 87471 } else { 87472 // Push normal for first face 87473 newNormal = new _main.default.Vector( 87474 parseFloat(parts[2]), 87475 parseFloat(parts[3]), 87476 parseFloat(parts[4]) 87477 ); 87478 87479 model.vertexNormals.push(newNormal, newNormal, newNormal); 87480 state = 'facet normal'; 87481 } 87482 break; 87483 87484 case 'facet normal': // After normal is defined 87485 if (parts[0] !== 'outer' || parts[1] !== 'loop') { 87486 // Invalid State 87487 console.error(line); 87488 console.error( 87489 'Invalid state "'.concat(parts[0], '", should be "outer loop"') 87490 ); 87491 return; 87492 } else { 87493 // Next should be vertices 87494 state = 'vertex'; 87495 } 87496 break; 87497 87498 case 'vertex': 87499 if (parts[0] === 'vertex') { 87500 //Vertex of triangle 87501 newVertex = new _main.default.Vector( 87502 parseFloat(parts[1]), 87503 parseFloat(parts[2]), 87504 parseFloat(parts[3]) 87505 ); 87506 87507 model.vertices.push(newVertex); 87508 model.uvs.push([0, 0]); 87509 curVertexIndex.push(model.vertices.indexOf(newVertex)); 87510 } else if (parts[0] === 'endloop') { 87511 // End of vertices 87512 model.faces.push(curVertexIndex); 87513 curVertexIndex = []; 87514 state = 'endloop'; 87515 } else { 87516 // Invalid State 87517 console.error(line); 87518 console.error( 87519 'Invalid state "'.concat( 87520 parts[0], 87521 '", should be "vertex" or "endloop"' 87522 ) 87523 ); 87524 87525 return; 87526 } 87527 break; 87528 87529 case 'endloop': 87530 if (parts[0] !== 'endfacet') { 87531 // End of face 87532 console.error(line); 87533 console.error( 87534 'Invalid state "'.concat(parts[0], '", should be "endfacet"') 87535 ); 87536 return; 87537 } else { 87538 state = 'endfacet'; 87539 } 87540 break; 87541 87542 case 'endfacet': 87543 if (parts[0] === 'endsolid') { 87544 // End of solid 87545 } else if (parts[0] === 'facet' && parts[1] === 'normal') { 87546 // Next face 87547 newNormal = new _main.default.Vector( 87548 parseFloat(parts[2]), 87549 parseFloat(parts[3]), 87550 parseFloat(parts[4]) 87551 ); 87552 87553 model.vertexNormals.push(newNormal, newNormal, newNormal); 87554 state = 'facet normal'; 87555 } else { 87556 // Invalid State 87557 console.error(line); 87558 console.error( 87559 'Invalid state "'.concat( 87560 parts[0], 87561 '", should be "endsolid" or "facet normal"' 87562 ) 87563 ); 87564 87565 return; 87566 } 87567 break; 87568 87569 default: 87570 console.error('Invalid state "'.concat(state, '"')); 87571 break; 87572 } 87573 } 87574 return model; 87575 } 87576 87577 /**
87578 * Render a 3d model to the screen. 87579 * 87580 * @method model 87581 * @param {p5.Geometry} model Loaded 3d model to be rendered 87582 * @example 87583 * <div> 87584 * <code> 87585 * //draw a spinning octahedron 87586 * let octahedron; 87587 * 87588 * function preload() { 87589 * octahedron = loadModel('assets/octahedron.obj'); 87590 * } 87591 * 87592 * function setup() { 87593 * createCanvas(100, 100, WEBGL); 87594 * } 87595 * 87596 * function draw() { 87597 * background(200); 87598 * rotateX(frameCount * 0.01); 87599 * rotateY(frameCount * 0.01); 87600 * model(octahedron); 87601 * } 87602 * </code> 87603 * </div> 87604 * 87605 * @alt 87606 * Vertically rotating 3-d octahedron. 87607 */ 87608 _main.default.prototype.model = function(model) { 87609 this._assert3d('model'); 87610 _main.default._validateParameters('model', arguments); 87611 if (model.vertices.length > 0) { 87612 if (!this._renderer.geometryInHash(model.gid)) { 87613 model._makeTriangleEdges()._edgesToVertices(); 87614 this._renderer.createBuffers(model.gid, model); 87615 } 87616 87617 this._renderer.drawBuffers(model.gid); 87618 } 87619 }; 87620 var _default = _main.default; 87621 exports.default = _default; 87622 }, 87623 { '../core/main': 59, './p5.Geometry': 108 } 87624 ], 87625 106: [ 87626 function(_dereq_, module, exports) { 87627 'use strict'; 87628 function _typeof(obj) { 87629 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') { 87630 _typeof = function _typeof(obj) { 87631 return typeof obj; 87632 }; 87633 } else { 87634 _typeof = function _typeof(obj) { 87635 return obj && 87636 typeof Symbol === 'function' && 87637 obj.constructor === Symbol && 87638 obj !== Symbol.prototype 87639 ? 'symbol' 87640 : typeof obj; 87641 }; 87642 } 87643 return _typeof(obj); 87644 } 87645 Object.defineProperty(exports, '__esModule', { value: true }); 87646 exports.default = void 0; 87647 87648 var _main = _interopRequireDefault(_dereq_('../core/main')); 87649 var constants = _interopRequireWildcard(_dereq_('../core/constants')); 87650 _dereq_('./p5.Texture'); 87651 function _getRequireWildcardCache() { 87652 if (typeof WeakMap !== 'function') return null; 87653 var cache = new WeakMap(); 87654 _getRequireWildcardCache = function _getRequireWildcardCache() { 87655 return cache; 87656 }; 87657 return cache; 87658 } 87659 function _interopRequireWildcard(obj) { 87660 if (obj && obj.__esModule) { 87661 return obj; 87662 } 87663 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) { 87664 return { default: obj }; 87665 } 87666 var cache = _getRequireWildcardCache(); 87667 if (cache && cache.has(obj)) { 87668 return cache.get(obj); 87669 } 87670 var newObj = {}; 87671 var hasPropertyDescriptor = 87672 Object.defineProperty && Object.getOwnPropertyDescriptor; 87673 for (var key in obj) { 87674 if (Object.prototype.hasOwnProperty.call(obj, key)) { 87675 var desc = hasPropertyDescriptor 87676 ? Object.getOwnPropertyDescriptor(obj, key) 87677 : null; 87678 if (desc && (desc.get || desc.set)) { 87679 Object.defineProperty(newObj, key, desc); 87680 } else { 87681 newObj[key] = obj[key]; 87682 } 87683 } 87684 } 87685 newObj.default = obj; 87686 if (cache) { 87687 cache.set(obj, newObj); 87688 } 87689 return newObj; 87690 } 87691 function _interopRequireDefault(obj) { 87692 return obj && obj.__esModule ? obj : { default: obj }; 87693 } 87694 /** 87695 * @module Lights, Camera 87696 * @submodule Material 87697 * @for p5 87698 * @requires core 87699 */ /** 87700 * Loads a custom shader from the provided vertex and fragment 87701 * shader paths. The shader files are loaded asynchronously in the 87702 * background, so this method should be used in <a href="#/p5/preload">preload()</a>. 87703 * 87704 * For now, there are three main types of shaders. p5 will automatically 87705 * supply appropriate vertices, normals, colors, and lighting attributes 87706 * if the parameters defined in the shader match the names. 87707 * 87708 * @method loadShader 87709 * @param {String} vertFilename path to file containing vertex shader 87710 * source code 87711 * @param {String} fragFilename path to file containing fragment shader 87712 * source code 87713 * @param {function} [callback] callback to be executed after loadShader 87714 * completes. On success, the Shader object is passed as the first argument. 87715 * @param {function} [errorCallback] callback to be executed when an error 87716 * occurs inside loadShader. On error, the error is passed as the first 87717 * argument. 87718 * @return {p5.Shader} a shader object created from the provided 87719 * vertex and fragment shader files. 87720 * 87721 * @example 87722 * <div modernizr='webgl'> 87723 * <code> 87724 * let mandel; 87725 * function preload() { 87726 * // load the shader definitions from files 87727 * mandel = loadShader('assets/shader.vert', 'assets/shader.frag'); 87728 * } 87729 * function setup() { 87730 * createCanvas(100, 100, WEBGL); 87731 * // use the shader 87732 * shader(mandel); 87733 * noStroke(); 87734 * mandel.setUniform('p', [-0.74364388703, 0.13182590421]); 87735 * } 87736 * 87737 * function draw() { 87738 * mandel.setUniform('r', 1.5 * exp(-6.5 * (1 + sin(millis() / 2000)))); 87739 * quad(-1, -1, 1, -1, 1, 1, -1, 1); 87740 * } 87741 * </code> 87742 * </div> 87743 * 87744 * @alt 87745 * zooming Mandelbrot set. a colorful, infinitely detailed fractal. 87746 */ _main.default.prototype.loadShader = function( 87747 vertFilename, 87748 fragFilename, 87749 callback, 87750 errorCallback 87751 ) { 87752 _main.default._validateParameters('loadShader', arguments); 87753 if (!errorCallback) { 87754 errorCallback = console.error; 87755 } 87756 87757 var loadedShader = new _main.default.Shader(); 87758 87759 var self = this; 87760 var loadedFrag = false;
87761 var loadedVert = false; 87762 87763 var onLoad = function onLoad() { 87764 self._decrementPreload(); 87765 if (callback) { 87766 callback(loadedShader); 87767 } 87768 }; 87769 87770 this.loadStrings( 87771 vertFilename, 87772 function(result) { 87773 loadedShader._vertSrc = result.join('\n'); 87774 loadedVert = true; 87775 if (loadedFrag) { 87776 onLoad(); 87777 } 87778 }, 87779 errorCallback 87780 ); 87781 87782 this.loadStrings( 87783 fragFilename, 87784 function(result) { 87785 loadedShader._fragSrc = result.join('\n'); 87786 loadedFrag = true; 87787 if (loadedVert) { 87788 onLoad(); 87789 } 87790 }, 87791 errorCallback 87792 ); 87793 87794 return loadedShader; 87795 }; 87796 87797 /** 87798 * @method createShader 87799 * @param {String} vertSrc source code for the vertex shader 87800 * @param {String} fragSrc source code for the fragment shader 87801 * @returns {p5.Shader} a shader object created from the provided 87802 * vertex and fragment shaders. 87803 * 87804 * @example 87805 * <div modernizr='webgl'> 87806 * <code> 87807 * // the 'varying's are shared between both vertex & fragment shaders 87808 * let varying = 'precision highp float; varying vec2 vPos;'; 87809 * 87810 * // the vertex shader is called for each vertex 87811 * let vs = 87812 * varying + 87813 * 'attribute vec3 aPosition;' + 87814 * 'void main() { vPos = (gl_Position = vec4(aPosition,1.0)).xy; }'; 87815 * 87816 * // the fragment shader is called for each pixel 87817 * let fs = 87818 * varying + 87819 * 'uniform vec2 p;' + 87820 * 'uniform float r;' + 87821 * 'const int I = 500;' + 87822 * 'void main() {' + 87823 * ' vec2 c = p + vPos * r, z = c;' + 87824 * ' float n = 0.0;' + 87825 * ' for (int i = I; i > 0; i --) {' + 87826 * ' if(z.x*z.x+z.y*z.y > 4.0) {' + 87827 * ' n = float(i)/float(I);' + 87828 * ' break;' + 87829 * ' }' + 87830 * ' z = vec2(z.x*z.x-z.y*z.y, 2.0*z.x*z.y) + c;' + 87831 * ' }' + 87832 * ' 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);' + 87833 * '}'; 87834 * 87835 * let mandel; 87836 * function setup() { 87837 * createCanvas(100, 100, WEBGL); 87838 * 87839 * // create and initialize the shader 87840 * mandel = createShader(vs, fs); 87841 * shader(mandel); 87842 * noStroke(); 87843 * 87844 * // 'p' is the center point of the Mandelbrot image 87845 * mandel.setUniform('p', [-0.74364388703, 0.13182590421]); 87846 * } 87847 * 87848 * function draw() { 87849 * // 'r' is the size of the image in Mandelbrot-space 87850 * mandel.setUniform('r', 1.5 * exp(-6.5 * (1 + sin(millis() / 2000)))); 87851 * quad(-1, -1, 1, -1, 1, 1, -1, 1); 87852 * } 87853 * </code> 87854 * </div> 87855 * 87856 * @alt 87857 * zooming Mandelbrot set. a colorful, infinitely detailed fractal. 87858 */ 87859 _main.default.prototype.createShader = function(vertSrc, fragSrc) { 87860 this._assert3d('createShader'); 87861 _main.default._validateParameters('createShader', arguments); 87862 return new _main.default.Shader(this._renderer, vertSrc, fragSrc); 87863 }; 87864 87865 /** 87866 * The <a href="#/p5/shader">shader()</a> function lets the user provide a custom shader 87867 * to fill in shapes in WEBGL mode. Users can create their 87868 * own shaders by loading vertex and fragment shaders with 87869 * <a href="#/p5/loadShader">loadShader()</a>. 87870 * 87871 * @method shader 87872 * @chainable 87873 * @param {p5.Shader} [s] the desired <a href="#/p5.Shader">p5.Shader</a> to use for rendering 87874 * shapes. 87875 * 87876 * @example 87877 * <div modernizr='webgl'> 87878 * <code> 87879 * // Click within the image to toggle 87880 * // the shader used by the quad shape 87881 * // Note: for an alternative approach to the same example, 87882 * // involving changing uniforms please refer to: 87883 * // https://p5js.org/reference/#/p5.Shader/setUniform 87884 * 87885 * let redGreen; 87886 * let orangeBlue; 87887 * let showRedGreen = false;
87888 * 87889 * function preload() { 87890 * // note that we are using two instances 87891 * // of the same vertex and fragment shaders 87892 * redGreen = loadShader('assets/shader.vert', 'assets/shader-gradient.frag'); 87893 * orangeBlue = loadShader('assets/shader.vert', 'assets/shader-gradient.frag'); 87894 * } 87895 * 87896 * function setup() { 87897 * createCanvas(100, 100, WEBGL); 87898 * 87899 * // initialize the colors for redGreen shader 87900 * shader(redGreen); 87901 * redGreen.setUniform('colorCenter', [1.0, 0.0, 0.0]); 87902 * redGreen.setUniform('colorBackground', [0.0, 1.0, 0.0]); 87903 * 87904 * // initialize the colors for orangeBlue shader 87905 * shader(orangeBlue); 87906 * orangeBlue.setUniform('colorCenter', [1.0, 0.5, 0.0]); 87907 * orangeBlue.setUniform('colorBackground', [0.226, 0.0, 0.615]); 87908 * 87909 * noStroke(); 87910 * } 87911 * 87912 * function draw() { 87913 * // update the offset values for each shader, 87914 * // moving orangeBlue in vertical and redGreen 87915 * // in horizontal direction 87916 * orangeBlue.setUniform('offset', [0, sin(millis() / 2000) + 1]); 87917 * redGreen.setUniform('offset', [sin(millis() / 2000), 1]); 87918 * 87919 * if (showRedGreen === true) { 87920 * shader(redGreen); 87921 * } else { 87922 * shader(orangeBlue); 87923 * } 87924 * quad(-1, -1, 1, -1, 1, 1, -1, 1); 87925 * } 87926 * 87927 * function mouseClicked() { 87928 * showRedGreen = !showRedGreen; 87929 * } 87930 * </code> 87931 * </div> 87932 * 87933 * @alt 87934 * 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. 87935 */ 87936 _main.default.prototype.shader = function(s) { 87937 this._assert3d('shader'); 87938 _main.default._validateParameters('shader', arguments); 87939 87940 if (s._renderer === undefined) { 87941 s._renderer = this._renderer; 87942 } 87943 87944 if (s.isStrokeShader()) { 87945 this._renderer.userStrokeShader = s; 87946 } else { 87947 this._renderer.userFillShader = s; 87948 this._renderer._useNormalMaterial = false; 87949 } 87950 87951 s.init(); 87952 87953 return this; 87954 }; 87955 87956 /** 87957 * This function restores the default shaders in WEBGL mode. Code that runs 87958 * after resetShader() will not be affected by previously defined 87959 * shaders. Should be run after <a href="#/p5/shader">shader()</a>. 87960 * 87961 * @method resetShader 87962 * @chainable 87963 */ 87964 _main.default.prototype.resetShader = function() { 87965 this._renderer.userFillShader = this._renderer.userStrokeShader = null; 87966 return this; 87967 }; 87968 87969 /** 87970 * Normal material for geometry is a material that is not affected by light. 87971 * It is not reflective and is a placeholder material often used for debugging. 87972 * Surfaces facing the X-axis, become red, those facing the Y-axis, become green and those facing the Z-axis, become blue. 87973 * You can view all possible materials in this 87974 * <a href="https://p5js.org/examples/3d-materials.html">example</a>. 87975 * @method normalMaterial 87976 * @chainable 87977 * @example 87978 * <div> 87979 * <code> 87980 * function setup() { 87981 * createCanvas(100, 100, WEBGL); 87982 * } 87983 * 87984 * function draw() { 87985 * background(200); 87986 * normalMaterial(); 87987 * sphere(40); 87988 * } 87989 * </code> 87990 * </div> 87991 * @alt 87992 * Red, green and blue gradient. 87993 */ 87994 _main.default.prototype.normalMaterial = function() { 87995 this._assert3d('normalMaterial'); 87996 for ( 87997 var _len = arguments.length, args = new Array(_len), _key = 0; 87998 _key < _len; 87999 _key++ 88000 ) { 88001 args[_key] = arguments[_key]; 88002 } 88003 _main.default._validateParameters('normalMaterial', args); 88004 this._renderer.drawMode = constants.FILL; 88005 this._renderer._useSpecularMaterial = false;
88006 this._renderer._useEmissiveMaterial = false; 88007 this._renderer._useNormalMaterial = true; 88008 this._renderer.curFillColor = [1, 1, 1, 1]; 88009 this._renderer._setProperty('_doFill', true); 88010 this.noStroke(); 88011 return this; 88012 }; 88013 88014 /** 88015 * Texture for geometry. You can view other possible materials in this 88016 * <a href="https://p5js.org/examples/3d-materials.html">example</a>. 88017 * @method texture 88018 * @param {p5.Image|p5.MediaElement|p5.Graphics} tex 2-dimensional graphics 88019 * to render as texture 88020 * @chainable 88021 * @example 88022 * <div> 88023 * <code> 88024 * let img; 88025 * function preload() { 88026 * img = loadImage('assets/laDefense.jpg'); 88027 * } 88028 * 88029 * function setup() { 88030 * createCanvas(100, 100, WEBGL); 88031 * } 88032 * 88033 * function draw() { 88034 * background(0); 88035 * rotateZ(frameCount * 0.01); 88036 * rotateX(frameCount * 0.01); 88037 * rotateY(frameCount * 0.01); 88038 * //pass image as texture 88039 * texture(img); 88040 * box(200, 200, 200); 88041 * } 88042 * </code> 88043 * </div> 88044 * 88045 * <div> 88046 * <code> 88047 * let pg; 88048 * 88049 * function setup() { 88050 * createCanvas(100, 100, WEBGL); 88051 * pg = createGraphics(200, 200); 88052 * pg.textSize(75); 88053 * } 88054 * 88055 * function draw() { 88056 * background(0); 88057 * pg.background(255); 88058 * pg.text('hello!', 0, 100); 88059 * //pass image as texture 88060 * texture(pg); 88061 * rotateX(0.5); 88062 * noStroke(); 88063 * plane(50); 88064 * } 88065 * </code> 88066 * </div> 88067 * 88068 * <div> 88069 * <code> 88070 * let vid; 88071 * function preload() { 88072 * vid = createVideo('assets/fingers.mov'); 88073 * vid.hide(); 88074 * } 88075 * function setup() { 88076 * createCanvas(100, 100, WEBGL); 88077 * } 88078 * 88079 * function draw() { 88080 * background(0); 88081 * //pass video frame as texture 88082 * texture(vid); 88083 * rect(-40, -40, 80, 80); 88084 * } 88085 * 88086 * function mousePressed() { 88087 * vid.loop(); 88088 * } 88089 * </code> 88090 * </div> 88091 * 88092 * @alt 88093 * Rotating view of many images umbrella and grid roof on a 3d plane 88094 * black canvas 88095 * black canvas 88096 */ 88097 _main.default.prototype.texture = function(tex) { 88098 this._assert3d('texture'); 88099 _main.default._validateParameters('texture', arguments); 88100 if (tex.gifProperties) { 88101 tex._animateGif(this); 88102 } 88103 88104 this._renderer.drawMode = constants.TEXTURE; 88105 this._renderer._useSpecularMaterial = false; 88106 this._renderer._useEmissiveMaterial = false; 88107 this._renderer._useNormalMaterial = false; 88108 this._renderer._tex = tex; 88109 this._renderer._setProperty('_doFill', true); 88110 88111 return this; 88112 }; 88113 88114 /** 88115 * Sets the coordinate space for texture mapping. The default mode is IMAGE 88116 * which refers to the actual coordinates of the image. 88117 * NORMAL refers to a normalized space of values ranging from 0 to 1. 88118 * This function only works in WEBGL mode. 88119 * 88120 * With IMAGE, if an image is 100 x 200 pixels, mapping the image onto the entire 88121 * size of a quad would require the points (0,0) (100, 0) (100,200) (0,200). 88122 * The same mapping in NORMAL is (0,0) (1,0) (1,1) (0,1). 88123 * @method textureMode 88124 * @param {Constant} mode either IMAGE or NORMAL 88125 * @example 88126 * <div> 88127 * <code> 88128 * let img; 88129 * 88130 * function preload() { 88131 * img = loadImage('assets/laDefense.jpg'); 88132 * } 88133 * 88134 * function setup() { 88135 * createCanvas(100, 100, WEBGL); 88136 * } 88137 * 88138 * function draw() { 88139 * texture(img); 88140 * textureMode(NORMAL); 88141 * beginShape(); 88142 * vertex(-50, -50, 0, 0); 88143 * vertex(50, -50, 1, 0); 88144 * vertex(50, 50, 1, 1); 88145 * vertex(-50, 50, 0, 1); 88146 * endShape(); 88147 * } 88148 * </code> 88149 * </div> 88150 * 88151 * @alt 88152 * the underside of a white umbrella and gridded ceiling above 88153 * 88154 * <div> 88155 * <code> 88156 * let img; 88157 * 88158 * function preload() { 88159 * img = loadImage('assets/laDefense.jpg'); 88160 * } 88161 * 88162 * function setup() { 88163 * createCanvas(100, 100, WEBGL); 88164 * } 88165 * 88166 * function draw() { 88167 * texture(img); 88168 * textureMode(NORMAL); 88169 * beginShape(); 88170 * vertex(-50, -50, 0, 0); 88171 * vertex(50, -50, img.width, 0); 88172 * vertex(50, 50, img.width, img.height); 88173 * vertex(-50, 50, 0, img.height); 88174 * endShape(); 88175 * } 88176 * </code> 88177 * </div> 88178 * 88179 * @alt 88180 * the underside of a white umbrella and gridded ceiling above 88181 */ 88182 _main.default.prototype.textureMode = function(mode) { 88183 if (mode !== constants.IMAGE && mode !== constants.NORMAL) { 88184 console.warn( 88185 'You tried to set '.concat( 88186 mode, 88187 ' textureMode only supports IMAGE & NORMAL ' 88188 ) 88189 ); 88190 } else { 88191 this._renderer.textureMode = mode; 88192 } 88193 }; 88194 88195 /** 88196 * Sets the global texture wrapping mode. This controls how textures behave 88197 * when their uv's go outside of the 0 - 1 range. There are three options: 88198 * CLAMP, REPEAT, and MIRROR. 88199 * 88200 * CLAMP causes the pixels at the edge of the texture to extend to the bounds 88201 * REPEAT causes the texture to tile repeatedly until reaching the bounds 88202 * MIRROR works similarly to REPEAT but it flips the texture with every new tile 88203 * 88204 * REPEAT & MIRROR are only available if the texture 88205 * is a power of two size (128, 256, 512, 1024, etc.). 88206 * 88207 * This method will affect all textures in your sketch until a subsequent 88208 * textureWrap call is made. 88209 * 88210 * If only one argument is provided, it will be applied to both the 88211 * horizontal and vertical axes. 88212 * @method textureWrap 88213 * @param {Constant} wrapX either CLAMP, REPEAT, or MIRROR 88214 * @param {Constant} [wrapY] either CLAMP, REPEAT, or MIRROR 88215 * @example 88216 * <div> 88217 * <code> 88218 * let img; 88219 * function preload() { 88220 * img = loadImage('assets/rockies128.jpg'); 88221 * } 88222 * 88223 * function setup() { 88224 * createCanvas(100, 100, WEBGL); 88225 * textureWrap(MIRROR); 88226 * } 88227 * 88228 * function draw() { 88229 * background(0); 88230 * 88231 * let dX = mouseX; 88232 * let dY = mouseY; 88233 * 88234 * let u = lerp(1.0, 2.0, dX); 88235 * let v = lerp(1.0, 2.0, dY); 88236 * 88237 * scale(width / 2); 88238 * 88239 * texture(img); 88240 * 88241 * beginShape(TRIANGLES); 88242 * vertex(-1, -1, 0, 0, 0); 88243 * vertex(1, -1, 0, u, 0); 88244 * vertex(1, 1, 0, u, v); 88245 * 88246 * vertex(1, 1, 0, u, v); 88247 * vertex(-1, 1, 0, 0, v); 88248 * vertex(-1, -1, 0, 0, 0); 88249 * endShape(); 88250 * } 88251 * </code> 88252 * </div> 88253 * 88254 * @alt 88255 * an image of the rocky mountains repeated in mirrored tiles 88256 */ 88257 _main.default.prototype.textureWrap = function(wrapX) { 88258 var wrapY = 88259 arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : wrapX; 88260 this._renderer.textureWrapX = wrapX; 88261 this._renderer.textureWrapY = wrapY; 88262 88263 var textures = this._renderer.textures; 88264 for (var i = 0; i < textures.length; i++) { 88265 textures[i].setWrapMode(wrapX, wrapY); 88266 } 88267 }; 88268 88269 /** 88270 * Ambient material for geometry with a given color. Ambient material defines the color the object reflects under any lighting. 88271 * 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. 88272 * Here's an <a href="https://p5js.org/examples/3d-materials.html">example containing all possible materials</a>. 88273 * @method ambientMaterial 88274 * @param {Number} v1 gray value, red or hue value 88275 * (depending on the current color mode), 88276 * @param {Number} [v2] green or saturation value 88277 * @param {Number} [v3] blue or brightness value 88278 * @chainable 88279 * @example 88280 * <div> 88281 * <code> 88282 * function setup() { 88283 * createCanvas(100, 100, WEBGL); 88284 * } 88285 * function draw() { 88286 * background(0); 88287 * noStroke(); 88288 * ambientLight(200); 88289 * ambientMaterial(70, 130, 230); 88290 * sphere(40); 88291 * } 88292 * </code> 88293 * </div> 88294 * <div> 88295 * <code> 88296 * // ambientLight is both red and blue (magenta), 88297 * // so object only reflects it's red and blue components 88298 * function setup() { 88299 * createCanvas(100, 100, WEBGL); 88300 * } 88301 * function draw() { 88302 * background(70); 88303 * ambientLight(100); // white light 88304 * ambientMaterial(255, 0, 255); // pink material 88305 * box(30); 88306 * } 88307 * </code> 88308 * </div> 88309 * <div> 88310 * <code> 88311 * // ambientLight is green. Since object does not contain 88312 * // green, it does not reflect any light 88313 * function setup() { 88314 * createCanvas(100, 100, WEBGL); 88315 * } 88316 * function draw() { 88317 * background(70); 88318 * ambientLight(0, 255, 0); // green light 88319 * ambientMaterial(255, 0, 255); // pink material 88320 * box(30); 88321 * } 88322 * </code> 88323 * </div> 88324 * @alt 88325 * radiating light source from top right of canvas 88326 * box reflecting only red and blue light 88327 * box reflecting no light 88328 */ 88329 /** 88330 * @method ambientMaterial 88331 * @param {Number[]|String|p5.Color} color color, color Array, or CSS color string 88332 * @chainable 88333 */ 88334 _main.default.prototype.ambientMaterial = function(v1, v2, v3) { 88335 this._assert3d('ambientMaterial'); 88336 _main.default._validateParameters('ambientMaterial', arguments); 88337 88338 var color = _main.default.prototype.color.apply(this, arguments); 88339 this._renderer.curFillColor = color._array; 88340 this._renderer._useSpecularMaterial = false;
88341 this._renderer._useEmissiveMaterial = false; 88342 this._renderer._useNormalMaterial = false; 88343 this._renderer._enableLighting = true; 88344 this._renderer._tex = null; 88345 88346 return this; 88347 }; 88348 88349 /** 88350 * Sets the emissive color of the material used for geometry drawn to 88351 * the screen. This is a misnomer in the sense that the material does not 88352 * actually emit light that effects surrounding polygons. Instead, 88353 * it gives the appearance that the object is glowing. An emissive material 88354 * will display at full strength even if there is no light for it to reflect. 88355 * @method emissiveMaterial 88356 * @param {Number} v1 gray value, red or hue value 88357 * (depending on the current color mode), 88358 * @param {Number} [v2] green or saturation value 88359 * @param {Number} [v3] blue or brightness value 88360 * @param {Number} [a] opacity 88361 * @chainable 88362 * @example 88363 * <div> 88364 * <code> 88365 * function setup() { 88366 * createCanvas(100, 100, WEBGL); 88367 * } 88368 * function draw() { 88369 * background(0); 88370 * noStroke(); 88371 * ambientLight(0); 88372 * emissiveMaterial(130, 230, 0); 88373 * sphere(40); 88374 * } 88375 * </code> 88376 * </div> 88377 * 88378 * @alt 88379 * radiating light source from top right of canvas 88380 */ 88381 /** 88382 * @method emissiveMaterial 88383 * @param {Number[]|String|p5.Color} color color, color Array, or CSS color string 88384 * @chainable 88385 */ 88386 _main.default.prototype.emissiveMaterial = function(v1, v2, v3, a) { 88387 this._assert3d('emissiveMaterial'); 88388 _main.default._validateParameters('emissiveMaterial', arguments); 88389 88390 var color = _main.default.prototype.color.apply(this, arguments); 88391 this._renderer.curFillColor = color._array; 88392 this._renderer._useSpecularMaterial = false; 88393 this._renderer._useEmissiveMaterial = true; 88394 this._renderer._useNormalMaterial = false; 88395 this._renderer._enableLighting = true; 88396 this._renderer._tex = null; 88397 88398 return this; 88399 }; 88400 88401 /** 88402 * Specular material for geometry with a given color. Specular material is a shiny reflective material. 88403 * Like ambient material it also defines the color the object reflects under ambient lighting. 88404 * 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. 88405 * 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. 88406 * Here's an <a href="https://p5js.org/examples/3d-materials.html">example containing all possible materials</a>. 88407 * 88408 * @method specularMaterial 88409 * @param {Number} gray number specifying value between white and black. 88410 * @param {Number} [alpha] alpha value relative to current color range 88411 * (default is 0-255) 88412 * @chainable 88413 */ 88414 88415 /** 88416 * @method specularMaterial 88417 * @param {Number} v1 red or hue value relative to 88418 * the current color range 88419 * @param {Number} v2 green or saturation value 88420 * relative to the current color range 88421 * @param {Number} v3 blue or brightness value 88422 * relative to the current color range 88423 * @param {Number} [alpha] 88424 * @chainable 88425 * 88426 * @example 88427 * <div> 88428 * <code> 88429 * function setup() { 88430 * createCanvas(100, 100, WEBGL); 88431 * } 88432 * function draw() { 88433 * background(0); 88434 * ambientLight(50); 88435 * pointLight(250, 250, 250, 100, 100, 30); 88436 * specularMaterial(250); 88437 * sphere(40); 88438 * } 88439 * </code> 88440 * </div> 88441 * @alt 88442 * diffused radiating light source from top right of canvas 88443 */ 88444 88445 /** 88446 * @method specularMaterial 88447 * @param {Number[]|String|p5.Color} color color Array, or CSS color string 88448 * @chainable 88449 */ 88450 _main.default.prototype.specularMaterial = function(v1, v2, v3, alpha) { 88451 this._assert3d('specularMaterial'); 88452 _main.default._validateParameters('specularMaterial', arguments); 88453 88454 var color = _main.default.prototype.color.apply(this, arguments); 88455 this._renderer.curFillColor = color._array; 88456 this._renderer._useSpecularMaterial = true; 88457 this._renderer._useEmissiveMaterial = false;
88458 this._renderer._useNormalMaterial = false; 88459 this._renderer._enableLighting = true; 88460 this._renderer._tex = null; 88461 88462 return this; 88463 }; 88464 88465 /** 88466 * Sets the amount of gloss in the surface of shapes. 88467 * Used in combination with specularMaterial() in setting 88468 * the material properties of shapes. The default and minimum value is 1. 88469 * @method shininess 88470 * @param {Number} shine Degree of Shininess. 88471 * Defaults to 1. 88472 * @chainable 88473 * @example 88474 * <div> 88475 * <code> 88476 * function setup() { 88477 * createCanvas(100, 100, WEBGL); 88478 * } 88479 * function draw() { 88480 * background(0); 88481 * noStroke(); 88482 * let locX = mouseX - width / 2; 88483 * let locY = mouseY - height / 2; 88484 * ambientLight(60, 60, 60); 88485 * pointLight(255, 255, 255, locX, locY, 50); 88486 * specularMaterial(250); 88487 * translate(-25, 0, 0); 88488 * shininess(1); 88489 * sphere(20); 88490 * translate(50, 0, 0); 88491 * shininess(20); 88492 * sphere(20); 88493 * } 88494 * </code> 88495 * </div> 88496 * @alt 88497 * Shininess on Camera changes position with mouse 88498 */ 88499 _main.default.prototype.shininess = function(shine) { 88500 this._assert3d('shininess'); 88501 _main.default._validateParameters('shininess', arguments); 88502 88503 if (shine < 1) { 88504 shine = 1; 88505 } 88506 this._renderer._useShininess = shine; 88507 return this; 88508 }; 88509 88510 /** 88511 * @private blends colors according to color components. 88512 * If alpha value is less than 1, or non-standard blendMode 88513 * we need to enable blending on our gl context. 88514 * @param {Number[]} color [description] 88515 * @return {Number[]]} Normalized numbers array 88516 */ 88517 _main.default.RendererGL.prototype._applyColorBlend = function(colors) { 88518 var gl = this.GL; 88519 88520 var isTexture = this.drawMode === constants.TEXTURE; 88521 var doBlend = isTexture || colors[colors.length - 1] < 1.0 || this._isErasing; 88522 88523 if (doBlend !== this._isBlending) { 88524 if ( 88525 doBlend || 88526 (this.curBlendMode !== constants.BLEND && 88527 this.curBlendMode !== constants.ADD) 88528 ) { 88529 gl.enable(gl.BLEND); 88530 } else { 88531 gl.disable(gl.BLEND); 88532 } 88533 gl.depthMask(true); 88534 this._isBlending = doBlend; 88535 } 88536 this._applyBlendMode(); 88537 return colors; 88538 }; 88539 88540 /** 88541 * @private sets blending in gl context to curBlendMode 88542 * @param {Number[]} color [description] 88543 * @return {Number[]]} Normalized numbers array 88544 */ 88545 _main.default.RendererGL.prototype._applyBlendMode = function() { 88546 if (this._cachedBlendMode === this.curBlendMode) { 88547 return; 88548 } 88549 var gl = this.GL; 88550 switch (this.curBlendMode) { 88551 case constants.BLEND: 88552 case constants.ADD: 88553 gl.blendEquation(gl.FUNC_ADD); 88554 gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); 88555 break; 88556 case constants.REMOVE: 88557 gl.blendEquation(gl.FUNC_REVERSE_SUBTRACT); 88558 gl.blendFunc(gl.SRC_ALPHA, gl.DST_ALPHA); 88559 break; 88560 case constants.MULTIPLY: 88561 gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD); 88562 gl.blendFuncSeparate(gl.ZERO, gl.SRC_COLOR, gl.ONE, gl.ONE); 88563 break; 88564 case constants.SCREEN: 88565 gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD); 88566 gl.blendFuncSeparate(gl.ONE_MINUS_DST_COLOR, gl.ONE, gl.ONE, gl.ONE); 88567 break; 88568 case constants.EXCLUSION: 88569 gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD); 88570 gl.blendFuncSeparate( 88571 gl.ONE_MINUS_DST_COLOR, 88572 gl.ONE_MINUS_SRC_COLOR,
88573 gl.ONE, 88574 gl.ONE 88575 ); 88576 88577 break; 88578 case constants.REPLACE: 88579 gl.blendEquation(gl.FUNC_ADD); 88580 gl.blendFunc(gl.ONE, gl.ZERO); 88581 break; 88582 case constants.SUBTRACT: 88583 gl.blendEquationSeparate(gl.FUNC_REVERSE_SUBTRACT, gl.FUNC_ADD); 88584 gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE, gl.ONE, gl.ONE); 88585 break; 88586 case constants.DARKEST: 88587 if (this.blendExt) { 88588 gl.blendEquationSeparate(this.blendExt.MIN_EXT, gl.FUNC_ADD); 88589 gl.blendFuncSeparate(gl.ONE, gl.ONE, gl.ONE, gl.ONE); 88590 } else { 88591 console.warn( 88592 'blendMode(DARKEST) does not work in your browser in WEBGL mode.' 88593 ); 88594 } 88595 break; 88596 case constants.LIGHTEST: 88597 if (this.blendExt) { 88598 gl.blendEquationSeparate(this.blendExt.MAX_EXT, gl.FUNC_ADD); 88599 gl.blendFuncSeparate(gl.ONE, gl.ONE, gl.ONE, gl.ONE); 88600 } else { 88601 console.warn( 88602 'blendMode(LIGHTEST) does not work in your browser in WEBGL mode.' 88603 ); 88604 } 88605 break; 88606 default: 88607 console.error( 88608 'Oops! Somehow RendererGL set curBlendMode to an unsupported mode.' 88609 ); 88610 88611 break; 88612 } 88613 88614 if (!this._isErasing) { 88615 this._cachedBlendMode = this.curBlendMode; 88616 } 88617 }; 88618 var _default = _main.default; 88619 exports.default = _default; 88620 }, 88621 { '../core/constants': 48, '../core/main': 59, './p5.Texture': 115 } 88622 ], 88623 107: [ 88624 function(_dereq_, module, exports) { 88625 'use strict'; 88626 Object.defineProperty(exports, '__esModule', { value: true }); 88627 exports.default = void 0; 88628 88629 var _main = _interopRequireDefault(_dereq_('../core/main')); 88630 function _interopRequireDefault(obj) { 88631 return obj && obj.__esModule ? obj : { default: obj }; 88632 } /** //////////////////////////////////////////////////////////////////////////////// 88633 * @module Lights, Camera 88634 * @submodule Camera 88635 * @requires core 88636 */ 88637 // p5.Prototype Methods
88638 //////////////////////////////////////////////////////////////////////////////// 88639 /** 88640 * Sets the camera position for a 3D sketch. Parameters for this function define 88641 * the position for the camera, the center of the sketch (where the camera is 88642 * pointing), and an up direction (the orientation of the camera). 88643 * 88644 * This function simulates the movements of the camera, allowing objects to be 88645 * viewed from various angles. Remember, it does not move the objects themselves 88646 * but the camera instead. For example when centerX value is positive, the camera 88647 * is rotating to the right side of the sketch, so the object would seem like 88648 * moving to the left. 88649 * 88650 * See this <a href = "https://www.openprocessing.org/sketch/740258">example</a> 88651 * to view the position of your camera. 88652 * 88653 * When called with no arguments, this function creates a default camera 88654 * equivalent to 88655 * camera(0, 0, (height/2.0) / tan(PI*30.0 / 180.0), 0, 0, 0, 0, 1, 0); 88656 * @method camera 88657 * @constructor 88658 * @for p5 88659 * @param {Number} [x] camera position value on x axis 88660 * @param {Number} [y] camera position value on y axis 88661 * @param {Number} [z] camera position value on z axis 88662 * @param {Number} [centerX] x coordinate representing center of the sketch 88663 * @param {Number} [centerY] y coordinate representing center of the sketch 88664 * @param {Number} [centerZ] z coordinate representing center of the sketch 88665 * @param {Number} [upX] x component of direction 'up' from camera 88666 * @param {Number} [upY] y component of direction 'up' from camera 88667 * @param {Number} [upZ] z component of direction 'up' from camera 88668 * @chainable 88669 * @example 88670 * <div> 88671 * <code> 88672 * function setup() { 88673 * createCanvas(100, 100, WEBGL); 88674 * } 88675 * function draw() { 88676 * background(204); 88677 * //move the camera away from the plane by a sin wave 88678 * camera(0, 0, 20 + sin(frameCount * 0.01) * 10, 0, 0, 0, 0, 1, 0); 88679 * plane(10, 10); 88680 * } 88681 * </code> 88682 * </div> 88683 * 88684 * @example 88685 * <div> 88686 * <code> 88687 * //move slider to see changes! 88688 * //sliders control the first 6 parameters of camera() 88689 * let sliderGroup = []; 88690 * let X; 88691 * let Y; 88692 * let Z; 88693 * let centerX; 88694 * let centerY; 88695 * let centerZ; 88696 * let h = 20; 88697 * 88698 * function setup() { 88699 * createCanvas(100, 100, WEBGL); 88700 * //create sliders 88701 * for (var i = 0; i < 6; i++) { 88702 * if (i === 2) { 88703 * sliderGroup[i] = createSlider(10, 400, 200); 88704 * } else { 88705 * sliderGroup[i] = createSlider(-400, 400, 0); 88706 * } 88707 * h = map(i, 0, 6, 5, 85); 88708 * sliderGroup[i].position(10, height + h); 88709 * sliderGroup[i].style('width', '80px'); 88710 * } 88711 * } 88712 * 88713 * function draw() { 88714 * background(60); 88715 * // assigning sliders' value to each parameters 88716 * X = sliderGroup[0].value(); 88717 * Y = sliderGroup[1].value(); 88718 * Z = sliderGroup[2].value(); 88719 * centerX = sliderGroup[3].value(); 88720 * centerY = sliderGroup[4].value(); 88721 * centerZ = sliderGroup[5].value(); 88722 * camera(X, Y, Z, centerX, centerY, centerZ, 0, 1, 0); 88723 * stroke(255); 88724 * fill(255, 102, 94); 88725 * box(85); 88726 * } 88727 * </code> 88728 * </div> 88729 * @alt 88730 * White square repeatedly grows to fill canvas and then shrinks. 88731 * An interactive example of a red cube with 3 sliders for moving it across x, y, 88732 * z axis and 3 sliders for shifting it's center. 88733 */ _main.default.prototype.camera = function() { 88734 var _this$_renderer$_curC; 88735 this._assert3d('camera'); 88736 for ( 88737 var _len = arguments.length, args = new Array(_len), _key = 0; 88738 _key < _len; 88739 _key++ 88740 ) { 88741 args[_key] = arguments[_key]; 88742 }
88743 _main.default._validateParameters('camera', args); 88744 (_this$_renderer$_curC = this._renderer._curCamera).camera.apply( 88745 _this$_renderer$_curC, 88746 args 88747 ); 88748 return this; 88749 }; 88750 88751 /** 88752 * Sets a perspective projection for the camera in a 3D sketch. This projection 88753 * represents depth through foreshortening: objects that are close to the camera 88754 * appear their actual size while those that are further away from the camera 88755 * appear smaller. The parameters to this function define the viewing frustum 88756 * (the truncated pyramid within which objects are seen by the camera) through 88757 * vertical field of view, aspect ratio (usually width/height), and near and far 88758 * clipping planes. 88759 * 88760 * When called with no arguments, the defaults 88761 * provided are equivalent to 88762 * perspective(PI/3.0, width/height, eyeZ/10.0, eyeZ*10.0), where eyeZ 88763 * is equal to ((height/2.0) / tan(PI*60.0/360.0)); 88764 * @method perspective 88765 * @for p5 88766 * @param {Number} [fovy] camera frustum vertical field of view, 88767 * from bottom to top of view, in <a href="#/p5/angleMode">angleMode</a> units 88768 * @param {Number} [aspect] camera frustum aspect ratio 88769 * @param {Number} [near] frustum near plane length 88770 * @param {Number} [far] frustum far plane length 88771 * @chainable 88772 * @example 88773 * <div> 88774 * <code> 88775 * //drag the mouse to look around! 88776 * function setup() { 88777 * createCanvas(100, 100, WEBGL); 88778 * perspective(PI / 3.0, width / height, 0.1, 500); 88779 * } 88780 * function draw() { 88781 * background(200); 88782 * orbitControl(); 88783 * normalMaterial(); 88784 * 88785 * rotateX(-0.3); 88786 * rotateY(-0.2); 88787 * translate(0, 0, -50); 88788 * 88789 * push(); 88790 * translate(-15, 0, sin(frameCount / 30) * 95); 88791 * box(30); 88792 * pop(); 88793 * push(); 88794 * translate(15, 0, sin(frameCount / 30 + PI) * 95); 88795 * box(30); 88796 * pop(); 88797 * } 88798 * </code> 88799 * </div> 88800 * 88801 * @alt 88802 * two colored 3D boxes move back and forth, rotating as mouse is dragged. 88803 */ 88804 _main.default.prototype.perspective = function() { 88805 var _this$_renderer$_curC2; 88806 this._assert3d('perspective'); 88807 for ( 88808 var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; 88809 _key2 < _len2; 88810 _key2++ 88811 ) { 88812 args[_key2] = arguments[_key2]; 88813 } 88814 _main.default._validateParameters('perspective', args); 88815 (_this$_renderer$_curC2 = this._renderer._curCamera).perspective.apply( 88816 _this$_renderer$_curC2, 88817 args 88818 ); 88819 return this; 88820 }; 88821 88822 /** 88823 * Sets an orthographic projection for the camera in a 3D sketch and defines a 88824 * box-shaped viewing frustum within which objects are seen. In this projection, 88825 * all objects with the same dimension appear the same size, regardless of 88826 * whether they are near or far from the camera. The parameters to this 88827 * function specify the viewing frustum where left and right are the minimum and 88828 * maximum x values, top and bottom are the minimum and maximum y values, and near 88829 * and far are the minimum and maximum z values. If no parameters are given, the 88830 * default is used: ortho(-width/2, width/2, -height/2, height/2). 88831 * @method ortho 88832 * @for p5 88833 * @param {Number} [left] camera frustum left plane 88834 * @param {Number} [right] camera frustum right plane 88835 * @param {Number} [bottom] camera frustum bottom plane 88836 * @param {Number} [top] camera frustum top plane 88837 * @param {Number} [near] camera frustum near plane 88838 * @param {Number} [far] camera frustum far plane 88839 * @chainable 88840 * @example 88841 * <div> 88842 * <code> 88843 * //drag the mouse to look around! 88844 * //there's no vanishing point 88845 * function setup() { 88846 * createCanvas(100, 100, WEBGL); 88847 * ortho(-width / 2, width / 2, height / 2, -height / 2, 0, 500); 88848 * } 88849 * function draw() { 88850 * background(200); 88851 * orbitControl(); 88852 * normalMaterial(); 88853 * 88854 * rotateX(0.2); 88855 * rotateY(-0.2); 88856 * push(); 88857 * translate(-15, 0, sin(frameCount / 30) * 65); 88858 * box(30); 88859 * pop(); 88860 * push(); 88861 * translate(15, 0, sin(frameCount / 30 + PI) * 65); 88862 * box(30); 88863 * pop(); 88864 * } 88865 * </code> 88866 * </div> 88867 * 88868 * @alt 88869 * two 3D boxes move back and forth along same plane, rotating as mouse is dragged. 88870 */ 88871 _main.default.prototype.ortho = function() { 88872 var _this$_renderer$_curC3; 88873 this._assert3d('ortho'); 88874 for ( 88875 var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; 88876 _key3 < _len3; 88877 _key3++ 88878 ) { 88879 args[_key3] = arguments[_key3]; 88880 } 88881 _main.default._validateParameters('ortho', args); 88882 (_this$_renderer$_curC3 = this._renderer._curCamera).ortho.apply( 88883 _this$_renderer$_curC3, 88884 args 88885 ); 88886 return this; 88887 }; 88888 88889 /** 88890 * Sets a perspective matrix as defined by the parameters. 88891 * 88892 * A frustum is a geometric form: a pyramid with its top 88893 * cut off. With the viewer's eye at the imaginary top of
88894 * the pyramid, the six planes of the frustum act as clipping 88895 * planes when rendering a 3D view. Thus, any form inside the 88896 * clipping planes is visible; anything outside 88897 * those planes is not visible. 88898 * 88899 * Setting the frustum changes the perspective of the scene being rendered. 88900 * This can be achieved more simply in many cases by using 88901 * <a href="https://p5js.org/reference/#/p5/perspective">perspective()</a>. 88902 * 88903 * @method frustum 88904 * @for p5 88905 * @param {Number} [left] camera frustum left plane 88906 * @param {Number} [right] camera frustum right plane 88907 * @param {Number} [bottom] camera frustum bottom plane 88908 * @param {Number} [top] camera frustum top plane 88909 * @param {Number} [near] camera frustum near plane 88910 * @param {Number} [far] camera frustum far plane 88911 * @chainable 88912 * @example 88913 * <div> 88914 * <code> 88915 * function setup() { 88916 * createCanvas(100, 100, WEBGL); 88917 * setAttributes('antialias', true); 88918 * frustum(-0.1, 0.1, -0.1, 0.1, 0.1, 200); 88919 * } 88920 * function draw() { 88921 * background(200); 88922 * orbitControl(); 88923 * strokeWeight(10); 88924 * stroke(0, 0, 255); 88925 * noFill(); 88926 * 88927 * rotateY(-0.2); 88928 * rotateX(-0.3); 88929 * push(); 88930 * translate(-15, 0, sin(frameCount / 30) * 25); 88931 * box(30); 88932 * pop(); 88933 * push(); 88934 * translate(15, 0, sin(frameCount / 30 + PI) * 25); 88935 * box(30); 88936 * pop(); 88937 * } 88938 * </code> 88939 * </div> 88940 * 88941 * @alt 88942 * two 3D boxes move back and forth along same plane, rotating as mouse is dragged. 88943 */ 88944 _main.default.prototype.frustum = function() { 88945 var _this$_renderer$_curC4; 88946 this._assert3d('frustum'); 88947 for ( 88948 var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; 88949 _key4 < _len4; 88950 _key4++ 88951 ) { 88952 args[_key4] = arguments[_key4]; 88953 } 88954 _main.default._validateParameters('frustum', args); 88955 (_this$_renderer$_curC4 = this._renderer._curCamera).frustum.apply( 88956 _this$_renderer$_curC4, 88957 args 88958 ); 88959 return this; 88960 }; 88961
88962 //////////////////////////////////////////////////////////////////////////////// 88963 // p5.Camera 88964 //////////////////////////////////////////////////////////////////////////////// 88965 88966 /** 88967 * Creates a new <a href="#/p5.Camera">p5.Camera</a> object and tells the 88968 * renderer to use that camera. 88969 * Returns the p5.Camera object. 88970 * @method createCamera 88971 * @return {p5.Camera} The newly created camera object. 88972 * @for p5 88973 * @example 88974 * <div><code> 88975 * // Creates a camera object and animates it around a box. 88976 * let camera; 88977 * function setup() { 88978 * createCanvas(100, 100, WEBGL); 88979 * background(0); 88980 * camera = createCamera(); 88981 * setCamera(camera); 88982 * } 88983 * 88984 * function draw() { 88985 * camera.lookAt(0, 0, 0); 88986 * camera.setPosition(sin(frameCount / 60) * 200, 0, 100); 88987 * box(20); 88988 * } 88989 * </code></div> 88990 * 88991 * @alt 88992 * An example that creates a camera and moves it around the box. 88993 */ 88994 _main.default.prototype.createCamera = function() { 88995 this._assert3d('createCamera'); 88996 var _cam = new _main.default.Camera(this._renderer); 88997 88998 // compute default camera settings, then set a default camera 88999 _cam._computeCameraDefaultSettings(); 89000 _cam._setDefaultCamera(); 89001 89002 // set renderer current camera to the new camera 89003 this._renderer._curCamera = _cam; 89004 89005 return _cam; 89006 }; 89007 89008 /** 89009 * This class describes a camera for use in p5's 89010 * <a href="https://github.com/processing/p5.js/wiki/Getting-started-with-WebGL-in-p5"> 89011 * WebGL mode</a>. It contains camera position, orientation, and projection 89012 * information necessary for rendering a 3D scene. 89013 * 89014 * New p5.Camera objects can be made through the 89015 * <a href="#/p5/createCamera">createCamera()</a> function and controlled through 89016 * the methods described below. A camera created in this way will use a default 89017 * position in the scene and a default perspective projection until these 89018 * properties are changed through the various methods available. It is possible 89019 * to create multiple cameras, in which case the current camera 89020 * can be set through the <a href="#/p5/setCamera">setCamera()</a> method. 89021 * 89022 * Note: 89023 * The methods below operate in two coordinate systems: the 'world' coordinate 89024 * system describe positions in terms of their relationship to the origin along 89025 * the X, Y and Z axes whereas the camera's 'local' coordinate system 89026 * describes positions from the camera's point of view: left-right, up-down, 89027 * and forward-backward. The <a href="#/p5.Camera/move">move()</a> method, 89028 * for instance, moves the camera along its own axes, whereas the 89029 * <a href="#/p5.Camera/setPosition">setPosition()</a> 89030 * method sets the camera's position in world-space. 89031 * 89032 * @class p5.Camera 89033 * @param {rendererGL} rendererGL instance of WebGL renderer 89034 * @example 89035 * <div> 89036 * <code> 89037 * let cam; 89038 * let delta = 0.01; 89039 * 89040 * function setup() { 89041 * createCanvas(100, 100, WEBGL); 89042 * normalMaterial(); 89043 * cam = createCamera(); 89044 * // set initial pan angle 89045 * cam.pan(-0.8); 89046 * } 89047 * 89048 * function draw() { 89049 * background(200); 89050 * 89051 * // pan camera according to angle 'delta' 89052 * cam.pan(delta); 89053 * 89054 * // every 160 frames, switch direction 89055 * if (frameCount % 160 === 0) { 89056 * delta *= -1; 89057 * } 89058 * 89059 * rotateX(frameCount * 0.01); 89060 * translate(-100, 0, 0); 89061 * box(20); 89062 * translate(35, 0, 0); 89063 * box(20); 89064 * translate(35, 0, 0); 89065 * box(20); 89066 * translate(35, 0, 0); 89067 * box(20); 89068 * translate(35, 0, 0); 89069 * box(20); 89070 * translate(35, 0, 0); 89071 * box(20); 89072 * translate(35, 0, 0); 89073 * box(20); 89074 * } 89075 * </code> 89076 * </div> 89077 * 89078 * @alt 89079 * camera view pans left and right across a series of rotating 3D boxes. 89080 */ 89081 _main.default.Camera = function(renderer) { 89082 this._renderer = renderer; 89083 89084 this.cameraType = 'default'; 89085 89086 this.cameraMatrix = new _main.default.Matrix(); 89087 this.projMatrix = new _main.default.Matrix(); 89088 }; 89089
89090 //////////////////////////////////////////////////////////////////////////////// 89091 // Camera Projection Methods 89092 //////////////////////////////////////////////////////////////////////////////// 89093 89094 /** 89095 * Sets a perspective projection for a p5.Camera object and sets parameters 89096 * for that projection according to <a href="#/p5/perspective">perspective()</a> 89097 * syntax. 89098 * @method perspective 89099 * @for p5.Camera 89100 */ 89101 _main.default.Camera.prototype.perspective = function(fovy, aspect, near, far) { 89102 this.cameraType = arguments.length > 0 ? 'custom' : 'default'; 89103 if (typeof fovy === 'undefined') { 89104 fovy = this.defaultCameraFOV; 89105 // this avoids issue where setting angleMode(DEGREES) before calling 89106 // perspective leads to a smaller than expected FOV (because 89107 // _computeCameraDefaultSettings computes in radians) 89108 this.cameraFOV = fovy; 89109 } else { 89110 this.cameraFOV = this._renderer._pInst._toRadians(fovy); 89111 } 89112 if (typeof aspect === 'undefined') { 89113 aspect = this.defaultAspectRatio; 89114 } 89115 if (typeof near === 'undefined') { 89116 near = this.defaultCameraNear; 89117 } 89118 if (typeof far === 'undefined') { 89119 far = this.defaultCameraFar; 89120 } 89121 89122 if (near <= 0.0001) { 89123 near = 0.01; 89124 console.log( 89125 'Avoid perspective near plane values close to or below 0. ' + 89126 'Setting value to 0.01.' 89127 ); 89128 } 89129 89130 if (far < near) { 89131 console.log( 89132 'Perspective far plane value is less than near plane value. ' + 89133 'Nothing will be shown.' 89134 ); 89135 } 89136 89137 this.aspectRatio = aspect; 89138 this.cameraNear = near; 89139 this.cameraFar = far; 89140 89141 this.projMatrix = _main.default.Matrix.identity(); 89142 89143 var f = 1.0 / Math.tan(this.cameraFOV / 2); 89144 var nf = 1.0 / (this.cameraNear - this.cameraFar); 89145 89146 // prettier-ignore 89147 this.projMatrix.set(f / aspect, 0, 0, 0, 89148 0, -f, 0, 0, 89149 0, 0, (far + near) * nf, -1, 89150 0, 0, 2 * far * near * nf, 0); 89151 89152 if (this._isActive()) { 89153 this._renderer.uPMatrix.set( 89154 this.projMatrix.mat4[0], 89155 this.projMatrix.mat4[1], 89156 this.projMatrix.mat4[2], 89157 this.projMatrix.mat4[3], 89158 this.projMatrix.mat4[4], 89159 this.projMatrix.mat4[5], 89160 this.projMatrix.mat4[6], 89161 this.projMatrix.mat4[7], 89162 this.projMatrix.mat4[8], 89163 this.projMatrix.mat4[9], 89164 this.projMatrix.mat4[10], 89165 this.projMatrix.mat4[11], 89166 this.projMatrix.mat4[12], 89167 this.projMatrix.mat4[13], 89168 this.projMatrix.mat4[14], 89169 this.projMatrix.mat4[15] 89170 ); 89171 } 89172 }; 89173 89174 /** 89175 * Sets an orthographic projection for a p5.Camera object and sets parameters 89176 * for that projection according to <a href="#/p5/ortho">ortho()</a> syntax. 89177 * @method ortho 89178 * @for p5.Camera 89179 */ 89180 _main.default.Camera.prototype.ortho = function( 89181 left, 89182 right, 89183 bottom, 89184 top, 89185 near, 89186 far 89187 ) { 89188 if (left === undefined) left = -this._renderer.width / 2; 89189 if (right === undefined) right = +this._renderer.width / 2; 89190 if (bottom === undefined) bottom = -this._renderer.height / 2; 89191 if (top === undefined) top = +this._renderer.height / 2; 89192 if (near === undefined) near = 0; 89193 if (far === undefined) 89194 far = Math.max(this._renderer.width, this._renderer.height); 89195 89196 var w = right - left; 89197 var h = top - bottom; 89198 var d = far - near; 89199 89200 var x = +2.0 / w; 89201 var y = +2.0 / h; 89202 var z = -2.0 / d; 89203 89204 var tx = -(right + left) / w; 89205 var ty = -(top + bottom) / h; 89206 var tz = -(far + near) / d; 89207 89208 this.projMatrix = _main.default.Matrix.identity(); 89209 89210 // prettier-ignore
89211 this.projMatrix.set(x, 0, 0, 0, 89212 0, -y, 0, 0, 89213 0, 0, z, 0, 89214 tx, ty, tz, 1); 89215 89216 if (this._isActive()) { 89217 this._renderer.uPMatrix.set( 89218 this.projMatrix.mat4[0], 89219 this.projMatrix.mat4[1], 89220 this.projMatrix.mat4[2], 89221 this.projMatrix.mat4[3], 89222 this.projMatrix.mat4[4], 89223 this.projMatrix.mat4[5], 89224 this.projMatrix.mat4[6], 89225 this.projMatrix.mat4[7], 89226 this.projMatrix.mat4[8], 89227 this.projMatrix.mat4[9], 89228 this.projMatrix.mat4[10], 89229 this.projMatrix.mat4[11], 89230 this.projMatrix.mat4[12], 89231 this.projMatrix.mat4[13], 89232 this.projMatrix.mat4[14], 89233 this.projMatrix.mat4[15] 89234 ); 89235 } 89236 89237 this.cameraType = 'custom'; 89238 }; 89239 89240 /** 89241 * @method frustum 89242 * @for p5.Camera 89243 */ 89244 _main.default.Camera.prototype.frustum = function( 89245 left, 89246 right, 89247 bottom, 89248 top, 89249 near, 89250 far 89251 ) { 89252 if (left === undefined) left = -this._renderer.width / 2; 89253 if (right === undefined) right = +this._renderer.width / 2; 89254 if (bottom === undefined) bottom = -this._renderer.height / 2; 89255 if (top === undefined) top = +this._renderer.height / 2; 89256 if (near === undefined) near = 0; 89257 if (far === undefined) 89258 far = Math.max(this._renderer.width, this._renderer.height); 89259 89260 var w = right - left; 89261 var h = top - bottom; 89262 var d = far - near; 89263 89264 var x = +(2.0 * near) / w; 89265 var y = +(2.0 * near) / h; 89266 var z = -(2.0 * far * near) / d; 89267 89268 var tx = (right + left) / w; 89269 var ty = (top + bottom) / h; 89270 var tz = -(far + near) / d; 89271 89272 this.projMatrix = _main.default.Matrix.identity(); 89273 89274 // prettier-ignore 89275 this.projMatrix.set(x, 0, 0, 0, 89276 0, y, 0, 0, 89277 tx, ty, tz, -1, 89278 0, 0, z, 0); 89279 89280 if (this._isActive()) { 89281 this._renderer.uPMatrix.set( 89282 this.projMatrix.mat4[0], 89283 this.projMatrix.mat4[1], 89284 this.projMatrix.mat4[2], 89285 this.projMatrix.mat4[3], 89286 this.projMatrix.mat4[4], 89287 this.projMatrix.mat4[5], 89288 this.projMatrix.mat4[6], 89289 this.projMatrix.mat4[7], 89290 this.projMatrix.mat4[8], 89291 this.projMatrix.mat4[9], 89292 this.projMatrix.mat4[10], 89293 this.projMatrix.mat4[11], 89294 this.projMatrix.mat4[12], 89295 this.projMatrix.mat4[13], 89296 this.projMatrix.mat4[14], 89297 this.projMatrix.mat4[15] 89298 ); 89299 } 89300 89301 this.cameraType = 'custom'; 89302 }; 89303
89304 //////////////////////////////////////////////////////////////////////////////// 89305 // Camera Orientation Methods 89306 //////////////////////////////////////////////////////////////////////////////// 89307 89308 /** 89309 * Rotate camera view about arbitrary axis defined by x,y,z 89310 * based on http://learnwebgl.brown37.net/07_cameras/camera_rotating_motion.html 89311 * @method _rotateView 89312 * @private 89313 */ 89314 _main.default.Camera.prototype._rotateView = function(a, x, y, z) { 89315 var centerX = this.centerX; 89316 var centerY = this.centerY; 89317 var centerZ = this.centerZ; 89318 89319 // move center by eye position such that rotation happens around eye position 89320 centerX -= this.eyeX; 89321 centerY -= this.eyeY; 89322 centerZ -= this.eyeZ; 89323 89324 var rotation = _main.default.Matrix.identity(this._renderer._pInst); 89325 rotation.rotate(this._renderer._pInst._toRadians(a), x, y, z); 89326 89327 // prettier-ignore 89328 var rotatedCenter = [ 89329 centerX * rotation.mat4[0] + centerY * rotation.mat4[4] + centerZ * rotation.mat4[8], 89330 centerX * rotation.mat4[1] + centerY * rotation.mat4[5] + centerZ * rotation.mat4[9], 89331 centerX * rotation.mat4[2] + centerY * rotation.mat4[6] + centerZ * rotation.mat4[10]]; 89332 89333 // add eye position back into center 89334 rotatedCenter[0] += this.eyeX; 89335 rotatedCenter[1] += this.eyeY; 89336 rotatedCenter[2] += this.eyeZ; 89337 89338 this.camera( 89339 this.eyeX, 89340 this.eyeY, 89341 this.eyeZ, 89342 rotatedCenter[0], 89343 rotatedCenter[1], 89344 rotatedCenter[2], 89345 this.upX, 89346 this.upY, 89347 this.upZ 89348 ); 89349 }; 89350 89351 /** 89352 * Panning rotates the camera view to the left and right. 89353 * @method pan 89354 * @param {Number} angle amount to rotate camera in current 89355 * <a href="#/p5/angleMode">angleMode</a> units. 89356 * Greater than 0 values rotate counterclockwise (to the left). 89357 * @example 89358 * <div> 89359 * <code> 89360 * let cam; 89361 * let delta = 0.01; 89362 * 89363 * function setup() { 89364 * createCanvas(100, 100, WEBGL); 89365 * normalMaterial(); 89366 * cam = createCamera(); 89367 * // set initial pan angle 89368 * cam.pan(-0.8); 89369 * } 89370 * 89371 * function draw() { 89372 * background(200); 89373 * 89374 * // pan camera according to angle 'delta' 89375 * cam.pan(delta); 89376 * 89377 * // every 160 frames, switch direction 89378 * if (frameCount % 160 === 0) { 89379 * delta *= -1; 89380 * } 89381 * 89382 * rotateX(frameCount * 0.01); 89383 * translate(-100, 0, 0); 89384 * box(20); 89385 * translate(35, 0, 0); 89386 * box(20); 89387 * translate(35, 0, 0); 89388 * box(20); 89389 * translate(35, 0, 0); 89390 * box(20); 89391 * translate(35, 0, 0); 89392 * box(20); 89393 * translate(35, 0, 0); 89394 * box(20); 89395 * translate(35, 0, 0); 89396 * box(20); 89397 * } 89398 * </code> 89399 * </div> 89400 * 89401 * @alt 89402 * camera view pans left and right across a series of rotating 3D boxes. 89403 */ 89404 _main.default.Camera.prototype.pan = function(amount) { 89405 var local = this._getLocalAxes(); 89406 this._rotateView(amount, local.y[0], local.y[1], local.y[2]); 89407 }; 89408 89409 /** 89410 * Tilting rotates the camera view up and down. 89411 * @method tilt 89412 * @param {Number} angle amount to rotate camera in current 89413 * <a href="#/p5/angleMode">angleMode</a> units. 89414 * Greater than 0 values rotate counterclockwise (to the left). 89415 * @example 89416 * <div> 89417 * <code> 89418 * let cam; 89419 * let delta = 0.01; 89420 * 89421 * function setup() { 89422 * createCanvas(100, 100, WEBGL); 89423 * normalMaterial(); 89424 * cam = createCamera(); 89425 * // set initial tilt 89426 * cam.tilt(-0.8); 89427 * } 89428 * 89429 * function draw() { 89430 * background(200); 89431 * 89432 * // pan camera according to angle 'delta' 89433 * cam.tilt(delta); 89434 * 89435 * // every 160 frames, switch direction 89436 * if (frameCount % 160 === 0) { 89437 * delta *= -1; 89438 * } 89439 * 89440 * rotateY(frameCount * 0.01); 89441 * translate(0, -100, 0); 89442 * box(20); 89443 * translate(0, 35, 0); 89444 * box(20); 89445 * translate(0, 35, 0); 89446 * box(20); 89447 * translate(0, 35, 0); 89448 * box(20); 89449 * translate(0, 35, 0); 89450 * box(20); 89451 * translate(0, 35, 0); 89452 * box(20); 89453 * translate(0, 35, 0); 89454 * box(20); 89455 * } 89456 * </code> 89457 * </div> 89458 * 89459 * @alt 89460 * camera view tilts up and down across a series of rotating 3D boxes. 89461 */ 89462 _main.default.Camera.prototype.tilt = function(amount) { 89463 var local = this._getLocalAxes(); 89464 this._rotateView(amount, local.x[0], local.x[1], local.x[2]); 89465 }; 89466 89467 /** 89468 * Reorients the camera to look at a position in world space. 89469 * @method lookAt 89470 * @for p5.Camera 89471 * @param {Number} x x position of a point in world space 89472 * @param {Number} y y position of a point in world space 89473 * @param {Number} z z position of a point in world space 89474 * @example 89475 * <div> 89476 * <code> 89477 * let cam; 89478 * 89479 * function setup() { 89480 * createCanvas(100, 100, WEBGL); 89481 * normalMaterial(); 89482 * cam = createCamera(); 89483 * } 89484 * 89485 * function draw() { 89486 * background(200); 89487 * 89488 * // look at a new random point every 60 frames 89489 * if (frameCount % 60 === 0) { 89490 * cam.lookAt(random(-100, 100), random(-50, 50), 0); 89491 * } 89492 * 89493 * rotateX(frameCount * 0.01); 89494 * translate(-100, 0, 0); 89495 * box(20); 89496 * translate(35, 0, 0); 89497 * box(20); 89498 * translate(35, 0, 0); 89499 * box(20); 89500 * translate(35, 0, 0); 89501 * box(20); 89502 * translate(35, 0, 0); 89503 * box(20); 89504 * translate(35, 0, 0); 89505 * box(20); 89506 * translate(35, 0, 0); 89507 * box(20); 89508 * } 89509 * </code> 89510 * </div> 89511 * 89512 * @alt 89513 * camera view of rotating 3D cubes changes to look at a new random 89514 * point every second . 89515 */ 89516 _main.default.Camera.prototype.lookAt = function(x, y, z) { 89517 this.camera( 89518 this.eyeX, 89519 this.eyeY, 89520 this.eyeZ, 89521 x, 89522 y, 89523 z, 89524 this.upX, 89525 this.upY, 89526 this.upZ 89527 ); 89528 }; 89529
89530 //////////////////////////////////////////////////////////////////////////////// 89531 // Camera Position Methods 89532 //////////////////////////////////////////////////////////////////////////////// 89533 89534 /** 89535 * Sets a camera's position and orientation. This is equivalent to calling 89536 * <a href="#/p5/camera">camera()</a> on a p5.Camera object. 89537 * @method camera 89538 * @for p5.Camera 89539 */ 89540 _main.default.Camera.prototype.camera = function( 89541 eyeX, 89542 eyeY, 89543 eyeZ, 89544 centerX, 89545 centerY, 89546 centerZ, 89547 upX, 89548 upY, 89549 upZ 89550 ) { 89551 if (typeof eyeX === 'undefined') { 89552 eyeX = this.defaultEyeX; 89553 eyeY = this.defaultEyeY; 89554 eyeZ = this.defaultEyeZ; 89555 centerX = eyeX; 89556 centerY = eyeY; 89557 centerZ = 0; 89558 upX = 0; 89559 upY = 1; 89560 upZ = 0; 89561 } 89562 89563 this.eyeX = eyeX; 89564 this.eyeY = eyeY; 89565 this.eyeZ = eyeZ; 89566 89567 if (typeof centerX !== 'undefined') { 89568 this.centerX = centerX; 89569 this.centerY = centerY; 89570 this.centerZ = centerZ; 89571 } 89572 89573 if (typeof upX !== 'undefined') { 89574 this.upX = upX; 89575 this.upY = upY; 89576 this.upZ = upZ; 89577 } 89578 89579 var local = this._getLocalAxes(); 89580 89581 // the camera affects the model view matrix, insofar as it 89582 // inverse translates the world to the eye position of the camera 89583 // and rotates it. 89584 // prettier-ignore 89585 this.cameraMatrix.set(local.x[0], local.y[0], local.z[0], 0, 89586 local.x[1], local.y[1], local.z[1], 0, 89587 local.x[2], local.y[2], local.z[2], 0, 89588 0, 0, 0, 1); 89589 89590 var tx = -eyeX; 89591 var ty = -eyeY; 89592 var tz = -eyeZ; 89593 89594 this.cameraMatrix.translate([tx, ty, tz]); 89595 89596 if (this._isActive()) { 89597 this._renderer.uMVMatrix.set( 89598 this.cameraMatrix.mat4[0], 89599 this.cameraMatrix.mat4[1], 89600 this.cameraMatrix.mat4[2], 89601 this.cameraMatrix.mat4[3], 89602 this.cameraMatrix.mat4[4], 89603 this.cameraMatrix.mat4[5], 89604 this.cameraMatrix.mat4[6], 89605 this.cameraMatrix.mat4[7], 89606 this.cameraMatrix.mat4[8], 89607 this.cameraMatrix.mat4[9], 89608 this.cameraMatrix.mat4[10], 89609 this.cameraMatrix.mat4[11], 89610 this.cameraMatrix.mat4[12], 89611 this.cameraMatrix.mat4[13], 89612 this.cameraMatrix.mat4[14], 89613 this.cameraMatrix.mat4[15] 89614 ); 89615 } 89616 return this; 89617 }; 89618 89619 /** 89620 * Move camera along its local axes while maintaining current camera orientation. 89621 * @method move 89622 * @param {Number} x amount to move along camera's left-right axis 89623 * @param {Number} y amount to move along camera's up-down axis 89624 * @param {Number} z amount to move along camera's forward-backward axis 89625 * @example 89626 * <div> 89627 * <code> 89628 * // see the camera move along its own axes while maintaining its orientation 89629 * let cam; 89630 * let delta = 0.5; 89631 * 89632 * function setup() { 89633 * createCanvas(100, 100, WEBGL); 89634 * normalMaterial(); 89635 * cam = createCamera(); 89636 * } 89637 * 89638 * function draw() { 89639 * background(200); 89640 * 89641 * // move the camera along its local axes 89642 * cam.move(delta, delta, 0); 89643 * 89644 * // every 100 frames, switch direction 89645 * if (frameCount % 150 === 0) { 89646 * delta *= -1; 89647 * } 89648 * 89649 * translate(-10, -10, 0); 89650 * box(50, 8, 50); 89651 * translate(15, 15, 0); 89652 * box(50, 8, 50); 89653 * translate(15, 15, 0); 89654 * box(50, 8, 50); 89655 * translate(15, 15, 0); 89656 * box(50, 8, 50); 89657 * translate(15, 15, 0); 89658 * box(50, 8, 50); 89659 * translate(15, 15, 0); 89660 * box(50, 8, 50); 89661 * } 89662 * </code> 89663 * </div> 89664 * 89665 * @alt 89666 * camera view moves along a series of 3D boxes, maintaining the same 89667 * orientation throughout the move 89668 */ 89669 _main.default.Camera.prototype.move = function(x, y, z) { 89670 var local = this._getLocalAxes(); 89671 89672 // scale local axes by movement amounts 89673 // based on http://learnwebgl.brown37.net/07_cameras/camera_linear_motion.html 89674 var dx = [local.x[0] * x, local.x[1] * x, local.x[2] * x]; 89675 var dy = [local.y[0] * y, local.y[1] * y, local.y[2] * y]; 89676 var dz = [local.z[0] * z, local.z[1] * z, local.z[2] * z]; 89677 89678 this.camera( 89679 this.eyeX + dx[0] + dy[0] + dz[0], 89680 this.eyeY + dx[1] + dy[1] + dz[1], 89681 this.eyeZ + dx[2] + dy[2] + dz[2], 89682 this.centerX + dx[0] + dy[0] + dz[0], 89683 this.centerY + dx[1] + dy[1] + dz[1], 89684 this.centerZ + dx[2] + dy[2] + dz[2], 89685 0, 89686 1, 89687 0 89688 ); 89689 }; 89690 89691 /** 89692 * Set camera position in world-space while maintaining current camera 89693 * orientation. 89694 * @method setPosition 89695 * @param {Number} x x position of a point in world space 89696 * @param {Number} y y position of a point in world space 89697 * @param {Number} z z position of a point in world space 89698 * @example 89699 * <div> 89700 * <code> 89701 * // press '1' '2' or '3' keys to set camera position 89702 * 89703 * let cam; 89704 * 89705 * function setup() { 89706 * createCanvas(100, 100, WEBGL); 89707 * normalMaterial(); 89708 * cam = createCamera(); 89709 * } 89710 * 89711 * function draw() { 89712 * background(200); 89713 * 89714 * // '1' key 89715 * if (keyIsDown(49)) { 89716 * cam.setPosition(30, 0, 80); 89717 * } 89718 * // '2' key 89719 * if (keyIsDown(50)) { 89720 * cam.setPosition(0, 0, 80); 89721 * } 89722 * // '3' key 89723 * if (keyIsDown(51)) { 89724 * cam.setPosition(-30, 0, 80); 89725 * } 89726 * 89727 * box(20); 89728 * } 89729 * </code> 89730 * </div> 89731 * 89732 * @alt 89733 * camera position changes as the user presses keys, altering view of a 3D box 89734 */ 89735 _main.default.Camera.prototype.setPosition = function(x, y, z) { 89736 var diffX = x - this.eyeX; 89737 var diffY = y - this.eyeY; 89738 var diffZ = z - this.eyeZ; 89739 89740 this.camera( 89741 x, 89742 y, 89743 z, 89744 this.centerX + diffX, 89745 this.centerY + diffY, 89746 this.centerZ + diffZ, 89747 0, 89748 1, 89749 0 89750 ); 89751 }; 89752
89753 //////////////////////////////////////////////////////////////////////////////// 89754 // Camera Helper Methods 89755 //////////////////////////////////////////////////////////////////////////////// 89756 89757 // @TODO: combine this function with _setDefaultCamera to compute these values 89758 // as-needed 89759 _main.default.Camera.prototype._computeCameraDefaultSettings = function() { 89760 this.defaultCameraFOV = 60 / 180 * Math.PI; 89761 this.defaultAspectRatio = this._renderer.width / this._renderer.height; 89762 this.defaultEyeX = 0; 89763 this.defaultEyeY = 0; 89764 this.defaultEyeZ = 89765 this._renderer.height / 2.0 / Math.tan(this.defaultCameraFOV / 2.0); 89766 this.defaultCenterX = 0; 89767 this.defaultCenterY = 0; 89768 this.defaultCenterZ = 0; 89769 this.defaultCameraNear = this.defaultEyeZ * 0.1; 89770 this.defaultCameraFar = this.defaultEyeZ * 10; 89771 }; 89772 89773 //detect if user didn't set the camera 89774 //then call this function below 89775 _main.default.Camera.prototype._setDefaultCamera = function() { 89776 this.cameraFOV = this.defaultCameraFOV; 89777 this.aspectRatio = this.defaultAspectRatio; 89778 this.eyeX = this.defaultEyeX; 89779 this.eyeY = this.defaultEyeY; 89780 this.eyeZ = this.defaultEyeZ; 89781 this.centerX = this.defaultCenterX; 89782 this.centerY = this.defaultCenterY; 89783 this.centerZ = this.defaultCenterZ; 89784 this.upX = 0; 89785 this.upY = 1; 89786 this.upZ = 0; 89787 this.cameraNear = this.defaultCameraNear; 89788 this.cameraFar = this.defaultCameraFar; 89789 89790 this.perspective(); 89791 this.camera(); 89792 89793 this.cameraType = 'default'; 89794 }; 89795 89796 _main.default.Camera.prototype._resize = function() { 89797 // If we're using the default camera, update the aspect ratio 89798 if (this.cameraType === 'default') { 89799 this._computeCameraDefaultSettings(); 89800 this._setDefaultCamera(); 89801 } else { 89802 this.perspective( 89803 this.cameraFOV, 89804 this._renderer.width / this._renderer.height 89805 ); 89806 } 89807 }; 89808 89809 /** 89810 * Returns a copy of a camera. 89811 * @method copy 89812 * @private 89813 */ 89814 _main.default.Camera.prototype.copy = function() { 89815 var _cam = new _main.default.Camera(this._renderer); 89816 _cam.cameraFOV = this.cameraFOV; 89817 _cam.aspectRatio = this.aspectRatio; 89818 _cam.eyeX = this.eyeX; 89819 _cam.eyeY = this.eyeY; 89820 _cam.eyeZ = this.eyeZ; 89821 _cam.centerX = this.centerX; 89822 _cam.centerY = this.centerY; 89823 _cam.centerZ = this.centerZ; 89824 _cam.cameraNear = this.cameraNear; 89825 _cam.cameraFar = this.cameraFar; 89826 89827 _cam.cameraType = this.cameraType; 89828 89829 _cam.cameraMatrix = this.cameraMatrix.copy(); 89830 _cam.projMatrix = this.projMatrix.copy(); 89831 89832 return _cam; 89833 }; 89834 89835 /** 89836 * Returns a camera's local axes: left-right, up-down, and forward-backward, 89837 * as defined by vectors in world-space. 89838 * @method _getLocalAxes 89839 * @private 89840 */ 89841 _main.default.Camera.prototype._getLocalAxes = function() { 89842 // calculate camera local Z vector 89843 var z0 = this.eyeX - this.centerX; 89844 var z1 = this.eyeY - this.centerY; 89845 var z2 = this.eyeZ - this.centerZ; 89846 89847 // normalize camera local Z vector 89848 var eyeDist = Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2); 89849 if (eyeDist !== 0) { 89850 z0 /= eyeDist; 89851 z1 /= eyeDist; 89852 z2 /= eyeDist; 89853 } 89854 89855 // calculate camera Y vector 89856 var y0 = this.upX; 89857 var y1 = this.upY; 89858 var y2 = this.upZ; 89859 89860 // compute camera local X vector as up vector (local Y) cross local Z 89861 var x0 = y1 * z2 - y2 * z1; 89862 var x1 = -y0 * z2 + y2 * z0; 89863 var x2 = y0 * z1 - y1 * z0; 89864 89865 // recompute y = z cross x 89866 y0 = z1 * x2 - z2 * x1; 89867 y1 = -z0 * x2 + z2 * x0; 89868 y2 = z0 * x1 - z1 * x0; 89869 89870 // cross product gives area of parallelogram, which is < 1.0 for 89871 // non-perpendicular unit-length vectors; so normalize x, y here: 89872 var xmag = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2); 89873 if (xmag !== 0) { 89874 x0 /= xmag; 89875 x1 /= xmag; 89876 x2 /= xmag; 89877 } 89878 89879 var ymag = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2); 89880 if (ymag !== 0) { 89881 y0 /= ymag; 89882 y1 /= ymag; 89883 y2 /= ymag; 89884 } 89885 89886 return { 89887 x: [x0, x1, x2], 89888 y: [y0, y1, y2], 89889 z: [z0, z1, z2] 89890 }; 89891 }; 89892 89893 /** 89894 * Orbits the camera about center point. For use with orbitControl(). 89895 * @method _orbit 89896 * @private 89897 * @param {Number} dTheta change in spherical coordinate theta 89898 * @param {Number} dPhi change in spherical coordinate phi 89899 * @param {Number} dRadius change in radius 89900 */ 89901 _main.default.Camera.prototype._orbit = function(dTheta, dPhi, dRadius) { 89902 var diffX = this.eyeX - this.centerX; 89903 var diffY = this.eyeY - this.centerY; 89904 var diffZ = this.eyeZ - this.centerZ; 89905 89906 // get spherical coorinates for current camera position about origin 89907 var camRadius = Math.sqrt(diffX * diffX + diffY * diffY + diffZ * diffZ); 89908 // from https://github.com/mrdoob/three.js/blob/dev/src/math/Spherical.js#L72-L73 89909 var camTheta = Math.atan2(diffX, diffZ); // equatorial angle 89910 var camPhi = Math.acos(Math.max(-1, Math.min(1, diffY / camRadius))); // polar angle 89911 89912 // add change 89913 camTheta += dTheta; 89914 camPhi += dPhi; 89915 camRadius += dRadius; 89916 89917 // prevent zooming through the center: 89918 if (camRadius < 0) { 89919 camRadius = 0.1; 89920 } 89921 89922 // prevent rotation over the zenith / under bottom 89923 if (camPhi > Math.PI) { 89924 camPhi = Math.PI; 89925 } else if (camPhi <= 0) { 89926 camPhi = 0.001; 89927 } 89928 89929 // from https://github.com/mrdoob/three.js/blob/dev/src/math/Vector3.js#L628-L632 89930 var _x = Math.sin(camPhi) * camRadius * Math.sin(camTheta); 89931 var _y = Math.cos(camPhi) * camRadius; 89932 var _z = Math.sin(camPhi) * camRadius * Math.cos(camTheta); 89933 89934 this.camera( 89935 _x + this.centerX, 89936 _y + this.centerY, 89937 _z + this.centerZ, 89938 this.centerX, 89939 this.centerY, 89940 this.centerZ, 89941 0, 89942 1, 89943 0 89944 ); 89945 }; 89946 89947 /** 89948 * Returns true if camera is currently attached to renderer. 89949 * @method _isActive 89950 * @private 89951 */ 89952 _main.default.Camera.prototype._isActive = function() { 89953 return this === this._renderer._curCamera; 89954 }; 89955 89956 /** 89957 * Sets rendererGL's current camera to a p5.Camera object. Allows switching 89958 * between multiple cameras. 89959 * @method setCamera 89960 * @param {p5.Camera} cam p5.Camera object 89961 * @for p5 89962 * @example 89963 * <div> 89964 * <code> 89965 * let cam1, cam2; 89966 * let currentCamera; 89967 * 89968 * function setup() { 89969 * createCanvas(100, 100, WEBGL); 89970 * normalMaterial(); 89971 * 89972 * cam1 = createCamera(); 89973 * cam2 = createCamera(); 89974 * cam2.setPosition(30, 0, 50); 89975 * cam2.lookAt(0, 0, 0); 89976 * cam2.ortho(); 89977 * 89978 * // set variable for previously active camera: 89979 * currentCamera = 1; 89980 * } 89981 * 89982 * function draw() { 89983 * background(200); 89984 * 89985 * // camera 1: 89986 * cam1.lookAt(0, 0, 0); 89987 * cam1.setPosition(sin(frameCount / 60) * 200, 0, 100); 89988 * 89989 * // every 100 frames, switch between the two cameras 89990 * if (frameCount % 100 === 0) { 89991 * if (currentCamera === 1) { 89992 * setCamera(cam1); 89993 * currentCamera = 0; 89994 * } else { 89995 * setCamera(cam2); 89996 * currentCamera = 1; 89997 * } 89998 * } 89999 * 90000 * drawBoxes(); 90001 * } 90002 * 90003 * function drawBoxes() { 90004 * rotateX(frameCount * 0.01); 90005 * translate(-100, 0, 0); 90006 * box(20); 90007 * translate(35, 0, 0); 90008 * box(20); 90009 * translate(35, 0, 0); 90010 * box(20); 90011 * translate(35, 0, 0); 90012 * box(20); 90013 * translate(35, 0, 0); 90014 * box(20); 90015 * translate(35, 0, 0); 90016 * box(20); 90017 * translate(35, 0, 0); 90018 * box(20); 90019 * } 90020 * </code> 90021 * </div> 90022 * 90023 * @alt 90024 * Canvas switches between two camera views, each showing a series of spinning 90025 * 3D boxes. 90026 */ 90027 _main.default.prototype.setCamera = function(cam) { 90028 this._renderer._curCamera = cam; 90029 90030 // set the projection matrix (which is not normally updated each frame) 90031 this._renderer.uPMatrix.set( 90032 cam.projMatrix.mat4[0], 90033 cam.projMatrix.mat4[1], 90034 cam.projMatrix.mat4[2], 90035 cam.projMatrix.mat4[3], 90036 cam.projMatrix.mat4[4], 90037 cam.projMatrix.mat4[5], 90038 cam.projMatrix.mat4[6], 90039 cam.projMatrix.mat4[7], 90040 cam.projMatrix.mat4[8], 90041 cam.projMatrix.mat4[9], 90042 cam.projMatrix.mat4[10], 90043 cam.projMatrix.mat4[11], 90044 cam.projMatrix.mat4[12], 90045 cam.projMatrix.mat4[13], 90046 cam.projMatrix.mat4[14], 90047 cam.projMatrix.mat4[15] 90048 ); 90049 }; 90050 var _default = _main.default.Camera; 90051 exports.default = _default; 90052 }, 90053 { '../core/main': 59 } 90054 ], 90055 108: [
90056 function(_dereq_, module, exports) { 90057 'use strict'; 90058 Object.defineProperty(exports, '__esModule', { value: true }); 90059 exports.default = void 0; 90060 90061 var _main = _interopRequireDefault(_dereq_('../core/main')); 90062 function _interopRequireDefault(obj) { 90063 return obj && obj.__esModule ? obj : { default: obj }; 90064 } /** //some of the functions are adjusted from Three.js(http://threejs.org) 90065 * @module Lights, Camera 90066 * @submodule Material 90067 * @for p5 90068 * @requires core 90069 * @requires p5.Geometry 90070 */ 90071 /** 90072 * p5 Geometry class 90073 * @class p5.Geometry 90074 * @constructor 90075 * @param {Integer} [detailX] number of vertices on horizontal surface 90076 * @param {Integer} [detailY] number of vertices on horizontal surface 90077 * @param {function} [callback] function to call upon object instantiation. 90078 */ _main.default.Geometry = function(detailX, detailY, callback) { 90079 //an array containing every vertex 90080 //@type [p5.Vector] 90081 this.vertices = []; //an array containing every vertex for stroke drawing 90082 this.lineVertices = []; //an array 1 normal per lineVertex with 90083 //final position representing which direction to 90084 //displace for strokeWeight 90085 //[[0,0,-1,1], [0,1,0,-1] ...]; 90086 this.lineNormals = []; 90087 90088 //an array containing 1 normal per vertex 90089 //@type [p5.Vector] 90090 //[p5.Vector, p5.Vector, p5.Vector,p5.Vector, p5.Vector, p5.Vector,...] 90091 this.vertexNormals = []; 90092 //an array containing each three vertex indices that form a face 90093 //[[0, 1, 2], [2, 1, 3], ...] 90094 this.faces = []; 90095 //a 2D array containing uvs for every vertex 90096 //[[0.0,0.0],[1.0,0.0], ...] 90097 this.uvs = []; 90098 // a 2D array containing edge connectivity pattern for create line vertices 90099 //based on faces for most objects; 90100 this.edges = []; 90101 this.vertexColors = []; 90102 this.detailX = detailX !== undefined ? detailX : 1; 90103 this.detailY = detailY !== undefined ? detailY : 1; 90104 this.dirtyFlags = {}; 90105 90106 if (callback instanceof Function) { 90107 callback.call(this); 90108 } 90109 return this; // TODO: is this a constructor? 90110 }; 90111 90112 _main.default.Geometry.prototype.reset = function() { 90113 this.lineVertices.length = 0; 90114 this.lineNormals.length = 0; 90115 90116 this.vertices.length = 0; 90117 this.edges.length = 0; 90118 this.vertexColors.length = 0; 90119 this.vertexNormals.length = 0; 90120 this.uvs.length = 0; 90121 90122 this.dirtyFlags = {}; 90123 }; 90124 90125 /** 90126 * computes faces for geometry objects based on the vertices. 90127 * @method computeFaces 90128 * @chainable 90129 */ 90130 _main.default.Geometry.prototype.computeFaces = function() { 90131 this.faces.length = 0; 90132 var sliceCount = this.detailX + 1; 90133 var a, b, c, d; 90134 for (var i = 0; i < this.detailY; i++) { 90135 for (var j = 0; j < this.detailX; j++) { 90136 a = i * sliceCount + j; // + offset; 90137 b = i * sliceCount + j + 1; // + offset; 90138 c = (i + 1) * sliceCount + j + 1; // + offset; 90139 d = (i + 1) * sliceCount + j; // + offset; 90140 this.faces.push([a, b, d]); 90141 this.faces.push([d, b, c]); 90142 } 90143 } 90144 return this; 90145 }; 90146 90147 _main.default.Geometry.prototype._getFaceNormal = function(faceId) { 90148 //This assumes that vA->vB->vC is a counter-clockwise ordering 90149 var face = this.faces[faceId]; 90150 var vA = this.vertices[face[0]]; 90151 var vB = this.vertices[face[1]]; 90152 var vC = this.vertices[face[2]]; 90153 var ab = _main.default.Vector.sub(vB, vA); 90154 var ac = _main.default.Vector.sub(vC, vA); 90155 var n = _main.default.Vector.cross(ab, ac); 90156 var ln = _main.default.Vector.mag(n); 90157 var sinAlpha = 90158 ln / (_main.default.Vector.mag(ab) * _main.default.Vector.mag(ac)); 90159 if (sinAlpha === 0 || isNaN(sinAlpha)) { 90160 console.warn(
90161 'p5.Geometry.prototype._getFaceNormal:', 90162 'face has colinear sides or a repeated vertex' 90163 ); 90164 90165 return n; 90166 } 90167 if (sinAlpha > 1) sinAlpha = 1; // handle float rounding error 90168 return n.mult(Math.asin(sinAlpha) / ln); 90169 }; 90170 /** 90171 * computes smooth normals per vertex as an average of each 90172 * face. 90173 * @method computeNormals 90174 * @chainable 90175 */ 90176 _main.default.Geometry.prototype.computeNormals = function() { 90177 var vertexNormals = this.vertexNormals; 90178 var vertices = this.vertices; 90179 var faces = this.faces; 90180 var iv; 90181 90182 // initialize the vertexNormals array with empty vectors 90183 vertexNormals.length = 0; 90184 for (iv = 0; iv < vertices.length; ++iv) { 90185 vertexNormals.push(new _main.default.Vector()); 90186 } 90187 90188 // loop through all the faces adding its normal to the normal 90189 // of each of its vertices 90190 for (var f = 0; f < faces.length; ++f) { 90191 var face = faces[f]; 90192 var faceNormal = this._getFaceNormal(f); 90193 90194 // all three vertices get the normal added 90195 for (var fv = 0; fv < 3; ++fv) { 90196 var vertexIndex = face[fv]; 90197 vertexNormals[vertexIndex].add(faceNormal); 90198 } 90199 } 90200 90201 // normalize the normals 90202 for (iv = 0; iv < vertices.length; ++iv) { 90203 vertexNormals[iv].normalize(); 90204 } 90205 90206 return this; 90207 }; 90208 90209 /** 90210 * Averages the vertex normals. Used in curved 90211 * surfaces 90212 * @method averageNormals 90213 * @chainable 90214 */ 90215 _main.default.Geometry.prototype.averageNormals = function() { 90216 for (var i = 0; i <= this.detailY; i++) { 90217 var offset = this.detailX + 1; 90218 var temp = _main.default.Vector.add( 90219 this.vertexNormals[i * offset], 90220 this.vertexNormals[i * offset + this.detailX] 90221 ); 90222 90223 temp = _main.default.Vector.div(temp, 2); 90224 this.vertexNormals[i * offset] = temp; 90225 this.vertexNormals[i * offset + this.detailX] = temp; 90226 } 90227 return this; 90228 }; 90229 90230 /** 90231 * Averages pole normals. Used in spherical primitives 90232 * @method averagePoleNormals 90233 * @chainable 90234 */ 90235 _main.default.Geometry.prototype.averagePoleNormals = function() { 90236 //average the north pole 90237 var sum = new _main.default.Vector(0, 0, 0); 90238 for (var i = 0; i < this.detailX; i++) { 90239 sum.add(this.vertexNormals[i]); 90240 } 90241 sum = _main.default.Vector.div(sum, this.detailX); 90242 90243 for (var _i = 0; _i < this.detailX; _i++) { 90244 this.vertexNormals[_i] = sum; 90245 } 90246 90247 //average the south pole 90248 sum = new _main.default.Vector(0, 0, 0); 90249 for ( 90250 var _i2 = this.vertices.length - 1; 90251 _i2 > this.vertices.length - 1 - this.detailX; 90252 _i2-- 90253 ) { 90254 sum.add(this.vertexNormals[_i2]); 90255 } 90256 sum = _main.default.Vector.div(sum, this.detailX); 90257 90258 for ( 90259 var _i3 = this.vertices.length - 1; 90260 _i3 > this.vertices.length - 1 - this.detailX; 90261 _i3-- 90262 ) { 90263 this.vertexNormals[_i3] = sum; 90264 } 90265 return this; 90266 }; 90267 90268 /** 90269 * Create a 2D array for establishing stroke connections 90270 * @private 90271 * @chainable 90272 */ 90273 _main.default.Geometry.prototype._makeTriangleEdges = function() { 90274 this.edges.length = 0; 90275 if (Array.isArray(this.strokeIndices)) { 90276 for (var i = 0, max = this.strokeIndices.length; i < max; i++) { 90277 this.edges.push(this.strokeIndices[i]); 90278 } 90279 } else { 90280 for (var j = 0; j < this.faces.length; j++) { 90281 this.edges.push([this.faces[j][0], this.faces[j][1]]); 90282 this.edges.push([this.faces[j][1], this.faces[j][2]]); 90283 this.edges.push([this.faces[j][2], this.faces[j][0]]); 90284 } 90285 } 90286 return this; 90287 }; 90288 90289 /** 90290 * Create 4 vertices for each stroke line, two at the beginning position 90291 * and two at the end position. These vertices are displaced relative to 90292 * that line's normal on the GPU 90293 * @private 90294 * @chainable 90295 */ 90296 _main.default.Geometry.prototype._edgesToVertices = function() { 90297 this.lineVertices.length = 0; 90298 this.lineNormals.length = 0; 90299 90300 for (var i = 0; i < this.edges.length; i++) { 90301 var begin = this.vertices[this.edges[i][0]]; 90302 var end = this.vertices[this.edges[i][1]]; 90303 var dir = end 90304 .copy() 90305 .sub(begin) 90306 .normalize(); 90307 var a = begin.array(); 90308 var b = begin.array(); 90309 var c = end.array(); 90310 var d = end.array(); 90311 var dirAdd = dir.array(); 90312 var dirSub = dir.array(); 90313 // below is used to displace the pair of vertices at beginning and end 90314 // in opposite directions 90315 dirAdd.push(1); 90316 dirSub.push(-1); 90317 this.lineNormals.push(dirAdd, dirSub, dirAdd, dirAdd, dirSub, dirSub); 90318 this.lineVertices.push(a, b, c, c, b, d); 90319 } 90320 return this; 90321 }; 90322 90323 /** 90324 * Modifies all vertices to be centered within the range -100 to 100. 90325 * @method normalize 90326 * @chainable 90327 */ 90328 _main.default.Geometry.prototype.normalize = function() { 90329 if (this.vertices.length > 0) { 90330 // Find the corners of our bounding box 90331 var maxPosition = this.vertices[0].copy(); 90332 var minPosition = this.vertices[0].copy(); 90333 90334 for (var i = 0; i < this.vertices.length; i++) { 90335 maxPosition.x = Math.max(maxPosition.x, this.vertices[i].x); 90336 minPosition.x = Math.min(minPosition.x, this.vertices[i].x); 90337 maxPosition.y = Math.max(maxPosition.y, this.vertices[i].y); 90338 minPosition.y = Math.min(minPosition.y, this.vertices[i].y); 90339 maxPosition.z = Math.max(maxPosition.z, this.vertices[i].z); 90340 minPosition.z = Math.min(minPosition.z, this.vertices[i].z); 90341 } 90342 90343 var center = _main.default.Vector.lerp(maxPosition, minPosition, 0.5); 90344 var dist = _main.default.Vector.sub(maxPosition, minPosition); 90345 var longestDist = Math.max(Math.max(dist.x, dist.y), dist.z); 90346 var scale = 200 / longestDist; 90347 90348 for (var _i4 = 0; _i4 < this.vertices.length; _i4++) { 90349 this.vertices[_i4].sub(center); 90350 this.vertices[_i4].mult(scale); 90351 } 90352 } 90353 return this; 90354 }; 90355 var _default = _main.default.Geometry; 90356 exports.default = _default; 90357 }, 90358 { '../core/main': 59 } 90359 ], 90360 109: [
90361 function(_dereq_, module, exports) { 90362 'use strict'; 90363 Object.defineProperty(exports, '__esModule', { value: true }); 90364 exports.default = void 0; 90365 90366 var _main = _interopRequireDefault(_dereq_('../core/main')); 90367 function _interopRequireDefault(obj) { 90368 return obj && obj.__esModule ? obj : { default: obj }; 90369 } 90370 /** 90371 * @requires constants 90372 * @todo see methods below needing further implementation. 90373 * future consideration: implement SIMD optimizations 90374 * when browser compatibility becomes available 90375 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/ 90376 * Reference/Global_Objects/SIMD 90377 */ var GLMAT_ARRAY_TYPE = Array; 90378 var isMatrixArray = function isMatrixArray(x) { 90379 return x instanceof Array; 90380 }; 90381 if (typeof Float32Array !== 'undefined') { 90382 GLMAT_ARRAY_TYPE = Float32Array; 90383 isMatrixArray = function isMatrixArray(x) { 90384 return x instanceof Array || x instanceof Float32Array; 90385 }; 90386 } 90387 90388 /** 90389 * A class to describe a 4x4 matrix 90390 * for model and view matrix manipulation in the p5js webgl renderer. 90391 * @class p5.Matrix 90392 * @private 90393 * @constructor 90394 * @param {Array} [mat4] array literal of our 4x4 matrix 90395 */ 90396 _main.default.Matrix = function() { 90397 var args = new Array(arguments.length); 90398 for (var i = 0; i < args.length; ++i) { 90399 args[i] = arguments[i]; 90400 } 90401 90402 // This is default behavior when object 90403 // instantiated using createMatrix() 90404 // @todo implement createMatrix() in core/math.js 90405 if (args.length && args[args.length - 1] instanceof _main.default) { 90406 this.p5 = args[args.length - 1]; 90407 } 90408 90409 if (args[0] === 'mat3') { 90410 this.mat3 = Array.isArray(args[1]) 90411 ? args[1] 90412 : new GLMAT_ARRAY_TYPE([1, 0, 0, 0, 1, 0, 0, 0, 1]); 90413 } else { 90414 this.mat4 = Array.isArray(args[0]) 90415 ? args[0] 90416 : new GLMAT_ARRAY_TYPE([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]); 90417 } 90418 return this; 90419 }; 90420 90421 /** 90422 * Sets the x, y, and z component of the vector using two or three separate 90423 * variables, the data from a p5.Matrix, or the values from a float array. 90424 * 90425 * @method set 90426 * @param {p5.Matrix|Float32Array|Number[]} [inMatrix] the input p5.Matrix or 90427 * an Array of length 16 90428 * @chainable 90429 */ 90430 /** 90431 * @method set 90432 * @param {Number[]} elements 16 numbers passed by value to avoid 90433 * array copying. 90434 * @chainable 90435 */ 90436 _main.default.Matrix.prototype.set = function(inMatrix) { 90437 if (inMatrix instanceof _main.default.Matrix) { 90438 this.mat4 = inMatrix.mat4; 90439 return this; 90440 } else if (isMatrixArray(inMatrix)) { 90441 this.mat4 = inMatrix; 90442 return this; 90443 } else if (arguments.length === 16) { 90444 this.mat4[0] = arguments[0]; 90445 this.mat4[1] = arguments[1]; 90446 this.mat4[2] = arguments[2]; 90447 this.mat4[3] = arguments[3]; 90448 this.mat4[4] = arguments[4]; 90449 this.mat4[5] = arguments[5]; 90450 this.mat4[6] = arguments[6]; 90451 this.mat4[7] = arguments[7]; 90452 this.mat4[8] = arguments[8]; 90453 this.mat4[9] = arguments[9]; 90454 this.mat4[10] = arguments[10]; 90455 this.mat4[11] = arguments[11]; 90456 this.mat4[12] = arguments[12]; 90457 this.mat4[13] = arguments[13]; 90458 this.mat4[14] = arguments[14]; 90459 this.mat4[15] = arguments[15]; 90460 } 90461 return this; 90462 }; 90463 90464 /** 90465 * Gets a copy of the vector, returns a p5.Matrix object. 90466 * 90467 * @method get 90468 * @return {p5.Matrix} the copy of the p5.Matrix object 90469 */ 90470 _main.default.Matrix.prototype.get = function() { 90471 return new _main.default.Matrix(this.mat4, this.p5); 90472 }; 90473 90474 /** 90475 * return a copy of a matrix 90476 * @method copy 90477 * @return {p5.Matrix} the result matrix 90478 */ 90479 _main.default.Matrix.prototype.copy = function() { 90480 var copied = new _main.default.Matrix(this.p5); 90481 copied.mat4[0] = this.mat4[0]; 90482 copied.mat4[1] = this.mat4[1]; 90483 copied.mat4[2] = this.mat4[2]; 90484 copied.mat4[3] = this.mat4[3]; 90485 copied.mat4[4] = this.mat4[4]; 90486 copied.mat4[5] = this.mat4[5]; 90487 copied.mat4[6] = this.mat4[6]; 90488 copied.mat4[7] = this.mat4[7]; 90489 copied.mat4[8] = this.mat4[8]; 90490 copied.mat4[9] = this.mat4[9]; 90491 copied.mat4[10] = this.mat4[10]; 90492 copied.mat4[11] = this.mat4[11]; 90493 copied.mat4[12] = this.mat4[12]; 90494 copied.mat4[13] = this.mat4[13]; 90495 copied.mat4[14] = this.mat4[14]; 90496 copied.mat4[15] = this.mat4[15]; 90497 return copied; 90498 }; 90499 90500 /** 90501 * return an identity matrix 90502 * @method identity 90503 * @return {p5.Matrix} the result matrix 90504 */ 90505 _main.default.Matrix.identity = function(pInst) { 90506 return new _main.default.Matrix(pInst); 90507 }; 90508 90509 /** 90510 * transpose according to a given matrix 90511 * @method transpose 90512 * @param {p5.Matrix|Float32Array|Number[]} a the matrix to be 90513 * based on to transpose 90514 * @chainable 90515 */ 90516 _main.default.Matrix.prototype.transpose = function(a) { 90517 var a01, a02, a03, a12, a13, a23; 90518 if (a instanceof _main.default.Matrix) { 90519 a01 = a.mat4[1]; 90520 a02 = a.mat4[2]; 90521 a03 = a.mat4[3]; 90522 a12 = a.mat4[6]; 90523 a13 = a.mat4[7]; 90524 a23 = a.mat4[11]; 90525 90526 this.mat4[0] = a.mat4[0]; 90527 this.mat4[1] = a.mat4[4]; 90528 this.mat4[2] = a.mat4[8]; 90529 this.mat4[3] = a.mat4[12]; 90530 this.mat4[4] = a01; 90531 this.mat4[5] = a.mat4[5]; 90532 this.mat4[6] = a.mat4[9]; 90533 this.mat4[7] = a.mat4[13]; 90534 this.mat4[8] = a02; 90535 this.mat4[9] = a12; 90536 this.mat4[10] = a.mat4[10]; 90537 this.mat4[11] = a.mat4[14]; 90538 this.mat4[12] = a03; 90539 this.mat4[13] = a13; 90540 this.mat4[14] = a23; 90541 this.mat4[15] = a.mat4[15]; 90542 } else if (isMatrixArray(a)) { 90543 a01 = a[1]; 90544 a02 = a[2]; 90545 a03 = a[3]; 90546 a12 = a[6]; 90547 a13 = a[7]; 90548 a23 = a[11]; 90549 90550 this.mat4[0] = a[0]; 90551 this.mat4[1] = a[4]; 90552 this.mat4[2] = a[8]; 90553 this.mat4[3] = a[12]; 90554 this.mat4[4] = a01; 90555 this.mat4[5] = a[5]; 90556 this.mat4[6] = a[9]; 90557 this.mat4[7] = a[13]; 90558 this.mat4[8] = a02; 90559 this.mat4[9] = a12; 90560 this.mat4[10] = a[10]; 90561 this.mat4[11] = a[14]; 90562 this.mat4[12] = a03; 90563 this.mat4[13] = a13; 90564 this.mat4[14] = a23; 90565 this.mat4[15] = a[15]; 90566 } 90567 return this; 90568 }; 90569 90570 /** 90571 * invert matrix according to a give matrix 90572 * @method invert 90573 * @param {p5.Matrix|Float32Array|Number[]} a the matrix to be 90574 * based on to invert 90575 * @chainable 90576 */ 90577 _main.default.Matrix.prototype.invert = function(a) { 90578 var a00, a01, a02, a03, a10, a11, a12, a13; 90579 var a20, a21, a22, a23, a30, a31, a32, a33; 90580 if (a instanceof _main.default.Matrix) { 90581 a00 = a.mat4[0]; 90582 a01 = a.mat4[1]; 90583 a02 = a.mat4[2]; 90584 a03 = a.mat4[3]; 90585 a10 = a.mat4[4]; 90586 a11 = a.mat4[5]; 90587 a12 = a.mat4[6]; 90588 a13 = a.mat4[7]; 90589 a20 = a.mat4[8]; 90590 a21 = a.mat4[9]; 90591 a22 = a.mat4[10]; 90592 a23 = a.mat4[11]; 90593 a30 = a.mat4[12]; 90594 a31 = a.mat4[13]; 90595 a32 = a.mat4[14]; 90596 a33 = a.mat4[15]; 90597 } else if (isMatrixArray(a)) { 90598 a00 = a[0]; 90599 a01 = a[1]; 90600 a02 = a[2]; 90601 a03 = a[3]; 90602 a10 = a[4]; 90603 a11 = a[5]; 90604 a12 = a[6]; 90605 a13 = a[7]; 90606 a20 = a[8]; 90607 a21 = a[9]; 90608 a22 = a[10]; 90609 a23 = a[11]; 90610 a30 = a[12]; 90611 a31 = a[13]; 90612 a32 = a[14]; 90613 a33 = a[15]; 90614 } 90615 var b00 = a00 * a11 - a01 * a10; 90616 var b01 = a00 * a12 - a02 * a10; 90617 var b02 = a00 * a13 - a03 * a10; 90618 var b03 = a01 * a12 - a02 * a11; 90619 var b04 = a01 * a13 - a03 * a11; 90620 var b05 = a02 * a13 - a03 * a12; 90621 var b06 = a20 * a31 - a21 * a30; 90622 var b07 = a20 * a32 - a22 * a30; 90623 var b08 = a20 * a33 - a23 * a30; 90624 var b09 = a21 * a32 - a22 * a31; 90625 var b10 = a21 * a33 - a23 * a31; 90626 var b11 = a22 * a33 - a23 * a32; 90627 90628 // Calculate the determinant 90629 var det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; 90630 90631 if (!det) { 90632 return null; 90633 } 90634 det = 1.0 / det; 90635 90636 this.mat4[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det; 90637 this.mat4[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det; 90638 this.mat4[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det; 90639 this.mat4[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det; 90640 this.mat4[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det; 90641 this.mat4[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det; 90642 this.mat4[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det; 90643 this.mat4[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det; 90644 this.mat4[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det; 90645 this.mat4[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det; 90646 this.mat4[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det; 90647 this.mat4[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det; 90648 this.mat4[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det; 90649 this.mat4[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det; 90650 this.mat4[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det; 90651 this.mat4[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det; 90652 90653 return this; 90654 }; 90655 90656 /** 90657 * Inverts a 3x3 matrix 90658 * @method invert3x3 90659 * @chainable 90660 */ 90661 _main.default.Matrix.prototype.invert3x3 = function() { 90662 var a00 = this.mat3[0]; 90663 var a01 = this.mat3[1]; 90664 var a02 = this.mat3[2]; 90665 var a10 = this.mat3[3]; 90666 var a11 = this.mat3[4]; 90667 var a12 = this.mat3[5]; 90668 var a20 = this.mat3[6]; 90669 var a21 = this.mat3[7]; 90670 var a22 = this.mat3[8]; 90671 var b01 = a22 * a11 - a12 * a21; 90672 var b11 = -a22 * a10 + a12 * a20; 90673 var b21 = a21 * a10 - a11 * a20; 90674 90675 // Calculate the determinant 90676 var det = a00 * b01 + a01 * b11 + a02 * b21; 90677 if (!det) { 90678 return null; 90679 } 90680 det = 1.0 / det; 90681 this.mat3[0] = b01 * det; 90682 this.mat3[1] = (-a22 * a01 + a02 * a21) * det; 90683 this.mat3[2] = (a12 * a01 - a02 * a11) * det; 90684 this.mat3[3] = b11 * det; 90685 this.mat3[4] = (a22 * a00 - a02 * a20) * det; 90686 this.mat3[5] = (-a12 * a00 + a02 * a10) * det; 90687 this.mat3[6] = b21 * det; 90688 this.mat3[7] = (-a21 * a00 + a01 * a20) * det; 90689 this.mat3[8] = (a11 * a00 - a01 * a10) * det; 90690 return this; 90691 }; 90692 90693 /** 90694 * transposes a 3x3 p5.Matrix by a mat3 90695 * @method transpose3x3 90696 * @param {Number[]} mat3 1-dimensional array 90697 * @chainable 90698 */ 90699 _main.default.Matrix.prototype.transpose3x3 = function(mat3) { 90700 var a01 = mat3[1], 90701 a02 = mat3[2], 90702 a12 = mat3[5]; 90703 this.mat3[1] = mat3[3]; 90704 this.mat3[2] = mat3[6]; 90705 this.mat3[3] = a01; 90706 this.mat3[5] = mat3[7]; 90707 this.mat3[6] = a02; 90708 this.mat3[7] = a12; 90709 return this; 90710 }; 90711 90712 /** 90713 * converts a 4x4 matrix to its 3x3 inverse transform 90714 * commonly used in MVMatrix to NMatrix conversions. 90715 * @method invertTranspose 90716 * @param {p5.Matrix} mat4 the matrix to be based on to invert 90717 * @chainable 90718 * @todo finish implementation 90719 */ 90720 _main.default.Matrix.prototype.inverseTranspose = function(matrix) { 90721 if (this.mat3 === undefined) { 90722 console.error('sorry, this function only works with mat3'); 90723 } else { 90724 //convert mat4 -> mat3 90725 this.mat3[0] = matrix.mat4[0]; 90726 this.mat3[1] = matrix.mat4[1]; 90727 this.mat3[2] = matrix.mat4[2]; 90728 this.mat3[3] = matrix.mat4[4]; 90729 this.mat3[4] = matrix.mat4[5]; 90730 this.mat3[5] = matrix.mat4[6]; 90731 this.mat3[6] = matrix.mat4[8]; 90732 this.mat3[7] = matrix.mat4[9]; 90733 this.mat3[8] = matrix.mat4[10]; 90734 } 90735 90736 var inverse = this.invert3x3(); 90737 // check inverse succeeded 90738 if (inverse) { 90739 inverse.transpose3x3(this.mat3); 90740 } else { 90741 // in case of singularity, just zero the matrix 90742 for (var i = 0; i < 9; i++) { 90743 this.mat3[i] = 0; 90744 } 90745 } 90746 return this; 90747 }; 90748 90749 /** 90750 * inspired by Toji's mat4 determinant 90751 * @method determinant 90752 * @return {Number} Determinant of our 4x4 matrix 90753 */ 90754 _main.default.Matrix.prototype.determinant = function() { 90755 var d00 = this.mat4[0] * this.mat4[5] - this.mat4[1] * this.mat4[4], 90756 d01 = this.mat4[0] * this.mat4[6] - this.mat4[2] * this.mat4[4],
90757 d02 = this.mat4[0] * this.mat4[7] - this.mat4[3] * this.mat4[4], 90758 d03 = this.mat4[1] * this.mat4[6] - this.mat4[2] * this.mat4[5], 90759 d04 = this.mat4[1] * this.mat4[7] - this.mat4[3] * this.mat4[5], 90760 d05 = this.mat4[2] * this.mat4[7] - this.mat4[3] * this.mat4[6], 90761 d06 = this.mat4[8] * this.mat4[13] - this.mat4[9] * this.mat4[12], 90762 d07 = this.mat4[8] * this.mat4[14] - this.mat4[10] * this.mat4[12], 90763 d08 = this.mat4[8] * this.mat4[15] - this.mat4[11] * this.mat4[12], 90764 d09 = this.mat4[9] * this.mat4[14] - this.mat4[10] * this.mat4[13], 90765 d10 = this.mat4[9] * this.mat4[15] - this.mat4[11] * this.mat4[13], 90766 d11 = this.mat4[10] * this.mat4[15] - this.mat4[11] * this.mat4[14]; 90767 90768 // Calculate the determinant 90769 return d00 * d11 - d01 * d10 + d02 * d09 + d03 * d08 - d04 * d07 + d05 * d06; 90770 }; 90771 90772 /** 90773 * multiply two mat4s 90774 * @method mult 90775 * @param {p5.Matrix|Float32Array|Number[]} multMatrix The matrix 90776 * we want to multiply by 90777 * @chainable 90778 */ 90779 _main.default.Matrix.prototype.mult = function(multMatrix) { 90780 var _src; 90781 90782 if (multMatrix === this || multMatrix === this.mat4) { 90783 _src = this.copy().mat4; // only need to allocate in this rare case 90784 } else if (multMatrix instanceof _main.default.Matrix) { 90785 _src = multMatrix.mat4; 90786 } else if (isMatrixArray(multMatrix)) { 90787 _src = multMatrix; 90788 } else if (arguments.length === 16) { 90789 _src = arguments; 90790 } else { 90791 return; // nothing to do. 90792 } 90793 90794 // each row is used for the multiplier 90795 var b0 = this.mat4[0], 90796 b1 = this.mat4[1], 90797 b2 = this.mat4[2], 90798 b3 = this.mat4[3]; 90799 this.mat4[0] = b0 * _src[0] + b1 * _src[4] + b2 * _src[8] + b3 * _src[12]; 90800 this.mat4[1] = b0 * _src[1] + b1 * _src[5] + b2 * _src[9] + b3 * _src[13]; 90801 this.mat4[2] = b0 * _src[2] + b1 * _src[6] + b2 * _src[10] + b3 * _src[14]; 90802 this.mat4[3] = b0 * _src[3] + b1 * _src[7] + b2 * _src[11] + b3 * _src[15]; 90803 90804 b0 = this.mat4[4]; 90805 b1 = this.mat4[5]; 90806 b2 = this.mat4[6]; 90807 b3 = this.mat4[7]; 90808 this.mat4[4] = b0 * _src[0] + b1 * _src[4] + b2 * _src[8] + b3 * _src[12]; 90809 this.mat4[5] = b0 * _src[1] + b1 * _src[5] + b2 * _src[9] + b3 * _src[13]; 90810 this.mat4[6] = b0 * _src[2] + b1 * _src[6] + b2 * _src[10] + b3 * _src[14]; 90811 this.mat4[7] = b0 * _src[3] + b1 * _src[7] + b2 * _src[11] + b3 * _src[15]; 90812 90813 b0 = this.mat4[8]; 90814 b1 = this.mat4[9]; 90815 b2 = this.mat4[10]; 90816 b3 = this.mat4[11]; 90817 this.mat4[8] = b0 * _src[0] + b1 * _src[4] + b2 * _src[8] + b3 * _src[12]; 90818 this.mat4[9] = b0 * _src[1] + b1 * _src[5] + b2 * _src[9] + b3 * _src[13]; 90819 this.mat4[10] = b0 * _src[2] + b1 * _src[6] + b2 * _src[10] + b3 * _src[14]; 90820 this.mat4[11] = b0 * _src[3] + b1 * _src[7] + b2 * _src[11] + b3 * _src[15]; 90821 90822 b0 = this.mat4[12]; 90823 b1 = this.mat4[13]; 90824 b2 = this.mat4[14]; 90825 b3 = this.mat4[15]; 90826 this.mat4[12] = b0 * _src[0] + b1 * _src[4] + b2 * _src[8] + b3 * _src[12]; 90827 this.mat4[13] = b0 * _src[1] + b1 * _src[5] + b2 * _src[9] + b3 * _src[13]; 90828 this.mat4[14] = b0 * _src[2] + b1 * _src[6] + b2 * _src[10] + b3 * _src[14]; 90829 this.mat4[15] = b0 * _src[3] + b1 * _src[7] + b2 * _src[11] + b3 * _src[15]; 90830 90831 return this; 90832 }; 90833 90834 _main.default.Matrix.prototype.apply = function(multMatrix) { 90835 var _src; 90836 90837 if (multMatrix === this || multMatrix === this.mat4) { 90838 _src = this.copy().mat4; // only need to allocate in this rare case 90839 } else if (multMatrix instanceof _main.default.Matrix) { 90840 _src = multMatrix.mat4; 90841 } else if (isMatrixArray(multMatrix)) { 90842 _src = multMatrix; 90843 } else if (arguments.length === 16) { 90844 _src = arguments; 90845 } else { 90846 return; // nothing to do. 90847 } 90848 90849 var mat4 = this.mat4; 90850 90851 // each row is used for the multiplier 90852 var m0 = mat4[0]; 90853 var m4 = mat4[4]; 90854 var m8 = mat4[8]; 90855 var m12 = mat4[12];
90856 mat4[0] = _src[0] * m0 + _src[1] * m4 + _src[2] * m8 + _src[3] * m12; 90857 mat4[4] = _src[4] * m0 + _src[5] * m4 + _src[6] * m8 + _src[7] * m12; 90858 mat4[8] = _src[8] * m0 + _src[9] * m4 + _src[10] * m8 + _src[11] * m12; 90859 mat4[12] = _src[12] * m0 + _src[13] * m4 + _src[14] * m8 + _src[15] * m12; 90860 90861 var m1 = mat4[1]; 90862 var m5 = mat4[5]; 90863 var m9 = mat4[9]; 90864 var m13 = mat4[13]; 90865 mat4[1] = _src[0] * m1 + _src[1] * m5 + _src[2] * m9 + _src[3] * m13; 90866 mat4[5] = _src[4] * m1 + _src[5] * m5 + _src[6] * m9 + _src[7] * m13; 90867 mat4[9] = _src[8] * m1 + _src[9] * m5 + _src[10] * m9 + _src[11] * m13; 90868 mat4[13] = _src[12] * m1 + _src[13] * m5 + _src[14] * m9 + _src[15] * m13; 90869 90870 var m2 = mat4[2]; 90871 var m6 = mat4[6]; 90872 var m10 = mat4[10]; 90873 var m14 = mat4[14]; 90874 mat4[2] = _src[0] * m2 + _src[1] * m6 + _src[2] * m10 + _src[3] * m14; 90875 mat4[6] = _src[4] * m2 + _src[5] * m6 + _src[6] * m10 + _src[7] * m14; 90876 mat4[10] = _src[8] * m2 + _src[9] * m6 + _src[10] * m10 + _src[11] * m14; 90877 mat4[14] = _src[12] * m2 + _src[13] * m6 + _src[14] * m10 + _src[15] * m14; 90878 90879 var m3 = mat4[3]; 90880 var m7 = mat4[7]; 90881 var m11 = mat4[11]; 90882 var m15 = mat4[15]; 90883 mat4[3] = _src[0] * m3 + _src[1] * m7 + _src[2] * m11 + _src[3] * m15; 90884 mat4[7] = _src[4] * m3 + _src[5] * m7 + _src[6] * m11 + _src[7] * m15; 90885 mat4[11] = _src[8] * m3 + _src[9] * m7 + _src[10] * m11 + _src[11] * m15; 90886 mat4[15] = _src[12] * m3 + _src[13] * m7 + _src[14] * m11 + _src[15] * m15; 90887 90888 return this; 90889 }; 90890 90891 /** 90892 * scales a p5.Matrix by scalars or a vector 90893 * @method scale 90894 * @param {p5.Vector|Float32Array|Number[]} s vector to scale by 90895 * @chainable 90896 */ 90897 _main.default.Matrix.prototype.scale = function(x, y, z) { 90898 if (x instanceof _main.default.Vector) { 90899 // x is a vector, extract the components from it. 90900 y = x.y; 90901 z = x.z; 90902 x = x.x; // must be last 90903 } else if (x instanceof Array) { 90904 // x is an array, extract the components from it. 90905 y = x[1]; 90906 z = x[2]; 90907 x = x[0]; // must be last 90908 } 90909 90910 this.mat4[0] *= x; 90911 this.mat4[1] *= x; 90912 this.mat4[2] *= x; 90913 this.mat4[3] *= x; 90914 this.mat4[4] *= y; 90915 this.mat4[5] *= y; 90916 this.mat4[6] *= y; 90917 this.mat4[7] *= y; 90918 this.mat4[8] *= z; 90919 this.mat4[9] *= z; 90920 this.mat4[10] *= z; 90921 this.mat4[11] *= z; 90922 90923 return this; 90924 }; 90925 90926 /** 90927 * rotate our Matrix around an axis by the given angle. 90928 * @method rotate 90929 * @param {Number} a The angle of rotation in radians 90930 * @param {p5.Vector|Number[]} axis the axis(es) to rotate around 90931 * @chainable 90932 * inspired by Toji's gl-matrix lib, mat4 rotation 90933 */ 90934 _main.default.Matrix.prototype.rotate = function(a, x, y, z) { 90935 if (x instanceof _main.default.Vector) { 90936 // x is a vector, extract the components from it. 90937 y = x.y; 90938 z = x.z; 90939 x = x.x; //must be last 90940 } else if (x instanceof Array) { 90941 // x is an array, extract the components from it. 90942 y = x[1]; 90943 z = x[2]; 90944 x = x[0]; //must be last 90945 } 90946 90947 var len = Math.sqrt(x * x + y * y + z * z); 90948 x *= 1 / len; 90949 y *= 1 / len; 90950 z *= 1 / len; 90951 90952 var a00 = this.mat4[0]; 90953 var a01 = this.mat4[1]; 90954 var a02 = this.mat4[2]; 90955 var a03 = this.mat4[3]; 90956 var a10 = this.mat4[4]; 90957 var a11 = this.mat4[5]; 90958 var a12 = this.mat4[6]; 90959 var a13 = this.mat4[7]; 90960 var a20 = this.mat4[8]; 90961 var a21 = this.mat4[9]; 90962 var a22 = this.mat4[10]; 90963 var a23 = this.mat4[11]; 90964 90965 //sin,cos, and tan of respective angle 90966 var sA = Math.sin(a);
90967 var cA = Math.cos(a); 90968 var tA = 1 - cA; 90969 // Construct the elements of the rotation matrix 90970 var b00 = x * x * tA + cA; 90971 var b01 = y * x * tA + z * sA; 90972 var b02 = z * x * tA - y * sA; 90973 var b10 = x * y * tA - z * sA; 90974 var b11 = y * y * tA + cA; 90975 var b12 = z * y * tA + x * sA; 90976 var b20 = x * z * tA + y * sA; 90977 var b21 = y * z * tA - x * sA; 90978 var b22 = z * z * tA + cA; 90979 90980 // rotation-specific matrix multiplication 90981 this.mat4[0] = a00 * b00 + a10 * b01 + a20 * b02; 90982 this.mat4[1] = a01 * b00 + a11 * b01 + a21 * b02; 90983 this.mat4[2] = a02 * b00 + a12 * b01 + a22 * b02; 90984 this.mat4[3] = a03 * b00 + a13 * b01 + a23 * b02; 90985 this.mat4[4] = a00 * b10 + a10 * b11 + a20 * b12; 90986 this.mat4[5] = a01 * b10 + a11 * b11 + a21 * b12; 90987 this.mat4[6] = a02 * b10 + a12 * b11 + a22 * b12; 90988 this.mat4[7] = a03 * b10 + a13 * b11 + a23 * b12; 90989 this.mat4[8] = a00 * b20 + a10 * b21 + a20 * b22; 90990 this.mat4[9] = a01 * b20 + a11 * b21 + a21 * b22; 90991 this.mat4[10] = a02 * b20 + a12 * b21 + a22 * b22; 90992 this.mat4[11] = a03 * b20 + a13 * b21 + a23 * b22; 90993 90994 return this; 90995 }; 90996 90997 /** 90998 * @todo finish implementing this method! 90999 * translates 91000 * @method translate 91001 * @param {Number[]} v vector to translate by 91002 * @chainable 91003 */ 91004 _main.default.Matrix.prototype.translate = function(v) { 91005 var x = v[0], 91006 y = v[1], 91007 z = v[2] || 0; 91008 this.mat4[12] += this.mat4[0] * x + this.mat4[4] * y + this.mat4[8] * z; 91009 this.mat4[13] += this.mat4[1] * x + this.mat4[5] * y + this.mat4[9] * z; 91010 this.mat4[14] += this.mat4[2] * x + this.mat4[6] * y + this.mat4[10] * z; 91011 this.mat4[15] += this.mat4[3] * x + this.mat4[7] * y + this.mat4[11] * z; 91012 }; 91013 91014 _main.default.Matrix.prototype.rotateX = function(a) { 91015 this.rotate(a, 1, 0, 0); 91016 }; 91017 _main.default.Matrix.prototype.rotateY = function(a) { 91018 this.rotate(a, 0, 1, 0); 91019 }; 91020 _main.default.Matrix.prototype.rotateZ = function(a) { 91021 this.rotate(a, 0, 0, 1); 91022 }; 91023 91024 /** 91025 * sets the perspective matrix 91026 * @method perspective 91027 * @param {Number} fovy [description] 91028 * @param {Number} aspect [description] 91029 * @param {Number} near near clipping plane 91030 * @param {Number} far far clipping plane 91031 * @chainable 91032 */ 91033 _main.default.Matrix.prototype.perspective = function(fovy, aspect, near, far) { 91034 var f = 1.0 / Math.tan(fovy / 2), 91035 nf = 1 / (near - far); 91036 91037 this.mat4[0] = f / aspect; 91038 this.mat4[1] = 0; 91039 this.mat4[2] = 0; 91040 this.mat4[3] = 0; 91041 this.mat4[4] = 0; 91042 this.mat4[5] = f; 91043 this.mat4[6] = 0; 91044 this.mat4[7] = 0; 91045 this.mat4[8] = 0; 91046 this.mat4[9] = 0; 91047 this.mat4[10] = (far + near) * nf; 91048 this.mat4[11] = -1; 91049 this.mat4[12] = 0; 91050 this.mat4[13] = 0; 91051 this.mat4[14] = 2 * far * near * nf; 91052 this.mat4[15] = 0; 91053 91054 return this; 91055 }; 91056 91057 /** 91058 * sets the ortho matrix 91059 * @method ortho 91060 * @param {Number} left [description] 91061 * @param {Number} right [description] 91062 * @param {Number} bottom [description] 91063 * @param {Number} top [description] 91064 * @param {Number} near near clipping plane 91065 * @param {Number} far far clipping plane 91066 * @chainable 91067 */ 91068 _main.default.Matrix.prototype.ortho = function( 91069 left, 91070 right, 91071 bottom, 91072 top, 91073 near, 91074 far 91075 ) { 91076 var lr = 1 / (left - right),
91077 bt = 1 / (bottom - top), 91078 nf = 1 / (near - far); 91079 this.mat4[0] = -2 * lr; 91080 this.mat4[1] = 0; 91081 this.mat4[2] = 0; 91082 this.mat4[3] = 0; 91083 this.mat4[4] = 0; 91084 this.mat4[5] = -2 * bt; 91085 this.mat4[6] = 0; 91086 this.mat4[7] = 0; 91087 this.mat4[8] = 0; 91088 this.mat4[9] = 0; 91089 this.mat4[10] = 2 * nf; 91090 this.mat4[11] = 0; 91091 this.mat4[12] = (left + right) * lr; 91092 this.mat4[13] = (top + bottom) * bt; 91093 this.mat4[14] = (far + near) * nf; 91094 this.mat4[15] = 1; 91095 91096 return this; 91097 }; 91098 91099 /** 91100 * PRIVATE 91101 */ 91102 // matrix methods adapted from: 91103 // https://developer.mozilla.org/en-US/docs/Web/WebGL/ 91104 // gluPerspective 91105 // 91106 // function _makePerspective(fovy, aspect, znear, zfar){ 91107 // const ymax = znear * Math.tan(fovy * Math.PI / 360.0); 91108 // const ymin = -ymax; 91109 // const xmin = ymin * aspect; 91110 // const xmax = ymax * aspect; 91111 // return _makeFrustum(xmin, xmax, ymin, ymax, znear, zfar); 91112 // } 91113 91114 //// 91115 //// glFrustum 91116 //// 91117 //function _makeFrustum(left, right, bottom, top, znear, zfar){ 91118 // const X = 2*znear/(right-left); 91119 // const Y = 2*znear/(top-bottom); 91120 // const A = (right+left)/(right-left); 91121 // const B = (top+bottom)/(top-bottom); 91122 // const C = -(zfar+znear)/(zfar-znear); 91123 // const D = -2*zfar*znear/(zfar-znear); 91124 // const frustrumMatrix =[ 91125 // X, 0, A, 0, 91126 // 0, Y, B, 0, 91127 // 0, 0, C, D, 91128 // 0, 0, -1, 0 91129 //]; 91130 //return frustrumMatrix; 91131 // } 91132 91133 // function _setMVPMatrices(){ 91134 ////an identity matrix 91135 ////@TODO use the p5.Matrix class to abstract away our MV matrices and 91136 ///other math 91137 //const _mvMatrix = 91138 //[ 91139 // 1.0,0.0,0.0,0.0, 91140 // 0.0,1.0,0.0,0.0, 91141 // 0.0,0.0,1.0,0.0, 91142 // 0.0,0.0,0.0,1.0 91143 //]; 91144 var _default = _main.default.Matrix; 91145 exports.default = _default; 91146 }, 91147 { '../core/main': 59 } 91148 ], 91149 110: [ 91150 function(_dereq_, module, exports) { 91151 'use strict'; 91152 Object.defineProperty(exports, '__esModule', { value: true }); 91153 exports.default = void 0; 91154 var _main = _interopRequireDefault(_dereq_('../core/main')); 91155 function _interopRequireDefault(obj) { 91156 return obj && obj.__esModule ? obj : { default: obj }; 91157 } 91158 91159 _main.default.RenderBuffer = function(size, src, dst, attr, renderer, map) { 91160 this.size = size; // the number of FLOATs in each vertex 91161 this.src = src; // the name of the model's source array 91162 this.dst = dst; // the name of the geometry's buffer 91163 this.attr = attr; // the name of the vertex attribute 91164 this._renderer = renderer; 91165 this.map = map; // optional, a transformation function to apply to src 91166 }; 91167 91168 /** 91169 * Enables and binds the buffers used by shader when the appropriate data exists in geometry. 91170 * Must always be done prior to drawing geometry in WebGL. 91171 * @param {p5.Geometry} geometry Geometry that is going to be drawn 91172 * @param {p5.Shader} shader Active shader 91173 * @private 91174 */ 91175 _main.default.RenderBuffer.prototype._prepareBuffer = function(geometry, shader) { 91176 var attributes = shader.attributes; 91177 var gl = this._renderer.GL; 91178 var model; 91179 if (geometry.model) { 91180 model = geometry.model; 91181 } else { 91182 model = geometry; 91183 } 91184 91185 // loop through each of the buffer definitions 91186 var attr = attributes[this.attr]; 91187 if (!attr) { 91188 return; 91189 } 91190 91191 // check if the model has the appropriate source array 91192 var buffer = geometry[this.dst]; 91193 var src = model[this.src]; 91194 if (src.length > 0) { 91195 // check if we need to create the GL buffer 91196 var createBuffer = !buffer; 91197 if (createBuffer) { 91198 // create and remember the buffer 91199 geometry[this.dst] = buffer = gl.createBuffer(); 91200 } 91201 // bind the buffer 91202 gl.bindBuffer(gl.ARRAY_BUFFER, buffer); 91203 91204 // check if we need to fill the buffer with data 91205 if (createBuffer || model.dirtyFlags[this.src] !== false) { 91206 var map = this.map; 91207 // get the values from the model, possibly transformed 91208 var values = map ? map(src) : src; 91209 // fill the buffer with the values 91210 this._renderer._bindBuffer(buffer, gl.ARRAY_BUFFER, values); 91211 91212 // mark the model's source array as clean 91213 model.dirtyFlags[this.src] = false;
91214 } 91215 // enable the attribute 91216 shader.enableAttrib(attr, this.size); 91217 } 91218 }; 91219 var _default = _main.default.RenderBuffer; 91220 exports.default = _default; 91221 }, 91222 { '../core/main': 59 } 91223 ], 91224 111: [ 91225 function(_dereq_, module, exports) { 91226 'use strict'; 91227 function _typeof(obj) { 91228 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') { 91229 _typeof = function _typeof(obj) { 91230 return typeof obj; 91231 }; 91232 } else { 91233 _typeof = function _typeof(obj) { 91234 return obj && 91235 typeof Symbol === 'function' && 91236 obj.constructor === Symbol && 91237 obj !== Symbol.prototype 91238 ? 'symbol' 91239 : typeof obj; 91240 }; 91241 } 91242 return _typeof(obj); 91243 } 91244 Object.defineProperty(exports, '__esModule', { value: true }); 91245 exports.default = void 0; 91246 91247 var _main = _interopRequireDefault(_dereq_('../core/main')); 91248 var constants = _interopRequireWildcard(_dereq_('../core/constants')); 91249 _dereq_('./p5.RenderBuffer'); 91250 function _getRequireWildcardCache() { 91251 if (typeof WeakMap !== 'function') return null; 91252 var cache = new WeakMap(); 91253 _getRequireWildcardCache = function _getRequireWildcardCache() { 91254 return cache; 91255 }; 91256 return cache; 91257 } 91258 function _interopRequireWildcard(obj) { 91259 if (obj && obj.__esModule) { 91260 return obj; 91261 } 91262 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) { 91263 return { default: obj }; 91264 } 91265 var cache = _getRequireWildcardCache(); 91266 if (cache && cache.has(obj)) { 91267 return cache.get(obj); 91268 } 91269 var newObj = {}; 91270 var hasPropertyDescriptor = 91271 Object.defineProperty && Object.getOwnPropertyDescriptor; 91272 for (var key in obj) { 91273 if (Object.prototype.hasOwnProperty.call(obj, key)) { 91274 var desc = hasPropertyDescriptor 91275 ? Object.getOwnPropertyDescriptor(obj, key) 91276 : null; 91277 if (desc && (desc.get || desc.set)) { 91278 Object.defineProperty(newObj, key, desc); 91279 } else { 91280 newObj[key] = obj[key]; 91281 } 91282 } 91283 } 91284 newObj.default = obj; 91285 if (cache) { 91286 cache.set(obj, newObj); 91287 } 91288 return newObj; 91289 } 91290 function _interopRequireDefault(obj) { 91291 return obj && obj.__esModule ? obj : { default: obj }; 91292 } 91293 /** 91294 * Welcome to RendererGL Immediate Mode. 91295 * Immediate mode is used for drawing custom shapes 91296 * from a set of vertices. Immediate Mode is activated 91297 * when you call <a href="#/p5/beginShape">beginShape()</a> & de-activated when you call <a href="#/p5/endShape">endShape()</a>. 91298 * Immediate mode is a style of programming borrowed 91299 * from OpenGL's (now-deprecated) immediate mode. 91300 * It differs from p5.js' default, Retained Mode, which caches 91301 * geometries and buffers on the CPU to reduce the number of webgl 91302 * draw calls. Retained mode is more efficient & performative, 91303 * however, Immediate Mode is useful for sketching quick 91304 * geometric ideas. 91305 */ /** 91306 * Begin shape drawing. This is a helpful way of generating 91307 * custom shapes quickly. However in WEBGL mode, application 91308 * performance will likely drop as a result of too many calls to 91309 * <a href="#/p5/beginShape">beginShape()</a> / <a href="#/p5/endShape">endShape()</a>. As a high performance alternative, 91310 * please use p5.js geometry primitives. 91311 * @private 91312 * @method beginShape 91313 * @param {Number} mode webgl primitives mode. beginShape supports the 91314 * following modes: 91315 * POINTS,LINES,LINE_STRIP,LINE_LOOP,TRIANGLES, 91316 * TRIANGLE_STRIP, TRIANGLE_FAN and TESS(WEBGL only) 91317 * @chainable 91318 */ _main.default.RendererGL.prototype.beginShape = function(mode) { 91319 this.immediateMode.shapeMode = 91320 mode !== undefined ? mode : constants.TRIANGLE_FAN; 91321 this.immediateMode.geometry.reset(); 91322 return this; 91323 }; 91324 /** 91325 * adds a vertex to be drawn in a custom Shape. 91326 * @private 91327 * @method vertex 91328 * @param {Number} x x-coordinate of vertex 91329 * @param {Number} y y-coordinate of vertex 91330 * @param {Number} z z-coordinate of vertex 91331 * @chainable 91332 * @TODO implement handling of <a href="#/p5.Vector">p5.Vector</a> args 91333 */ _main.default.RendererGL.prototype.vertex = function(x, y) { 91334 var z, u, v; 91335 91336 // default to (x, y) mode: all other arugments assumed to be 0. 91337 z = u = v = 0; 91338 91339 if (arguments.length === 3) { 91340 // (x, y, z) mode: (u, v) assumed to be 0. 91341 z = arguments[2]; 91342 } else if (arguments.length === 4) { 91343 // (x, y, u, v) mode: z assumed to be 0. 91344 u = arguments[2]; 91345 v = arguments[3]; 91346 } else if (arguments.length === 5) { 91347 // (x, y, z, u, v) mode 91348 z = arguments[2]; 91349 u = arguments[3]; 91350 v = arguments[4]; 91351 } 91352 var vert = new _main.default.Vector(x, y, z); 91353 this.immediateMode.geometry.vertices.push(vert); 91354 var vertexColor = this.curFillColor || [0.5, 0.5, 0.5, 1.0]; 91355 this.immediateMode.geometry.vertexColors.push( 91356 vertexColor[0], 91357 vertexColor[1], 91358 vertexColor[2], 91359 vertexColor[3] 91360 ); 91361 91362 if (this.textureMode === constants.IMAGE) { 91363 if (this._tex !== null) { 91364 if (this._tex.width > 0 && this._tex.height > 0) { 91365 u /= this._tex.width; 91366 v /= this._tex.height; 91367 } 91368 } else if (this._tex === null && arguments.length >= 4) { 91369 // Only throw this warning if custom uv's have been provided 91370 console.warn( 91371 'You must first call texture() before using' + 91372 ' vertex() with image based u and v coordinates' 91373 ); 91374 } 91375 } 91376 91377 this.immediateMode.geometry.uvs.push(u, v); 91378 91379 this.immediateMode._bezierVertex[0] = x; 91380 this.immediateMode._bezierVertex[1] = y; 91381 this.immediateMode._bezierVertex[2] = z; 91382 91383 this.immediateMode._quadraticVertex[0] = x; 91384 this.immediateMode._quadraticVertex[1] = y; 91385 this.immediateMode._quadraticVertex[2] = z; 91386 91387 return this; 91388 }; 91389 91390 /** 91391 * End shape drawing and render vertices to screen. 91392 * @chainable 91393 */ 91394 _main.default.RendererGL.prototype.endShape = function( 91395 mode, 91396 isCurve, 91397 isBezier, 91398 isQuadratic, 91399 isContour, 91400 shapeKind 91401 ) { 91402 if (this.immediateMode.shapeMode === constants.POINTS) { 91403 this._drawPoints( 91404 this.immediateMode.geometry.vertices, 91405 this.immediateMode.buffers.point 91406 ); 91407 91408 return this; 91409 } 91410 this._processVertices.apply(this, arguments); 91411 if (this._doFill) { 91412 if (this.immediateMode.geometry.vertices.length > 1) { 91413 this._drawImmediateFill(); 91414 } 91415 } 91416 if (this._doStroke) { 91417 if (this.immediateMode.geometry.lineVertices.length > 1) { 91418 this._drawImmediateStroke(); 91419 } 91420 } 91421 91422 this.isBezier = false;
91423 this.isQuadratic = false; 91424 this.isCurve = false; 91425 this.immediateMode._bezierVertex.length = 0; 91426 this.immediateMode._quadraticVertex.length = 0; 91427 this.immediateMode._curveVertex.length = 0; 91428 return this; 91429 }; 91430 91431 /** 91432 * Called from endShape(). This function calculates the stroke vertices for custom shapes and 91433 * tesselates shapes when applicable. 91434 * @private 91435 * @param {Number} mode webgl primitives mode. beginShape supports the 91436 * following modes: 91437 * POINTS,LINES,LINE_STRIP,LINE_LOOP,TRIANGLES, 91438 * TRIANGLE_STRIP, TRIANGLE_FAN and TESS(WEBGL only) 91439 */ 91440 _main.default.RendererGL.prototype._processVertices = function(mode) { 91441 if (this.immediateMode.geometry.vertices.length === 0) return; 91442 91443 var calculateStroke = this._doStroke && this.drawMode !== constants.TEXTURE; 91444 var shouldClose = mode === constants.CLOSE; 91445 if (calculateStroke) { 91446 this.immediateMode.geometry.edges = this._calculateEdges( 91447 this.immediateMode.shapeMode, 91448 this.immediateMode.geometry.vertices, 91449 shouldClose 91450 ); 91451 91452 this.immediateMode.geometry._edgesToVertices(); 91453 } 91454 // For hollow shapes, user must set mode to TESS 91455 var convexShape = this.immediateMode.shapeMode === constants.TESS; 91456 // We tesselate when drawing curves or convex shapes 91457 var shouldTess = 91458 (this.isBezier || this.isQuadratic || this.isCurve || convexShape) && 91459 this.immediateMode.shapeMode !== constants.LINES; 91460 91461 if (shouldTess) { 91462 this._tesselateShape(); 91463 } 91464 }; 91465 91466 /** 91467 * Called from _processVertices(). This function calculates the stroke vertices for custom shapes and 91468 * tesselates shapes when applicable. 91469 * @private 91470 * @returns {Array[Number]} indices for custom shape vertices indicating edges. 91471 */ 91472 _main.default.RendererGL.prototype._calculateEdges = function( 91473 shapeMode, 91474 verts, 91475 shouldClose 91476 ) { 91477 var res = []; 91478 var i = 0; 91479 switch (shapeMode) { 91480 case constants.TRIANGLE_STRIP: 91481 for (i = 0; i < verts.length - 2; i++) { 91482 res.push([i, i + 1]); 91483 res.push([i, i + 2]); 91484 } 91485 res.push([i, i + 1]); 91486 break; 91487 case constants.TRIANGLES: 91488 for (i = 0; i < verts.length - 2; i = i + 3) { 91489 res.push([i, i + 1]); 91490 res.push([i + 1, i + 2]); 91491 res.push([i + 2, i]); 91492 } 91493 break; 91494 case constants.LINES: 91495 for (i = 0; i < verts.length - 1; i = i + 2) { 91496 res.push([i, i + 1]); 91497 } 91498 break; 91499 default: 91500 for (i = 0; i < verts.length - 1; i++) { 91501 res.push([i, i + 1]); 91502 } 91503 break; 91504 } 91505 91506 if (shouldClose) { 91507 res.push([verts.length - 1, 0]); 91508 } 91509 return res; 91510 }; 91511 91512 /** 91513 * Called from _processVertices() when applicable. This function tesselates immediateMode.geometry. 91514 * @private 91515 */ 91516 _main.default.RendererGL.prototype._tesselateShape = function() { 91517 this.immediateMode.shapeMode = constants.TRIANGLES; 91518 var contours = [ 91519 new Float32Array(this._vToNArray(this.immediateMode.geometry.vertices)) 91520 ]; 91521 91522 var polyTriangles = this._triangulate(contours); 91523 this.immediateMode.geometry.vertices = []; 91524 for ( 91525 var j = 0, polyTriLength = polyTriangles.length; 91526 j < polyTriLength; 91527 j = j + 3 91528 ) {
91529 this.vertex(polyTriangles[j], polyTriangles[j + 1], polyTriangles[j + 2]); 91530 } 91531 }; 91532 91533 /** 91534 * Called from endShape(). Responsible for calculating normals, setting shader uniforms, 91535 * enabling all appropriate buffers, applying color blend, and drawing the fill geometry. 91536 * @private 91537 */ 91538 _main.default.RendererGL.prototype._drawImmediateFill = function() { 91539 var gl = this.GL; 91540 var shader = this._getImmediateFillShader(); 91541 91542 this._calculateNormals(this.immediateMode.geometry); 91543 this._setFillUniforms(shader); 91544 var _iteratorNormalCompletion = true; 91545 var _didIteratorError = false; 91546 var _iteratorError = undefined; 91547 try { 91548 for ( 91549 var _iterator = this.immediateMode.buffers.fill[Symbol.iterator](), _step; 91550 !(_iteratorNormalCompletion = (_step = _iterator.next()).done); 91551 _iteratorNormalCompletion = true 91552 ) { 91553 var buff = _step.value; 91554 buff._prepareBuffer(this.immediateMode.geometry, shader); 91555 } 91556 91557 // LINE_STRIP and LINES are not used for rendering, instead 91558 // they only indicate a way to modify vertices during the _processVertices() step 91559 } catch (err) { 91560 _didIteratorError = true; 91561 _iteratorError = err; 91562 } finally { 91563 try { 91564 if (!_iteratorNormalCompletion && _iterator.return != null) { 91565 _iterator.return(); 91566 } 91567 } finally { 91568 if (_didIteratorError) { 91569 throw _iteratorError; 91570 } 91571 } 91572 } 91573 if ( 91574 this.immediateMode.shapeMode === constants.LINE_STRIP || 91575 this.immediateMode.shapeMode === constants.LINES 91576 ) { 91577 this.immediateMode.shapeMode = constants.TRIANGLE_FAN; 91578 } 91579 91580 this._applyColorBlend(this.curFillColor); 91581 gl.drawArrays( 91582 this.immediateMode.shapeMode, 91583 0, 91584 this.immediateMode.geometry.vertices.length 91585 ); 91586 91587 shader.unbindShader(); 91588 }; 91589 91590 /** 91591 * Called from endShape(). Responsible for calculating normals, setting shader uniforms, 91592 * enabling all appropriate buffers, applying color blend, and drawing the stroke geometry. 91593 * @private 91594 */ 91595 _main.default.RendererGL.prototype._drawImmediateStroke = function() { 91596 var gl = this.GL; 91597 var shader = this._getImmediateStrokeShader(); 91598 this._setStrokeUniforms(shader); 91599 var _iteratorNormalCompletion2 = true; 91600 var _didIteratorError2 = false;
91601 var _iteratorError2 = undefined; 91602 try { 91603 for ( 91604 var _iterator2 = this.immediateMode.buffers.stroke[Symbol.iterator](), 91605 _step2; 91606 !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); 91607 _iteratorNormalCompletion2 = true 91608 ) { 91609 var buff = _step2.value; 91610 buff._prepareBuffer(this.immediateMode.geometry, shader); 91611 } 91612 } catch (err) { 91613 _didIteratorError2 = true; 91614 _iteratorError2 = err; 91615 } finally { 91616 try { 91617 if (!_iteratorNormalCompletion2 && _iterator2.return != null) { 91618 _iterator2.return(); 91619 } 91620 } finally { 91621 if (_didIteratorError2) { 91622 throw _iteratorError2; 91623 } 91624 } 91625 } 91626 this._applyColorBlend(this.curStrokeColor); 91627 gl.drawArrays(gl.TRIANGLES, 0, this.immediateMode.geometry.lineVertices.length); 91628 91629 shader.unbindShader(); 91630 }; 91631 91632 /** 91633 * Called from _drawImmediateFill(). Currently adds default normals which 91634 * only work for flat shapes. 91635 * @parem 91636 * @private 91637 */ 91638 _main.default.RendererGL.prototype._calculateNormals = function(geometry) { 91639 geometry.vertices.forEach(function() { 91640 geometry.vertexNormals.push(new _main.default.Vector(0, 0, 1)); 91641 }); 91642 }; 91643 var _default = _main.default.RendererGL; 91644 exports.default = _default; 91645 }, 91646 { '../core/constants': 48, '../core/main': 59, './p5.RenderBuffer': 110 } 91647 ], 91648 112: [ 91649 function(_dereq_, module, exports) { 91650 'use strict'; 91651 Object.defineProperty(exports, '__esModule', { value: true }); 91652 exports.default = void 0; 91653 91654 var _main = _interopRequireDefault(_dereq_('../core/main')); 91655 _dereq_('./p5.RendererGL'); 91656 _dereq_('./p5.RenderBuffer'); 91657 function _interopRequireDefault(obj) { 91658 return obj && obj.__esModule ? obj : { default: obj }; 91659 } //Retained Mode. The default mode for rendering 3D primitives 91660 //in WEBGL. 91661 var hashCount = 0; 91662 /** 91663 * _initBufferDefaults 91664 * @private 91665 * @description initializes buffer defaults. runs each time a new geometry is 91666 * registered 91667 * @param {String} gId key of the geometry object 91668 * @returns {Object} a new buffer object 91669 */ 91670 _main.default.RendererGL.prototype._initBufferDefaults = function(gId) { 91671 this._freeBuffers(gId); 91672 91673 //@TODO remove this limit on hashes in retainedMode.geometry 91674 hashCount++; 91675 if (hashCount > 1000) { 91676 var key = Object.keys(this.retainedMode.geometry)[0]; 91677 delete this.retainedMode.geometry[key]; 91678 hashCount--; 91679 } 91680 91681 //create a new entry in our retainedMode.geometry 91682 return (this.retainedMode.geometry[gId] = {}); 91683 }; 91684 91685 _main.default.RendererGL.prototype._freeBuffers = function(gId) { 91686 var buffers = this.retainedMode.geometry[gId]; 91687 if (!buffers) { 91688 return; 91689 } 91690 91691 delete this.retainedMode.geometry[gId]; 91692 hashCount--; 91693 91694 var gl = this.GL; 91695 if (buffers.indexBuffer) { 91696 gl.deleteBuffer(buffers.indexBuffer); 91697 } 91698 91699 function freeBuffers(defs) { 91700 var _iteratorNormalCompletion = true; 91701 var _didIteratorError = false; 91702 var _iteratorError = undefined; 91703 try { 91704 for ( 91705 var _iterator = defs[Symbol.iterator](), _step; 91706 !(_iteratorNormalCompletion = (_step = _iterator.next()).done); 91707 _iteratorNormalCompletion = true 91708 ) { 91709 var def = _step.value; 91710 if (buffers[def.dst]) { 91711 gl.deleteBuffer(buffers[def.dst]); 91712 buffers[def.dst] = null; 91713 } 91714 } 91715 } catch (err) {
91716 _didIteratorError = true; 91717 _iteratorError = err; 91718 } finally { 91719 try { 91720 if (!_iteratorNormalCompletion && _iterator.return != null) { 91721 _iterator.return(); 91722 } 91723 } finally { 91724 if (_didIteratorError) { 91725 throw _iteratorError; 91726 } 91727 } 91728 } 91729 } 91730 91731 // free all the buffers 91732 freeBuffers(this.retainedMode.buffers.stroke); 91733 freeBuffers(this.retainedMode.buffers.fill); 91734 }; 91735 91736 /** 91737 * creates a buffers object that holds the WebGL render buffers 91738 * for a geometry. 91739 * @private 91740 * @param {String} gId key of the geometry object 91741 * @param {p5.Geometry} model contains geometry data 91742 */ 91743 _main.default.RendererGL.prototype.createBuffers = function(gId, model) { 91744 var gl = this.GL; 91745 //initialize the gl buffers for our geom groups 91746 var buffers = this._initBufferDefaults(gId); 91747 buffers.model = model; 91748 91749 var indexBuffer = buffers.indexBuffer; 91750 91751 if (model.faces.length) { 91752 // allocate space for faces 91753 if (!indexBuffer) indexBuffer = buffers.indexBuffer = gl.createBuffer(); 91754 var vals = _main.default.RendererGL.prototype._flatten(model.faces); 91755 this._bindBuffer(indexBuffer, gl.ELEMENT_ARRAY_BUFFER, vals, Uint16Array); 91756 91757 // the vertex count is based on the number of faces 91758 buffers.vertexCount = model.faces.length * 3; 91759 } else { 91760 // the index buffer is unused, remove it 91761 if (indexBuffer) { 91762 gl.deleteBuffer(indexBuffer); 91763 buffers.indexBuffer = null; 91764 } 91765 // the vertex count comes directly from the model 91766 buffers.vertexCount = model.vertices ? model.vertices.length : 0; 91767 } 91768 91769 buffers.lineVertexCount = model.lineVertices ? model.lineVertices.length : 0; 91770 91771 return buffers; 91772 }; 91773 91774 /** 91775 * Draws buffers given a geometry key ID 91776 * @private 91777 * @param {String} gId ID in our geom hash 91778 * @chainable 91779 */ 91780 _main.default.RendererGL.prototype.drawBuffers = function(gId) { 91781 var gl = this.GL; 91782 var geometry = this.retainedMode.geometry[gId]; 91783 91784 if (this._doStroke && geometry.lineVertexCount > 0) { 91785 var strokeShader = this._getRetainedStrokeShader(); 91786 this._setStrokeUniforms(strokeShader); 91787 var _iteratorNormalCompletion2 = true; 91788 var _didIteratorError2 = false;
91789 var _iteratorError2 = undefined; 91790 try { 91791 for ( 91792 var _iterator2 = this.retainedMode.buffers.stroke[Symbol.iterator](), 91793 _step2; 91794 !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); 91795 _iteratorNormalCompletion2 = true 91796 ) { 91797 var buff = _step2.value; 91798 buff._prepareBuffer(geometry, strokeShader); 91799 } 91800 } catch (err) { 91801 _didIteratorError2 = true; 91802 _iteratorError2 = err; 91803 } finally { 91804 try { 91805 if (!_iteratorNormalCompletion2 && _iterator2.return != null) { 91806 _iterator2.return(); 91807 } 91808 } finally { 91809 if (_didIteratorError2) { 91810 throw _iteratorError2; 91811 } 91812 } 91813 } 91814 this._applyColorBlend(this.curStrokeColor); 91815 this._drawArrays(gl.TRIANGLES, gId); 91816 strokeShader.unbindShader(); 91817 } 91818 91819 if (this._doFill) { 91820 var fillShader = this._getRetainedFillShader(); 91821 this._setFillUniforms(fillShader); 91822 var _iteratorNormalCompletion3 = true; 91823 var _didIteratorError3 = false; 91824 var _iteratorError3 = undefined; 91825 try { 91826 for ( 91827 var _iterator3 = this.retainedMode.buffers.fill[Symbol.iterator](), 91828 _step3; 91829 !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); 91830 _iteratorNormalCompletion3 = true 91831 ) { 91832 var _buff = _step3.value; 91833 _buff._prepareBuffer(geometry, fillShader); 91834 } 91835 } catch (err) { 91836 _didIteratorError3 = true; 91837 _iteratorError3 = err; 91838 } finally { 91839 try { 91840 if (!_iteratorNormalCompletion3 && _iterator3.return != null) { 91841 _iterator3.return(); 91842 } 91843 } finally { 91844 if (_didIteratorError3) { 91845 throw _iteratorError3; 91846 } 91847 } 91848 } 91849 if (geometry.indexBuffer) { 91850 //vertex index buffer 91851 this._bindBuffer(geometry.indexBuffer, gl.ELEMENT_ARRAY_BUFFER); 91852 } 91853 this._applyColorBlend(this.curFillColor); 91854 this._drawElements(gl.TRIANGLES, gId); 91855 fillShader.unbindShader(); 91856 } 91857 return this; 91858 }; 91859 91860 /** 91861 * Calls drawBuffers() with a scaled model/view matrix. 91862 * 91863 * This is used by various 3d primitive methods (in primitives.js, eg. plane, 91864 * box, torus, etc...) to allow caching of un-scaled geometries. Those 91865 * geometries are generally created with unit-length dimensions, cached as 91866 * such, and then scaled appropriately in this method prior to rendering. 91867 * 91868 * @private 91869 * @method drawBuffersScaled 91870 * @param {String} gId ID in our geom hash 91871 * @param {Number} scaleX the amount to scale in the X direction 91872 * @param {Number} scaleY the amount to scale in the Y direction 91873 * @param {Number} scaleZ the amount to scale in the Z direction 91874 */ 91875 _main.default.RendererGL.prototype.drawBuffersScaled = function( 91876 gId, 91877 scaleX, 91878 scaleY, 91879 scaleZ 91880 ) { 91881 var uMVMatrix = this.uMVMatrix.copy(); 91882 try { 91883 this.uMVMatrix.scale(scaleX, scaleY, scaleZ); 91884 this.drawBuffers(gId); 91885 } finally { 91886 this.uMVMatrix = uMVMatrix; 91887 } 91888 }; 91889 91890 _main.default.RendererGL.prototype._drawArrays = function(drawMode, gId) { 91891 this.GL.drawArrays( 91892 drawMode, 91893 0, 91894 this.retainedMode.geometry[gId].lineVertexCount 91895 ); 91896 91897 return this; 91898 }; 91899 91900 _main.default.RendererGL.prototype._drawElements = function(drawMode, gId) { 91901 var buffers = this.retainedMode.geometry[gId]; 91902 var gl = this.GL; 91903 // render the fill 91904 if (buffers.indexBuffer) { 91905 // we're drawing faces 91906 gl.drawElements(gl.TRIANGLES, buffers.vertexCount, gl.UNSIGNED_SHORT, 0); 91907 } else { 91908 // drawing vertices 91909 gl.drawArrays(drawMode || gl.TRIANGLES, 0, buffers.vertexCount); 91910 } 91911 }; 91912 91913 _main.default.RendererGL.prototype._drawPoints = function( 91914 vertices, 91915 vertexBuffer 91916 ) { 91917 var gl = this.GL; 91918 var pointShader = this._getImmediatePointShader(); 91919 this._setPointUniforms(pointShader); 91920 91921 this._bindBuffer( 91922 vertexBuffer, 91923 gl.ARRAY_BUFFER, 91924 this._vToNArray(vertices), 91925 Float32Array, 91926 gl.STATIC_DRAW 91927 ); 91928 91929 pointShader.enableAttrib(pointShader.attributes.aPosition, 3); 91930 91931 gl.drawArrays(gl.Points, 0, vertices.length); 91932 91933 pointShader.unbindShader(); 91934 }; 91935 var _default = _main.default.RendererGL; 91936 exports.default = _default; 91937 }, 91938 { '../core/main': 59, './p5.RenderBuffer': 110, './p5.RendererGL': 113 } 91939 ], 91940 113: [
91941 function(_dereq_, module, exports) { 91942 'use strict'; 91943 function _typeof(obj) { 91944 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') { 91945 _typeof = function _typeof(obj) { 91946 return typeof obj; 91947 }; 91948 } else { 91949 _typeof = function _typeof(obj) { 91950 return obj && 91951 typeof Symbol === 'function' && 91952 obj.constructor === Symbol && 91953 obj !== Symbol.prototype 91954 ? 'symbol' 91955 : typeof obj; 91956 }; 91957 } 91958 return _typeof(obj); 91959 } 91960 Object.defineProperty(exports, '__esModule', { value: true }); 91961 exports.default = void 0; 91962 var _main = _interopRequireDefault(_dereq_('../core/main')); 91963 var constants = _interopRequireWildcard(_dereq_('../core/constants')); 91964 var _libtess = _interopRequireDefault(_dereq_('libtess')); 91965 _dereq_('./p5.Shader'); 91966 _dereq_('./p5.Camera'); 91967 _dereq_('../core/p5.Renderer'); 91968 _dereq_('./p5.Matrix'); 91969 91970 var _path = _dereq_('path'); 91971 function _getRequireWildcardCache() { 91972 if (typeof WeakMap !== 'function') return null; 91973 var cache = new WeakMap(); 91974 _getRequireWildcardCache = function _getRequireWildcardCache() { 91975 return cache; 91976 }; 91977 return cache; 91978 } 91979 function _interopRequireWildcard(obj) { 91980 if (obj && obj.__esModule) { 91981 return obj; 91982 } 91983 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) { 91984 return { default: obj }; 91985 } 91986 var cache = _getRequireWildcardCache(); 91987 if (cache && cache.has(obj)) { 91988 return cache.get(obj); 91989 } 91990 var newObj = {}; 91991 var hasPropertyDescriptor = 91992 Object.defineProperty && Object.getOwnPropertyDescriptor; 91993 for (var key in obj) { 91994 if (Object.prototype.hasOwnProperty.call(obj, key)) { 91995 var desc = hasPropertyDescriptor 91996 ? Object.getOwnPropertyDescriptor(obj, key) 91997 : null; 91998 if (desc && (desc.get || desc.set)) { 91999 Object.defineProperty(newObj, key, desc); 92000 } else { 92001 newObj[key] = obj[key]; 92002 } 92003 } 92004 } 92005 newObj.default = obj; 92006 if (cache) { 92007 cache.set(obj, newObj); 92008 } 92009 return newObj; 92010 } 92011 function _interopRequireDefault(obj) { 92012 return obj && obj.__esModule ? obj : { default: obj }; 92013 } 92014 function _toConsumableArray(arr) { 92015 return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); 92016 } 92017 function _nonIterableSpread() { 92018 throw new TypeError('Invalid attempt to spread non-iterable instance'); 92019 } 92020 function _iterableToArray(iter) { 92021 if ( 92022 Symbol.iterator in Object(iter) || 92023 Object.prototype.toString.call(iter) === '[object Arguments]' 92024 ) 92025 return Array.from(iter); 92026 } 92027 function _arrayWithoutHoles(arr) { 92028 if (Array.isArray(arr)) { 92029 for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { 92030 arr2[i] = arr[i]; 92031 } 92032 return arr2; 92033 } 92034 } 92035 92036 var lightingShader = 92037 '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) {\
92037n\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'; 92038 92039 var defaultShaders = { 92040 immediateVert: 92041 'attribute vec3 aPosition;\nattribute vec4 aVertexColor;\n\nuniform mat4 uModelViewMatrix;\nuniform mat4 uProjectionMatrix;\nuniform float uResolution;\nuniform float uPointSize;\n\nvarying vec4 vColor;
92041\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', 92042 92043 vertexColorVert: 92044 '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', 92045 92046 vertexColorFrag: 92047 'precision mediump float;\nvarying vec4 vColor;\nvoid main(void) {\n gl_FragColor = vColor;\n}', 92048 92049 normalVert: 92050 '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
92050);\n gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;\n vVertexNormal = normalize(vec3( uNormalMatrix * aNormal ));\n vVertTexCoord = aTexCoord;\n}\n', 92051 normalFrag: 92052 'precision mediump float;\nvarying vec3 vVertexNormal;\nvoid main(void) {\n gl_FragColor = vec4(vVertexNormal, 1.0);\n}', 92053 basicFrag: 92054 'precision mediump float;\nuniform vec4 uMaterialColor;\nvoid main(void) {\n gl_FragColor = uMaterialColor;\n}', 92055 lightVert: 92056 lightingShader + 92057 '// 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', 92058 92059 lightTextureFrag: 92060 '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}', 92061 92062 phongVert: 92063 '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
92063);\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', 92064 phongFrag: 92065 lightingShader + 92066 '// 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}', 92067 92068 fontVert: 92069 "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;
92069\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", 92070 fontFrag: 92071 "#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;
92071\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}", 92072 lineVert: 92073 "/*\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 c
92073omponents 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", 92074 lineFrag: 92075 'precision mediump float;\nprecision mediump int;\n\nuniform vec4 uMaterialColor;\n\nvoid main() {\n gl_FragColor = uMaterialColor;\n}', 92076 pointVert: 92077 'attribute vec3 aPosition;\nuniform float uPointSize;\nvarying float vStrokeWeight;\nuniform mat4 uModelViewMatrix;\nuniform mat4 uProjectionMatrix;
92077\nvoid main() {\n\tvec4 positionVec4 = vec4(aPosition, 1.0);\n\tgl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;\n\tgl_PointSize = uPointSize;\n\tvStrokeWeight = uPointSize;\n}', 92078 pointFrag: 92079 '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}' 92080 }; 92081 92082 /** 92083 * 3D graphics class 92084 * @private 92085 * @class p5.RendererGL 92086 * @constructor 92087 * @extends p5.Renderer 92088 * @todo extend class to include public method for offscreen 92089 * rendering (FBO). 92090 */ 92091 _main.default.RendererGL = function(elt, pInst, isMainCanvas, attr) { 92092 _main.default.Renderer.call(this, elt, pInst, isMainCanvas); 92093 this._setAttributeDefaults(pInst); 92094 this._initContext(); 92095 this.isP3D = true; //lets us know we're in 3d mode 92096 92097 // This redundant property is useful in reminding you that you are 92098 // interacting with WebGLRenderingContext, still worth considering future removal 92099 this.GL = this.drawingContext; 92100 this._pInst._setProperty('drawingContext', this.drawingContext); 92101 92102 // erasing 92103 this._isErasing = false; 92104 92105 // lights 92106 this._enableLighting = false; 92107 92108 this.ambientLightColors = []; 92109 this.specularColors = [1, 1, 1]; 92110 92111 this.directionalLightDirections = []; 92112 this.directionalLightDiffuseColors = []; 92113 this.directionalLightSpecularColors = []; 92114 92115 this.pointLightPositions = []; 92116 this.pointLightDiffuseColors = []; 92117 this.pointLightSpecularColors = []; 92118 92119 this.spotLightPositions = []; 92120 this.spotLightDirections = []; 92121 this.spotLightDiffuseColors = []; 92122 this.spotLightSpecularColors = []; 92123 this.spotLightAngle = []; 92124 this.spotLightConc = []; 92125 92126 this.drawMode = constants.FILL; 92127 92128 this.curFillColor = this._cachedFillStyle = [1, 1, 1, 1]; 92129 this.curStrokeColor = this._cachedStrokeStyle = [0, 0, 0, 1]; 92130 92131 this.curBlendMode = constants.BLEND; 92132 this._cachedBlendMode = undefined; 92133 this.blendExt = this.GL.getExtension('EXT_blend_minmax'); 92134 this._isBlending = false; 92135 92136 this._useSpecularMaterial = false; 92137 this._useEmissiveMaterial = false; 92138 this._useNormalMaterial = false; 92139 this._useShininess = 1; 92140 92141 this._tint = [255, 255, 255, 255]; 92142 92143 // lightFalloff variables 92144 this.constantAttenuation = 1; 92145 this.linearAttenuation = 0; 92146 this.quadraticAttenuation = 0; 92147 92148 /** 92149 * model view, projection, & normal 92150 * matrices 92151 */ 92152 this.uMVMatrix = new _main.default.Matrix(); 92153 this.uPMatrix = new _main.default.Matrix(); 92154 this.uNMatrix = new _main.default.Matrix('mat3'); 92155 92156 // Camera 92157 this._curCamera = new _main.default.Camera(this); 92158 this._curCamera._computeCameraDefaultSettings(); 92159 this._curCamera._setDefaultCamera(); 92160 92161 this._defaultLightShader = undefined; 92162 this._defaultImmediateModeShader = undefined; 92163 this._defaultNormalShader = undefined; 92164 this._defaultColorShader = undefined; 92165 this._defaultPointShader = undefined; 92166 92167 this.userFillShader = undefined; 92168 this.userStrokeShader = undefined; 92169 this.userPointShader = undefined; 92170 92171 // Default drawing is done in Retained Mode 92172 // Geometry and Material hashes stored here 92173 this.retainedMode = { 92174 geometry: {}, 92175 buffers: { 92176 // prettier-ignore 92177 stroke: [ 92178 new _main.default.RenderBuffer(3, 'lineVertices', 'lineVertexBuffer', 'aPosition', this, this._flatten), 92179 new _main.default.RenderBuffer(4, 'lineNormals', 'lineNormalBuffer', 'aDirection', this, this._flatten)], 92180 92181 // prettier-ignore 92182 fill: [ 92183 new _main.default.RenderBuffer(3, 'vertices', 'vertexBuffer', 'aPosition', this, this._vToNArray), 92184 new _main.default.RenderBuffer(3, 'vertexNormals', 'normalBuffer', 'aNormal', this, this._vToNArray), 92185 new _main.default.RenderBuffer(4, 'vertexColors', 'colorBuffer', 'aMaterialColor', this), 92186 new _main.default.RenderBuffer(3, 'vertexAmbients', 'ambientBuffer', 'aAmbientColor', this), 92187 //new BufferDef(3, 'vertexSpeculars', 'specularBuffer', 'aSpecularColor'), 92188 new _main.default.RenderBuffer(2, 'uvs', 'uvBuffer', 'aTexCoord', this, this._flatten)], 92189 92190 // prettier-ignore 92191 text: [ 92192 new _main.default.RenderBuffer(3, 'vertices', 'vertexBuffer', 'aPosition', this, this._vToNArray), 92193 new _main.default.RenderBuffer(2, 'uvs', 'uvBuffer', 'aTexCoord', this, this._flatten)] 92194 } 92195 }; 92196 92197 // Immediate Mode 92198 // Geometry and Material hashes stored here 92199 this.immediateMode = { 92200 geometry: new _main.default.Geometry(), 92201 shapeMode: constants.TRIANGLE_FAN, 92202 _bezierVertex: [], 92203 _quadraticVertex: [], 92204 _curveVertex: [], 92205 buffers: { 92206 // prettier-ignore 92207 fill: [ 92208 new _main.default.RenderBuffer(3, 'vertices', 'vertexBuffer', 'aPosition', this, this._vToNArray), 92209 new _main.default.RenderBuffer(3, 'vertexNormals', 'normalBuffer', 'aNormal', this, this._vToNArray), 92210 new _main.default.RenderBuffer(4, 'vertexColors', 'colorBuffer', 'aVertexColor', this), 92211 new _main.default.RenderBuffer(3, 'vertexAmbients', 'ambientBuffer', 'aAmbientColor', this), 92212 new _main.default.RenderBuffer(2, 'uvs', 'uvBuffer', 'aTexCoord', this, this._flatten)], 92213 92214 // prettier-ignore 92215 stroke: [ 92216 new _main.default.RenderBuffer(3, 'lineVertices', 'lineVertexBuffer', 'aPosition', this, this._flatten), 92217 new _main.default.RenderBuffer(4, 'lineNormals', 'lineNormalBuffer', 'aDirection', this, this._flatten)], 92218 92219 point: this.GL.createBuffer() 92220 } 92221 }; 92222 92223 this.pointSize = 5.0; //default point size 92224 this.curStrokeWeight = 1; 92225 92226 // array of textures created in this gl context via this.getTexture(src) 92227 this.textures = []; 92228 92229 this.textureMode = constants.IMAGE; 92230 // default wrap settings 92231 this.textureWrapX = constants.CLAMP; 92232 this.textureWrapY = constants.CLAMP; 92233 this._tex = null; 92234 this._curveTightness = 6; 92235 92236 // lookUpTable for coefficients needed to be calculated for bezierVertex, same are used for curveVertex 92237 this._lookUpTableBezier = []; 92238 // lookUpTable for coefficients needed to be calculated for quadraticVertex 92239 this._lookUpTableQuadratic = []; 92240 92241 // current curveDetail in the Bezier lookUpTable 92242 this._lutBezierDetail = 0; 92243 // current curveDetail in the Quadratic lookUpTable 92244 this._lutQuadraticDetail = 0; 92245 92246 this._tessy = this._initTessy(); 92247 92248 this.fontInfos = {}; 92249 92250 this._curShader = undefined; 92251 92252 return this; 92253 }; 92254 92255 _main.default.RendererGL.prototype = Object.create( 92256 _main.default.Renderer.prototype 92257 ); 92258
92259 ////////////////////////////////////////////// 92260 // Setting 92261 ////////////////////////////////////////////// 92262 92263 _main.default.RendererGL.prototype._setAttributeDefaults = function(pInst) { 92264 // See issue #3850, safer to enable AA in Safari 92265 var applyAA = navigator.userAgent.toLowerCase().includes('safari'); 92266 var defaults = { 92267 alpha: true, 92268 depth: true, 92269 stencil: true, 92270 antialias: applyAA, 92271 premultipliedAlpha: false, 92272 preserveDrawingBuffer: true, 92273 perPixelLighting: true 92274 }; 92275 92276 if (pInst._glAttributes === null) { 92277 pInst._glAttributes = defaults; 92278 } else { 92279 pInst._glAttributes = Object.assign(defaults, pInst._glAttributes); 92280 } 92281 return; 92282 }; 92283 92284 _main.default.RendererGL.prototype._initContext = function() { 92285 try { 92286 this.drawingContext = 92287 this.canvas.getContext('webgl', this._pInst._glAttributes) || 92288 this.canvas.getContext('experimental-webgl', this._pInst._glAttributes); 92289 if (this.drawingContext === null) { 92290 throw new Error('Error creating webgl context'); 92291 } else { 92292 var gl = this.drawingContext; 92293 gl.enable(gl.DEPTH_TEST); 92294 gl.depthFunc(gl.LEQUAL); 92295 gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); 92296 this._viewport = this.drawingContext.getParameter( 92297 this.drawingContext.VIEWPORT 92298 ); 92299 } 92300 } catch (er) { 92301 throw er; 92302 } 92303 }; 92304 92305 //This is helper function to reset the context anytime the attributes 92306 //are changed with setAttributes() 92307 92308 _main.default.RendererGL.prototype._resetContext = function(options, callback) { 92309 var w = this.width; 92310 var h = this.height; 92311 var defaultId = this.canvas.id; 92312 var isPGraphics = this._pInst instanceof _main.default.Graphics; 92313 92314 if (isPGraphics) { 92315 var pg = this._pInst; 92316 pg.canvas.parentNode.removeChild(pg.canvas); 92317 pg.canvas = document.createElement('canvas'); 92318 var node = pg._pInst._userNode || document.body; 92319 node.appendChild(pg.canvas); 92320 _main.default.Element.call(pg, pg.canvas, pg._pInst); 92321 pg.width = w; 92322 pg.height = h; 92323 } else { 92324 var c = this.canvas; 92325 if (c) { 92326 c.parentNode.removeChild(c); 92327 } 92328 c = document.createElement('canvas'); 92329 c.id = defaultId; 92330 if (this._pInst._userNode) { 92331 this._pInst._userNode.appendChild(c); 92332 } else { 92333 document.body.appendChild(c); 92334 } 92335 this._pInst.canvas = c; 92336 } 92337 92338 var renderer = new _main.default.RendererGL( 92339 this._pInst.canvas, 92340 this._pInst, 92341 !isPGraphics 92342 ); 92343 92344 this._pInst._setProperty('_renderer', renderer); 92345 renderer.resize(w, h); 92346 renderer._applyDefaults(); 92347 92348 if (!isPGraphics) { 92349 this._pInst._elements.push(renderer); 92350 } 92351 92352 if (typeof callback === 'function') { 92353 //setTimeout with 0 forces the task to the back of the queue, this ensures that 92354 //we finish switching out the renderer 92355 setTimeout(function() { 92356 callback.apply(window._renderer, options); 92357 }, 0); 92358 } 92359 }; 92360 /** 92361 * @module Rendering 92362 * @submodule Rendering 92363 * @for p5 92364 */ 92365 /** 92366 * Set attributes for the WebGL Drawing context. 92367 * This is a way of adjusting how the WebGL 92368 * renderer works to fine-tune the display and performance. 92369 * 92370 * Note that this will reinitialize the drawing context 92371 * if called after the WebGL canvas is made. 92372 * 92373 * If an object is passed as the parameter, all attributes 92374 * not declared in the object will be set to defaults. 92375 * 92376 * The available attributes are: 92377 * <br> 92378 * alpha - indicates if the canvas contains an alpha buffer 92379 * default is true 92380 * 92381 * depth - indicates whether the drawing buffer has a depth buffer 92382 * of at least 16 bits - default is true 92383 * 92384 * stencil - indicates whether the drawing buffer has a stencil buffer 92385 * of at least 8 bits 92386 * 92387 * antialias - indicates whether or not to perform anti-ali
92387asing 92388 * default is false (true in Safari) 92389 * 92390 * premultipliedAlpha - indicates that the page compositor will assume 92391 * the drawing buffer contains colors with pre-multiplied alpha 92392 * default is false 92393 * 92394 * preserveDrawingBuffer - if true the buffers will not be cleared and 92395 * and will preserve their values until cleared or overwritten by author 92396 * (note that p5 clears automatically on draw loop) 92397 * default is true 92398 * 92399 * perPixelLighting - if true, per-pixel lighting will be used in the 92400 * lighting shader otherwise per-vertex lighting is used. 92401 * default is true. 92402 * 92403 * @method setAttributes 92404 * @for p5 92405 * @param {String} key Name of attribute 92406 * @param {Boolean} value New value of named attribute 92407 * @example 92408 * <div> 92409 * <code> 92410 * function setup() { 92411 * createCanvas(100, 100, WEBGL); 92412 * } 92413 * 92414 * function draw() { 92415 * background(255); 92416 * push(); 92417 * rotateZ(frameCount * 0.02); 92418 * rotateX(frameCount * 0.02); 92419 * rotateY(frameCount * 0.02); 92420 * fill(0, 0, 0); 92421 * box(50); 92422 * pop(); 92423 * } 92424 * </code> 92425 * </div> 92426 * <br> 92427 * Now with the antialias attribute set to true. 92428 * <br> 92429 * <div> 92430 * <code> 92431 * function setup() { 92432 * setAttributes('antialias', true); 92433 * createCanvas(100, 100, WEBGL); 92434 * } 92435 * 92436 * function draw() { 92437 * background(255); 92438 * push(); 92439 * rotateZ(frameCount * 0.02); 92440 * rotateX(frameCount * 0.02); 92441 * rotateY(frameCount * 0.02); 92442 * fill(0, 0, 0); 92443 * box(50); 92444 * pop(); 92445 * } 92446 * </code> 92447 * </div> 92448 * 92449 * <div> 92450 * <code> 92451 * // press the mouse button to disable perPixelLighting 92452 * function setup() { 92453 * createCanvas(100, 100, WEBGL); 92454 * noStroke(); 92455 * fill(255); 92456 * } 92457 * 92458 * let lights = [ 92459 * { c: '#f00', t: 1.12, p: 1.91, r: 0.2 }, 92460 * { c: '#0f0', t: 1.21, p: 1.31, r: 0.2 }, 92461 * { c: '#00f', t: 1.37, p: 1.57, r: 0.2 }, 92462 * { c: '#ff0', t: 1.12, p: 1.91, r: 0.7 }, 92463 * { c: '#0ff', t: 1.21, p: 1.31, r: 0.7 }, 92464 * { c: '#f0f', t: 1.37, p: 1.57, r: 0.7 } 92465 * ]; 92466 * 92467 * function draw() { 92468 * let t = millis() / 1000 + 1000; 92469 * background(0); 92470 * directionalLight(color('#222'), 1, 1, 1); 92471 * 92472 * for (let i = 0; i < lights.length; i++) { 92473 * let light = lights[i]; 92474 * pointLight( 92475 * color(light.c), 92476 * p5.Vector.fromAngles(t * light.t, t * light.p, width * light.r) 92477 * ); 92478 * } 92479 * 92480 * specularMaterial(255); 92481 * sphere(width * 0.1); 92482 * 92483 * rotateX(t * 0.77); 92484 * rotateY(t * 0.83); 92485 * rotateZ(t * 0.91); 92486 * torus(width * 0.3, width * 0.07, 24, 10); 92487 * } 92488 * 92489 * function mousePressed() { 92490 * setAttributes('perPixelLighting', false); 92491 * noStroke(); 92492 * fill(255); 92493 * } 92494 * function mouseReleased() { 92495 * setAttributes('perPixelLighting', true); 92496 * noStroke(); 92497 * fill(255); 92498 * } 92499 * </code> 92500 * </div> 92501 * 92502 * @alt a rotating cube with smoother edges 92503 */ 92504 /** 92505 * @method setAttributes 92506 * @for p5 92507 * @param {Object} obj object with key-value pairs 92508 */ 92509 92510 _main.default.prototype.setAttributes = function(key, value) { 92511 if (typeof this._glAttributes === 'undefined') { 92512 console.log( 92513 'You are trying to use setAttributes on a p5.Graphics object ' + 92514 'that does not use a WEBGL renderer.' 92515 ); 92516 92517 return; 92518 } 92519 var unchanged = true; 92520 if (typeof value !== 'undefined') { 92521 //first time modifying the attributes 92522 if (this._glAttributes === null) { 92523 this._glAttributes = {}; 92524 } 92525 if (this._glAttributes[key] !== value) { 92526 //changing value of previously altered attribute 92527 this._glAttributes[key] = value; 92528 unchanged = false;
92529 } 92530 //setting all attributes with some change 92531 } else if (key instanceof Object) { 92532 if (this._glAttributes !== key) { 92533 this._glAttributes = key; 92534 unchanged = false; 92535 } 92536 } 92537 //@todo_FES 92538 if (!this._renderer.isP3D || unchanged) { 92539 return; 92540 } 92541 92542 if (!this._setupDone) { 92543 for (var x in this._renderer.retainedMode.geometry) { 92544 if (this._renderer.retainedMode.geometry.hasOwnProperty(x)) { 92545 console.error( 92546 'Sorry, Could not set the attributes, you need to call setAttributes() ' + 92547 'before calling the other drawing methods in setup()' 92548 ); 92549 92550 return; 92551 } 92552 } 92553 } 92554 92555 this.push(); 92556 this._renderer._resetContext(); 92557 this.pop(); 92558 92559 if (this._renderer._curCamera) { 92560 this._renderer._curCamera._renderer = this._renderer; 92561 } 92562 }; 92563 92564 /** 92565 * @class p5.RendererGL 92566 */ 92567 92568 _main.default.RendererGL.prototype._update = function() { 92569 // reset model view and apply initial camera transform 92570 // (containing only look at info; no projection). 92571 this.uMVMatrix.set( 92572 this._curCamera.cameraMatrix.mat4[0], 92573 this._curCamera.cameraMatrix.mat4[1], 92574 this._curCamera.cameraMatrix.mat4[2], 92575 this._curCamera.cameraMatrix.mat4[3], 92576 this._curCamera.cameraMatrix.mat4[4], 92577 this._curCamera.cameraMatrix.mat4[5], 92578 this._curCamera.cameraMatrix.mat4[6], 92579 this._curCamera.cameraMatrix.mat4[7], 92580 this._curCamera.cameraMatrix.mat4[8], 92581 this._curCamera.cameraMatrix.mat4[9], 92582 this._curCamera.cameraMatrix.mat4[10], 92583 this._curCamera.cameraMatrix.mat4[11], 92584 this._curCamera.cameraMatrix.mat4[12], 92585 this._curCamera.cameraMatrix.mat4[13], 92586 this._curCamera.cameraMatrix.mat4[14], 92587 this._curCamera.cameraMatrix.mat4[15] 92588 ); 92589 92590 // reset light data for new frame. 92591 92592 this.ambientLightColors.length = 0; 92593 this.specularColors = [1, 1, 1]; 92594 92595 this.directionalLightDirections.length = 0; 92596 this.directionalLightDiffuseColors.length = 0; 92597 this.directionalLightSpecularColors.length = 0; 92598 92599 this.pointLightPositions.length = 0; 92600 this.pointLightDiffuseColors.length = 0; 92601 this.pointLightSpecularColors.length = 0; 92602 92603 this.spotLightPositions.length = 0; 92604 this.spotLightDirections.length = 0; 92605 this.spotLightDiffuseColors.length = 0; 92606 this.spotLightSpecularColors.length = 0; 92607 this.spotLightAngle.length = 0; 92608 this.spotLightConc.length = 0; 92609 92610 this._enableLighting = false; 92611 92612 //reset tint value for new frame 92613 this._tint = [255, 255, 255, 255]; 92614 92615 //Clear depth every frame 92616 this.GL.clear(this.GL.DEPTH_BUFFER_BIT); 92617 }; 92618 92619 /** 92620 * [background description] 92621 */ 92622 _main.default.RendererGL.prototype.background = function() { 92623 var _this$_pInst; 92624 var _col = (_this$_pInst = this._pInst).color.apply(_this$_pInst, arguments); 92625 var _r = _col.levels[0] / 255; 92626 var _g = _col.levels[1] / 255; 92627 var _b = _col.levels[2] / 255; 92628 var _a = _col.levels[3] / 255; 92629 this.GL.clearColor(_r, _g, _b, _a); 92630 92631 this.GL.clear(this.GL.COLOR_BUFFER_BIT); 92632 }; 92633
92634 ////////////////////////////////////////////// 92635 // COLOR 92636 ////////////////////////////////////////////// 92637 /** 92638 * Basic fill material for geometry with a given color 92639 * @method fill 92640 * @class p5.RendererGL 92641 * @param {Number|Number[]|String|p5.Color} v1 gray value, 92642 * red or hue value (depending on the current color mode), 92643 * or color Array, or CSS color string 92644 * @param {Number} [v2] green or saturation value 92645 * @param {Number} [v3] blue or brightness value 92646 * @param {Number} [a] opacity 92647 * @chainable 92648 * @example 92649 * <div> 92650 * <code> 92651 * function setup() { 92652 * createCanvas(200, 200, WEBGL); 92653 * } 92654 * 92655 * function draw() { 92656 * background(0); 92657 * noStroke(); 92658 * fill(100, 100, 240); 92659 * rotateX(frameCount * 0.01); 92660 * rotateY(frameCount * 0.01); 92661 * box(75, 75, 75); 92662 * } 92663 * </code> 92664 * </div> 92665 * 92666 * @alt 92667 * black canvas with purple cube spinning 92668 */ 92669 _main.default.RendererGL.prototype.fill = function(v1, v2, v3, a) { 92670 //see material.js for more info on color blending in webgl 92671 var color = _main.default.prototype.color.apply(this._pInst, arguments); 92672 this.curFillColor = color._array; 92673 this.drawMode = constants.FILL; 92674 this._useNormalMaterial = false; 92675 this._tex = null; 92676 }; 92677 92678 /** 92679 * Basic stroke material for geometry with a given color 92680 * @method stroke 92681 * @param {Number|Number[]|String|p5.Color} v1 gray value, 92682 * red or hue value (depending on the current color mode), 92683 * or color Array, or CSS color string 92684 * @param {Number} [v2] green or saturation value 92685 * @param {Number} [v3] blue or brightness value 92686 * @param {Number} [a] opacity 92687 * @example 92688 * <div> 92689 * <code> 92690 * function setup() { 92691 * createCanvas(200, 200, WEBGL); 92692 * } 92693 * 92694 * function draw() { 92695 * background(0); 92696 * stroke(240, 150, 150); 92697 * fill(100, 100, 240); 92698 * rotateX(frameCount * 0.01); 92699 * rotateY(frameCount * 0.01); 92700 * box(75, 75, 75); 92701 * } 92702 * </code> 92703 * </div> 92704 * 92705 * @alt 92706 * black canvas with purple cube with pink outline spinning 92707 */ 92708 _main.default.RendererGL.prototype.stroke = function(r, g, b, a) { 92709 //@todo allow transparency in stroking currently doesn't have 92710 //any impact and causes problems with specularMaterial 92711 arguments[3] = 255; 92712 var color = _main.default.prototype.color.apply(this._pInst, arguments); 92713 this.curStrokeColor = color._array; 92714 }; 92715 92716 _main.default.RendererGL.prototype.strokeCap = function(cap) { 92717 // @TODO : to be implemented 92718 console.error('Sorry, strokeCap() is not yet implemented in WEBGL mode'); 92719 }; 92720 92721 _main.default.RendererGL.prototype.strokeJoin = function(join) { 92722 // @TODO : to be implemented 92723 // https://processing.org/reference/strokeJoin_.html 92724 console.error('Sorry, strokeJoin() is not yet implemented in WEBGL mode'); 92725 }; 92726 92727 _main.default.RendererGL.prototype.filter = function(filterType) { 92728 // filter can be achieved using custom shaders. 92729 // https://github.com/aferriss/p5jsShaderExamples 92730 // https://itp-xstory.github.io/p5js-shaders/#/ 92731 console.error('filter() does not work in WEBGL mode'); 92732 }; 92733 92734 _main.default.RendererGL.prototype.blendMode = function(mode) { 92735 if ( 92736 mode === constants.DARKEST || 92737 mode === constants.LIGHTEST || 92738 mode === constants.ADD || 92739 mode === constants.BLEND || 92740 mode === constants.SUBTRACT || 92741 mode === constants.SCREEN || 92742 mode === constants.EXCLUSION || 92743 mode === constants.REPLACE || 92744 mode === constants.MULTIPLY || 92745 mode === constants.REMOVE 92746 )
92747 this.curBlendMode = mode; 92748 else if ( 92749 mode === constants.BURN || 92750 mode === constants.OVERLAY || 92751 mode === constants.HARD_LIGHT || 92752 mode === constants.SOFT_LIGHT || 92753 mode === constants.DODGE 92754 ) { 92755 console.warn( 92756 'BURN, OVERLAY, HARD_LIGHT, SOFT_LIGHT, and DODGE only work for blendMode in 2D mode.' 92757 ); 92758 } 92759 }; 92760 92761 _main.default.RendererGL.prototype.erase = function(opacityFill, opacityStroke) { 92762 if (!this._isErasing) { 92763 this._applyBlendMode(constants.REMOVE); 92764 this._isErasing = true; 92765 92766 this._cachedFillStyle = this.curFillColor.slice(); 92767 this.curFillColor = [1, 1, 1, opacityFill / 255]; 92768 92769 this._cachedStrokeStyle = this.curStrokeColor.slice(); 92770 this.curStrokeColor = [1, 1, 1, opacityStroke / 255]; 92771 } 92772 }; 92773 92774 _main.default.RendererGL.prototype.noErase = function() { 92775 if (this._isErasing) { 92776 this._isErasing = false; 92777 this.curFillColor = this._cachedFillStyle.slice(); 92778 this.curStrokeColor = this._cachedStrokeStyle.slice(); 92779 this.blendMode(this._cachedBlendMode); 92780 } 92781 }; 92782 92783 /** 92784 * Change weight of stroke 92785 * @method strokeWeight 92786 * @param {Number} stroke weight to be used for drawing 92787 * @example 92788 * <div> 92789 * <code> 92790 * function setup() { 92791 * createCanvas(200, 400, WEBGL); 92792 * setAttributes('antialias', true); 92793 * } 92794 * 92795 * function draw() { 92796 * background(0); 92797 * noStroke(); 92798 * translate(0, -100, 0); 92799 * stroke(240, 150, 150); 92800 * fill(100, 100, 240); 92801 * push(); 92802 * strokeWeight(8); 92803 * rotateX(frameCount * 0.01); 92804 * rotateY(frameCount * 0.01); 92805 * sphere(75); 92806 * pop(); 92807 * push(); 92808 * translate(0, 200, 0); 92809 * strokeWeight(1); 92810 * rotateX(frameCount * 0.01); 92811 * rotateY(frameCount * 0.01); 92812 * sphere(75); 92813 * pop(); 92814 * } 92815 * </code> 92816 * </div> 92817 * 92818 * @alt 92819 * black canvas with two purple rotating spheres with pink 92820 * outlines the sphere on top has much heavier outlines, 92821 */ 92822 _main.default.RendererGL.prototype.strokeWeight = function(w) { 92823 if (this.curStrokeWeight !== w) { 92824 this.pointSize = w; 92825 this.curStrokeWeight = w; 92826 } 92827 }; 92828 92829 // x,y are canvas-relative (pre-scaled by _pixelDensity) 92830 _main.default.RendererGL.prototype._getPixel = function(x, y) { 92831 var imageData, index; 92832 imageData = new Uint8Array(4); 92833 // prettier-ignore 92834 this.drawingContext.readPixels( 92835 x, y, 1, 1, 92836 this.drawingContext.RGBA, this.drawingContext.UNSIGNED_BYTE, 92837 imageData); 92838 92839 index = 0; 92840 return [ 92841 imageData[index + 0], 92842 imageData[index + 1], 92843 imageData[index + 2], 92844 imageData[index + 3] 92845 ]; 92846 }; 92847 92848 /** 92849 * Loads the pixels data for this canvas into the pixels[] attribute. 92850 * Note that updatePixels() and set() do not work. 92851 * Any pixel manipulation must be done directly to the pixels[] array. 92852 * 92853 * @private 92854 * @method loadPixels 92855 */ 92856 92857 _main.default.RendererGL.prototype.loadPixels = function() { 92858 var pixelsState = this._pixelsState; 92859 92860 //@todo_FES 92861 if (this._pInst._glAttributes.preserveDrawingBuffer !== true) { 92862 console.log( 92863 'loadPixels only works in WebGL when preserveDrawingBuffer ' + 'is true.' 92864 ); 92865 92866 return; 92867 } 92868 92869 //if there isn't a renderer-level temporary pixels buffer 92870 //make a new one 92871 var pixels = pixelsState.pixels; 92872 var len = this.GL.drawingBufferWidth * this.GL.drawingBufferHeight * 4; 92873 if (!(pixels instanceof Uint8Array) || pixels.length !== len) { 92874 pixels = new Uint8Array(len); 92875 this._pixelsState._setProperty('pixels', pixels); 92876 } 92877 92878 var pd = this._pInst._pixelDensity; 92879 // prettier-ignore 92880 this.GL.readPixels( 92881 0, 0, this.width * pd, this.height * pd, 92882 this.GL.RGBA, this.GL.UNSIGNED_BYTE, 92883 pixels); 92884 }; 92885
92886 ////////////////////////////////////////////// 92887 // HASH | for geometry 92888 ////////////////////////////////////////////// 92889 92890 _main.default.RendererGL.prototype.geometryInHash = function(gId) { 92891 return this.retainedMode.geometry[gId] !== undefined; 92892 }; 92893 92894 /** 92895 * [resize description] 92896 * @private 92897 * @param {Number} w [description] 92898 * @param {Number} h [description] 92899 */ 92900 _main.default.RendererGL.prototype.resize = function(w, h) { 92901 _main.default.Renderer.prototype.resize.call(this, w, h); 92902 this.GL.viewport(0, 0, this.GL.drawingBufferWidth, this.GL.drawingBufferHeight); 92903 92904 this._viewport = this.GL.getParameter(this.GL.VIEWPORT); 92905 92906 this._curCamera._resize(); 92907 92908 //resize pixels buffer 92909 var pixelsState = this._pixelsState; 92910 if (typeof pixelsState.pixels !== 'undefined') { 92911 pixelsState._setProperty( 92912 'pixels', 92913 new Uint8Array(this.GL.drawingBufferWidth * this.GL.drawingBufferHeight * 4) 92914 ); 92915 } 92916 }; 92917 92918 /** 92919 * clears color and depth buffers 92920 * with r,g,b,a 92921 * @private 92922 * @param {Number} r normalized red val. 92923 * @param {Number} g normalized green val. 92924 * @param {Number} b normalized blue val. 92925 * @param {Number} a normalized alpha val. 92926 */ 92927 _main.default.RendererGL.prototype.clear = function() { 92928 var _r = (arguments.length <= 0 ? undefined : arguments[0]) || 0; 92929 var _g = (arguments.length <= 1 ? undefined : arguments[1]) || 0; 92930 var _b = (arguments.length <= 2 ? undefined : arguments[2]) || 0; 92931 var _a = (arguments.length <= 3 ? undefined : arguments[3]) || 0; 92932 this.GL.clearColor(_r, _g, _b, _a); 92933 this.GL.clear(this.GL.COLOR_BUFFER_BIT | this.GL.DEPTH_BUFFER_BIT); 92934 }; 92935 92936 _main.default.RendererGL.prototype.applyMatrix = function(a, b, c, d, e, f) { 92937 if (arguments.length === 16) { 92938 _main.default.Matrix.prototype.apply.apply(this.uMVMatrix, arguments); 92939 } else { 92940 // prettier-ignore 92941 this.uMVMatrix.apply([ 92942 a, b, 0, 0, 92943 c, d, 0, 0, 92944 0, 0, 1, 0, 92945 e, f, 0, 1]); 92946 } 92947 }; 92948 92949 /** 92950 * [translate description] 92951 * @private 92952 * @param {Number} x [description] 92953 * @param {Number} y [description] 92954 * @param {Number} z [description] 92955 * @chainable 92956 * @todo implement handle for components or vector as args 92957 */ 92958 _main.default.RendererGL.prototype.translate = function(x, y, z) { 92959 if (x instanceof _main.default.Vector) { 92960 z = x.z; 92961 y = x.y; 92962 x = x.x; 92963 } 92964 this.uMVMatrix.translate([x, y, z]); 92965 return this; 92966 }; 92967 92968 /** 92969 * Scales the Model View Matrix by a vector 92970 * @private 92971 * @param {Number | p5.Vector | Array} x [description] 92972 * @param {Number} [y] y-axis scalar 92973 * @param {Number} [z] z-axis scalar 92974 * @chainable 92975 */ 92976 _main.default.RendererGL.prototype.scale = function(x, y, z) { 92977 this.uMVMatrix.scale(x, y, z); 92978 return this; 92979 }; 92980 92981 _main.default.RendererGL.prototype.rotate = function(rad, axis) { 92982 if (typeof axis === 'undefined') { 92983 return this.rotateZ(rad); 92984 } 92985 _main.default.Matrix.prototype.rotate.apply(this.uMVMatrix, arguments); 92986 return this; 92987 }; 92988 92989 _main.default.RendererGL.prototype.rotateX = function(rad) { 92990 this.rotate(rad, 1, 0, 0); 92991 return this; 92992 }; 92993 92994 _main.default.RendererGL.prototype.rotateY = function(rad) { 92995 this.rotate(rad, 0, 1, 0); 92996 return this; 92997 }; 92998 92999 _main.default.RendererGL.prototype.rotateZ = function(rad) { 93000 this.rotate(rad, 0, 0, 1); 93001 return this; 93002 }; 93003 93004 _main.default.RendererGL.prototype.push = function() { 93005 // get the base renderer style 93006 var style = _main.default.Renderer.prototype.push.apply(this); 93007 93008 // add webgl-specific style properties 93009 var properties = style.properties; 93010 93011 properties.uMVMatrix = this.uMVMatrix.copy(); 93012 properties.uPMatrix = this.uPMatrix.copy(); 93013 properties._curCamera = this._curCamera; 93014 93015 // make a copy of the current camera for the push state 93016 // this preserves any references stored using 'createCamera' 93017 this._curCamera = this._curCamera.copy(); 93018 93019 properties.ambientLightColors = this.ambientLightColors.slice(); 93020 properties.specularColors = this.specularColors.slice(); 93021 93022 properties.directionalLightDirections = this.directionalLightDirections.slice(); 93023 properties.directionalLightDiffuseColors = this.directionalLightDiffuseColors.slice(); 93024 properties.directionalLightSpecularColors = this.directionalLightSpecularColors.slice(); 93025 93026 properties.pointLightPositions = this.pointLightPositions.slice(); 93027 properties.pointLightDiffuseColors = this.pointLightDiffuseColors.slice(); 93028 properties.pointLightSpecularColors = this.pointLightSpecularColors.slice(); 93029 93030 properties.spotLightPositions = this.spotLightPositions.slice(); 93031 properties.spotLightDirections = this.spotLightDirections.slice(); 93032 properties.spotLightDiffuseColors = this.spotLightDiffuseColors.slice(); 93033 properties.spotLightSpecularColors = this.spotLightSpecularColors.slice(); 93034 properties.spotLightAngle = this.spotLightAngle.slice(); 93035 properties.spotLightConc = this.spotLightConc.slice(); 93036 93037 properties.userFillShader = this.userFillShader; 93038 properties.userStrokeShader = this.userStrokeShader; 93039 properties.userPointShader = this.userPointShader; 93040 93041 properties.pointSize = this.pointSize; 93042 properties.curStrokeWeight = this.curStrokeWeight; 93043 properties.curStrokeColor = this.curStrokeColor; 93044 properties.curFillColor = this.curFillColor; 93045 93046 properties._useSpecularMaterial = this._useSpecularMaterial; 93047 properties._useEmissiveMaterial = this._useEmissiveMaterial; 93048 properties._useShininess = this._useShininess; 93049 93050 properties.constantAttenuation = this.constantAttenuation; 93051 properties.linearAttenuation = this.linearAttenuation; 93052 properties.quadraticAttenuation = this.quadraticAttenuation; 93053 93054 properties._enableLighting = this._enableLighting; 93055 properties._useNormalMaterial = this._useNormalMaterial; 93056 properties._tex = this._tex; 93057 properties.drawMode = this.drawMode; 93058 93059 return style; 93060 }; 93061 93062 _main.default.RendererGL.prototype.resetMatrix = function() { 93063 this.uMVMatrix = _main.default.Matrix.identity(this._pInst); 93064 return this; 93065 }; 93066
93067 ////////////////////////////////////////////// 93068 // SHADER 93069 ////////////////////////////////////////////// 93070 93071 /* 93072 * shaders are created and cached on a per-renderer basis, 93073 * on the grounds that each renderer will have its own gl context 93074 * and the shader must be valid in that context. 93075 */ 93076 93077 _main.default.RendererGL.prototype._getImmediateStrokeShader = function() { 93078 // select the stroke shader to use 93079 var stroke = this.userStrokeShader; 93080 if (!stroke || !stroke.isStrokeShader()) { 93081 return this._getLineShader(); 93082 } 93083 return stroke; 93084 }; 93085 93086 _main.default.RendererGL.prototype._getRetainedStrokeShader = 93087 _main.default.RendererGL.prototype._getImmediateStrokeShader; 93088 93089 /* 93090 * selects which fill shader should be used based on renderer state, 93091 * for use with begin/endShape and immediate vertex mode. 93092 */ 93093 _main.default.RendererGL.prototype._getImmediateFillShader = function() { 93094 var fill = this.userFillShader; 93095 if (this._useNormalMaterial) { 93096 if (!fill || !fill.isNormalShader()) { 93097 return this._getNormalShader(); 93098 } 93099 } 93100 if (this._enableLighting) { 93101 if (!fill || !fill.isLightShader()) { 93102 return this._getLightShader(); 93103 } 93104 } else if (this._tex) { 93105 if (!fill || !fill.isTextureShader()) { 93106 return this._getLightShader(); 93107 } 93108 } else if (!fill /*|| !fill.isColorShader()*/) { 93109 return this._getImmediateModeShader(); 93110 } 93111 return fill; 93112 }; 93113 93114 /* 93115 * selects which fill shader should be used based on renderer state 93116 * for retained mode. 93117 */ 93118 _main.default.RendererGL.prototype._getRetainedFillShader = function() { 93119 if (this._useNormalMaterial) { 93120 return this._getNormalShader(); 93121 } 93122 93123 var fill = this.userFillShader; 93124 if (this._enableLighting) { 93125 if (!fill || !fill.isLightShader()) { 93126 return this._getLightShader(); 93127 } 93128 } else if (this._tex) { 93129 if (!fill || !fill.isTextureShader()) { 93130 return this._getLightShader(); 93131 } 93132 } else if (!fill /* || !fill.isColorShader()*/) { 93133 return this._getColorShader(); 93134 } 93135 return fill; 93136 }; 93137 93138 _main.default.RendererGL.prototype._getImmediatePointShader = function() { 93139 // select the point shader to use 93140 var point = this.userPointShader; 93141 if (!point || !point.isPointShader()) { 93142 return this._getPointShader(); 93143 } 93144 return point; 93145 }; 93146 93147 _main.default.RendererGL.prototype._getRetainedLineShader = 93148 _main.default.RendererGL.prototype._getImmediateLineShader; 93149 93150 _main.default.RendererGL.prototype._getLightShader = function() { 93151 if (!this._defaultLightShader) { 93152 if (this._pInst._glAttributes.perPixelLighting) { 93153 this._defaultLightShader = new _main.default.Shader( 93154 this, 93155 defaultShaders.phongVert, 93156 defaultShaders.phongFrag 93157 ); 93158 } else { 93159 this._defaultLightShader = new _main.default.Shader( 93160 this, 93161 defaultShaders.lightVert, 93162 defaultShaders.lightTextureFrag 93163 ); 93164 } 93165 } 93166 93167 return this._defaultLightShader; 93168 }; 93169 93170 _main.default.RendererGL.prototype._getImmediateModeShader = function() { 93171 if (!this._defaultImmediateModeShader) { 93172 this._defaultImmediateModeShader = new _main.default.Shader( 93173 this, 93174 defaultShaders.immediateVert, 93175 defaultShaders.vertexColorFrag 93176 ); 93177 } 93178 93179 return this._defaultImmediateModeShader; 93180 }; 93181 93182 _main.default.RendererGL.prototype._getNormalShader = function() { 93183 if (!this._defaultNormalShader) { 93184 this._defaultNormalShader = new _main.default.Shader( 93185 this, 93186 defaultShaders.normalVert, 93187 defaultShaders.normalFrag 93188 ); 93189 } 93190 93191 return this._defaultNormalShader; 93192 }; 93193 93194 _main.default.RendererGL.prototype._getColorShader = function() { 93195 if (!this._defaultColorShader) { 93196 this._defaultColorShader = new _main.default.Shader( 93197 this, 93198 defaultShaders.normalVert, 93199 defaultShaders.basicFrag 93200 ); 93201 } 93202 93203 return this._defaultColorShader; 93204 }; 93205 93206 _main.default.RendererGL.prototype._getPointShader = function() { 93207 if (!this._defaultPointShader) { 93208 this._defaultPointShader = new _main.default.Shader( 93209 this, 93210 defaultShaders.pointVert, 93211 defaultShaders.pointFrag 93212 ); 93213 } 93214 return this._defaultPointShader; 93215 }; 93216 93217 _main.default.RendererGL.prototype._getLineShader = function() { 93218 if (!this._defaultLineShader) { 93219 this._defaultLineShader = new _main.default.Shader( 93220 this, 93221 defaultShaders.lineVert, 93222 defaultShaders.lineFrag 93223 ); 93224 } 93225 93226 return this._defaultLineShader; 93227 }; 93228 93229 _main.default.RendererGL.prototype._getFontShader = function() { 93230 if (!this._defaultFontShader) { 93231 this.GL.getExtension('OES_standard_derivatives'); 93232 this._defaultFontShader = new _main.default.Shader( 93233 this, 93234 defaultShaders.fontVert, 93235 defaultShaders.fontFrag 93236 ); 93237 } 93238 return this._defaultFontShader; 93239 }; 93240 93241 _main.default.RendererGL.prototype._getEmptyTexture = function() { 93242 if (!this._emptyTexture) { 93243 // a plain white texture RGBA, full alpha, single pixel. 93244 var im = new _main.default.Image(1, 1); 93245 im.set(0, 0, 255); 93246 this._emptyTexture = new _main.default.Texture(this, im); 93247 } 93248 return this._emptyTexture; 93249 }; 93250 93251 _main.default.RendererGL.prototype.getTexture = function(img) { 93252 var textures = this.textures; 93253 var _iteratorNormalCompletion = true; 93254 var _didIteratorError = false;
93255 var _iteratorError = undefined; 93256 try { 93257 for ( 93258 var _iterator = textures[Symbol.iterator](), _step; 93259 !(_iteratorNormalCompletion = (_step = _iterator.next()).done); 93260 _iteratorNormalCompletion = true 93261 ) { 93262 var texture = _step.value; 93263 if (texture.src === img) return texture; 93264 } 93265 } catch (err) { 93266 _didIteratorError = true; 93267 _iteratorError = err; 93268 } finally { 93269 try { 93270 if (!_iteratorNormalCompletion && _iterator.return != null) { 93271 _iterator.return(); 93272 } 93273 } finally { 93274 if (_didIteratorError) { 93275 throw _iteratorError; 93276 } 93277 } 93278 } 93279 93280 var tex = new _main.default.Texture(this, img); 93281 textures.push(tex); 93282 return tex; 93283 }; 93284 93285 _main.default.RendererGL.prototype._setStrokeUniforms = function(strokeShader) { 93286 strokeShader.bindShader(); 93287 93288 // set the uniform values 93289 strokeShader.setUniform('uMaterialColor', this.curStrokeColor); 93290 strokeShader.setUniform('uStrokeWeight', this.curStrokeWeight); 93291 }; 93292 93293 _main.default.RendererGL.prototype._setFillUniforms = function(fillShader) { 93294 fillShader.bindShader(); 93295 93296 // TODO: optimize 93297 fillShader.setUniform('uMaterialColor', this.curFillColor); 93298 fillShader.setUniform('isTexture', !!this._tex); 93299 if (this._tex) { 93300 fillShader.setUniform('uSampler', this._tex); 93301 } 93302 fillShader.setUniform('uTint', this._tint); 93303 93304 fillShader.setUniform('uSpecular', this._useSpecularMaterial); 93305 fillShader.setUniform('uEmissive', this._useEmissiveMaterial); 93306 fillShader.setUniform('uShininess', this._useShininess); 93307 93308 fillShader.setUniform('uUseLighting', this._enableLighting); 93309 93310 var pointLightCount = this.pointLightDiffuseColors.length / 3; 93311 fillShader.setUniform('uPointLightCount', pointLightCount); 93312 fillShader.setUniform('uPointLightLocation', this.pointLightPositions); 93313 fillShader.setUniform('uPointLightDiffuseColors', this.pointLightDiffuseColors); 93314 93315 fillShader.setUniform( 93316 'uPointLightSpecularColors', 93317 this.pointLightSpecularColors 93318 ); 93319 93320 var directionalLightCount = this.directionalLightDiffuseColors.length / 3; 93321 fillShader.setUniform('uDirectionalLightCount', directionalLightCount); 93322 fillShader.setUniform('uLightingDirection', this.directionalLightDirections); 93323 fillShader.setUniform( 93324 'uDirectionalDiffuseColors', 93325 this.directionalLightDiffuseColors 93326 ); 93327 93328 fillShader.setUniform( 93329 'uDirectionalSpecularColors', 93330 this.directionalLightSpecularColors 93331 ); 93332 93333 // TODO: sum these here... 93334 var ambientLightCount = this.ambientLightColors.length / 3; 93335 fillShader.setUniform('uAmbientLightCount', ambientLightCount); 93336 fillShader.setUniform('uAmbientColor', this.ambientLightColors); 93337 93338 var spotLightCount = this.spotLightDiffuseColors.length / 3; 93339 fillShader.setUniform('uSpotLightCount', spotLightCount); 93340 fillShader.setUniform('uSpotLightAngle', this.spotLightAngle); 93341 fillShader.setUniform('uSpotLightConc', this.spotLightConc); 93342 fillShader.setUniform('uSpotLightDiffuseColors', this.spotLightDiffuseColors); 93343 fillShader.setUniform('uSpotLightSpecularColors', this.spotLightSpecularColors); 93344 93345 fillShader.setUniform('uSpotLightLocation', this.spotLightPositions); 93346 fillShader.setUniform('uSpotLightDirection', this.spotLightDirections); 93347 93348 fillShader.setUniform('uConstantAttenuation', this.constantAttenuation); 93349 fillShader.setUniform('uLinearAttenuation', this.linearAttenuation); 93350 fillShader.setUniform('uQuadraticAttenuation', this.quadraticAttenuation); 93351 93352 fillShader.bindTextures(); 93353 }; 93354 93355 _main.default.RendererGL.prototype._setPointUniforms = function(pointShader) { 93356 pointShader.bindShader(); 93357 93358 // set the uniform values 93359 pointShader.setUniform('uMaterialColor', this.curStrokeColor); 93360 // @todo is there an instance where this isn't stroke weight? 93361 // should be they be same var? 93362 pointShader.setUniform( 93363 'uPointSize', 93364 this.pointSize * this._pInst._pixelDensity 93365 ); 93366 }; 93367 93368 /* Binds a buffer to the drawing context 93369 * when passed more than two arguments it also updates or initializes 93370 * the data associated with the buffer 93371 */ 93372 _main.default.RendererGL.prototype._bindBuffer = function( 93373 buffer, 93374 target, 93375 values, 93376 type, 93377 usage 93378 ) { 93379 if (!target) target = this.GL.ARRAY_BUFFER; 93380 this.GL.bindBuffer(target, buffer); 93381 if (values !== undefined) { 93382 var data = new (type || Float32Array)(values); 93383 this.GL.bufferData(target, data, usage || this.GL.STATIC_DRAW); 93384 } 93385 }; 93386
93387 /////////////////////////////// 93388 //// UTILITY FUNCTIONS 93389 ////////////////////////////// 93390 _main.default.RendererGL.prototype._arraysEqual = function(a, b) { 93391 var aLength = a.length; 93392 if (aLength !== b.length) return false; 93393 for (var i = 0; i < aLength; i++) { 93394 if (a[i] !== b[i]) return false; 93395 } 93396 return true; 93397 }; 93398 93399 _main.default.RendererGL.prototype._isTypedArray = function(arr) { 93400 var res = false; 93401 res = arr instanceof Float32Array; 93402 res = arr instanceof Float64Array; 93403 res = arr instanceof Int16Array; 93404 res = arr instanceof Uint16Array; 93405 res = arr instanceof Uint32Array; 93406 return res; 93407 }; 93408 /** 93409 * turn a two dimensional array into one dimensional array 93410 * @private 93411 * @param {Array} arr 2-dimensional array 93412 * @return {Array} 1-dimensional array 93413 * [[1, 2, 3],[4, 5, 6]] -> [1, 2, 3, 4, 5, 6] 93414 */ 93415 _main.default.RendererGL.prototype._flatten = function(arr) { 93416 //when empty, return empty 93417 if (arr.length === 0) { 93418 return []; 93419 } else if (arr.length > 20000) { 93420 //big models , load slower to avoid stack overflow 93421 //faster non-recursive flatten via axelduch 93422 //stackoverflow.com/questions/27266550/how-to-flatten-nested-array-in-javascript 93423 var _toString = Object.prototype.toString; 93424 var arrayTypeStr = '[object Array]'; 93425 var result = []; 93426 var nodes = arr.slice(); 93427 var node; 93428 node = nodes.pop(); 93429 do { 93430 if (_toString.call(node) === arrayTypeStr) { 93431 nodes.push.apply(nodes, _toConsumableArray(node)); 93432 } else { 93433 result.push(node); 93434 } 93435 } while (nodes.length && (node = nodes.pop()) !== undefined); 93436 result.reverse(); // we reverse result to restore the original order 93437 return result; 93438 } else { 93439 var _ref; 93440 //otherwise if model within limits for browser 93441 //use faster recursive loading 93442 return (_ref = []).concat.apply(_ref, _toConsumableArray(arr)); 93443 } 93444 }; 93445 93446 /** 93447 * turn a p5.Vector Array into a one dimensional number array 93448 * @private 93449 * @param {p5.Vector[]} arr an array of p5.Vector 93450 * @return {Number[]} a one dimensional array of numbers 93451 * [p5.Vector(1, 2, 3), p5.Vector(4, 5, 6)] -> 93452 * [1, 2, 3, 4, 5, 6] 93453 */ 93454 _main.default.RendererGL.prototype._vToNArray = function(arr) { 93455 var ret = []; 93456 var _iteratorNormalCompletion2 = true; 93457 var _didIteratorError2 = false;
93458 var _iteratorError2 = undefined; 93459 try { 93460 for ( 93461 var _iterator2 = arr[Symbol.iterator](), _step2; 93462 !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); 93463 _iteratorNormalCompletion2 = true 93464 ) { 93465 var item = _step2.value; 93466 ret.push(item.x, item.y, item.z); 93467 } 93468 } catch (err) { 93469 _didIteratorError2 = true; 93470 _iteratorError2 = err; 93471 } finally { 93472 try { 93473 if (!_iteratorNormalCompletion2 && _iterator2.return != null) { 93474 _iterator2.return(); 93475 } 93476 } finally { 93477 if (_didIteratorError2) { 93478 throw _iteratorError2; 93479 } 93480 } 93481 } 93482 93483 return ret; 93484 }; 93485 93486 /** 93487 * ensures that p5 is using a 3d renderer. throws an error if not. 93488 */ 93489 _main.default.prototype._assert3d = function(name) { 93490 if (!this._renderer.isP3D) 93491 throw new Error( 93492 ''.concat( 93493 name, 93494 "() 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." 93495 ) 93496 ); 93497 }; 93498 93499 // function to initialize GLU Tesselator 93500 93501 _main.default.RendererGL.prototype._initTessy = function initTesselator() { 93502 // function called for each vertex of tesselator output 93503 function vertexCallback(data, polyVertArray) { 93504 polyVertArray[polyVertArray.length] = data[0]; 93505 polyVertArray[polyVertArray.length] = data[1]; 93506 polyVertArray[polyVertArray.length] = data[2]; 93507 } 93508 93509 function begincallback(type) { 93510 if (type !== _libtess.default.primitiveType.GL_TRIANGLES) { 93511 console.log('expected TRIANGLES but got type: '.concat(type)); 93512 } 93513 } 93514 93515 function errorcallback(errno) { 93516 console.log('error callback'); 93517 console.log('error number: '.concat(errno)); 93518 } 93519 // callback for when segments intersect and must be split 93520 function combinecallback(coords, data, weight) { 93521 return [coords[0], coords[1], coords[2]]; 93522 } 93523 93524 function edgeCallback(flag) { 93525 // don't really care about the flag, but need no-strip/no-fan behavior 93526 } 93527 93528 var tessy = new _libtess.default.GluTesselator(); 93529 tessy.gluTessCallback( 93530 _libtess.default.gluEnum.GLU_TESS_VERTEX_DATA, 93531 vertexCallback 93532 ); 93533 tessy.gluTessCallback(_libtess.default.gluEnum.GLU_TESS_BEGIN, begincallback); 93534 tessy.gluTessCallback(_libtess.default.gluEnum.GLU_TESS_ERROR, errorcallback); 93535 tessy.gluTessCallback( 93536 _libtess.default.gluEnum.GLU_TESS_COMBINE, 93537 combinecallback 93538 ); 93539 tessy.gluTessCallback( 93540 _libtess.default.gluEnum.GLU_TESS_EDGE_FLAG, 93541 edgeCallback 93542 ); 93543 93544 return tessy; 93545 }; 93546 93547 _main.default.RendererGL.prototype._triangulate = function(contours) { 93548 // libtess will take 3d verts and flatten to a plane for tesselation 93549 // since only doing 2d tesselation here, provide z=1 normal to skip 93550 // iterating over verts only to get the same answer. 93551 // comment out to test normal-generation code 93552 this._tessy.gluTessNormal(0, 0, 1); 93553 93554 var triangleVerts = []; 93555 this._tessy.gluTessBeginPolygon(triangleVerts); 93556 93557 for (var i = 0; i < contours.length; i++) { 93558 this._tessy.gluTessBeginContour(); 93559 var contour = contours[i]; 93560 for (var j = 0; j < contour.length; j += 3) { 93561 var coords = [contour[j], contour[j + 1], contour[j + 2]]; 93562 this._tessy.gluTessVertex(coords, coords); 93563 } 93564 this._tessy.gluTessEndContour(); 93565 } 93566 93567 // finish polygon 93568 this._tessy.gluTessEndPolygon(); 93569 93570 return triangleVerts; 93571 }; 93572 93573 // function to calculate BezierVertex Coefficients 93574 _main.default.RendererGL.prototype._bezierCoefficients = function(t) { 93575 var t2 = t * t; 93576 var t3 = t2 * t; 93577 var mt = 1 - t; 93578 var mt2 = mt * mt; 93579 var mt3 = mt2 * mt; 93580 return [mt3, 3 * mt2 * t, 3 * mt * t2, t3]; 93581 }; 93582 93583 // function to calculate QuadraticVertex Coefficients 93584 _main.default.RendererGL.prototype._quadraticCoefficients = function(t) { 93585 var t2 = t * t; 93586 var mt = 1 - t; 93587 var mt2 = mt * mt; 93588 return [mt2, 2 * mt * t, t2]; 93589 }; 93590 93591 // function to convert Bezier coordinates to Catmull Rom Splines 93592 _main.default.RendererGL.prototype._bezierToCatmull = function(w) { 93593 var p1 = w[1]; 93594 var p2 = w[1] + (w[2] - w[0]) / this._curveTightness; 93595 var p3 = w[2] - (w[3] - w[1]) / this._curveTightness; 93596 var p4 = w[2]; 93597 var p = [p1, p2, p3, p4]; 93598 return p; 93599 }; 93600 var _default = _main.default.RendererGL; 93601 exports.default = _default; 93602 }, 93603 { 93604 '../core/constants': 48, 93605 '../core/main': 59, 93606 '../core/p5.Renderer': 62, 93607 './p5.Camera': 107, 93608 './p5.Matrix': 109, 93609 './p5.Shader': 114, 93610 libtess: 32, 93611 path: 35 93612 } 93613 ], 93614 114: [
93615 function(_dereq_, module, exports) { 93616 'use strict'; 93617 Object.defineProperty(exports, '__esModule', { value: true }); 93618 exports.default = void 0; 93619 93620 var _main = _interopRequireDefault(_dereq_('../core/main')); 93621 function _interopRequireDefault(obj) { 93622 return obj && obj.__esModule ? obj : { default: obj }; 93623 } 93624 /** 93625 * This module defines the p5.Shader class 93626 * @module Lights, Camera 93627 * @submodule Material 93628 * @for p5 93629 * @requires core 93630 */ /** 93631 * Shader class for WEBGL Mode 93632 * @class p5.Shader 93633 * @constructor 93634 * @param {p5.RendererGL} renderer an instance of p5.RendererGL that 93635 * will provide the GL context for this new p5.Shader 93636 * @param {String} vertSrc source code for the vertex shader (as a string) 93637 * @param {String} fragSrc source code for the fragment shader (as a string) 93638 */ _main.default.Shader = function(renderer, vertSrc, fragSrc) { 93639 // TODO: adapt this to not take ids, but rather, 93640 // to take the source for a vertex and fragment shader 93641 // to enable custom shaders at some later date 93642 this._renderer = renderer; 93643 this._vertSrc = vertSrc; 93644 this._fragSrc = fragSrc; 93645 this._vertShader = -1; 93646 this._fragShader = -1; 93647 this._glProgram = 0; 93648 this._loadedAttributes = false; 93649 this.attributes = {}; 93650 this._loadedUniforms = false; 93651 this.uniforms = {}; 93652 this._bound = false; 93653 this.samplers = []; 93654 }; 93655 93656 /** 93657 * Creates, compiles, and links the shader based on its 93658 * sources for the vertex and fragment shaders (provided 93659 * to the constructor). Populates known attributes and 93660 * uniforms from the shader. 93661 * @method init 93662 * @chainable 93663 * @private 93664 */ 93665 _main.default.Shader.prototype.init = function() { 93666 if (this._glProgram === 0 /* or context is stale? */) { 93667 var gl = this._renderer.GL; 93668 93669 // @todo: once custom shading is allowed, 93670 // friendly error messages should be used here to share 93671 // compiler and linker errors. 93672 93673 //set up the shader by 93674 // 1. creating and getting a gl id for the shader program, 93675 // 2. compliling its vertex & fragment sources, 93676 // 3. linking the vertex and fragment shaders 93677 this._vertShader = gl.createShader(gl.VERTEX_SHADER); 93678 //load in our default vertex shader 93679 gl.shaderSource(this._vertShader, this._vertSrc); 93680 gl.compileShader(this._vertShader); 93681 // if our vertex shader failed compilation? 93682 if (!gl.getShaderParameter(this._vertShader, gl.COMPILE_STATUS)) { 93683 console.error( 93684 'Yikes! An error occurred compiling the vertex shader:'.concat( 93685 gl.getShaderInfoLog(this._vertShader) 93686 ) 93687 ); 93688 93689 return null; 93690 } 93691 93692 this._fragShader = gl.createShader(gl.FRAGMENT_SHADER); 93693 //load in our material frag shader 93694 gl.shaderSource(this._fragShader, this._fragSrc); 93695 gl.compileShader(this._fragShader); 93696 // if our frag shader failed compilation? 93697 if (!gl.getShaderParameter(this._fragShader, gl.COMPILE_STATUS)) { 93698 console.error( 93699 'Darn! An error occurred compiling the fragment shader:'.concat( 93700 gl.getShaderInfoLog(this._fragShader) 93701 ) 93702 ); 93703 93704 return null; 93705 } 93706 93707 this._glProgram = gl.createProgram(); 93708 gl.attachShader(this._glProgram, this._vertShader); 93709 gl.attachShader(this._glProgram, this._fragShader); 93710 gl.linkProgram(this._glProgram); 93711 if (!gl.getProgramParameter(this._glProgram, gl.LINK_STATUS)) { 93712 console.error( 93713 'Snap! Error linking shader program: '.concat( 93714 gl.getProgramInfoLog(this._glProgram) 93715 ) 93716 ); 93717 } 93718 93719 this._loadAttributes(); 93720 this._loadUniforms(); 93721 } 93722 return this; 93723 }; 93724 93725 /** 93726 * Queries the active attributes for this shader and loads 93727 * their names and locations into the attributes array. 93728 * @method _loadAttributes 93729 * @private 93730 */ 93731 _main.default.Shader.prototype._loadAttributes = function() { 93732 if (this._loadedAttributes) { 93733 return; 93734 } 93735 93736 this.attributes = {}; 93737 93738 var gl = this._renderer.GL; 93739 93740 var numAttributes = gl.getProgramParameter( 93741 this._glProgram, 93742 gl.ACTIVE_ATTRIBUTES 93743 ); 93744 93745 for (var i = 0; i < numAttributes; ++i) { 93746 var attributeInfo = gl.getActiveAttrib(this._glProgram, i); 93747 var name = attributeInfo.name; 93748 var location = gl.getAttribLocation(this._glProgram, name); 93749 var attribute = {}; 93750 attribute.name = name; 93751 attribute.location = location; 93752 attribute.index = i; 93753 attribute.type = attributeInfo.type; 93754 attribute.size = attributeInfo.size; 93755 this.attributes[name] = attribute; 93756 } 93757 93758 this._loadedAttributes = true; 93759 }; 93760 93761 /** 93762 * Queries the active uniforms for this shader and loads 93763 * their names and locations into the uniforms array. 93764 * @method _loadUniforms 93765 * @private 93766 */ 93767 _main.default.Shader.prototype._loadUniforms = function() { 93768 if (this._loadedUniforms) { 93769 return; 93770 } 93771 93772 var gl = this._renderer.GL; 93773 93774 // Inspect shader and cache uniform info 93775 var numUniforms = gl.getProgramParameter(this._glProgram, gl.ACTIVE_UNIFORMS); 93776 93777 var samplerIndex = 0; 93778 for (var i = 0; i < numUniforms; ++i) { 93779 var uniformInfo = gl.getActiveUniform(this._glProgram, i); 93780 var uniform = {}; 93781 uniform.location = gl.getUniformLocation(this._glProgram, uniformInfo.name); 93782 uniform.size = uniformInfo.size; 93783 var uniformName = uniformInfo.name; 93784 //uniforms thats are arrays have their name returned as 93785 //someUniform[0] which is a bit silly so we trim it 93786 //off here. The size property tells us that its an array 93787 //so we dont lose any information by doing this 93788 if (uniformInfo.size > 1) { 93789 uniformName = uniformName.substring(0, uniformName.indexOf('[0]')); 93790 } 93791 uniform.name = uniformName; 93792 uniform.type = uniformInfo.type; 93793 uniform._cachedData = undefined; 93794 if (uniform.type === gl.SAMPLER_2D) { 93795 uniform.samplerIndex = samplerIndex; 93796 samplerIndex++; 93797 this.samplers.push(uniform); 93798 } 93799 uniform.isArray = 93800 uniform.type === gl.FLOAT_MAT3 || 93801 uniform.type === gl.FLOAT_MAT4 || 93802 uniform.type === gl.FLOAT_VEC2 || 93803 uniform.type === gl.FLOAT_VEC3 || 93804 uniform.type === gl.FLOAT_VEC4 || 93805 uniform.type === gl.INT_VEC2 || 93806 uniform.type === gl.INT_VEC3 || 93807 uniform.type === gl.INT_VEC4; 93808 93809 this.uniforms[uniformName] = uniform; 93810 } 93811 this._loadedUniforms = true; 93812 }; 93813 93814 _main.default.Shader.prototype.compile = function() { 93815 // TODO 93816 }; 93817 93818 /** 93819 * initializes (if needed) and binds the shader program. 93820 * @method bindShader 93821 * @private 93822 */ 93823 _main.default.Shader.prototype.bindShader = function() { 93824 this.init(); 93825 if (!this._bound) { 93826 this.useProgram(); 93827 this._bound = true; 93828 93829 this._setMatrixUniforms(); 93830 93831 this.setUniform('uViewport', this._renderer._viewport); 93832 } 93833 }; 93834 93835 /** 93836 * @method unbindShader 93837 * @chainable 93838 * @private 93839 */ 93840 _main.default.Shader.prototype.unbindShader = function() { 93841 if (this._bound) { 93842 this.unbindTextures(); 93843 //this._renderer.GL.useProgram(0); ?? 93844 this._bound = false;
93845 } 93846 return this; 93847 }; 93848 93849 _main.default.Shader.prototype.bindTextures = function() { 93850 var gl = this._renderer.GL; 93851 var _iteratorNormalCompletion = true; 93852 var _didIteratorError = false; 93853 var _iteratorError = undefined; 93854 try { 93855 for ( 93856 var _iterator = this.samplers[Symbol.iterator](), _step; 93857 !(_iteratorNormalCompletion = (_step = _iterator.next()).done); 93858 _iteratorNormalCompletion = true 93859 ) { 93860 var uniform = _step.value; 93861 var tex = uniform.texture; 93862 if (tex === undefined) { 93863 // user hasn't yet supplied a texture for this slot. 93864 // (or there may not be one--maybe just lighting), 93865 // so we supply a default texture instead. 93866 tex = this._renderer._getEmptyTexture(); 93867 } 93868 gl.activeTexture(gl.TEXTURE0 + uniform.samplerIndex); 93869 tex.bindTexture(); 93870 tex.update(); 93871 gl.uniform1i(uniform.location, uniform.samplerIndex); 93872 } 93873 } catch (err) { 93874 _didIteratorError = true; 93875 _iteratorError = err; 93876 } finally { 93877 try { 93878 if (!_iteratorNormalCompletion && _iterator.return != null) { 93879 _iterator.return(); 93880 } 93881 } finally { 93882 if (_didIteratorError) { 93883 throw _iteratorError; 93884 } 93885 } 93886 } 93887 }; 93888 93889 _main.default.Shader.prototype.updateTextures = function() { 93890 var _iteratorNormalCompletion2 = true; 93891 var _didIteratorError2 = false;
93892 var _iteratorError2 = undefined; 93893 try { 93894 for ( 93895 var _iterator2 = this.samplers[Symbol.iterator](), _step2; 93896 !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); 93897 _iteratorNormalCompletion2 = true 93898 ) { 93899 var uniform = _step2.value; 93900 var tex = uniform.texture; 93901 if (tex) { 93902 tex.update(); 93903 } 93904 } 93905 } catch (err) { 93906 _didIteratorError2 = true; 93907 _iteratorError2 = err; 93908 } finally { 93909 try { 93910 if (!_iteratorNormalCompletion2 && _iterator2.return != null) { 93911 _iterator2.return(); 93912 } 93913 } finally { 93914 if (_didIteratorError2) { 93915 throw _iteratorError2; 93916 } 93917 } 93918 } 93919 }; 93920 93921 _main.default.Shader.prototype.unbindTextures = function() { 93922 // TODO: migrate stuff from material.js here 93923 // - OR - have material.js define this function 93924 }; 93925 93926 _main.default.Shader.prototype._setMatrixUniforms = function() { 93927 this.setUniform('uProjectionMatrix', this._renderer.uPMatrix.mat4); 93928 if (this.isStrokeShader()) { 93929 if (this._renderer._curCamera.cameraType === 'default') { 93930 // strokes scale up as they approach camera, default 93931 this.setUniform('uPerspective', 1); 93932 } else { 93933 // strokes have uniform scale regardless of distance from camera 93934 this.setUniform('uPerspective', 0); 93935 } 93936 } 93937 this.setUniform('uModelViewMatrix', this._renderer.uMVMatrix.mat4); 93938 this.setUniform('uViewMatrix', this._renderer._curCamera.cameraMatrix.mat4); 93939 if (this.uniforms.uNormalMatrix) { 93940 this._renderer.uNMatrix.inverseTranspose(this._renderer.uMVMatrix); 93941 this.setUniform('uNormalMatrix', this._renderer.uNMatrix.mat3); 93942 } 93943 }; 93944 93945 /** 93946 * @method useProgram 93947 * @chainable 93948 * @private 93949 */ 93950 _main.default.Shader.prototype.useProgram = function() { 93951 var gl = this._renderer.GL; 93952 if (this._renderer._curShader !== this) { 93953 gl.useProgram(this._glProgram); 93954 this._renderer._curShader = this; 93955 } 93956 return this; 93957 }; 93958 93959 /** 93960 * Wrapper around gl.uniform functions. 93961 * As we store uniform info in the shader we can use that 93962 * to do type checking on the supplied data and call 93963 * the appropriate function. 93964 * @method setUniform 93965 * @chainable 93966 * @param {String} uniformName the name of the uniform in the 93967 * shader program 93968 * @param {Object|Number|Boolean|Number[]} data the data to be associated 93969 * with that uniform; type varies (could be a single numerical value, array, 93970 * matrix, or texture / sampler reference) 93971 * 93972 * @example 93973 * <div modernizr='webgl'> 93974 * <code> 93975 * // Click within the image to toggle the value of uniforms 93976 * // Note: for an alternative approach to the same example, 93977 * // involving toggling between shaders please refer to: 93978 * // https://p5js.org/reference/#/p5/shader 93979 * 93980 * let grad; 93981 * let showRedGreen = false; 93982 * 93983 * function preload() { 93984 * // note that we are using two instances 93985 * // of the same vertex and fragment shaders 93986 * grad = loadShader('assets/shader.vert', 'assets/shader-gradient.frag'); 93987 * } 93988 * 93989 * function setup() { 93990 * createCanvas(100, 100, WEBGL); 93991 * shader(grad); 93992 * noStroke(); 93993 * } 93994 * 93995 * function draw() { 93996 * // update the offset values for each scenario, 93997 * // moving the "grad" shader in either vertical or 93998 * // horizontal direction each with differing colors 93999 * 94000 * if (showRedGreen === true) { 94001 * grad.setUniform('colorCenter', [1, 0, 0]);
94002 * grad.setUniform('colorBackground', [0, 1, 0]); 94003 * grad.setUniform('offset', [sin(millis() / 2000), 1]); 94004 * } else { 94005 * grad.setUniform('colorCenter', [1, 0.5, 0]); 94006 * grad.setUniform('colorBackground', [0.226, 0, 0.615]); 94007 * grad.setUniform('offset', [0, sin(millis() / 2000) + 1]); 94008 * } 94009 * quad(-1, -1, 1, -1, 1, 1, -1, 1); 94010 * } 94011 * 94012 * function mouseClicked() { 94013 * showRedGreen = !showRedGreen; 94014 * } 94015 * </code> 94016 * </div> 94017 * 94018 * @alt 94019 * 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. 94020 */ 94021 _main.default.Shader.prototype.setUniform = function(uniformName, data) { 94022 var uniform = this.uniforms[uniformName]; 94023 if (!uniform) { 94024 return; 94025 } 94026 var gl = this._renderer.GL; 94027 94028 if (uniform.isArray) { 94029 if ( 94030 uniform._cachedData && 94031 this._renderer._arraysEqual(uniform._cachedData, data) 94032 ) { 94033 return; 94034 } else { 94035 uniform._cachedData = data.slice(0); 94036 } 94037 } else if (uniform._cachedData && uniform._cachedData === data) { 94038 return; 94039 } else { 94040 uniform._cachedData = data; 94041 } 94042 94043 var location = uniform.location; 94044 94045 this.useProgram(); 94046 94047 switch (uniform.type) { 94048 case gl.BOOL: 94049 if (data === true) { 94050 gl.uniform1i(location, 1); 94051 } else { 94052 gl.uniform1i(location, 0); 94053 } 94054 break; 94055 case gl.INT: 94056 if (uniform.size > 1) { 94057 data.length && gl.uniform1iv(location, data); 94058 } else { 94059 gl.uniform1i(location, data); 94060 } 94061 break; 94062 case gl.FLOAT: 94063 if (uniform.size > 1) { 94064 data.length && gl.uniform1fv(location, data); 94065 } else { 94066 gl.uniform1f(location, data); 94067 } 94068 break; 94069 case gl.FLOAT_MAT3: 94070 gl.uniformMatrix3fv(location, false, data); 94071 break; 94072 case gl.FLOAT_MAT4: 94073 gl.uniformMatrix4fv(location, false, data); 94074 break; 94075 case gl.FLOAT_VEC2: 94076 if (uniform.size > 1) { 94077 data.length && gl.uniform2fv(location, data); 94078 } else { 94079 gl.uniform2f(location, data[0], data[1]); 94080 } 94081 break; 94082 case gl.FLOAT_VEC3: 94083 if (uniform.size > 1) { 94084 data.length && gl.uniform3fv(location, data); 94085 } else { 94086 gl.uniform3f(location, data[0], data[1], data[2]); 94087 } 94088 break; 94089 case gl.FLOAT_VEC4: 94090 if (uniform.size > 1) { 94091 data.length && gl.uniform4fv(location, data); 94092 } else { 94093 gl.uniform4f(location, data[0], data[1], data[2], data[3]); 94094 } 94095 break; 94096 case gl.INT_VEC2: 94097 if (uniform.size > 1) { 94098 data.length && gl.uniform2iv(location, data); 94099 } else { 94100 gl.uniform2i(location, data[0], data[1]); 94101 } 94102 break; 94103 case gl.INT_VEC3: 94104 if (uniform.size > 1) { 94105 data.length && gl.uniform3iv(location, data); 94106 } else { 94107 gl.uniform3i(location, data[0], data[1], data[2]); 94108 } 94109 break; 94110 case gl.INT_VEC4: 94111 if (uniform.size > 1) { 94112 data.length && gl.uniform4iv(location, data); 94113 } else { 94114 gl.uniform4i(location, data[0], data[1], data[2], data[3]); 94115 } 94116 break; 94117 case gl.SAMPLER_2D: 94118 gl.activeTexture(gl.TEXTURE0 + uniform.samplerIndex); 94119 uniform.texture = this._renderer.getTexture(data); 94120 gl.uniform1i(uniform.location, uniform.samplerIndex); 94121 break; 94122 //@todo complete all types 94123 } 94124 return this; 94125 }; 94126 94127 /* NONE OF THIS IS FAST OR EFFICIENT BUT BEAR WITH ME 94128 * 94129 * these shader "type" query methods are used by various 94130 * facilities of the renderer to determine if changing
94131 * the shader type for the required action (for example, 94132 * do we need to load the default lighting shader if the 94133 * current shader cannot handle lighting?) 94134 * 94135 **/ 94136 94137 _main.default.Shader.prototype.isLightShader = function() { 94138 return ( 94139 this.attributes.aNormal !== undefined || 94140 this.uniforms.uUseLighting !== undefined || 94141 this.uniforms.uAmbientLightCount !== undefined || 94142 this.uniforms.uDirectionalLightCount !== undefined || 94143 this.uniforms.uPointLightCount !== undefined || 94144 this.uniforms.uAmbientColor !== undefined || 94145 this.uniforms.uDirectionalDiffuseColors !== undefined || 94146 this.uniforms.uDirectionalSpecularColors !== undefined || 94147 this.uniforms.uPointLightLocation !== undefined || 94148 this.uniforms.uPointLightDiffuseColors !== undefined || 94149 this.uniforms.uPointLightSpecularColors !== undefined || 94150 this.uniforms.uLightingDirection !== undefined || 94151 this.uniforms.uSpecular !== undefined 94152 ); 94153 }; 94154 94155 _main.default.Shader.prototype.isNormalShader = function() { 94156 return this.attributes.aNormal !== undefined; 94157 }; 94158 94159 _main.default.Shader.prototype.isTextureShader = function() { 94160 return this.samplerIndex > 0; 94161 }; 94162 94163 _main.default.Shader.prototype.isColorShader = function() { 94164 return ( 94165 this.attributes.aVertexColor !== undefined || 94166 this.uniforms.uMaterialColor !== undefined 94167 ); 94168 }; 94169 94170 _main.default.Shader.prototype.isTexLightShader = function() { 94171 return this.isLightShader() && this.isTextureShader(); 94172 }; 94173 94174 _main.default.Shader.prototype.isStrokeShader = function() { 94175 return this.uniforms.uStrokeWeight !== undefined; 94176 }; 94177 94178 /** 94179 * @method enableAttrib 94180 * @chainable 94181 * @private 94182 */ 94183 _main.default.Shader.prototype.enableAttrib = function( 94184 attr, 94185 size, 94186 type, 94187 normalized, 94188 stride, 94189 offset 94190 ) { 94191 if (attr) { 94192 if ( 94193 typeof IS_MINIFIED === 'undefined' && 94194 this.attributes[attr.name] !== attr 94195 ) { 94196 console.warn( 94197 'The attribute "'.concat( 94198 attr.name, 94199 '"passed to enableAttrib does not belong to this shader.' 94200 ) 94201 ); 94202 } 94203 var loc = attr.location; 94204 if (loc !== -1) { 94205 var gl = this._renderer.GL; 94206 if (!attr.enabled) { 94207 gl.enableVertexAttribArray(loc); 94208 attr.enabled = true; 94209 } 94210 this._renderer.GL.vertexAttribPointer( 94211 loc, 94212 size, 94213 type || gl.FLOAT, 94214 normalized || false, 94215 stride || 0, 94216 offset || 0 94217 ); 94218 } 94219 } 94220 return this; 94221 }; 94222 var _default = _main.default.Shader; 94223 exports.default = _default; 94224 }, 94225 { '../core/main': 59 } 94226 ], 94227 115: [ 94228 function(_dereq_, module, exports) { 94229 'use strict'; 94230 function _typeof(obj) { 94231 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') { 94232 _typeof = function _typeof(obj) { 94233 return typeof obj; 94234 }; 94235 } else { 94236 _typeof = function _typeof(obj) { 94237 return obj && 94238 typeof Symbol === 'function' && 94239 obj.constructor === Symbol && 94240 obj !== Symbol.prototype 94241 ? 'symbol' 94242 : typeof obj; 94243 }; 94244 } 94245 return _typeof(obj); 94246 } 94247 Object.defineProperty(exports, '__esModule', { value: true }); 94248 exports.default = void 0; 94249 94250 var _main = _interopRequireDefault(_dereq_('../core/main')); 94251 var constants = _interopRequireWildcard(_dereq_('../core/constants')); 94252 function _getRequireWildcardCache() { 94253 if (typeof WeakMap !== 'function') return null; 94254 var cache = new WeakMap(); 94255 _getRequireWildcardCache = function _getRequireWildcardCache() { 94256 return cache; 94257 }; 94258 return cache; 94259 } 94260 function _interopRequireWildcard(obj) { 94261 if (obj && obj.__esModule) { 94262 return obj; 94263 } 94264 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) { 94265 return { default: obj }; 94266 } 94267 var cache = _getRequireWildcardCache(); 94268 if (cache && cache.has(obj)) { 94269 return cache.get(obj); 94270 } 94271 var newObj = {}; 94272 var hasPropertyDescriptor = 94273 Object.defineProperty && Object.getOwnPropertyDescriptor; 94274 for (var key in obj) { 94275 if (Object.prototype.hasOwnProperty.call(obj, key)) { 94276 var desc = hasPropertyDescriptor 94277 ? Object.getOwnPropertyDescriptor(obj, key) 94278 : null; 94279 if (desc && (desc.get || desc.set)) { 94280 Object.defineProperty(newObj, key, desc); 94281 } else { 94282 newObj[key] = obj[key]; 94283 } 94284 } 94285 } 94286 newObj.default = obj; 94287 if (cache) { 94288 cache.set(obj, newObj); 94289 } 94290 return newObj; 94291 } 94292 function _interopRequireDefault(obj) { 94293 return obj && obj.__esModule ? obj : { default: obj }; 94294 } 94295 /** 94296 * This module defines the p5.Texture class 94297 * @module Lights, Camera 94298 * @submodule Material 94299 * @for p5 94300 * @requires core 94301 */ /** 94302 * Texture class for WEBGL Mode 94303 * @private 94304 * @class p5.Texture 94305 * @param {p5.RendererGL} renderer an instance of p5.RendererGL that 94306 * will provide the GL context for this new p5.Texture 94307 * @param {p5.Image|p5.Graphics|p5.Element|p5.MediaElement|ImageData} [obj] the
94308 * object containing the image data to store in the texture. 94309 */ _main.default.Texture = function(renderer, obj) { 94310 this._renderer = renderer; 94311 var gl = this._renderer.GL; 94312 94313 this.src = obj; 94314 this.glTex = undefined; 94315 this.glTarget = gl.TEXTURE_2D; 94316 this.glFormat = gl.RGBA; 94317 this.mipmaps = false; 94318 this.glMinFilter = gl.LINEAR; 94319 this.glMagFilter = gl.LINEAR; 94320 this.glWrapS = gl.CLAMP_TO_EDGE; 94321 this.glWrapT = gl.CLAMP_TO_EDGE; 94322 94323 // used to determine if this texture might need constant updating 94324 // because it is a video or gif. 94325 this.isSrcMediaElement = 94326 typeof _main.default.MediaElement !== 'undefined' && 94327 obj instanceof _main.default.MediaElement; 94328 this._videoPrevUpdateTime = 0; 94329 this.isSrcHTMLElement = 94330 typeof _main.default.Element !== 'undefined' && 94331 obj instanceof _main.default.Element && 94332 !(obj instanceof _main.default.Graphics); 94333 this.isSrcP5Image = obj instanceof _main.default.Image; 94334 this.isSrcP5Graphics = obj instanceof _main.default.Graphics; 94335 this.isImageData = typeof ImageData !== 'undefined' && obj instanceof ImageData; 94336 94337 var textureData = this._getTextureDataFromSource(); 94338 this.width = textureData.width; 94339 this.height = textureData.height; 94340 94341 this.init(textureData); 94342 return this; 94343 }; 94344 94345 _main.default.Texture.prototype._getTextureDataFromSource = function() { 94346 var textureData; 94347 if (this.isSrcP5Image) { 94348 // param is a p5.Image 94349 textureData = this.src.canvas; 94350 } else if ( 94351 this.isSrcMediaElement || 94352 this.isSrcP5Graphics || 94353 this.isSrcHTMLElement 94354 ) { 94355 // if param is a video HTML element 94356 textureData = this.src.elt; 94357 } else if (this.isImageData) { 94358 textureData = this.src; 94359 } 94360 return textureData; 94361 }; 94362 94363 /** 94364 * Initializes common texture parameters, creates a gl texture, 94365 * tries to upload the texture for the first time if data is 94366 * already available. 94367 * @private 94368 * @method init 94369 */ 94370 _main.default.Texture.prototype.init = function(data) { 94371 var gl = this._renderer.GL; 94372 this.glTex = gl.createTexture(); 94373 94374 this.glWrapS = this._renderer.textureWrapX; 94375 this.glWrapT = this._renderer.textureWrapY; 94376 94377 this.setWrapMode(this.glWrapS, this.glWrapT); 94378 this.bindTexture(); 94379 94380 //gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); 94381 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, this.glMagFilter); 94382 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, this.glMinFilter); 94383 94384 if ( 94385 this.width === 0 || 94386 this.height === 0 || 94387 (this.isSrcMediaElement && !this.src.loadedmetadata) 94388 ) { 94389 // assign a 1x1 empty texture initially, because data is not yet ready, 94390 // so that no errors occur in gl console! 94391 var tmpdata = new Uint8Array([1, 1, 1, 1]); 94392 gl.texImage2D( 94393 this.glTarget, 94394 0, 94395 gl.RGBA, 94396 1, 94397 1, 94398 0, 94399 this.glFormat, 94400 gl.UNSIGNED_BYTE, 94401 tmpdata 94402 ); 94403 } else { 94404 // data is ready: just push the texture! 94405 gl.texImage2D( 94406 this.glTarget, 94407 0, 94408 this.glFormat, 94409 this.glFormat, 94410 gl.UNSIGNED_BYTE, 94411 data 94412 ); 94413 } 94414 }; 94415 94416 /** 94417 * Checks if the source data for this texture has changed (if it's 94418 * easy to do so) and reuploads the texture if necessary. If it's not 94419 * possible or to expensive to do a calculation to determine wheter or 94420 * not the data has occurred, this method simply re-uploads the texture. 94421 * @method update 94422 */ 94423 _main.default.Texture.prototype.update = function() { 94424 var data = this.src; 94425 if (data.width === 0 || data.height === 0) { 94426 return false; // nothing to do! 94427 } 94428 94429 var textureData = this._getTextureDataFromSource(); 94430 var updated = false;
94431 94432 var gl = this._renderer.GL; 94433 // pull texture from data, make sure width & height are appropriate 94434 if (textureData.width !== this.width || textureData.height !== this.height) { 94435 updated = true; 94436 94437 // make sure that if the width and height of this.src have changed 94438 // for some reason, we update our metadata and upload the texture again 94439 this.width = textureData.width; 94440 this.height = textureData.height; 94441 94442 if (this.isSrcP5Image) { 94443 data.setModified(false); 94444 } else if (this.isSrcMediaElement || this.isSrcHTMLElement) { 94445 // on the first frame the metadata comes in, the size will be changed 94446 // from 0 to actual size, but pixels may not be available. 94447 // flag for update in a future frame. 94448 // if we don't do this, a paused video, for example, may not 94449 // send the first frame to texture memory. 94450 data.setModified(true); 94451 } 94452 } else if (this.isSrcP5Image) { 94453 // for an image, we only update if the modified field has been set, 94454 // for example, by a call to p5.Image.set 94455 if (data.isModified()) { 94456 updated = true; 94457 data.setModified(false); 94458 } 94459 } else if (this.isSrcMediaElement) { 94460 // for a media element (video), we'll check if the current time in 94461 // the video frame matches the last time. if it doesn't match, the 94462 // video has advanced or otherwise been taken to a new frame, 94463 // and we need to upload it. 94464 if (data.isModified()) { 94465 // p5.MediaElement may have also had set/updatePixels, etc. called 94466 // on it and should be updated, or may have been set for the first 94467 // time! 94468 updated = true; 94469 data.setModified(false); 94470 } else if (data.loadedmetadata) { 94471 // if the meta data has been loaded, we can ask the video 94472 // what it's current position (in time) is. 94473 if (this._videoPrevUpdateTime !== data.time()) { 94474 // update the texture in gpu mem only if the current 94475 // video timestamp does not match the timestamp of the last 94476 // time we uploaded this texture (and update the time we 94477 // last uploaded, too) 94478 this._videoPrevUpdateTime = data.time(); 94479 updated = true; 94480 } 94481 } 94482 } else if (this.isImageData) { 94483 if (data._dirty) { 94484 data._dirty = false; 94485 updated = true; 94486 } 94487 } else { 94488 /* data instanceof p5.Graphics, probably */ 94489 // there is not enough information to tell if the texture can be 94490 // conditionally updated; so to be safe, we just go ahead and upload it. 94491 updated = true; 94492 } 94493 94494 if (updated) { 94495 this.bindTexture(); 94496 gl.texImage2D( 94497 this.glTarget, 94498 0, 94499 this.glFormat, 94500 this.glFormat, 94501 gl.UNSIGNED_BYTE, 94502 textureData 94503 ); 94504 } 94505 94506 return updated; 94507 }; 94508 94509 /** 94510 * Binds the texture to the appropriate GL target. 94511 * @method bindTexture 94512 */ 94513 _main.default.Texture.prototype.bindTexture = function() { 94514 // bind texture using gl context + glTarget and 94515 // generated gl texture object 94516 var gl = this._renderer.GL; 94517 gl.bindTexture(this.glTarget, this.glTex); 94518 94519 return this; 94520 }; 94521 94522 /** 94523 * Unbinds the texture from the appropriate GL target. 94524 * @method unbindTexture 94525 */ 94526 _main.default.Texture.prototype.unbindTexture = function() { 94527 // unbind per above, disable texturing on glTarget 94528 var gl = this._renderer.GL; 94529 gl.bindTexture(this.glTarget, null); 94530 }; 94531 94532 /**
94533 * Sets how a texture is be interpolated when upscaled or downscaled. 94534 * Nearest filtering uses nearest neighbor scaling when interpolating 94535 * Linear filtering uses WebGL's linear scaling when interpolating 94536 * @method setInterpolation 94537 * @param {String} downScale Specifies the texture filtering when 94538 * textures are shrunk. Options are LINEAR or NEAREST 94539 * @param {String} upScale Specifies the texture filtering when 94540 * textures are magnified. Options are LINEAR or NEAREST 94541 * @todo implement mipmapping filters 94542 */ 94543 _main.default.Texture.prototype.setInterpolation = function(downScale, upScale) { 94544 var gl = this._renderer.GL; 94545 94546 if (downScale === constants.NEAREST) { 94547 this.glMinFilter = gl.NEAREST; 94548 } else { 94549 this.glMinFilter = gl.LINEAR; 94550 } 94551 94552 if (upScale === constants.NEAREST) { 94553 this.glMagFilter = gl.NEAREST; 94554 } else { 94555 this.glMagFilter = gl.LINEAR; 94556 } 94557 94558 this.bindTexture(); 94559 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, this.glMinFilter); 94560 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, this.glMagFilter); 94561 this.unbindTexture(); 94562 }; 94563 94564 /** 94565 * Sets the texture wrapping mode. This controls how textures behave 94566 * when their uv's go outside of the 0 - 1 range. There are three options: 94567 * CLAMP, REPEAT, and MIRROR. REPEAT & MIRROR are only available if the texture 94568 * is a power of two size (128, 256, 512, 1024, etc.). 94569 * @method setWrapMode 94570 * @param {String} wrapX Controls the horizontal texture wrapping behavior 94571 * @param {String} wrapY Controls the vertical texture wrapping behavior 94572 */ 94573 _main.default.Texture.prototype.setWrapMode = function(wrapX, wrapY) { 94574 var gl = this._renderer.GL; 94575 94576 // for webgl 1 we need to check if the texture is power of two 94577 // if it isn't we will set the wrap mode to CLAMP 94578 // webgl2 will support npot REPEAT and MIRROR but we don't check for it yet 94579 var isPowerOfTwo = function isPowerOfTwo(x) { 94580 return (x & (x - 1)) === 0; 94581 }; 94582 94583 var widthPowerOfTwo = isPowerOfTwo(this.width); 94584 var heightPowerOfTwo = isPowerOfTwo(this.height); 94585 94586 if (wrapX === constants.REPEAT) { 94587 if (widthPowerOfTwo && heightPowerOfTwo) { 94588 this.glWrapS = gl.REPEAT; 94589 } else { 94590 console.warn( 94591 'You tried to set the wrap mode to REPEAT but the texture size is not a power of two. Setting to CLAMP instead' 94592 ); 94593 94594 this.glWrapS = gl.CLAMP_TO_EDGE; 94595 } 94596 } else if (wrapX === constants.MIRROR) { 94597 if (widthPowerOfTwo && heightPowerOfTwo) { 94598 this.glWrapS = gl.MIRRORED_REPEAT; 94599 } else { 94600 console.warn( 94601 'You tried to set the wrap mode to MIRROR but the texture size is not a power of two. Setting to CLAMP instead' 94602 ); 94603 94604 this.glWrapS = gl.CLAMP_TO_EDGE; 94605 } 94606 } else { 94607 // falling back to default if didn't get a proper mode 94608 this.glWrapS = gl.CLAMP_TO_EDGE; 94609 } 94610 94611 if (wrapY === constants.REPEAT) { 94612 if (widthPowerOfTwo && heightPowerOfTwo) { 94613 this.glWrapT = gl.REPEAT; 94614 } else { 94615 console.warn( 94616 'You tried to set the wrap mode to REPEAT but the texture size is not a power of two. Setting to CLAMP instead' 94617 ); 94618 94619 this.glWrapT = gl.CLAMP_TO_EDGE; 94620 } 94621 } else if (wrapY === constants.MIRROR) { 94622 if (widthPowerOfTwo && heightPowerOfTwo) { 94623 this.glWrapT = gl.MIRRORED_REPEAT; 94624 } else { 94625 console.warn( 94626 'You tried to set the wrap mode to MIRROR but the texture size is not a power of two. Setting to CLAMP instead' 94627 ); 94628 94629 this.glWrapT = gl.CLAMP_TO_EDGE; 94630 } 94631 } else { 94632 // falling back to default if didn't get a proper mode 94633 this.glWrapT = gl.CLAMP_TO_EDGE; 94634 } 94635 94636 this.bindTexture(); 94637 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, this.glWrapS); 94638 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, this.glWrapT); 94639 this.unbindTexture(); 94640 }; 94641 var _default = _main.default.Texture; 94642 exports.default = _default; 94643 }, 94644 { '../core/constants': 48, '../core/main': 59 } 94645 ], 94646 116: [
94647 function(_dereq_, module, exports) { 94648 'use strict'; 94649 function _typeof(obj) { 94650 if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') { 94651 _typeof = function _typeof(obj) { 94652 return typeof obj; 94653 }; 94654 } else { 94655 _typeof = function _typeof(obj) { 94656 return obj && 94657 typeof Symbol === 'function' && 94658 obj.constructor === Symbol && 94659 obj !== Symbol.prototype 94660 ? 'symbol' 94661 : typeof obj; 94662 }; 94663 } 94664 return _typeof(obj); 94665 } 94666 var _main = _interopRequireDefault(_dereq_('../core/main')); 94667 var constants = _interopRequireWildcard(_dereq_('../core/constants')); 94668 _dereq_('./p5.Shader'); 94669 _dereq_('./p5.RendererGL.Retained'); 94670 function _getRequireWildcardCache() { 94671 if (typeof WeakMap !== 'function') return null; 94672 var cache = new WeakMap(); 94673 _getRequireWildcardCache = function _getRequireWildcardCache() { 94674 return cache; 94675 }; 94676 return cache; 94677 } 94678 function _interopRequireWildcard(obj) { 94679 if (obj && obj.__esModule) { 94680 return obj; 94681 } 94682 if (obj === null || (_typeof(obj) !== 'object' && typeof obj !== 'function')) { 94683 return { default: obj }; 94684 } 94685 var cache = _getRequireWildcardCache(); 94686 if (cache && cache.has(obj)) { 94687 return cache.get(obj); 94688 } 94689 var newObj = {}; 94690 var hasPropertyDescriptor = 94691 Object.defineProperty && Object.getOwnPropertyDescriptor; 94692 for (var key in obj) { 94693 if (Object.prototype.hasOwnProperty.call(obj, key)) { 94694 var desc = hasPropertyDescriptor 94695 ? Object.getOwnPropertyDescriptor(obj, key) 94696 : null; 94697 if (desc && (desc.get || desc.set)) { 94698 Object.defineProperty(newObj, key, desc); 94699 } else { 94700 newObj[key] = obj[key]; 94701 } 94702 } 94703 } 94704 newObj.default = obj; 94705 if (cache) { 94706 cache.set(obj, newObj); 94707 } 94708 return newObj; 94709 } 94710 function _interopRequireDefault(obj) { 94711 return obj && obj.__esModule ? obj : { default: obj }; 94712 } 94713 94714 // Text/Typography 94715 // @TODO: 94716 _main.default.RendererGL.prototype._applyTextProperties = function() { 94717 //@TODO finish implementation 94718 //console.error('text commands not yet implemented in webgl'); 94719 }; 94720 94721 _main.default.RendererGL.prototype.textWidth = function(s) { 94722 if (this._isOpenType()) { 94723 return this._textFont._textWidth(s, this._textSize); 94724 } 94725 94726 return 0; // TODO: error 94727 }; 94728 94729 // rendering constants 94730 94731 // the number of rows/columns dividing each glyph 94732 var charGridWidth = 9; 94733 var charGridHeight = charGridWidth; 94734 94735 // size of the image holding the bezier stroke info 94736 var strokeImageWidth = 64; 94737 var strokeImageHeight = 64; 94738 94739 // size of the image holding the stroke indices for each row/col 94740 var gridImageWidth = 64; 94741 var gridImageHeight = 64; 94742 94743 // size of the image holding the offset/length of each row/col stripe 94744 var cellImageWidth = 64; 94745 var cellImageHeight = 64; 94746 94747 /** 94748 * @private 94749 * @class ImageInfos 94750 * @param {Integer} width 94751 * @param {Integer} height 94752 * 94753 * the ImageInfos class holds a list of ImageDatas of a given size. 94754 */ 94755 function ImageInfos(width, height) { 94756 this.width = width; 94757 this.height = height; 94758 this.infos = []; // the list of images 94759 94760 /** 94761 * 94762 * @method findImage 94763 * @param {Integer} space 94764 * @return {Object} contains the ImageData, and pixel index into that 94765 * ImageData where the free space was allocated. 94766 * 94767 * finds free space of a given size in the ImageData list 94768 */ 94769 this.findImage = function(space) { 94770 var imageSize = this.width * this.height; 94771 if (space > imageSize) throw new Error('font is too complex to render in 3D'); 94772 94773 // search through the list of images, looking for one with 94774 // anough unused space. 94775 var imageInfo, imageData; 94776 for (var ii = this.infos.length - 1; ii >= 0; --ii) { 94777 var imageInfoTest = this.infos[ii]; 94778 if (imageInfoTest.index + space < imageSize) { 94779 // found one 94780 imageInfo = imageInfoTest; 94781 imageData = imageInfoTest.imageData; 94782 break; 94783 } 94784 } 94785 94786 if (!imageInfo) { 94787 try { 94788 // create a new image 94789 imageData = new ImageData(this.width, this.height); 94790 } catch (err) { 94791 // for browsers that don't support ImageData constructors (ie IE11) 94792 // create an ImageData using the old method 94793 var canvas = document.getElementsByTagName('canvas')[0]; 94794 var created = !canvas; 94795 if (!canvas) { 94796 // create a temporary canvas 94797 canvas = document.createElement('canvas'); 94798 canvas.style.display = 'none'; 94799 document.body.appendChild(canvas); 94800 } 94801 var ctx = canvas.getContext('2d'); 94802 if (ctx) { 94803 imageData = ctx.createImageData(this.width, this.height); 94804 } 94805 if (created) { 94806 // distroy the temporary canvas, if necessary 94807 document.body.removeChild(canvas); 94808 } 94809 } 94810 // construct & dd the new image info 94811 imageInfo = { index: 0, imageData: imageData }; 94812 this.infos.push(imageInfo); 94813 } 94814 94815 var index = imageInfo.index; 94816 imageInfo.index += space; // move to the start of the next image 94817 imageData._dirty = true; 94818 return { imageData: imageData, index: index }; 94819 }; 94820 } 94821 94822 /** 94823 * @function setPixel 94824 * @param {Object} imageInfo 94825 * @param {Number} r 94826 * @param {Number} g 94827 * @param {Number} b 94828 * @param {Number} a 94829 * 94830 * writes the next pixel into an indexed ImageData 94831 */ 94832 function setPixel(imageInfo, r, g, b, a) { 94833 var imageData = imageInfo.imageData; 94834 var pixels = imageData.data; 94835 var index = imageInfo.index++ * 4; 94836 pixels[index++] = r; 94837 pixels[index++] = g; 94838 pixels[index++] = b; 94839 pixels[index++] = a; 94840 } 94841 94842 var SQRT3 = Math.sqrt(3); 94843 94844 /** 94845 * @private 94846 * @class FontInfo 94847 * @param {Object} font an opentype.js font object 94848 * 94849 * contains cached images and glyph information for an opentype font 94850 */ 94851 var FontInfo = function FontInfo(font) { 94852 this.font = font; 94853 // the bezier curve coordinates 94854 this.strokeImageInfos = new ImageInfos(strokeImageWidth, strokeImageHeight); 94855 // lists of curve indices for each row/column slice 94856 this.colDimImageInfos = new ImageInfos(gridImageWidth, gridImageHeight); 94857 this.rowDimImageInfos = new ImageInfos(gridImageWidth, gridImageHeight); 94858 // the offset & length of each row/col slice in the glyph 94859 this.colCellImageInfos = new ImageInfos(cellImageWidth, cellImageHeight); 94860 this.rowCellImageInfos = new ImageInfos(cellImageWidth, cellImageHeight); 94861 94862 // the cached information for each glyph 94863 this.glyphInfos = {}; 94864 94865 /** 94866 * @method getGlyphInfo 94867 * @param {Glyph} glyph the x positions of points in the curve 94868 * @returns {Object} the glyphInfo for that glyph 94869 * 94870 * calculates rendering info for a glyph, including the curve information, 94871 * row & column stripes compiled into textures. 94872 */ 94873 94874 this.getGlyphInfo = function(glyph) { 94875 // check the cache 94876 var gi = this.glyphInfos[glyph.index]; 94877 if (gi) return gi; 94878 94879 // get the bounding box of the glyph from opentype.js 94880 var bb = glyph.getBoundingBox(); 94881 var xMin = bb.x1; 94882 var yMin = bb.y1; 94883 var gWidth = bb.x2 - xMin; 94884 var gHeight = bb.y2 - yMin; 94885 var cmds = glyph.path.commands; 94886 // don't bother rendering invisible glyphs 94887 if (gWidth === 0 || gHeight === 0 || !cmds.length) { 94888 return (this.glyphInfos[glyph.index] = {}); 94889 } 94890 94891 var i; 94892 var strokes = []; // the strokes in this glyph 94893 var rows = []; // the indices of strokes in each row 94894 var cols = []; // the indices of strokes in each column 94895 for (i = charGridWidth - 1; i >= 0; --i) { 94896 cols.push([]); 94897 } 94898 for (i = charGridHeight - 1; i >= 0; --i) { 94899 rows.push([]); 94900 } 94901 94902 /** 94903 * @function push 94904 * @param {Number[]} xs the x positions of points in the curve 94905 * @param {Number[]} ys the y positions of points in the curve 94906 * @param {Object} v the curve information 94907 * 94908 * adds a curve to the rows & columns that it intersects with 94909 */ 94910 function push(xs, ys, v) { 94911 var index = strokes.length; // the index of this stroke 94912 strokes.push(v);
94912 // add this stroke to the list 94913 94914 /** 94915 * @function minMax 94916 * @param {Number[]} rg the list of values to compare 94917 * @param {Number} min the initial minimum value 94918 * @param {Number} max the initial maximum value 94919 * 94920 * find the minimum & maximum value in a list of values 94921 */ 94922 function minMax(rg, min, max) { 94923 for (var _i = rg.length; _i-- > 0; ) { 94924 var _v = rg[_i]; 94925 if (min > _v) min = _v; 94926 if (max < _v) max = _v; 94927 } 94928 return { min: min, max: max }; 94929 } 94930 94931 // loop through the rows & columns that the curve intersects 94932 // adding the curve to those slices 94933 var mmX = minMax(xs, 1, 0); 94934 var ixMin = Math.max(Math.floor(mmX.min * charGridWidth), 0); 94935 var ixMax = Math.min(Math.ceil(mmX.max * charGridWidth), charGridWidth); 94936 for (var iCol = ixMin; iCol < ixMax; ++iCol) { 94937 cols[iCol].push(index); 94938 } 94939 94940 var mmY = minMax(ys, 1, 0); 94941 var iyMin = Math.max(Math.floor(mmY.min * charGridHeight), 0); 94942 var iyMax = Math.min(Math.ceil(mmY.max * charGridHeight), charGridHeight); 94943 94944 for (var iRow = iyMin; iRow < iyMax; ++iRow) { 94945 rows[iRow].push(index); 94946 } 94947 } 94948 94949 /** 94950 * @function clamp 94951 * @param {Number} v the value to clamp 94952 * @param {Number} min the minimum value 94953 * @param {Number} max the maxmimum value 94954 * 94955 * clamps a value between a minimum & maximum value 94956 */ 94957 function clamp(v, min, max) { 94958 if (v < min) return min; 94959 if (v > max) return max; 94960 return v; 94961 } 94962 94963 /** 94964 * @function byte 94965 * @param {Number} v the value to scale 94966 * 94967 * converts a floating-point number in the range 0-1 to a byte 0-255 94968 */ 94969 function byte(v) { 94970 return clamp(255 * v, 0, 255); 94971 } 94972 94973 /** 94974 * @private 94975 * @class Cubic 94976 * @param {Number} p0 the start point of the curve 94977 * @param {Number} c0 the first control point 94978 * @param {Number} c1 the second control point 94979 * @param {Number} p1 the end point 94980 * 94981 * a cubic curve 94982 */ 94983 function Cubic(p0, c0, c1, p1) { 94984 this.p0 = p0; 94985 this.c0 = c0; 94986 this.c1 = c1; 94987 this.p1 = p1; 94988 94989 /** 94990 * @method toQuadratic 94991 * @return {Object} the quadratic approximation 94992 * 94993 * converts the cubic to a quadtratic approximation by 94994 * picking an appropriate quadratic control point 94995 */ 94996 this.toQuadratic = function() { 94997 return { 94998 x: this.p0.x, 94999 y: this.p0.y, 95000 x1: this.p1.x, 95001 y1: this.p1.y, 95002 cx: ((this.c0.x + this.c1.x) * 3 - (this.p0.x + this.p1.x)) / 4, 95003 cy: ((this.c0.y + this.c1.y) * 3 - (this.p0.y + this.p1.y)) / 4 95004 }; 95005 }; 95006 95007 /** 95008 * @method quadError 95009 * @return {Number} the error 95010 * 95011 * calculates the magnitude of error of this curve's 95012 * quadratic approximation. 95013 */ 95014 this.quadError = function() { 95015 return ( 95016 _main.default.Vector.sub( 95017 _main.default.Vector.sub(this.p1, this.p0), 95018 _main.default.Vector.mult( 95019 _main.default.Vector.sub(this.c1, this.c0), 95020 3 95021 ) 95022 ).mag() / 2 95023 ); 95024 }; 95025 95026 /** 95027 * @method split 95028 * @param {Number} t the value (0-1) at which to split 95029 * @return {Cubic} the second part of the curve 95030 * 95031 * splits the cubic into two parts at a point 't' along the curve. 95032 * this cubic keeps its start point and its end point becomes the 95033 * point at 't'. the 'end half is returned. 95034 */ 95035 this.split = function(t) { 95036 var m1 = _main.default.Vector.lerp(this.p0, this.c0, t); 95037 var m2 = _main.default.Vector.lerp(this.c0, this.c1, t); 95038 var mm1 = _main.default.Vector.lerp(m1, m2, t); 95039
95040 this.c1 = _main.default.Vector.lerp(this.c1, this.p1, t); 95041 this.c0 = _main.default.Vector.lerp(m2, this.c1, t); 95042 var pt = _main.default.Vector.lerp(mm1, this.c0, t); 95043 var part1 = new Cubic(this.p0, m1, mm1, pt); 95044 this.p0 = pt; 95045 return part1; 95046 }; 95047 95048 /** 95049 * @method splitInflections 95050 * @return {Cubic[]} the non-inflecting pieces of this cubic 95051 * 95052 * returns an array containing 0, 1 or 2 cubics split resulting 95053 * from splitting this cubic at its inflection points. 95054 * this cubic is (potentially) altered and returned in the list. 95055 */ 95056 this.splitInflections = function() { 95057 var a = _main.default.Vector.sub(this.c0, this.p0); 95058 var b = _main.default.Vector.sub( 95059 _main.default.Vector.sub(this.c1, this.c0), 95060 a 95061 ); 95062 var c = _main.default.Vector.sub( 95063 _main.default.Vector.sub(_main.default.Vector.sub(this.p1, this.c1), a), 95064 _main.default.Vector.mult(b, 2) 95065 ); 95066 95067 var cubics = []; 95068 95069 // find the derivative coefficients 95070 var A = b.x * c.y - b.y * c.x; 95071 if (A !== 0) { 95072 var B = a.x * c.y - a.y * c.x; 95073 var C = a.x * b.y - a.y * b.x; 95074 var disc = B * B - 4 * A * C; 95075 if (disc >= 0) { 95076 if (A < 0) { 95077 A = -A; 95078 B = -B; 95079 C = -C; 95080 } 95081 95082 var Q = Math.sqrt(disc); 95083 var t0 = (-B - Q) / (2 * A); // the first inflection point 95084 var t1 = (-B + Q) / (2 * A); // the second inflection point 95085 95086 // test if the first inflection point lies on the curve 95087 if (t0 > 0 && t0 < 1) { 95088 // split at the first inflection point 95089 cubics.push(this.split(t0)); 95090 // scale t2 into the second part 95091 t1 = 1 - (1 - t1) / (1 - t0); 95092 } 95093 95094 // test if the second inflection point lies on the curve 95095 if (t1 > 0 && t1 < 1) { 95096 // split at the second inflection point 95097 cubics.push(this.split(t1)); 95098 } 95099 } 95100 } 95101 95102 cubics.push(this); 95103 return cubics; 95104 }; 95105 } 95106 95107 /** 95108 * @function cubicToQuadratics 95109 * @param {Number} x0 95110 * @param {Number} y0 95111 * @param {Number} cx0 95112 * @param {Number} cy0 95113 * @param {Number} cx1 95114 * @param {Number} cy1 95115 * @param {Number} x1 95116 * @param {Number} y1 95117 * @returns {Cubic[]} an array of cubics whose quadratic approximations 95118 * closely match the civen cubic. 95119 * 95120 * converts a cubic curve to a list of quadratics. 95121 */ 95122 function cubicToQuadratics(x0, y0, cx0, cy0, cx1, cy1, x1, y1) { 95123 // create the Cubic object and split it at its inflections 95124 var cubics = new Cubic( 95125 new _main.default.Vector(x0, y0), 95126 new _main.default.Vector(cx0, cy0), 95127 new _main.default.Vector(cx1, cy1), 95128 new _main.default.Vector(x1, y1) 95129 ).splitInflections(); 95130 95131 var qs = []; // the final list of quadratics 95132 var precision = 30 / SQRT3; 95133 95134 // for each of the non-inflected pieces of the original cubic 95135 var _iteratorNormalCompletion = true; 95136 var _didIteratorError = false;
95137 var _iteratorError = undefined; 95138 try { 95139 for ( 95140 var _iterator = cubics[Symbol.iterator](), _step; 95141 !(_iteratorNormalCompletion = (_step = _iterator.next()).done); 95142 _iteratorNormalCompletion = true 95143 ) { 95144 var cubic = _step.value; 95145 // the cubic is iteratively split in 3 pieces: 95146 // the first piece is accumulated in 'qs', the result. 95147 // the last piece is accumulated in 'tail', temporarily. 95148 // the middle piece is repeatedly split again, while necessary. 95149 var tail = []; 95150 95151 var t3 = void 0; 95152 for (;;) { 95153 // calculate this cubic's precision 95154 t3 = precision / cubic.quadError(); 95155 if (t3 >= 0.5 * 0.5 * 0.5) { 95156 break; // not too bad, we're done 95157 } 95158 95159 // find a split point based on the error 95160 var t = Math.pow(t3, 1.0 / 3.0); 95161 // split the cubic in 3 95162 var start = cubic.split(t); 95163 var middle = cubic.split(1 - t / (1 - t)); 95164 95165 qs.push(start); // the first part 95166 tail.push(cubic); // the last part 95167 cubic = middle; // iterate on the middle piece 95168 } 95169 95170 if (t3 < 1) { 95171 // a little excess error, split the middle in two 95172 qs.push(cubic.split(0.5)); 95173 } 95174 // add the middle piece to the result 95175 qs.push(cubic); 95176 95177 // finally add the tail, reversed, onto the result 95178 Array.prototype.push.apply(qs, tail.reverse()); 95179 } 95180 } catch (err) { 95181 _didIteratorError = true; 95182 _iteratorError = err; 95183 } finally { 95184 try { 95185 if (!_iteratorNormalCompletion && _iterator.return != null) { 95186 _iterator.return(); 95187 } 95188 } finally { 95189 if (_didIteratorError) { 95190 throw _iteratorError; 95191 } 95192 } 95193 } 95194 95195 return qs; 95196 } 95197 95198 /** 95199 * @function pushLine 95200 * @param {Number} x0 95201 * @param {Number} y0 95202 * @param {Number} x1 95203 * @param {Number} y1 95204 * 95205 * add a straight line to the row/col grid of a glyph 95206 */ 95207 function pushLine(x0, y0, x1, y1) { 95208 var mx = (x0 + x1) / 2; 95209 var my = (y0 + y1) / 2; 95210 push([x0, x1], [y0, y1], { x: x0, y: y0, cx: mx, cy: my }); 95211 } 95212 95213 /** 95214 * @function samePoint 95215 * @param {Number} x0 95216 * @param {Number} y0 95217 * @param {Number} x1 95218 * @param {Number} y1 95219 * @return {Boolean} true if the two points are sufficiently close 95220 * 95221 * tests if two points are close enough to be considered the same 95222 */ 95223 function samePoint(x0, y0, x1, y1) { 95224 return Math.abs(x1 - x0) < 0.00001 && Math.abs(y1 - y0) < 0.00001; 95225 } 95226 95227 var x0, y0, xs, ys; 95228 var _iteratorNormalCompletion2 = true; 95229 var _didIteratorError2 = false;
95230 var _iteratorError2 = undefined; 95231 try { 95232 for ( 95233 var _iterator2 = cmds[Symbol.iterator](), _step2; 95234 !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); 95235 _iteratorNormalCompletion2 = true 95236 ) { 95237 var cmd = _step2.value; 95238 // scale the coordinates to the range 0-1 95239 var x1 = (cmd.x - xMin) / gWidth; 95240 var y1 = (cmd.y - yMin) / gHeight; 95241 95242 // don't bother if this point is the same as the last 95243 if (samePoint(x0, y0, x1, y1)) continue; 95244 95245 switch (cmd.type) { 95246 case 'M': { 95247 // move 95248 xs = x1; 95249 ys = y1; 95250 break; 95251 } 95252 case 'L': { 95253 // line 95254 pushLine(x0, y0, x1, y1); 95255 break; 95256 } 95257 case 'Q': { 95258 // quadratic 95259 var cx = (cmd.x1 - xMin) / gWidth; 95260 var cy = (cmd.y1 - yMin) / gHeight; 95261 push([x0, x1, cx], [y0, y1, cy], { x: x0, y: y0, cx: cx, cy: cy }); 95262 break; 95263 } 95264 case 'Z': { 95265 // end 95266 if (!samePoint(x0, y0, xs, ys)) { 95267 // add an extra line closing the loop, if necessary 95268 pushLine(x0, y0, xs, ys); 95269 strokes.push({ x: xs, y: ys }); 95270 } else { 95271 strokes.push({ x: x0, y: y0 }); 95272 } 95273 break; 95274 } 95275 case 'C': { 95276 // cubic 95277 var cx1 = (cmd.x1 - xMin) / gWidth; 95278 var cy1 = (cmd.y1 - yMin) / gHeight; 95279 var cx2 = (cmd.x2 - xMin) / gWidth; 95280 var cy2 = (cmd.y2 - yMin) / gHeight; 95281 var qs = cubicToQuadratics(x0, y0, cx1, cy1, cx2, cy2, x1, y1); 95282 for (var iq = 0; iq < qs.length; iq++) { 95283 var q = qs[iq].toQuadratic(); 95284 push([q.x, q.x1, q.cx], [q.y, q.y1, q.cy], q); 95285 } 95286 break; 95287 } 95288 default: 95289 throw new Error('unknown command type: '.concat(cmd.type)); 95290 } 95291 95292 x0 = x1; 95293 y0 = y1; 95294 } 95295 95296 // allocate space for the strokes 95297 } catch (err) { 95298 _didIteratorError2 = true; 95299 _iteratorError2 = err; 95300 } finally { 95301 try { 95302 if (!_iteratorNormalCompletion2 && _iterator2.return != null) { 95303 _iterator2.return(); 95304 } 95305 } finally { 95306 if (_didIteratorError2) { 95307 throw _iteratorError2; 95308 } 95309 } 95310 } 95311 var strokeCount = strokes.length; 95312 var strokeImageInfo = this.strokeImageInfos.findImage(strokeCount); 95313 var strokeOffset = strokeImageInfo.index; 95314 95315 // fill the stroke image 95316 for (var il = 0; il < strokeCount; ++il) { 95317 var s = strokes[il]; 95318 setPixel(strokeImageInfo, byte(s.x), byte(s.y), byte(s.cx), byte(s.cy)); 95319 } 95320 95321 /** 95322 * @function layout 95323 * @param {Number[][]} dim 95324 * @param {ImageInfo[]} dimImageInfos 95325 * @param {ImageInfo[]} cellImageInfos 95326 * @return {Object} 95327 * 95328 * lays out the curves in a dimension (row or col) into two 95329 * images, one for the indices of the curves themselves, and 95330 * one containing the offset and length of those index spans. 95331 */ 95332 function layout(dim, dimImageInfos, cellImageInfos) { 95333 var dimLength = dim.length; // the number of slices in this dimension 95334 var dimImageInfo = dimImageInfos.findImage(dimLength); 95335 var dimOffset = dimImageInfo.index; 95336 // calculate the total number of stroke indices in this dimension 95337 var totalStrokes = 0; 95338 for (var id = 0; id < dimLength; ++id) { 95339 totalStrokes += dim[id].length; 95340 } 95341 95342 // allocate space for the stroke indices 95343 var cellImageInfo = cellImageInfos.findImage(totalStrokes); 95344 95345 // for each slice in the glyph 95346 for (var _i2 = 0; _i2 < dimLength; ++_i2) { 95347 var strokeIndices = dim[_i2]; 95348 var _strokeCount = strokeIndices.length; 95349 var cellLineIndex = cellImageInfo.index; 95350 95351 // write the offset and count into the glyph slice image 95352 setPixel( 95353 dimImageInfo, 95354 cellLineIndex >> 7, 95355 cellLineIndex & 0x7f, 95356 _strokeCount >> 7, 95357 _strokeCount & 0x7f 95358 ); 95359 95360 // for each stroke index in that slice 95361 for (var iil = 0; iil < _strokeCount; ++iil) { 95362 // write the stroke index into the slice's image 95363 var strokeIndex = strokeIndices[iil] + strokeOffset; 95364 setPixel(cellImageInfo, strokeIndex >> 7, strokeIndex & 0x7f, 0, 0); 95365 } 95366 } 95367 95368 return { 95369 cellImageInfo: cellImageInfo, 95370 dimOffset: dimOffset, 95371 dimImageInfo: dimImageInfo 95372 }; 95373 } 95374 95375 // initialize the info for this glyph 95376 gi = this.glyphInfos[glyph.index] = { 95377 glyph: glyph, 95378 uGlyphRect: [bb.x1, -bb.y1, bb.x2, -bb.y2], 95379 strokeImageInfo: strokeImageInfo, 95380 strokes: strokes, 95381 colInfo: layout(cols, this.colDimImageInfos, this.colCellImageInfos), 95382 rowInfo: layout(rows, this.rowDimImageInfos, this.rowCellImageInfos) 95383 }; 95384 95385 gi.uGridOffset = [gi.colInfo.dimOffset, gi.rowInfo.dimOffset]; 95386 return gi; 95387 }; 95388 }; 95389 95390 _main.default.RendererGL.prototype._renderText = function(p, line, x, y, maxY) { 95391 if (!this._textFont || typeof this._textFont === 'string') { 95392 console.log( 95393 'WEBGL: you must load and set a font before drawing text. See `loadFont` and `textFont` for more details.' 95394 ); 95395 95396 return; 95397 } 95398 if (y >= maxY || !this._doFill) { 95399 return; // don't render lines beyond our maxY position 95400 } 95401 95402 if (!this._isOpenType()) { 95403 console.log( 95404 'WEBGL: only Opentype (.otf) and Truetype (.ttf) fonts are supported' 95405 ); 95406 95407 return p; 95408 } 95409 95410 p.push(); // fix to #803 95411 95412 // remember this state, so it can be restored later 95413 var doStroke = this._doStroke; 95414 var drawMode = this.drawMode; 95415 95416 this._doStroke = false;
95417 this.drawMode = constants.TEXTURE; 95418 95419 // get the cached FontInfo object 95420 var font = this._textFont.font; 95421 var fontInfo = this._textFont._fontInfo; 95422 if (!fontInfo) { 95423 fontInfo = this._textFont._fontInfo = new FontInfo(font); 95424 } 95425 95426 // calculate the alignment and move/scale the view accordingly 95427 var pos = this._textFont._handleAlignment(this, line, x, y); 95428 var fontSize = this._textSize; 95429 var scale = fontSize / font.unitsPerEm; 95430 this.translate(pos.x, pos.y, 0); 95431 this.scale(scale, scale, 1); 95432 95433 // initialize the font shader 95434 var gl = this.GL; 95435 var initializeShader = !this._defaultFontShader; 95436 var sh = this._getFontShader(); 95437 sh.init(); 95438 sh.bindShader(); // first time around, bind the shader fully 95439 95440 if (initializeShader) { 95441 // these are constants, really. just initialize them one-time. 95442 sh.setUniform('uGridImageSize', [gridImageWidth, gridImageHeight]); 95443 sh.setUniform('uCellsImageSize', [cellImageWidth, cellImageHeight]); 95444 sh.setUniform('uStrokeImageSize', [strokeImageWidth, strokeImageHeight]); 95445 sh.setUniform('uGridSize', [charGridWidth, charGridHeight]); 95446 } 95447 this._applyColorBlend(this.curFillColor); 95448 95449 var g = this.retainedMode.geometry['glyph']; 95450 if (!g) { 95451 // create the geometry for rendering a quad 95452 var geom = (this._textGeom = new _main.default.Geometry(1, 1, function() { 95453 for (var i = 0; i <= 1; i++) { 95454 for (var j = 0; j <= 1; j++) { 95455 this.vertices.push(new _main.default.Vector(j, i, 0)); 95456 this.uvs.push(j, i); 95457 } 95458 } 95459 })); 95460 geom.computeFaces().computeNormals(); 95461 g = this.createBuffers('glyph', geom); 95462 } 95463 95464 // bind the shader buffers 95465 var _iteratorNormalCompletion3 = true; 95466 var _didIteratorError3 = false; 95467 var _iteratorError3 = undefined; 95468 try { 95469 for ( 95470 var _iterator3 = this.retainedMode.buffers.text[Symbol.iterator](), _step3; 95471 !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); 95472 _iteratorNormalCompletion3 = true 95473 ) { 95474 var buff = _step3.value; 95475 buff._prepareBuffer(g, sh); 95476 } 95477 } catch (err) { 95478 _didIteratorError3 = true; 95479 _iteratorError3 = err; 95480 } finally { 95481 try { 95482 if (!_iteratorNormalCompletion3 && _iterator3.return != null) { 95483 _iterator3.return(); 95484 } 95485 } finally { 95486 if (_didIteratorError3) { 95487 throw _iteratorError3; 95488 } 95489 } 95490 } 95491 this._bindBuffer(g.indexBuffer, gl.ELEMENT_ARRAY_BUFFER); 95492 95493 // this will have to do for now... 95494 sh.setUniform('uMaterialColor', this.curFillColor); 95495 95496 try { 95497 var dx = 0; // the x position in the line 95498 var glyphPrev = null; // the previous glyph, used for kerning 95499 // fetch the glyphs in the line of text 95500 var glyphs = font.stringToGlyphs(line); 95501 var _iteratorNormalCompletion4 = true; 95502 var _didIteratorError4 = false; 95503 var _iteratorError4 = undefined; 95504 try { 95505 for ( 95506 var _iterator4 = glyphs[Symbol.iterator](), _step4; 95507 !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); 95508 _iteratorNormalCompletion4 = true 95509 ) { 95510 var glyph = _step4.value; 95511 // kern 95512 if (glyphPrev) dx += font.getKerningValue(glyphPrev, glyph); 95513 95514 var gi = fontInfo.getGlyphInfo(glyph); 95515 if (gi.uGlyphRect) { 95516 var rowInfo = gi.rowInfo; 95517 var colInfo = gi.colInfo; 95518 sh.setUniform('uSamplerStrokes', gi.strokeImageInfo.imageData); 95519 sh.setUniform('uSamplerRowStrokes', rowInfo.cellImageInfo.imageData); 95520 sh.setUniform('uSamplerRows', rowInfo.dimImageInfo.imageData); 95521 sh.setUniform('uSamplerColStrokes', colInfo.cellImageInfo.imageData); 95522 sh.setUniform('uSamplerCols', colInfo.dimImageInfo.imageData); 95523 sh.setUniform('uGridOffset', gi.uGridOffset); 95524 sh.setUniform('uGlyphRect', gi.uGlyphRect); 95525 sh.setUniform('uGlyphOffset', dx); 95526 95527 sh.bindTextures(); // afterwards, only textures need updating 95528 95529 // draw it 95530 gl.drawElements(gl.TRIANGLES, 6, this.GL.UNSIGNED_SHORT, 0); 95531 } 95532 dx += glyph.advanceWidth; 95533 glyphPrev = glyph; 95534 } 95535 } catch (err) {
95536 _didIteratorError4 = true; 95537 _iteratorError4 = err; 95538 } finally { 95539 try { 95540 if (!_iteratorNormalCompletion4 && _iterator4.return != null) { 95541 _iterator4.return(); 95542 } 95543 } finally { 95544 if (_didIteratorError4) { 95545 throw _iteratorError4; 95546 } 95547 } 95548 } 95549 } finally { 95550 // clean up 95551 sh.unbindShader(); 95552 95553 this._doStroke = doStroke; 95554 this.drawMode = drawMode; 95555 95556 p.pop(); 95557 } 95558 95559 return p; 95560 }; 95561 }, 95562 { 95563 '../core/constants': 48, 95564 '../core/main': 59, 95565 './p5.RendererGL.Retained': 112, 95566 './p5.Shader': 114 95567 } 95568 ], 95569 117: [ 95570 function(_dereq_, module, exports) { 95571 module.exports = { 95572 fes: { 95573 autoplay: 95574 "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.", 95575 checkUserDefinedFns: 95576 "It seems that you may have accidentally written {{name}} instead of {{actualName}}.\n\nPlease correct it if it's not intentional.", 95577 fileLoadError: { 95578 bytes: 95579 'It looks like there was a problem loading your file. {{suggestion}}', 95580 font: 'It looks like there was a problem loading your font. {{suggestion}}', 95581 gif: 95582 'There was some trouble loading your GIF. Make sure that your GIF is using 87a or 89a encoding.', 95583 image: 95584 'It looks like there was a problem loading your image. {{suggestion}}', 95585 json: 95586 'It looks like there was a problem loading your JSON file. {{suggestion}}', 95587 large: 95588 "If your large file isn't fetched successfully, we recommend splitting the file into smaller segments and fetching those.", 95589 strings: 95590 'It looks like there was a problem loading your text file. {{suggestion}}', 95591 suggestion: 95592 'Try checking if the file path ({{filePath}}) is correct, hosting the file online, or running a local server. (More info at {{link}})', 95593 table: 95594 'It looks like there was a problem loading your table file. {{suggestion}}', 95595 xml: 95596 'It looks like there was a problem loading your XML file. {{suggestion}}' 95597 }, 95598 friendlyParamError: { 95599 type_EMPTY_VAR: 95600 '{{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}}', 95601 type_TOO_FEW_ARGUMENTS: 95602 '{{func}}() was expecting at least {{minParams}} arguments, but received only {{argCount}}. {{location}}', 95603 type_TOO_MANY_ARGUMENTS: 95604 '{{func}}() was expecting no more than {{maxParams}} arguments, but received {{argCount}}. {{location}}', 95605 type_WRONG_TYPE: 95606 '{{func}}() was expecting {{formatType}} for the {{position}} parameter, received {{argType}} instead. {{location}}' 95607 }, 95608 globalErrors: { 95609 reference: { 95610 notDefined: 95611 '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}}' 95612 }, 95613 stackSubseq: 95614 'â¶ï¸ Called from line {{line}} in "{{func}}" in {{file}} ({{location}})\n\n', 95615 stackTop: 95616 'â¶ï¸ Error at line {{line}} in "{{func}}" in {{file}} ({{location}})\n\n', 95617 syntax: { 95618 invalidToken: 95619 "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}}", 95620 unexpectedToken: 95621 "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}}" 95622 }, 95623 type: { 95624 notfunc: 95625 '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}}', 95626 notfuncObj: 95627 '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}}' 95628 } 95629 }, 95630 libraryError: 95631 '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}}.', 95632 location: '(on line {{line}} in {{file}} [{{location}}])', 95633 misspelling: 95634 'It seems that you may have accidentally written "{{name}}" instead of "{{actualName}}" {{location}}.\n\nPlease correct it to {{actualName}} if you wish to use the {{type}} from p5.js', 95635 misspelling_plural: 95636 'It seems that you may have accidentally written "{{name}}" {{location}}.\n\nYou may have meant one of the following:\n{{suggestions}}', 95637 misusedTopLevel: 95638 "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}}", 95639 positions: { 95640 p_1: 'first', 95641 p_10: 'tenth', 95642 p_11: 'eleventh', 95643 p_12: 'twelfth', 95644 p_2: 'second', 95645 p_3: 'third', 95646 p_4: 'fourth', 95647 p_5: 'fifth', 95648 p_6: 'sixth', 95649 p_7: 'seventh', 95650 p_8: 'eighth', 95651 p_9: 'ninth' 95652 }, 95653 pre: '\nð¸ p5.js says: {{message}}', 95654 welcome:
95655 'Welcome! This is your friendly debugger. To turn me off, switch to using p5.min.js.', 95656 wrongPreload: 95657 '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.' 95658 } 95659 }; 95660 }, 95661 {} 95662 ], 95663 118: [ 95664 function(_dereq_, module, exports) { 95665 'use strict'; 95666 Object.defineProperty(exports, '__esModule', { value: true }); 95667 exports.languages = exports.default = void 0; 95668 var _translation = _interopRequireDefault(_dereq_('./en/translation')); 95669 function _interopRequireDefault(obj) { 95670 return obj && obj.__esModule ? obj : { default: obj }; 95671 } 95672 95673 // Only one language is imported above. This is intentional as other languages 95674 // will be hosted online and then downloaded whenever needed 95675 95676 /** 95677 * Here, we define a default/fallback language which we can use without internet. 95678 * You won't have to change this when adding a new language. 95679 * 95680 * `translation` is the namespace we are using for our initial set of strings 95681 */ var _default = { 95682 en: { 95683 translation: _translation.default 95684 } 95685 }; 95686 95687 /** 95688 * This is a list of languages that we have added so far. 95689 * If you have just added a new language (yay!), add its key to the list below 95690 * (`en` is english, `es` es español). Also add its export to 95691 * dev.js, which is another file in this folder. 95692 */ exports.default = _default; 95693 var languages = ['en', 'es']; 95694 exports.languages = languages; 95695 }, 95696 { './en/translation': 117 } 95697 ] 95698 }, 95699 {}, 95700 [43] 95701 )(43); 95702});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.