vendor: 4,255 bytes, lines 1-125
1/*! p5.js v0.6.1 April 27, 2018 */ 2(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.p5 = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){ 3module.exports={ 4 "project": { 5 "name": "p5", 6 "description": "[](https://travis-ci.org/processing/p5.js) [](https://www.npmjs.com/package/p5)", 7 "version": "0.6.1", 8 "url": "https://github.com/processing/p5.js#readme" 9 }, 10 "files": { 11 "src/color/color_conversion.js": { 12 "name": "src/color/color_conversion.js", 13 "modules": { 14 "Color Conversion": 1 15 }, 16 "classes": {}, 17 "fors": { 18 "p5": 1 19 }, 20 "namespaces": {} 21 }, 22 "src/color/creating_reading.js": { 23 "name": "src/color/creating_reading.js", 24 "modules": { 25 "Creating & Reading": 1 26 }, 27 "classes": {}, 28 "fors": { 29 "p5": 1 30 }, 31 "namespaces": {} 32 }, 33 "src/color/p5.Color.js": { 34 "name": "src/color/p5.Color.js", 35 "modules": {}, 36 "classes": { 37 "p5.Color": 1 38 }, 39 "fors": { 40 "p5": 1 41 }, 42 "namespaces": {} 43 }, 44 "src/color/setting.js": { 45 "name": "src/color/setting.js", 46 "modules": { 47 "Setting": 1 48 }, 49 "classes": {}, 50 "fors": { 51 "p5": 1 52 }, 53 "namespaces": {} 54 }, 55 "src/core/2d_primitives.js": { 56 "name": "src/core/2d_primitives.js", 57 "modules": { 58 "2D Primitives": 1 59 }, 60 "classes": {}, 61 "fors": { 62 "p5": 1 63 }, 64 "namespaces": {} 65 }, 66 "src/core/attributes.js": { 67 "name": "src/core/attributes.js", 68 "modules": { 69 "Attributes": 1 70 }, 71 "classes": {}, 72 "fors": { 73 "p5": 1 74 }, 75 "namespaces": {} 76 }, 77 "src/core/canvas.js": { 78 "name": "src/core/canvas.js", 79 "modules": {}, 80 "classes": {}, 81 "fors": {}, 82 "namespaces": {} 83 }, 84 "src/core/constants.js": { 85 "name": "src/core/constants.js", 86 "modules": { 87 "Constants": 1 88 }, 89 "classes": {}, 90 "fors": { 91 "p5": 1 92 }, 93 "namespaces": {} 94 }, 95 "src/core/core.js": { 96 "name": "src/core/core.js", 97 "modules": { 98 "Structure": 1 99 }, 100 "classes": { 101 "p5": 1 102 }, 103 "fors": { 104 "p5": 1 105 }, 106 "namespaces": {} 107 }, 108 "src/core/curves.js": { 109 "name": "src/core/curves.js", 110 "modules": { 111 "Curves": 1 112 }, 113 "classes": {}, 114 "fors": { 115 "p5": 1 116 }, 117 "namespaces": {} 118 }, 119 "src/core/environment.js": { 120 "name": "src/core/environment.js", 121 "modules": { 122 "Environment": 1 123 }, 124 "classes": {}, 125 "fors": {
126 "p5": 1 127 }, 128 "namespaces": {} 129 }, 130 "src/core/error_helpers.js": { 131 "name": "src/core/error_helpers.js", 132 "modules": {}, 133 "classes": {}, 134 "fors": { 135 "p5": 1 136 }, 137 "namespaces": {} 138 }, 139 "src/core/init.js": { 140 "name": "src/core/init.js", 141 "modules": {}, 142 "classes": {}, 143 "fors": {}, 144 "namespaces": {} 145 }, 146 "src/core/p5.Element.js": { 147 "name": "src/core/p5.Element.js", 148 "modules": { 149 "DOM": 1 150 }, 151 "classes": { 152 "p5.Element": 1 153 }, 154 "fors": { 155 "p5.Element": 1 156 }, 157 "namespaces": {} 158 }, 159 "src/core/p5.Graphics.js": { 160 "name": "src/core/p5.Graphics.js", 161 "modules": { 162 "Rendering": 1 163 }, 164 "classes": { 165 "p5.Graphics": 1 166 }, 167 "fors": { 168 "p5": 1 169 }, 170 "namespaces": {} 171 }, 172 "src/core/p5.Renderer.js": { 173 "name": "src/core/p5.Renderer.js", 174 "modules": {}, 175 "classes": { 176 "p5.Renderer": 1 177 }, 178 "fors": { 179 "p5": 1 180 }, 181 "namespaces": {} 182 }, 183 "src/core/p5.Renderer2D.js": { 184 "name": "src/core/p5.Renderer2D.js", 185 "modules": {}, 186 "classes": {}, 187 "fors": {}, 188 "namespaces": {} 189 }, 190 "src/core/rendering.js": { 191 "name": "src/core/rendering.js", 192 "modules": {}, 193 "classes": {}, 194 "fors": { 195 "p5": 1 196 }, 197 "namespaces": {} 198 }, 199 "src/core/shim.js": { 200 "name": "src/core/shim.js", 201 "modules": {}, 202 "classes": {}, 203 "fors": {}, 204 "namespaces": {} 205 }, 206 "src/core/structure.js": { 207 "name": "src/core/structure.js", 208 "modules": {}, 209 "classes": {}, 210 "fors": { 211 "p5": 1 212 }, 213 "namespaces": {} 214 }, 215 "src/core/transform.js": { 216 "name": "src/core/transform.js", 217 "modules": { 218 "Transform": 1 219 }, 220 "classes": {}, 221 "fors": { 222 "p5": 1 223 }, 224 "namespaces": {} 225 }, 226 "src/core/vertex.js": { 227 "name": "src/core/vertex.js", 228 "modules": { 229 "Vertex": 1 230 }, 231 "classes": {}, 232 "fors": { 233 "p5": 1 234 }, 235 "namespaces": {} 236 }, 237 "src/data/p5.TypedDict.js": { 238 "name": "src/data/p5.TypedDict.js", 239 "modules": { 240 "Dictionary": 1 241 }, 242 "classes": { 243 "p5.TypedDict": 1, 244 "p5.StringDict": 1, 245 "p5.NumberDict": 1 246 }, 247 "fors": { 248 "p5.TypedDict": 1, 249 "p5": 1 250 }, 251 "namespaces": {} 252 }, 253 "src/events/acceleration.js": { 254 "name": "src/events/acceleration.js", 255 "modules": { 256 "Acceleration": 1 257 }, 258 "classes": {}, 259 "fors": { 260 "p5": 1 261 }, 262 "namespaces": {} 263 }, 264 "src/events/keyboard.js": { 265 "name": "src/events/keyboard.js", 266 "modules": { 267 "Keyboard": 1 268 }, 269 "classes": {}, 270 "fors": { 271 "p5": 1 272 }, 273 "namespaces": {} 274 }, 275 "src/events/mouse.js": { 276 "name": "src/events/mouse.js", 277 "modules": { 278 "Mouse": 1 279 }, 280 "classes": {}, 281 "fors": { 282 "p5": 1 283 }, 284 "namespaces": {} 285 }, 286 "src/events/touch.js": { 287 "name": "src/events/touch.js", 288 "modules": { 289 "Touch": 1 290 }, 291 "classes": {}, 292 "fors": {
293 "p5": 1 294 }, 295 "namespaces": {} 296 }, 297 "src/image/filters.js": { 298 "name": "src/image/filters.js", 299 "modules": {}, 300 "classes": {}, 301 "fors": {}, 302 "namespaces": {} 303 }, 304 "src/image/image.js": { 305 "name": "src/image/image.js", 306 "modules": { 307 "Image": 1 308 }, 309 "classes": {}, 310 "fors": { 311 "p5": 1 312 }, 313 "namespaces": {} 314 }, 315 "src/image/loading_displaying.js": { 316 "name": "src/image/loading_displaying.js", 317 "modules": { 318 "Loading & Displaying": 1 319 }, 320 "classes": {}, 321 "fors": { 322 "p5": 1 323 }, 324 "namespaces": {} 325 }, 326 "src/image/p5.Image.js": { 327 "name": "src/image/p5.Image.js", 328 "modules": {}, 329 "classes": { 330 "p5.Image": 1 331 }, 332 "fors": {}, 333 "namespaces": {} 334 }, 335 "src/image/pixels.js": { 336 "name": "src/image/pixels.js", 337 "modules": { 338 "Pixels": 1 339 }, 340 "classes": {}, 341 "fors": { 342 "p5": 1 343 }, 344 "namespaces": {} 345 }, 346 "src/io/files.js": { 347 "name": "src/io/files.js", 348 "modules": { 349 "Input": 1, 350 "Output": 1 351 }, 352 "classes": { 353 "p5.PrintWriter": 1 354 }, 355 "fors": { 356 "p5": 1 357 }, 358 "namespaces": {} 359 }, 360 "src/io/p5.Table.js": { 361 "name": "src/io/p5.Table.js", 362 "modules": { 363 "Table": 1 364 }, 365 "classes": { 366 "p5.Table": 1 367 }, 368 "fors": {}, 369 "namespaces": {} 370 }, 371 "src/io/p5.TableRow.js": { 372 "name": "src/io/p5.TableRow.js", 373 "modules": {}, 374 "classes": { 375 "p5.TableRow": 1 376 }, 377 "fors": {}, 378 "namespaces": {} 379 }, 380 "src/io/p5.XML.js": { 381 "name": "src/io/p5.XML.js", 382 "modules": { 383 "XML": 1 384 }, 385 "classes": { 386 "p5.XML": 1 387 }, 388 "fors": {}, 389 "namespaces": {} 390 }, 391 "src/math/calculation.js": { 392 "name": "src/math/calculation.js", 393 "modules": { 394 "Calculation": 1 395 }, 396 "classes": {}, 397 "fors": { 398 "p5": 1 399 }, 400 "namespaces": {} 401 }, 402 "src/math/math.js": { 403 "name": "src/math/math.js", 404 "modules": { 405 "Math": 1 406 }, 407 "classes": {}, 408 "fors": { 409 "p5": 1 410 }, 411 "namespaces": {} 412 }, 413 "src/math/noise.js": { 414 "name": "src/math/noise.js", 415 "modules": { 416 "Noise": 1 417 }, 418 "classes": {}, 419 "fors": { 420 "p5": 1 421 }, 422 "namespaces": {} 423 }, 424 "src/math/p5.Vector.js": { 425 "name": "src/math/p5.Vector.js", 426 "modules": {}, 427 "classes": { 428 "p5.Vector": 1 429 }, 430 "fors": {}, 431 "namespaces": {} 432 }, 433 "src/math/random.js": { 434 "name": "src/math/random.js", 435 "modules": { 436 "Random": 1 437 }, 438 "classes": {}, 439 "fors": { 440 "p5": 1 441 }, 442 "namespaces": {} 443 }, 444 "src/math/trigonometry.js": { 445 "name": "src/math/trigonometry.js", 446 "modules": { 447 "Trigonometry": 1 448 }, 449 "classes": {}, 450 "fors": { 451 "p5": 1 452 }, 453 "namespaces": {} 454 }, 455 "src/typography/attributes.js": { 456 "name": "src/typography/attributes.js", 457 "modules": {}, 458 "classes": {}, 459 "fors": {
460 "p5": 1 461 }, 462 "namespaces": {} 463 }, 464 "src/typography/loading_displaying.js": { 465 "name": "src/typography/loading_displaying.js", 466 "modules": {}, 467 "classes": {}, 468 "fors": { 469 "p5": 1 470 }, 471 "namespaces": {} 472 }, 473 "src/typography/p5.Font.js": { 474 "name": "src/typography/p5.Font.js", 475 "modules": { 476 "Font": 1 477 }, 478 "classes": { 479 "p5.Font": 1 480 }, 481 "fors": {}, 482 "namespaces": {} 483 }, 484 "src/utilities/array_functions.js": { 485 "name": "src/utilities/array_functions.js", 486 "modules": { 487 "Array Functions": 1 488 }, 489 "classes": {}, 490 "fors": { 491 "p5": 1 492 }, 493 "namespaces": {} 494 }, 495 "src/utilities/conversion.js": { 496 "name": "src/utilities/conversion.js", 497 "modules": { 498 "Conversion": 1 499 }, 500 "classes": {}, 501 "fors": { 502 "p5": 1 503 }, 504 "namespaces": {} 505 }, 506 "src/utilities/string_functions.js": { 507 "name": "src/utilities/string_functions.js", 508 "modules": { 509 "String Functions": 1 510 }, 511 "classes": {}, 512 "fors": { 513 "p5": 1 514 }, 515 "namespaces": {} 516 }, 517 "src/utilities/time_date.js": { 518 "name": "src/utilities/time_date.js", 519 "modules": { 520 "Time & Date": 1 521 }, 522 "classes": {}, 523 "fors": { 524 "p5": 1 525 }, 526 "namespaces": {} 527 }, 528 "src/webgl/camera.js": { 529 "name": "src/webgl/camera.js", 530 "modules": { 531 "Camera": 1 532 }, 533 "classes": {}, 534 "fors": { 535 "p5": 1 536 }, 537 "namespaces": {} 538 }, 539 "src/webgl/interaction.js": { 540 "name": "src/webgl/interaction.js", 541 "modules": {}, 542 "classes": {}, 543 "fors": { 544 "p5": 1 545 }, 546 "namespaces": {} 547 }, 548 "src/webgl/light.js": { 549 "name": "src/webgl/light.js", 550 "modules": { 551 "Lights": 1 552 }, 553 "classes": {}, 554 "fors": { 555 "p5": 1 556 }, 557 "namespaces": {} 558 }, 559 "src/webgl/loading.js": { 560 "name": "src/webgl/loading.js", 561 "modules": { 562 "3D Models": 1 563 }, 564 "classes": {}, 565 "fors": { 566 "p5": 1 567 }, 568 "namespaces": {} 569 }, 570 "src/webgl/material.js": { 571 "name": "src/webgl/material.js", 572 "modules": { 573 "Material": 1 574 }, 575 "classes": {}, 576 "fors": { 577 "p5": 1 578 }, 579 "namespaces": {} 580 }, 581 "src/webgl/p5.Geometry.js": { 582 "name": "src/webgl/p5.Geometry.js", 583 "modules": {}, 584 "classes": { 585 "p5.Geometry": 1 586 }, 587 "fors": {}, 588 "namespaces": {} 589 }, 590 "src/webgl/p5.Matrix.js": { 591 "name": "src/webgl/p5.Matrix.js", 592 "modules": {}, 593 "classes": { 594 "p5.Matrix": 1 595 }, 596 "fors": {}, 597 "namespaces": {} 598 }, 599 "src/webgl/p5.RendererGL.Immediate.js": { 600 "name": "src/webgl/p5.RendererGL.Immediate.js", 601 "modules": {}, 602 "classes": {}, 603 "fors": {}, 604 "namespaces": {} 605 }, 606 "src/webgl/p5.RendererGL.Retained.js": { 607 "name": "src/webgl/p5.RendererGL.Retained.js", 608 "modules": {}, 609 "classes": {}, 610 "fors": {}, 611 "namespaces": {} 612 }, 613 "src/webgl/p5.RendererGL.js": { 614 "name": "src/webgl/p5.RendererGL.js", 615 "modules": {}, 616 "classes": {
617 "p5.RendererGL": 1 618 }, 619 "fors": { 620 "p5": 1 621 }, 622 "namespaces": {} 623 }, 624 "src/webgl/p5.Shader.js": { 625 "name": "src/webgl/p5.Shader.js", 626 "modules": { 627 "Shaders": 1 628 }, 629 "classes": { 630 "p5.Shader": 1 631 }, 632 "fors": { 633 "p5": 1 634 }, 635 "namespaces": {} 636 }, 637 "src/webgl/p5.Texture.js": { 638 "name": "src/webgl/p5.Texture.js", 639 "modules": {}, 640 "classes": { 641 "p5.Texture": 1 642 }, 643 "fors": { 644 "p5": 1 645 }, 646 "namespaces": {} 647 }, 648 "src/webgl/primitives.js": { 649 "name": "src/webgl/primitives.js", 650 "modules": { 651 "3D Primitives": 1 652 }, 653 "classes": {}, 654 "fors": { 655 "p5": 1 656 }, 657 "namespaces": {} 658 }, 659 "lib/addons/p5.dom.js": { 660 "name": "lib/addons/p5.dom.js", 661 "modules": { 662 "p5.dom": 1 663 }, 664 "classes": { 665 "p5.MediaElement": 1, 666 "p5.File": 1 667 }, 668 "fors": { 669 "p5.dom": 1, 670 "p5.Element": 1 671 }, 672 "namespaces": {} 673 }, 674 "lib/addons/p5.sound.js": { 675 "name": "lib/addons/p5.sound.js", 676 "modules": { 677 "p5.sound": 1 678 }, 679 "classes": { 680 "p5.SoundFile": 1, 681 "p5.Amplitude": 1, 682 "p5.FFT": 1, 683 "p5.Signal": 1, 684 "p5.Oscillator": 1, 685 "p5.SinOsc": 1, 686 "p5.TriOsc": 1, 687 "p5.SawOsc": 1, 688 "p5.SqrOsc": 1, 689 "p5.Env": 1, 690 "p5.Pulse": 1, 691 "p5.Noise": 1, 692 "p5.AudioIn": 1, 693 "p5.Effect": 1, 694 "p5.Filter": 1, 695 "p5.LowPass": 1, 696 "p5.HighPass": 1, 697 "p5.BandPass": 1, 698 "p5.EQ": 1, 699 "p5.Panner3D": 1, 700 "p5.Delay": 1, 701 "p5.Reverb": 1, 702 "p5.Convolver": 1, 703 "p5.Phrase": 1, 704 "p5.Part": 1, 705 "p5.Score": 1, 706 "p5.SoundLoop": 1, 707 "p5.Compressor": 1, 708 "p5.SoundRecorder": 1, 709 "p5.PeakDetect": 1, 710 "p5.Gain": 1, 711 "p5.AudioVoice": 1, 712 "p5.MonoSynth": 1, 713 "p5.PolySynth": 1, 714 "p5.Distortion": 1 715 }, 716 "fors": { 717 "p5.sound": 1, 718 "p5": 1 719 }, 720 "namespaces": {} 721 }, 722 "lib/addons/p5.sound.min.js": { 723 "name": "lib/addons/p5.sound.min.js", 724 "modules": {}, 725 "classes": {}, 726 "fors": {}, 727 "namespaces": {} 728 } 729 }, 730 "modules": { 731 "Conversion": { 732 "name": "Conversion", 733 "submodules": { 734 "Color Conversion": 1 735 }, 736 "elements": {}, 737 "classes": {}, 738 "fors": { 739 "p5": 1 740 }, 741 "namespaces": {}, 742 "module": "Data", 743 "file": "src/utilities/conversion.js", 744 "line": 1, 745 "requires": [ 746 "core" 747 ] 748 }, 749 "Color Conversion": { 750 "name": "Color Conversion", 751 "submodules": {}, 752 "elements": {}, 753 "classes": {}, 754 "fors": { 755 "p5": 1 756 }, 757 "is_submodule": 1, 758 "namespaces": {}, 759 "module": "Conversion", 760 "namespace": "", 761 "file": "src/color/color_conversion.js", 762 "line": 1, 763 "requires": [ 764 "core" 765 ] 766 }, 767 "Color": { 768 "name": "Color", 769 "submodules": { 770 "Creating & Reading": 1, 771 "Setting": 1 772 }, 773 "elements": {}, 774 "classes": {
775 "p5.Color": 1 776 }, 777 "fors": { 778 "p5": 1 779 }, 780 "namespaces": {}, 781 "file": "src/color/p5.Color.js", 782 "line": 16 783 }, 784 "Creating & Reading": { 785 "name": "Creating & Reading", 786 "submodules": {}, 787 "elements": {}, 788 "classes": { 789 "p5.Color": 1 790 }, 791 "fors": { 792 "p5": 1 793 }, 794 "is_submodule": 1, 795 "namespaces": {}, 796 "module": "Color", 797 "namespace": "", 798 "file": "src/color/p5.Color.js", 799 "line": 16, 800 "requires": [ 801 "core", 802 "constants" 803 ], 804 "description": "<p>Each color stores the color mode and level maxes that applied at the\ntime of its construction. These are used to interpret the input arguments\n(at construction and later for that instance of color) and to format the\noutput e.g. when saturation() is requested.</p>\n<p>Internally we store an array representing the ideal RGBA values in floating\npoint form, normalized from 0 to 1. From this we calculate the closest\nscreen color (RGBA levels from 0 to 255) and expose this to the renderer.</p>\n<p>We also cache normalized, floating point components of the color in various\nrepresentations as they are calculated. This is done to prevent repeating a\nconversion that has already been performed.</p>\n" 805 }, 806 "Setting": { 807 "name": "Setting", 808 "submodules": {}, 809 "elements": {}, 810 "classes": {}, 811 "fors": { 812 "p5": 1 813 }, 814 "is_submodule": 1, 815 "namespaces": {}, 816 "module": "Color", 817 "namespace": "", 818 "file": "src/color/setting.js", 819 "line": 1, 820 "requires": [ 821 "core", 822 "constants" 823 ] 824 }, 825 "Shape": { 826 "name": "Shape", 827 "submodules": { 828 "2D Primitives": 1, 829 "Curves": 1, 830 "Vertex": 1, 831 "3D Models": 1, 832 "3D Primitives": 1 833 }, 834 "elements": {}, 835 "classes": {}, 836 "fors": { 837 "p5": 1 838 }, 839 "namespaces": {} 840 }, 841 "2D Primitives": { 842 "name": "2D Primitives", 843 "submodules": {}, 844 "elements": {}, 845 "classes": {}, 846 "fors": { 847 "p5": 1 848 }, 849 "is_submodule": 1, 850 "namespaces": {}, 851 "module": "Shape", 852 "namespace": "", 853 "file": "src/core/2d_primitives.js", 854 "line": 1, 855 "requires": [ 856 "core", 857 "constants" 858 ] 859 }, 860 "Attributes": { 861 "name": "Attributes", 862 "submodules": {}, 863 "elements": {}, 864 "classes": {}, 865 "fors": { 866 "p5": 1 867 }, 868 "is_submodule": 1, 869 "namespaces": {}, 870 "module": "Typography", 871 "namespace": "", 872 "file": "src/core/attributes.js", 873 "line": 1, 874 "requires": [ 875 "core", 876 "constants" 877 ] 878 }, 879 "Constants": { 880 "name": "Constants", 881 "submodules": {}, 882 "elements": {}, 883 "classes": {}, 884 "fors": { 885 "p5": 1 886 }, 887 "namespaces": {}, 888 "module": "Constants", 889 "file": "src/core/constants.js", 890 "line": 1 891 }, 892 "Structure": { 893 "name": "Structure", 894 "submodules": {}, 895 "elements": {}, 896 "classes": {}, 897 "fors": { 898 "p5": 1 899 }, 900 "namespaces": {}, 901 "module": "IO", 902 "file": "src/core/core.js", 903 "line": 1, 904 "requires": [ 905 "constants" 906 ] 907 }, 908 "Curves": { 909 "name": "Curves", 910 "submodules": {}, 911 "elements": {}, 912 "classes": {}, 913 "fors": {
914 "p5": 1 915 }, 916 "is_submodule": 1, 917 "namespaces": {}, 918 "module": "Shape", 919 "namespace": "", 920 "file": "src/core/curves.js", 921 "line": 1, 922 "requires": [ 923 "core" 924 ] 925 }, 926 "Environment": { 927 "name": "Environment", 928 "submodules": {}, 929 "elements": {}, 930 "classes": {}, 931 "fors": { 932 "p5": 1 933 }, 934 "namespaces": {}, 935 "module": "Environment", 936 "file": "src/core/environment.js", 937 "line": 1, 938 "requires": [ 939 "core", 940 "constants" 941 ] 942 }, 943 "DOM": { 944 "name": "DOM", 945 "submodules": {}, 946 "elements": {}, 947 "classes": { 948 "p5.Element": 1 949 }, 950 "fors": { 951 "p5.Element": 1 952 }, 953 "namespaces": {}, 954 "module": "DOM", 955 "file": "src/core/p5.Element.js", 956 "line": 11, 957 "description": "<p>Base class for all elements added to a sketch, including canvas,\ngraphics buffers, and other HTML elements. Methods in blue are\nincluded in the core functionality, methods in brown are added\nwith the <a href=\"http://p5js.org/reference/#/libraries/p5.dom\">p5.dom\nlibrary</a>.\nIt is not called directly, but p5.Element\nobjects are created by calling createCanvas, createGraphics,\nor in the p5.dom library, createDiv, createImg, createInput, etc.</p>\n" 958 }, 959 "Rendering": { 960 "name": "Rendering", 961 "submodules": { 962 "undefined": 1 963 }, 964 "elements": {}, 965 "classes": { 966 "p5.RendererGL": 1, 967 "p5.Graphics": 1, 968 "p5.Renderer": 1 969 }, 970 "fors": { 971 "p5": 1 972 }, 973 "namespaces": {}, 974 "module": "Rendering", 975 "file": "src/webgl/p5.RendererGL.js", 976 "line": 439, 977 "description": "<p>Thin wrapper around a renderer, to be used for creating a\ngraphics buffer object. Use this class if you need\nto draw into an off-screen graphics buffer. The two parameters define the\nwidth and height in pixels. The fields and methods for this class are\nextensive, but mirror the normal drawing API for p5.</p>\n" 978 }, 979 "Transform": { 980 "name": "Transform", 981 "submodules": {}, 982 "elements": {}, 983 "classes": {}, 984 "fors": { 985 "p5": 1 986 }, 987 "namespaces": {}, 988 "module": "Transform", 989 "file": "src/core/transform.js", 990 "line": 1, 991 "requires": [ 992 "core", 993 "constants" 994 ] 995 }, 996 "Vertex": { 997 "name": "Vertex", 998 "submodules": {}, 999 "elements": {}, 1000 "classes": {}, 1001 "fors": { 1002 "p5": 1 1003 }, 1004 "is_submodule": 1, 1005 "namespaces": {}, 1006 "module": "Shape", 1007 "namespace": "", 1008 "file": "src/core/vertex.js", 1009 "line": 1, 1010 "requires": [ 1011 "core", 1012 "constants" 1013 ] 1014 }, 1015 "Data": { 1016 "name": "Data", 1017 "submodules": { 1018 "Dictionary": 1, 1019 "Array Functions": 1, 1020 "String Functions": 1 1021 }, 1022 "elements": {}, 1023 "classes": { 1024 "p5.TypedDict": 1, 1025 "p5.StringDict": 1, 1026 "p5.NumberDict": 1 1027 }, 1028 "fors": { 1029 "p5.TypedDict": 1, 1030 "p5": 1 1031 }, 1032 "namespaces": {}, 1033 "file": "src/data/p5.TypedDict.js", 1034 "line": 407 1035 }, 1036 "Dictionary": { 1037 "name": "Dictionary", 1038 "submodules": {}, 1039 "elements": {}, 1040 "classes": {
1041 "p5.TypedDict": 1, 1042 "p5.StringDict": 1, 1043 "p5.NumberDict": 1 1044 }, 1045 "fors": { 1046 "p5.TypedDict": 1, 1047 "p5": 1 1048 }, 1049 "is_submodule": 1, 1050 "namespaces": {}, 1051 "module": "Data", 1052 "namespace": "", 1053 "file": "src/data/p5.TypedDict.js", 1054 "line": 407, 1055 "requires": [ 1056 "core\n\nThis module defines the p5 methods for the p5 Dictionary classes\nthese classes StringDict and NumberDict are for storing and working\nwith key", 1057 "value pairs" 1058 ], 1059 "description": "<p>Base class for all p5.Dictionary types. More specifically\n typed Dictionary objects inherit from this</p>\n" 1060 }, 1061 "Events": { 1062 "name": "Events", 1063 "submodules": { 1064 "Acceleration": 1, 1065 "Keyboard": 1, 1066 "Mouse": 1, 1067 "Touch": 1 1068 }, 1069 "elements": {}, 1070 "classes": {}, 1071 "fors": { 1072 "p5": 1 1073 }, 1074 "namespaces": {} 1075 }, 1076 "Acceleration": { 1077 "name": "Acceleration", 1078 "submodules": {}, 1079 "elements": {}, 1080 "classes": {}, 1081 "fors": { 1082 "p5": 1 1083 }, 1084 "is_submodule": 1, 1085 "namespaces": {}, 1086 "module": "Events", 1087 "namespace": "", 1088 "file": "src/events/acceleration.js", 1089 "line": 1, 1090 "requires": [ 1091 "core" 1092 ] 1093 }, 1094 "Keyboard": { 1095 "name": "Keyboard", 1096 "submodules": {}, 1097 "elements": {}, 1098 "classes": {}, 1099 "fors": { 1100 "p5": 1 1101 }, 1102 "is_submodule": 1, 1103 "namespaces": {}, 1104 "module": "Events", 1105 "namespace": "", 1106 "file": "src/events/keyboard.js", 1107 "line": 1, 1108 "requires": [ 1109 "core" 1110 ] 1111 }, 1112 "Mouse": { 1113 "name": "Mouse", 1114 "submodules": {}, 1115 "elements": {}, 1116 "classes": {}, 1117 "fors": { 1118 "p5": 1 1119 }, 1120 "is_submodule": 1, 1121 "namespaces": {}, 1122 "module": "Events", 1123 "namespace": "", 1124 "file": "src/events/mouse.js", 1125 "line": 1, 1126 "requires": [ 1127 "core", 1128 "constants" 1129 ] 1130 }, 1131 "Touch": { 1132 "name": "Touch", 1133 "submodules": {}, 1134 "elements": {}, 1135 "classes": {}, 1136 "fors": { 1137 "p5": 1 1138 }, 1139 "is_submodule": 1, 1140 "namespaces": {}, 1141 "module": "Events", 1142 "namespace": "", 1143 "file": "src/events/touch.js", 1144 "line": 1, 1145 "requires": [ 1146 "core" 1147 ] 1148 }, 1149 "Image": { 1150 "name": "Image", 1151 "submodules": { 1152 "Pixels": 1 1153 }, 1154 "elements": {}, 1155 "classes": { 1156 "p5.Image": 1 1157 }, 1158 "fors": { 1159 "p5": 1 1160 }, 1161 "namespaces": {}, 1162 "module": "Image", 1163 "file": "src/image/p5.Image.js", 1164 "line": 23, 1165 "requires": [ 1166 "core" 1167 ], 1168 "description": "<p>Creates a new p5.Image. A p5.Image is a canvas backed representation of an\nimage.\n<br><br>\np5 can display .gif, .jpg and .png images. Images may be displayed\nin 2D and 3D space. Before an image is used, it must be loaded with the\nloadImage() function. The p5.Image class contains fields for the width and\nheight of the image, as well as an array called pixels[] that contains the\nvalues for every pixel in the image.\n<br><br>\nThe methods described below allow easy access to the image's pixels and\nalpha channel and simplify the process of compositing.\n<br><br>\nBefore using the pixels[] array, be sure to use the loadPixels() method on\nthe image to make sure that the pixel data is properly loaded.</p>\n" 1169 }, 1170 "Loading & Displaying": { 1171 "name": "Loading & Displaying", 1172 "submodules": {}, 1173 "elements": {}, 1174 "classes": {}, 1175 "fors": {
1176 "p5": 1 1177 }, 1178 "is_submodule": 1, 1179 "namespaces": {}, 1180 "module": "Typography", 1181 "namespace": "", 1182 "file": "src/image/loading_displaying.js", 1183 "line": 1, 1184 "requires": [ 1185 "core" 1186 ] 1187 }, 1188 "Pixels": { 1189 "name": "Pixels", 1190 "submodules": {}, 1191 "elements": {}, 1192 "classes": {}, 1193 "fors": { 1194 "p5": 1 1195 }, 1196 "is_submodule": 1, 1197 "namespaces": {}, 1198 "module": "Image", 1199 "namespace": "", 1200 "file": "src/image/pixels.js", 1201 "line": 1, 1202 "requires": [ 1203 "core" 1204 ] 1205 }, 1206 "IO": { 1207 "name": "IO", 1208 "submodules": { 1209 "Structure": 1, 1210 "Input": 1, 1211 "Output": 1, 1212 "Table": 1, 1213 "XML": 1, 1214 "Time & Date": 1 1215 }, 1216 "elements": {}, 1217 "classes": { 1218 "p5": 1, 1219 "p5.PrintWriter": 1, 1220 "p5.Table": 1, 1221 "p5.TableRow": 1, 1222 "p5.XML": 1 1223 }, 1224 "fors": { 1225 "p5": 1 1226 }, 1227 "namespaces": {}, 1228 "file": "src/io/p5.XML.js", 1229 "line": 11 1230 }, 1231 "Input": { 1232 "name": "Input", 1233 "submodules": {}, 1234 "elements": {}, 1235 "classes": {}, 1236 "fors": { 1237 "p5": 1 1238 }, 1239 "is_submodule": 1, 1240 "namespaces": {}, 1241 "module": "IO", 1242 "namespace": "", 1243 "file": "src/io/files.js", 1244 "line": 1, 1245 "requires": [ 1246 "core" 1247 ] 1248 }, 1249 "Output": { 1250 "name": "Output", 1251 "submodules": {}, 1252 "elements": {}, 1253 "classes": { 1254 "p5": 1, 1255 "p5.PrintWriter": 1 1256 }, 1257 "fors": { 1258 "p5": 1 1259 }, 1260 "is_submodule": 1, 1261 "namespaces": {}, 1262 "module": "IO", 1263 "namespace": "", 1264 "file": "src/io/files.js", 1265 "line": 1169, 1266 "description": "<p>This is the p5 instance constructor.</p>\n<p>A p5 instance holds all the properties and methods related to\na p5 sketch. It expects an incoming sketch closure and it can also\ntake an optional node parameter for attaching the generated p5 canvas\nto a node. The sketch closure takes the newly created p5 instance as\nits sole argument and may optionally set preload(), setup(), and/or\ndraw() properties on it for running a sketch.</p>\n<p>A p5 sketch can run in "global" or "instance" mode:\n"global" - all properties and methods are attached to the window\n"instance" - all properties and methods are bound to this p5 object</p>\n" 1267 }, 1268 "Table": { 1269 "name": "Table", 1270 "submodules": {}, 1271 "elements": {}, 1272 "classes": { 1273 "p5.Table": 1, 1274 "p5.TableRow": 1 1275 }, 1276 "fors": {}, 1277 "is_submodule": 1, 1278 "namespaces": {}, 1279 "module": "IO", 1280 "namespace": "", 1281 "file": "src/io/p5.TableRow.js", 1282 "line": 11, 1283 "requires": [ 1284 "core" 1285 ], 1286 "description": "<p>Table objects store data with multiple rows and columns, much\nlike in a traditional spreadsheet. Tables can be generated from\nscratch, dynamically, or using data from an existing file.</p>\n" 1287 }, 1288 "XML": { 1289 "name": "XML", 1290 "submodules": {}, 1291 "elements": {}, 1292 "classes": { 1293 "p5.XML": 1 1294 }, 1295 "fors": {}, 1296 "is_submodule": 1, 1297 "namespaces": {}, 1298 "module": "IO", 1299 "namespace": "", 1300 "file": "src/io/p5.XML.js", 1301 "line": 11, 1302 "requires": [ 1303 "core" 1304 ], 1305 "description": "<p>XML is a representation of an XML object, able to parse XML code. Use\nloadXML() to load external XML files and create XML objects.</p>\n" 1306 }, 1307 "Math": { 1308 "name": "Math", 1309 "submodules": { 1310 "Calculation": 1, 1311 "Noise": 1, 1312 "Random": 1, 1313 "Trigonometry": 1 1314 }, 1315 "elements": {}, 1316 "classes": {
1317 "p5.Vector": 1 1318 }, 1319 "fors": { 1320 "p5": 1 1321 }, 1322 "namespaces": {}, 1323 "module": "Math", 1324 "file": "src/math/p5.Vector.js", 1325 "line": 12, 1326 "requires": [ 1327 "core" 1328 ], 1329 "description": "<p>A class to describe a two or three dimensional vector, specifically\na Euclidean (also known as geometric) vector. A vector is an entity\nthat has both magnitude and direction. The datatype, however, stores\nthe components of the vector (x, y for 2D, and x, y, z for 3D). The magnitude\nand direction can be accessed via the methods mag() and heading().\n<br><br>\nIn many of the p5.js examples, you will see p5.Vector used to describe a\nposition, velocity, or acceleration. For example, if you consider a rectangle\nmoving across the screen, at any given instant it has a position (a vector\nthat points from the origin to its location), a velocity (the rate at which\nthe object's position changes per time unit, expressed as a vector), and\nacceleration (the rate at which the object's velocity changes per time\nunit, expressed as a vector).\n<br><br>\nSince vectors represent groupings of values, we cannot simply use\ntraditional addition/multiplication/etc. Instead, we'll need to do some\n"vector" math, which is made easy by the methods inside the p5.Vector class.</p>\n" 1330 }, 1331 "Calculation": { 1332 "name": "Calculation", 1333 "submodules": {}, 1334 "elements": {}, 1335 "classes": {}, 1336 "fors": { 1337 "p5": 1 1338 }, 1339 "is_submodule": 1, 1340 "namespaces": {}, 1341 "module": "Math", 1342 "namespace": "", 1343 "file": "src/math/calculation.js", 1344 "line": 1, 1345 "requires": [ 1346 "core" 1347 ] 1348 }, 1349 "Noise": { 1350 "name": "Noise", 1351 "submodules": {}, 1352 "elements": {}, 1353 "classes": {}, 1354 "fors": { 1355 "p5": 1 1356 }, 1357 "is_submodule": 1, 1358 "namespaces": {}, 1359 "module": "Math", 1360 "namespace": "", 1361 "file": "src/math/noise.js", 1362 "line": 14, 1363 "requires": [ 1364 "core" 1365 ] 1366 }, 1367 "Random": { 1368 "name": "Random", 1369 "submodules": {}, 1370 "elements": {}, 1371 "classes": {}, 1372 "fors": { 1373 "p5": 1 1374 }, 1375 "is_submodule": 1, 1376 "namespaces": {}, 1377 "module": "Math", 1378 "namespace": "", 1379 "file": "src/math/random.js", 1380 "line": 1, 1381 "requires": [ 1382 "core" 1383 ] 1384 }, 1385 "Trigonometry": { 1386 "name": "Trigonometry", 1387 "submodules": {}, 1388 "elements": {}, 1389 "classes": {}, 1390 "fors": { 1391 "p5": 1 1392 }, 1393 "is_submodule": 1, 1394 "namespaces": {}, 1395 "module": "Math", 1396 "namespace": "", 1397 "file": "src/math/trigonometry.js", 1398 "line": 1, 1399 "requires": [ 1400 "core", 1401 "constants" 1402 ] 1403 }, 1404 "Typography": { 1405 "name": "Typography", 1406 "submodules": { 1407 "Attributes": 1, 1408 "Loading & Displaying": 1, 1409 "Font": 1 1410 }, 1411 "elements": {}, 1412 "classes": { 1413 "p5.Font": 1 1414 }, 1415 "fors": { 1416 "p5": 1 1417 }, 1418 "namespaces": {}, 1419 "file": "src/typography/p5.Font.js", 1420 "line": 21 1421 }, 1422 "Font": { 1423 "name": "Font", 1424 "submodules": {}, 1425 "elements": {}, 1426 "classes": { 1427 "p5.Font": 1 1428 }, 1429 "fors": {}, 1430 "is_submodule": 1, 1431 "namespaces": {}, 1432 "module": "Typography", 1433 "namespace": "", 1434 "file": "src/typography/p5.Font.js", 1435 "line": 21, 1436 "description": "<p>This module defines the p5.Font class and functions for\ndrawing text to the display canvas.</p>\n", 1437 "requires": [ 1438 "core", 1439 "constants" 1440 ] 1441 }, 1442 "Array Functions": { 1443 "name": "Array Functions", 1444 "submodules": {}, 1445 "elements": {}, 1446 "classes": {}, 1447 "fors": {
1448 "p5": 1 1449 }, 1450 "is_submodule": 1, 1451 "namespaces": {}, 1452 "module": "Data", 1453 "namespace": "", 1454 "file": "src/utilities/array_functions.js", 1455 "line": 1, 1456 "requires": [ 1457 "core" 1458 ] 1459 }, 1460 "String Functions": { 1461 "name": "String Functions", 1462 "submodules": {}, 1463 "elements": {}, 1464 "classes": {}, 1465 "fors": { 1466 "p5": 1 1467 }, 1468 "is_submodule": 1, 1469 "namespaces": {}, 1470 "module": "Data", 1471 "namespace": "", 1472 "file": "src/utilities/string_functions.js", 1473 "line": 1, 1474 "requires": [ 1475 "core" 1476 ] 1477 }, 1478 "Time & Date": { 1479 "name": "Time & Date", 1480 "submodules": {}, 1481 "elements": {}, 1482 "classes": {}, 1483 "fors": { 1484 "p5": 1 1485 }, 1486 "is_submodule": 1, 1487 "namespaces": {}, 1488 "module": "IO", 1489 "namespace": "", 1490 "file": "src/utilities/time_date.js", 1491 "line": 1, 1492 "requires": [ 1493 "core" 1494 ] 1495 }, 1496 "Lights, Camera": { 1497 "name": "Lights, Camera", 1498 "submodules": { 1499 "Camera": 1, 1500 "Lights": 1, 1501 "Material": 1, 1502 "Shaders": 1 1503 }, 1504 "elements": {}, 1505 "classes": { 1506 "p5.Geometry": 1, 1507 "p5.Matrix": 1, 1508 "p5.Shader": 1, 1509 "p5.Texture": 1 1510 }, 1511 "fors": { 1512 "p5": 1 1513 }, 1514 "namespaces": {}, 1515 "file": "src/webgl/p5.Texture.js", 1516 "line": 13 1517 }, 1518 "Camera": { 1519 "name": "Camera", 1520 "submodules": {}, 1521 "elements": {}, 1522 "classes": {}, 1523 "fors": { 1524 "p5": 1 1525 }, 1526 "is_submodule": 1, 1527 "namespaces": {}, 1528 "module": "Lights, Camera", 1529 "namespace": "", 1530 "file": "src/webgl/camera.js", 1531 "line": 1, 1532 "requires": [ 1533 "core" 1534 ] 1535 }, 1536 "Lights": { 1537 "name": "Lights", 1538 "submodules": {}, 1539 "elements": {}, 1540 "classes": {}, 1541 "fors": { 1542 "p5": 1 1543 }, 1544 "is_submodule": 1, 1545 "namespaces": {}, 1546 "module": "Lights, Camera", 1547 "namespace": "", 1548 "file": "src/webgl/light.js", 1549 "line": 1, 1550 "requires": [ 1551 "core" 1552 ] 1553 }, 1554 "3D Models": { 1555 "name": "3D Models", 1556 "submodules": {}, 1557 "elements": {}, 1558 "classes": {}, 1559 "fors": { 1560 "p5": 1 1561 }, 1562 "is_submodule": 1, 1563 "namespaces": {}, 1564 "module": "Shape", 1565 "namespace": "", 1566 "file": "src/webgl/loading.js", 1567 "line": 1, 1568 "requires": [ 1569 "core", 1570 "p5.Geometry" 1571 ] 1572 }, 1573 "Material": { 1574 "name": "Material", 1575 "submodules": {}, 1576 "elements": {}, 1577 "classes": { 1578 "p5.Texture": 1 1579 }, 1580 "fors": { 1581 "p5": 1 1582 }, 1583 "is_submodule": 1, 1584 "namespaces": {}, 1585 "module": "Lights, Camera", 1586 "namespace": "", 1587 "file": "src/webgl/p5.Texture.js", 1588 "line": 13, 1589 "requires": [ 1590 "core" 1591 ], 1592 "description": "<p>This module defines the p5.Texture class</p>\n" 1593 }, 1594 "Shaders": { 1595 "name": "Shaders", 1596 "submodules": {}, 1597 "elements": {}, 1598 "classes": { 1599 "p5.Shader": 1 1600 }, 1601 "fors": {
1602 "p5": 1 1603 }, 1604 "is_submodule": 1, 1605 "namespaces": {}, 1606 "module": "Lights, Camera", 1607 "namespace": "", 1608 "file": "src/webgl/p5.Shader.js", 1609 "line": 13, 1610 "description": "<p>This module defines the p5.Shader class</p>\n", 1611 "requires": [ 1612 "core" 1613 ] 1614 }, 1615 "3D Primitives": { 1616 "name": "3D Primitives", 1617 "submodules": {}, 1618 "elements": {}, 1619 "classes": {}, 1620 "fors": { 1621 "p5": 1 1622 }, 1623 "is_submodule": 1, 1624 "namespaces": {}, 1625 "module": "Shape", 1626 "namespace": "", 1627 "file": "src/webgl/primitives.js", 1628 "line": 1, 1629 "requires": [ 1630 "core", 1631 "p5.Geometry" 1632 ] 1633 }, 1634 "p5.dom": { 1635 "name": "p5.dom", 1636 "submodules": {}, 1637 "elements": {}, 1638 "classes": { 1639 "p5.dom": 1, 1640 "p5.MediaElement": 1, 1641 "p5.File": 1 1642 }, 1643 "fors": { 1644 "p5.dom": 1, 1645 "p5.Element": 1 1646 }, 1647 "namespaces": {}, 1648 "module": "p5.dom", 1649 "file": "lib/addons/p5.dom.js", 1650 "line": 2885, 1651 "description": "<p><p>The web is much more than just canvas and p5.dom makes it easy to interact\nwith other HTML5 objects, including text, hyperlink, image, input, video,\naudio, and webcam.</p></p>\n<p><p>There is a set of creation methods, DOM manipulation methods, and\nan extended p5.Element that supports a range of HTML elements. See the\n<a href='https://github.com/processing/p5.js/wiki/Beyond-the-canvas'>\nbeyond the canvas tutorial</a> for a full overview of how this addon works.</p>\n<p><p>Methods and properties shown in black are part of the p5.js core, items in\nblue are part of the p5.dom library. You will need to include an extra file\nin order to access the blue functions. See the\n<a href='http://p5js.org/libraries/#using-a-library'>using a library</a>\nsection for information on how to include this library. p5.dom comes with\n<a href='http://p5js.org/download'>p5 complete</a> or you can download the single file\n<a href='https://raw.githubusercontent.com/lmccart/p5.js/master/lib/addons/p5.dom.js'>\nhere</a>.</p></p>\n<p><p>See <a href='https://github.com/processing/p5.js/wiki/Beyond-the-canvas'>tutorial: beyond the canvas</a>\nfor more info on how to use this libary.</a></p>\n", 1652 "tag": "main", 1653 "itemtype": "main" 1654 }, 1655 "p5.sound": { 1656 "name": "p5.sound", 1657 "submodules": {}, 1658 "elements": {}, 1659 "classes": { 1660 "p5.sound": 1, 1661 "p5.SoundFile": 1, 1662 "p5.Amplitude": 1, 1663 "p5.FFT": 1, 1664 "p5.Signal": 1, 1665 "p5.Oscillator": 1, 1666 "p5.SinOsc": 1, 1667 "p5.TriOsc": 1, 1668 "p5.SawOsc": 1, 1669 "p5.SqrOsc": 1, 1670 "p5.Env": 1, 1671 "p5.Pulse": 1, 1672 "p5.Noise": 1, 1673 "p5.AudioIn": 1, 1674 "p5.Effect": 1, 1675 "p5.Filter": 1, 1676 "p5.LowPass": 1, 1677 "p5.HighPass": 1, 1678 "p5.BandPass": 1, 1679 "p5.EQ": 1, 1680 "p5.Panner3D": 1, 1681 "p5.Delay": 1, 1682 "p5.Reverb": 1, 1683 "p5.Convolver": 1, 1684 "p5.Phrase": 1, 1685 "p5.Part": 1, 1686 "p5.Score": 1, 1687 "p5.SoundLoop": 1, 1688 "p5.Compressor": 1, 1689 "p5.SoundRecorder": 1, 1690 "p5.PeakDetect": 1, 1691 "p5.Gain": 1, 1692 "p5.AudioVoice": 1, 1693 "p5.MonoSynth": 1, 1694 "p5.PolySynth": 1, 1695 "p5.Distortion": 1 1696 }, 1697 "fors": { 1698 "p5.sound": 1, 1699 "p5": 1 1700 }, 1701 "namespaces": {}, 1702 "module": "p5.sound", 1703 "file": "lib/addons/p5.sound.js", 1704 "line": 12243, 1705 "description": "<p>p5.sound extends p5 with <a href=\"http://caniuse.com/audio-api\"\ntarget=\"_blank\">Web Audio</a> functionality including audio input,\nplayback, analysis and synthesis.\n<br/><br/>\n<a href=\"#/p5.SoundFile\"><b>p5.SoundFile</b></a>: Load and play sound files.<br/>\n<a href=\"#/p5.Amplitude\"><b>p5.Amplitude</b></a>: Get the current volume of a sound.<br/>\n<a href=\"#/p5.AudioIn\"><b>p5.AudioIn</b></a>: Get sound from an input source, typically\n a computer microphone.<br/>\n<a href=\"#/p5.FFT\"><b>p5.FFT</b></a>: Analyze the frequency of sound. Returns\n results from the frequency spectrum or time domain (waveform).<br/>\n<a href=\"#/p5.Oscillator\"><b>p5.Oscillator</b></a>: Generate Sine,\n Triangle, Square and Sawtooth waveforms. Base class of\n
1705<a href=\"#/p5.Noise\">p5.Noise</a> and <a href=\"#/p5.Pulse\">p5.Pulse</a>.\n <br/>\n<a href=\"#/p5.Env\"><b>p5.Env</b></a>: An Envelope is a series\n of fades over time. Often used to control an object's\n output gain level as an "ADSR Envelope" (Attack, Decay,\n Sustain, Release). Can also modulate other parameters.<br/>\n<a href=\"#/p5.Delay\"><b>p5.Delay</b></a>: A delay effect with\n parameters for feedback, delayTime, and lowpass filter.<br/>\n<a href=\"#/p5.Filter\"><b>p5.Filter</b></a>: Filter the frequency range of a\n sound.\n<br/>\n<a href=\"#/p5.Reverb\"><b>p5.Reverb</b></a>: Add reverb to a sound by specifying\n duration and decay. <br/>\n<b><a href=\"#/p5.Convolver\">p5.Convolver</a>:</b> Extends\n<a href=\"#/p5.Reverb\">p5.Reverb</a> to simulate the sound of real\n physical spaces through convolution.<br/>\n<b><a href=\"#/p5.SoundRecorder\">p5.SoundRecorder</a></b>: Record sound for playback\n / save the .wav file.\n<b><a href=\"#/p5.Phrase\">p5.Phrase</a></b>, <b><a href=\"#/p5.Part\">p5.Part</a></b> and\n<b><a href=\"#/p5.Score\">p5.Score</a></b>: Compose musical sequences.\n<br/><br/>\np5.sound is on <a href=\"https://github.com/therewasaguy/p5.sound/\">GitHub</a>.\nDownload the latest version\n<a href=\"https://github.com/therewasaguy/p5.sound/blob/master/lib/p5.sound.js\">here</a>.</p>\n", 1706 "tag": "main", 1707 "itemtype": "main" 1708 } 1709 }, 1710 "classes": { 1711 "p5": { 1712 "name": "p5", 1713 "shortname": "p5", 1714 "classitems": [], 1715 "plugins": [], 1716 "extensions": [], 1717 "plugin_for": [], 1718 "extension_for": [], 1719 "module": "IO", 1720 "submodule": "Output", 1721 "namespace": "", 1722 "file": "src/core/core.js", 1723 "line": 15, 1724 "description": "<p>This is the p5 instance constructor.</p>\n<p>A p5 instance holds all the properties and methods related to\na p5 sketch. It expects an incoming sketch closure and it can also\ntake an optional node parameter for attaching the generated p5 canvas\nto a node. The sketch closure takes the newly created p5 instance as\nits sole argument and may optionally set preload(), setup(), and/or\ndraw() properties on it for running a sketch.</p>\n<p>A p5 sketch can run in "global" or "instance" mode:\n"global" - all properties and methods are attached to the window\n"instance" - all properties and methods are bound to this p5 object</p>\n", 1725 "is_constructor": 1, 1726 "params": [ 1727 { 1728 "name": "sketch", 1729 "description": "<p>a closure that can set optional preload(),\n setup(), and/or draw() properties on the\n given p5 instance</p>\n", 1730 "type": "Function" 1731 }, 1732 { 1733 "name": "node", 1734 "description": "<p>element to attach canvas to, if a\n boolean is passed in use it as sync</p>\n", 1735 "type": "HTMLElement|Boolean", 1736 "optional": true 1737 }, 1738 { 1739 "name": "sync", 1740 "description": "<p>start synchronously (optional)</p>\n", 1741 "type": "Boolean", 1742 "optional": true 1743 } 1744 ], 1745 "return": { 1746 "description": "a p5 instance", 1747 "type": "P5" 1748 } 1749 }, 1750 "p5.Color": { 1751 "name": "p5.Color", 1752 "shortname": "p5.Color", 1753 "classitems": [], 1754 "plugins": [], 1755 "extensions": [], 1756 "plugin_for": [], 1757 "extension_for": [], 1758 "module": "Color", 1759 "submodule": "Creating & Reading", 1760 "namespace": "", 1761 "file": "src/color/p5.Color.js", 1762 "line": 16, 1763 "description": "<p>Each color stores the color mode and level maxes that applied at the\ntime of its construction. These are used to interpret the input arguments\n(at construction and later for that instance of color) and to format the\noutput e.g. when saturation() is requested.</p>\n<p>Internally we store an array representing the ideal RGBA values in floating\npoint form, normalized from 0 to 1. From this we calculate the closest\nscreen color (RGBA levels from 0 to 255) and expose this to the renderer.</p>\n<p>We also cache normalized, floating point components of the color in various\nrepresentations as they are calculated. This is done to prevent repeating a\nconversion that has already been performed.</p>\n" 1764 },
1765 "p5.Element": { 1766 "name": "p5.Element", 1767 "shortname": "p5.Element", 1768 "classitems": [], 1769 "plugins": [], 1770 "extensions": [], 1771 "plugin_for": [], 1772 "extension_for": [], 1773 "module": "DOM", 1774 "submodule": "DOM", 1775 "namespace": "", 1776 "file": "src/core/p5.Element.js", 1777 "line": 11, 1778 "description": "<p>Base class for all elements added to a sketch, including canvas,\ngraphics buffers, and other HTML elements. Methods in blue are\nincluded in the core functionality, methods in brown are added\nwith the <a href=\"http://p5js.org/reference/#/libraries/p5.dom\">p5.dom\nlibrary</a>.\nIt is not called directly, but p5.Element\nobjects are created by calling createCanvas, createGraphics,\nor in the p5.dom library, createDiv, createImg, createInput, etc.</p>\n", 1779 "params": [ 1780 { 1781 "name": "elt", 1782 "description": "<p>DOM node that is wrapped</p>\n", 1783 "type": "String" 1784 }, 1785 { 1786 "name": "pInst", 1787 "description": "<p>pointer to p5 instance</p>\n", 1788 "type": "P5", 1789 "optional": true 1790 } 1791 ] 1792 }, 1793 "p5.Graphics": { 1794 "name": "p5.Graphics", 1795 "shortname": "p5.Graphics", 1796 "classitems": [], 1797 "plugins": [], 1798 "extensions": [], 1799 "plugin_for": [], 1800 "extension_for": [], 1801 "module": "Rendering", 1802 "submodule": "Rendering", 1803 "namespace": "", 1804 "file": "src/core/p5.Graphics.js", 1805 "line": 12, 1806 "description": "<p>Thin wrapper around a renderer, to be used for creating a\ngraphics buffer object. Use this class if you need\nto draw into an off-screen graphics buffer. The two parameters define the\nwidth and height in pixels. The fields and methods for this class are\nextensive, but mirror the normal drawing API for p5.</p>\n", 1807 "extends": "p5.Element", 1808 "params": [ 1809 { 1810 "name": "w", 1811 "description": "<p>width</p>\n", 1812 "type": "Number" 1813 }, 1814 { 1815 "name": "h", 1816 "description": "<p>height</p>\n", 1817 "type": "Number" 1818 }, 1819 { 1820 "name": "renderer", 1821 "description": "<p>the renderer to use, either P2D or WEBGL</p>\n", 1822 "type": "Constant" 1823 }, 1824 { 1825 "name": "pInst", 1826 "description": "<p>pointer to p5 instance</p>\n", 1827 "type": "P5", 1828 "optional": true 1829 } 1830 ] 1831 }, 1832 "p5.Renderer": { 1833 "name": "p5.Renderer", 1834 "shortname": "p5.Renderer", 1835 "classitems": [], 1836 "plugins": [], 1837 "extensions": [], 1838 "plugin_for": [], 1839 "extension_for": [], 1840 "module": "Rendering", 1841 "submodule": "Rendering", 1842 "namespace": "", 1843 "file": "src/core/p5.Renderer.js", 1844 "line": 12, 1845 "description": "<p>Main graphics and rendering context, as well as the base API\nimplementation for p5.js "core". To be used as the superclass for\nRenderer2D and Renderer3D classes, respecitvely.</p>\n", 1846 "is_constructor": 1, 1847 "extends": "p5.Element", 1848 "params": [ 1849 { 1850 "name": "elt", 1851 "description": "<p>DOM node that is wrapped</p>\n", 1852 "type": "String" 1853 }, 1854 { 1855 "name": "pInst", 1856 "description": "<p>pointer to p5 instance</p>\n", 1857 "type": "P5", 1858 "optional": true 1859 }, 1860 { 1861 "name": "isMainCanvas", 1862 "description": "<p>whether we're using it as main canvas</p>\n", 1863 "type": "Boolean", 1864 "optional": true 1865 } 1866 ] 1867 },
1868 "p5.TypedDict": { 1869 "name": "p5.TypedDict", 1870 "shortname": "p5.TypedDict", 1871 "classitems": [], 1872 "plugins": [], 1873 "extensions": [], 1874 "plugin_for": [], 1875 "extension_for": [], 1876 "module": "Data", 1877 "submodule": "Dictionary", 1878 "namespace": "", 1879 "file": "src/data/p5.TypedDict.js", 1880 "line": 78, 1881 "description": "<p>Base class for all p5.Dictionary types. More specifically\n typed Dictionary objects inherit from this</p>\n" 1882 }, 1883 "p5.StringDict": { 1884 "name": "p5.StringDict", 1885 "shortname": "p5.StringDict", 1886 "classitems": [], 1887 "plugins": [], 1888 "extensions": [], 1889 "plugin_for": [], 1890 "extension_for": [], 1891 "module": "Data", 1892 "submodule": "Dictionary", 1893 "namespace": "", 1894 "file": "src/data/p5.TypedDict.js", 1895 "line": 387, 1896 "description": "<p>A Dictionary class for Strings.</p>\n", 1897 "extends": "p5.TypedDict" 1898 }, 1899 "p5.NumberDict": { 1900 "name": "p5.NumberDict", 1901 "shortname": "p5.NumberDict", 1902 "classitems": [], 1903 "plugins": [], 1904 "extensions": [], 1905 "plugin_for": [], 1906 "extension_for": [], 1907 "module": "Data", 1908 "submodule": "Dictionary", 1909 "namespace": "", 1910 "file": "src/data/p5.TypedDict.js", 1911 "line": 407, 1912 "description": "<p>A simple Dictionary class for Numbers.</p>\n", 1913 "extends": "p5.TypedDict" 1914 }, 1915 "p5.Image": { 1916 "name": "p5.Image", 1917 "shortname": "p5.Image", 1918 "classitems": [], 1919 "plugins": [], 1920 "extensions": [], 1921 "plugin_for": [], 1922 "extension_for": [], 1923 "module": "Image", 1924 "submodule": "Image", 1925 "namespace": "", 1926 "file": "src/image/p5.Image.js", 1927 "line": 23, 1928 "description": "<p>Creates a new p5.Image. A p5.Image is a canvas backed representation of an\nimage.\n<br><br>\np5 can display .gif, .jpg and .png images. Images may be displayed\nin 2D and 3D space. Before an image is used, it must be loaded with the\nloadImage() function. The p5.Image class contains fields for the width and\nheight of the image, as well as an array called pixels[] that contains the\nvalues for every pixel in the image.\n<br><br>\nThe methods described below allow easy access to the image's pixels and\nalpha channel and simplify the process of compositing.\n<br><br>\nBefore using the pixels[] array, be sure to use the loadPixels() method on\nthe image to make sure that the pixel data is properly loaded.</p>\n", 1929 "example": [ 1930 "\n<div><code>\nfunction setup() {\n var img = createImage(100, 100); // same as new p5.Image(100, 100);\n img.loadPixels();\n createCanvas(100, 100);\n background(0);\n\n // helper for writing color to array\n function writeColor(image, x, y, red, green, blue, alpha) {\n var index = (x + y * width) * 4;\n image.pixels[index] = red;\n image.pixels[index + 1] = green;\n image.pixels[index + 2] = blue;\n image.pixels[index + 3] = alpha;\n }\n\n var x, y;\n // fill with random colors\n for (y = 0; y < img.height; y++) {\n for (x = 0; x < img.width; x++) {\n var red = random(255);\n var green = random(255);\n var blue = random(255);\n var alpha = 255;\n writeColor(img, x, y, red, green, blue, alpha);\n }\n }\n\n // draw a red line\n y = 0;\n for (x = 0; x < img.width; x++) {\n writeColor(img, x, y, 255, 0, 0, 255);\n }\n\n // draw a green line\n y = img.height - 1;\n for (x = 0; x < img.width; x++) {\n writeColor(img, x, y, 0, 255, 0, 255);\n }\n\n img.updatePixels();\n image(img, 0, 0);\n}\n</code></div>" 1931 ], 1932 "params": [ 1933 { 1934 "name": "width", 1935 "description": "", 1936 "type": "Number" 1937 }, 1938 { 1939 "name": "height", 1940 "description": "", 1941 "type": "Number" 1942 } 1943 ] 1944 },
1945 "p5.PrintWriter": { 1946 "name": "p5.PrintWriter", 1947 "shortname": "p5.PrintWriter", 1948 "classitems": [], 1949 "plugins": [], 1950 "extensions": [], 1951 "plugin_for": [], 1952 "extension_for": [], 1953 "module": "IO", 1954 "submodule": "Output", 1955 "namespace": "", 1956 "file": "src/io/files.js", 1957 "line": 1169, 1958 "params": [ 1959 { 1960 "name": "filename", 1961 "description": "", 1962 "type": "String" 1963 }, 1964 { 1965 "name": "extension", 1966 "description": "", 1967 "type": "String", 1968 "optional": true 1969 } 1970 ] 1971 }, 1972 "p5.Table": { 1973 "name": "p5.Table", 1974 "shortname": "p5.Table", 1975 "classitems": [], 1976 "plugins": [], 1977 "extensions": [], 1978 "plugin_for": [], 1979 "extension_for": [], 1980 "module": "IO", 1981 "submodule": "Table", 1982 "namespace": "", 1983 "file": "src/io/p5.Table.js", 1984 "line": 35, 1985 "description": "<p>Table objects store data with multiple rows and columns, much\nlike in a traditional spreadsheet. Tables can be generated from\nscratch, dynamically, or using data from an existing file.</p>\n", 1986 "is_constructor": 1, 1987 "params": [ 1988 { 1989 "name": "rows", 1990 "description": "<p>An array of p5.TableRow objects</p>\n", 1991 "type": "p5.TableRow[]", 1992 "optional": true 1993 } 1994 ] 1995 }, 1996 "p5.TableRow": { 1997 "name": "p5.TableRow", 1998 "shortname": "p5.TableRow", 1999 "classitems": [], 2000 "plugins": [], 2001 "extensions": [], 2002 "plugin_for": [], 2003 "extension_for": [], 2004 "module": "IO", 2005 "submodule": "Table", 2006 "namespace": "", 2007 "file": "src/io/p5.TableRow.js", 2008 "line": 11, 2009 "description": "<p>A TableRow object represents a single row of data values,\nstored in columns, from a table.</p>\n<p>A Table Row contains both an ordered array, and an unordered\nJSON object.</p>\n", 2010 "is_constructor": 1, 2011 "params": [ 2012 { 2013 "name": "str", 2014 "description": "<p>optional: populate the row with a\n string of values, separated by the\n separator</p>\n", 2015 "type": "String", 2016 "optional": true 2017 }, 2018 { 2019 "name": "separator", 2020 "description": "<p>comma separated values (csv) by default</p>\n", 2021 "type": "String", 2022 "optional": true 2023 } 2024 ] 2025 }, 2026 "p5.XML": { 2027 "name": "p5.XML", 2028 "shortname": "p5.XML", 2029 "classitems": [], 2030 "plugins": [], 2031 "extensions": [], 2032 "plugin_for": [], 2033 "extension_for": [], 2034 "module": "IO", 2035 "submodule": "XML", 2036 "namespace": "", 2037 "file": "src/io/p5.XML.js", 2038 "line": 11, 2039 "description": "<p>XML is a representation of an XML object, able to parse XML code. Use\nloadXML() to load external XML files and create XML objects.</p>\n", 2040 "is_constructor": 1, 2041 "example": [ 2042 "\n<div class='norender'><code>\n// The following short XML file called \"mammals.xml\" is parsed\n// in the code below.\n//\n// <?xml version=\"1.0\"?>\n// <mammals>\n// <animal id=\"0\" species=\"Capra hircus\">Goat</animal>\n// <animal id=\"1\" species=\"Panthera pardus\">Leopard</animal>\n// <animal id=\"2\" species=\"Equus zebra\">Zebra</animal>\n// </mammals>\n\nvar xml;\n\nfunction preload() {\n xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n var children = xml.getChildren('animal');\n\n for (var i = 0; i < children.length;
2042 i++) {\n var id = children[i].getNum('id');\n var coloring = children[i].getString('species');\n var name = children[i].getContent();\n print(id + ', ' + coloring + ', ' + name);\n }\n}\n\n// Sketch prints:\n// 0, Capra hircus, Goat\n// 1, Panthera pardus, Leopard\n// 2, Equus zebra, Zebra\n</code></div>" 2043 ], 2044 "alt": "no image displayed" 2045 }, 2046 "p5.Vector": { 2047 "name": "p5.Vector", 2048 "shortname": "p5.Vector", 2049 "classitems": [], 2050 "plugins": [], 2051 "extensions": [], 2052 "plugin_for": [], 2053 "extension_for": [], 2054 "module": "Math", 2055 "submodule": "Math", 2056 "namespace": "", 2057 "file": "src/math/p5.Vector.js", 2058 "line": 12, 2059 "description": "<p>A class to describe a two or three dimensional vector, specifically\na Euclidean (also known as geometric) vector. A vector is an entity\nthat has both magnitude and direction. The datatype, however, stores\nthe components of the vector (x, y for 2D, and x, y, z for 3D). The magnitude\nand direction can be accessed via the methods mag() and heading().\n<br><br>\nIn many of the p5.js examples, you will see p5.Vector used to describe a\nposition, velocity, or acceleration. For example, if you consider a rectangle\nmoving across the screen, at any given instant it has a position (a vector\nthat points from the origin to its location), a velocity (the rate at which\nthe object's position changes per time unit, expressed as a vector), and\nacceleration (the rate at which the object's velocity changes per time\nunit, expressed as a vector).\n<br><br>\nSince vectors represent groupings of values, we cannot simply use\ntraditional addition/multiplication/etc. Instead, we'll need to do some\n"vector" math, which is made easy by the methods inside the p5.Vector class.</p>\n", 2060 "params": [ 2061 { 2062 "name": "x", 2063 "description": "<p>x component of the vector</p>\n", 2064 "type": "Number", 2065 "optional": true 2066 }, 2067 { 2068 "name": "y", 2069 "description": "<p>y component of the vector</p>\n", 2070 "type": "Number", 2071 "optional": true 2072 }, 2073 { 2074 "name": "z", 2075 "description": "<p>z component of the vector</p>\n", 2076 "type": "Number", 2077 "optional": true 2078 } 2079 ], 2080 "example": [ 2081 "\n<div>\n<code>\nvar v1 = createVector(40, 50);\nvar v2 = createVector(40, 50);\n\nellipse(v1.x, v1.y, 50, 50);\nellipse(v2.x, v2.y, 50, 50);\nv1.add(v2);\nellipse(v1.x, v1.y, 50, 50);\n</code>\n</div>" 2082 ], 2083 "alt": "2 white ellipses. One center-left the other bottom right and off canvas" 2084 }, 2085 "p5.Font": { 2086 "name": "p5.Font", 2087 "shortname": "p5.Font", 2088 "classitems": [], 2089 "plugins": [], 2090 "extensions": [], 2091 "plugin_for": [], 2092 "extension_for": [], 2093 "module": "Typography", 2094 "submodule": "Font", 2095 "namespace": "", 2096 "file": "src/typography/p5.Font.js", 2097 "line": 21, 2098 "description": "<p>Base class for font handling</p>\n", 2099 "params": [ 2100 { 2101 "name": "pInst", 2102 "description": "<p>pointer to p5 instance</p>\n", 2103 "type": "P5", 2104 "optional": true 2105 } 2106 ] 2107 }, 2108 "p5.Geometry": { 2109 "name": "p5.Geometry", 2110 "shortname": "p5.Geometry", 2111 "classitems": [], 2112 "plugins": [], 2113 "extensions": [], 2114 "plugin_for": [], 2115 "extension_for": [], 2116 "module": "Lights, Camera", 2117 "namespace": "", 2118 "file": "src/webgl/p5.Geometry.js", 2119 "line": 6, 2120 "description": "<p>p5 Geometry class</p>\n", 2121 "is_constructor": 1, 2122 "params": [ 2123 { 2124 "name": "vertData", 2125 "description": "<p>callback function or Object\n containing routine(s) for vertex data generation</p>\n", 2126 "type": "Function | Object" 2127 }, 2128 { 2129 "name": "detailX", 2130 "description": "<p>number of vertices on horizontal surface</p>\n", 2131 "type": "Integer", 2132 "optional": true 2133 }, 2134 { 2135 "name": "detailY", 2136 "description": "<p>number of vertices on horizontal surface</p>\n", 2137 "type": "Integer", 2138 "optional": true 2139 }, 2140 { 2141 "name": "callback", 2142 "description": "<p>function to call upon object instantiation.</p>\n", 2143 "type": "Function", 2144 "optional": true 2145 } 2146 ] 2147 },
2148 "p5.Shader": { 2149 "name": "p5.Shader", 2150 "shortname": "p5.Shader", 2151 "classitems": [], 2152 "plugins": [], 2153 "extensions": [], 2154 "plugin_for": [], 2155 "extension_for": [], 2156 "module": "Lights, Camera", 2157 "submodule": "Shaders", 2158 "namespace": "", 2159 "file": "src/webgl/p5.Shader.js", 2160 "line": 13, 2161 "description": "<p>Shader class for WEBGL Mode</p>\n", 2162 "params": [ 2163 { 2164 "name": "renderer", 2165 "description": "<p>an instance of p5.RendererGL that\nwill provide the GL context for this new p5.Shader</p>\n", 2166 "type": "p5.RendererGL" 2167 }, 2168 { 2169 "name": "vertSrc", 2170 "description": "<p>source code for the vertex shader (as a string)</p>\n", 2171 "type": "String" 2172 }, 2173 { 2174 "name": "fragSrc", 2175 "description": "<p>source code for the fragment shader (as a string)</p>\n", 2176 "type": "String" 2177 } 2178 ] 2179 }, 2180 "p5.dom": { 2181 "name": "p5.dom", 2182 "shortname": "p5.dom", 2183 "classitems": [], 2184 "plugins": [], 2185 "extensions": [], 2186 "plugin_for": [], 2187 "extension_for": [], 2188 "module": "p5.dom", 2189 "submodule": "p5.dom", 2190 "namespace": "" 2191 }, 2192 "p5.MediaElement": { 2193 "name": "p5.MediaElement", 2194 "shortname": "p5.MediaElement", 2195 "classitems": [], 2196 "plugins": [], 2197 "extensions": [], 2198 "plugin_for": [], 2199 "extension_for": [], 2200 "module": "p5.dom", 2201 "submodule": "p5.dom", 2202 "namespace": "", 2203 "file": "lib/addons/p5.dom.js", 2204 "line": 1829, 2205 "description": "<p>Extends p5.Element to handle audio and video. In addition to the methods\nof p5.Element, it also contains methods for controlling media. It is not\ncalled directly, but p5.MediaElements are created by calling createVideo,\ncreateAudio, and createCapture.</p>\n", 2206 "is_constructor": 1, 2207 "params": [ 2208 { 2209 "name": "elt", 2210 "description": "<p>DOM node that is wrapped</p>\n", 2211 "type": "String" 2212 } 2213 ] 2214 }, 2215 "p5.File": { 2216 "name": "p5.File", 2217 "shortname": "p5.File", 2218 "classitems": [], 2219 "plugins": [], 2220 "extensions": [], 2221 "plugin_for": [], 2222 "extension_for": [], 2223 "module": "p5.dom", 2224 "submodule": "p5.dom", 2225 "namespace": "", 2226 "file": "lib/addons/p5.dom.js", 2227 "line": 2885, 2228 "description": "<p>Base class for a file\nUsing this for createFileInput</p>\n", 2229 "is_constructor": 1, 2230 "params": [ 2231 { 2232 "name": "file", 2233 "description": "<p>File that is wrapped</p>\n", 2234 "type": "File" 2235 } 2236 ] 2237 }, 2238 "p5.sound": { 2239 "name": "p5.sound", 2240 "shortname": "p5.sound", 2241 "classitems": [], 2242 "plugins": [], 2243 "extensions": [], 2244 "plugin_for": [], 2245 "extension_for": [], 2246 "module": "p5.sound", 2247 "submodule": "p5.sound", 2248 "namespace": "" 2249 }, 2250 "p5.SoundFile": { 2251 "name": "p5.SoundFile", 2252 "shortname": "p5.SoundFile", 2253 "classitems": [], 2254 "plugins": [], 2255 "extensions": [], 2256 "plugin_for": [], 2257 "extension_for": [], 2258 "module": "p5.sound", 2259 "submodule": "p5.sound", 2260 "namespace": "", 2261 "file": "lib/addons/p5.sound.js", 2262 "line": 740, 2263 "description": "<p>SoundFile object with a path to a file.</p>\n\n<p>The p5.SoundFile may not be available immediately because\nit loads the file information asynchronously.</p>\n\n<p>To do something with the sound as soon as it loads\npass the name of a function as the second parameter.</p>\n\n<p>Only one file path is required. However, audio file formats\n(i.e. mp3, ogg, wav and m4a/aac) are not supported by all\nweb browsers. If you want to ensure compatability, instead of a single\nfile path, you may include an Array of filepaths, and the browser will\nchoose a format that works.</p>", 2264 "is_constructor": 1, 2265 "params": [ 2266 { 2267 "name": "path", 2268 "description": "<p>path to a sound file (String). Optionally,\n you may include multiple file formats in\n an array. Alternately, accepts an object\n from the HTML5 File API, or a p5.File.</p>\n", 2269 "type": "String|Array" 2270 }, 2271 { 2272 "name": "successCallback", 2273 "description": "<p>Name of a function to call once file loads</p>\n", 2274 "type": "Function", 2275 "optional": true 2276 }, 2277 { 2278 "name": "errorCallback", 2279 "description": "<p>Name of a function to call if file fails to\n load. This function will receive an error or\n XMLHttpRequest object with information\n about what went wrong.</p>\n", 2280 "type": "Function", 2281 "optional": true 2282 }, 2283 { 2284 "name": "whileLoadingCallback", 2285 "description": "<p>Name of a function to call while file\n is loading. That function will\n receive progress of the request to\n load the sound file\n (between 0 and 1) as its first\n parameter. This progress\n does not account for the additional\n time needed to decode the audio data.</p>\n", 2286 "type": "Function", 2287 "optional": true 2288 } 2289 ], 2290 "example": [ 2291 "\n<div><code>\n\nfunction preload() {\n soundFormats('mp3', 'ogg');\n mySound = loadSound('assets/doorbell.mp3');\n}\n\nfunction setup() {\n mySound.setVolume(0.1);\n mySound.play();\n}\n\n </code></div>" 2292 ] 2293 },
2294 "p5.Amplitude": { 2295 "name": "p5.Amplitude", 2296 "shortname": "p5.Amplitude", 2297 "classitems": [], 2298 "plugins": [], 2299 "extensions": [], 2300 "plugin_for": [], 2301 "extension_for": [], 2302 "module": "p5.sound", 2303 "submodule": "p5.sound", 2304 "namespace": "", 2305 "file": "lib/addons/p5.sound.js", 2306 "line": 2154, 2307 "description": "<p>Amplitude measures volume between 0.0 and 1.0.\nListens to all p5sound by default, or use setInput()\nto listen to a specific sound source. Accepts an optional\nsmoothing value, which defaults to 0.</p>\n", 2308 "is_constructor": 1, 2309 "params": [ 2310 { 2311 "name": "smoothing", 2312 "description": "<p>between 0.0 and .999 to smooth\n amplitude readings (defaults to 0)</p>\n", 2313 "type": "Number", 2314 "optional": true 2315 } 2316 ], 2317 "example": [ 2318 "\n<div><code>\nvar sound, amplitude, cnv;\n\nfunction preload(){\n sound = loadSound('assets/beat.mp3');\n}\nfunction setup() {\n cnv = createCanvas(100,100);\n amplitude = new p5.Amplitude();\n\n // start / stop the sound when canvas is clicked\n cnv.mouseClicked(function() {\n if (sound.isPlaying() ){\n sound.stop();\n } else {\n sound.play();\n }\n });\n}\nfunction draw() {\n background(0);\n fill(255);\n var level = amplitude.getLevel();\n var size = map(level, 0, 1, 0, 200);\n ellipse(width/2, height/2, size, size);\n}\n\n</code></div>" 2319 ] 2320 }, 2321 "p5.FFT": { 2322 "name": "p5.FFT", 2323 "shortname": "p5.FFT", 2324 "classitems": [], 2325 "plugins": [], 2326 "extensions": [], 2327 "plugin_for": [], 2328 "extension_for": [], 2329 "module": "p5.sound", 2330 "submodule": "p5.sound", 2331 "namespace": "", 2332 "file": "lib/addons/p5.sound.js", 2333 "line": 2426, 2334 "description": "<p>FFT (Fast Fourier Transform) is an analysis algorithm that\nisolates individual\n<a href=\"https://en.wikipedia.org/wiki/Audio_frequency\">\naudio frequencies</a> within a waveform.</p>\n\n<p>Once instantiated, a p5.FFT object can return an array based on\ntwo types of analyses: <br> ⢠<code>FFT.waveform()</code> computes\namplitude values along the time domain. The array indices correspond\nto samples across a brief moment in time. Each value represents\namplitude of the waveform at that sample of time.<br>\n⢠<code>FFT.analyze() </code> computes amplitude values along the\nfrequency domain. The array indices correspond to frequencies (i.e.\npitches), from the lowest to the highest that humans can hear. Each\nvalue represents amplitude at that slice of the frequency spectrum.\nUse with <code>getEnergy()</code> to measure amplitude at specific\nfrequencies, or within a range of frequencies. </p>\n\n<p>FFT analyzes a very short snapshot of sound called a sample\nbuffer. It returns an array of amplitude measurements, referred\nto as <code>bins</code>. The array is 1024 bins long by default.\nYou can change the bin array length, but it must be a power of 2\nbetween 16 and 1024 in order for the FFT algorithm to function\ncorrectly. The actual size of the FFT buffer is twice the\nnumber of bins, so given a standard sample rate, the buffer is\n2048/44100 seconds long.</p>", 2335 "is_constructor": 1, 2336 "params": [ 2337 { 2338 "name": "smoothing", 2339 "description": "<p>Smooth results of Freq Spectrum.\n 0.0 < smoothing < 1.0.\n Defaults to 0.8.</p>\n", 2340 "type": "Number", 2341 "optional": true 2342 }, 2343 { 2344 "name": "bins", 2345 "description": "<p>Length of resulting array.\n Must be a power of two between\n 16 and 1024. Defaults to 1024.</p>\n", 2346 "type": "Number", 2347 "optional": true 2348 } 2349 ], 2350 "example": [ 2351 "\n<div><code>\nfunction preload(){\n sound = loadSound('assets/Damscray_DancingTiger.mp3');\n}\n\nfunction setup(){\n var cnv = createCanvas(100,100);\n cnv.mouseClicked(togglePlay);\n fft = new p5.FFT();\n sound.amp(0.2);\n}\n\nfunction draw(){\n background(0);\n\n var spectrum = fft.analyze();\n noStroke();\n fill(0,255,0); // spectrum is green\n for (var i = 0; i< spectrum.length; i++){\n var x = map(i, 0, spectrum.length, 0, width);\n var h = -height + map(spectrum[i], 0, 255, height, 0);\n rect(x, height, width / spectrum.length, h )\n }\n\n var waveform = fft.waveform();\n noFill();\n beginShape();\n stroke(255,0,0); // waveform is red\n strokeWeight(1);\n for (var i = 0; i< waveform.length; i++){\n var x = map(i, 0, waveform.length, 0, width);\n var y = map( waveform[i], -1, 1, 0, height);\n vertex(x,y);\n }\n endShape();\n\n text('click to play/pause', 4, 10);\n}\n\n// fade sound if mouse is over canvas\nfunction togglePlay() {\n if (sound.isPlaying()) {\n sound.pause();\n } else {\n sound.loop();\n }\n}\n</code></div>" 2352 ] 2353 },
2354 "p5.Signal": { 2355 "name": "p5.Signal", 2356 "shortname": "p5.Signal", 2357 "classitems": [], 2358 "plugins": [], 2359 "extensions": [], 2360 "plugin_for": [], 2361 "extension_for": [], 2362 "module": "p5.sound", 2363 "submodule": "p5.sound", 2364 "namespace": "", 2365 "file": "lib/addons/p5.sound.js", 2366 "line": 4828, 2367 "description": "<p>p5.Signal is a constant audio-rate signal used by p5.Oscillator\nand p5.Envelope for modulation math.</p>\n\n<p>This is necessary because Web Audio is processed on a seprate clock.\nFor example, the p5 draw loop runs about 60 times per second. But\nthe audio clock must process samples 44100 times per second. If we\nwant to add a value to each of those samples, we can't do it in the\ndraw loop, but we can do it by adding a constant-rate audio signal.</p.\n\n<p>This class mostly functions behind the scenes in p5.sound, and returns\na Tone.Signal from the Tone.js library by Yotam Mann.\nIf you want to work directly with audio signals for modular\nsynthesis, check out\n<a href='http://bit.ly/1oIoEng' target=_'blank'>tone.js.</a></p>", 2368 "is_constructor": 1, 2369 "return": { 2370 "description": "A Signal object from the Tone.js library", 2371 "type": "Tone.Signal" 2372 }, 2373 "example": [ 2374 "\n<div><code>\nfunction setup() {\n carrier = new p5.Oscillator('sine');\n carrier.amp(1); // set amplitude\n carrier.freq(220); // set frequency\n carrier.start(); // start oscillating\n\n modulator = new p5.Oscillator('sawtooth');\n modulator.disconnect();\n modulator.amp(1);\n modulator.freq(4);\n modulator.start();\n\n // Modulator's default amplitude range is -1 to 1.\n // Multiply it by -200, so the range is -200 to 200\n // then add 220 so the range is 20 to 420\n carrier.freq( modulator.mult(-200).add(220) );\n}\n</code></div>" 2375 ] 2376 }, 2377 "p5.Oscillator": { 2378 "name": "p5.Oscillator", 2379 "shortname": "p5.Oscillator", 2380 "classitems": [], 2381 "plugins": [], 2382 "extensions": [], 2383 "plugin_for": [], 2384 "extension_for": [], 2385 "module": "p5.sound", 2386 "submodule": "p5.sound", 2387 "namespace": "", 2388 "file": "lib/addons/p5.sound.js", 2389 "line": 4974, 2390 "description": "<p>Creates a signal that oscillates between -1.0 and 1.0.\nBy default, the oscillation takes the form of a sinusoidal\nshape ('sine'). Additional types include 'triangle',\n'sawtooth' and 'square'. The frequency defaults to\n440 oscillations per second (440Hz, equal to the pitch of an\n'A' note).</p>\n\n<p>Set the type of oscillation with setType(), or by instantiating a\nspecific oscillator: <a href=\"/reference/#/p5.SinOsc\">p5.SinOsc</a>, <a\nhref=\"/reference/#/p5.TriOsc\">p5.TriOsc</a>, <a\nhref=\"/reference/#/p5.SqrOsc\">p5.SqrOsc</a>, or <a\nhref=\"/reference/#/p5.SawOsc\">p5.SawOsc</a>.\n</p>", 2391 "is_constructor": 1, 2392 "params": [ 2393 { 2394 "name": "freq", 2395 "description": "<p>frequency defaults to 440Hz</p>\n", 2396 "type": "Number", 2397 "optional": true 2398 }, 2399 { 2400 "name": "type", 2401 "description": "<p>type of oscillator. Options:\n 'sine' (default), 'triangle',\n 'sawtooth', 'square'</p>\n", 2402 "type": "String", 2403 "optional": true 2404 } 2405 ], 2406 "example": [ 2407 "\n<div><code>\nvar osc;\nvar playing = false;\n\nfunction setup() {\n backgroundColor = color(255,0,255);\n textAlign(CENTER);\n\n osc = new p5.Oscillator();\n osc.setType('sine');\n osc.freq(240);\n osc.amp(0);\n osc.start();\n}\n\nfunction draw() {\n background(backgroundColor)\n text('click to play', width/2, height/2);\n}\n\nfunction mouseClicked() {\n if (mouseX > 0 && mouseX < width && mouseY < height && mouseY > 0) {\n if (!playing) {\n // ramp amplitude to 0.5 over 0.05 seconds\n osc.amp(0.5, 0.05);\n playing = true;\n backgroundColor = color(0,255,255);\n } else {\n // ramp amplitude to 0 over 0.5 seconds\n osc.amp(0, 0.5);\n playing = false;\n backgroundColor = color(255,0,255);\n }\n }\n}\n</code> </div>" 2408 ] 2409 },
2410 "p5.SinOsc": { 2411 "name": "p5.SinOsc", 2412 "shortname": "p5.SinOsc", 2413 "classitems": [], 2414 "plugins": [], 2415 "extensions": [], 2416 "plugin_for": [], 2417 "extension_for": [], 2418 "module": "p5.sound", 2419 "submodule": "p5.sound", 2420 "namespace": "", 2421 "file": "lib/addons/p5.sound.js", 2422 "line": 5409, 2423 "description": "<p>Constructor: <code>new p5.SinOsc()</code>.\nThis creates a Sine Wave Oscillator and is\nequivalent to <code> new p5.Oscillator('sine')\n</code> or creating a p5.Oscillator and then calling\nits method <code>setType('sine')</code>.\nSee p5.Oscillator for methods.</p>\n", 2424 "is_constructor": 1, 2425 "extends": "p5.Oscillator", 2426 "params": [ 2427 { 2428 "name": "freq", 2429 "description": "<p>Set the frequency</p>\n", 2430 "type": "Number", 2431 "optional": true 2432 } 2433 ] 2434 }, 2435 "p5.TriOsc": { 2436 "name": "p5.TriOsc", 2437 "shortname": "p5.TriOsc", 2438 "classitems": [], 2439 "plugins": [], 2440 "extensions": [], 2441 "plugin_for": [], 2442 "extension_for": [], 2443 "module": "p5.sound", 2444 "submodule": "p5.sound", 2445 "namespace": "", 2446 "file": "lib/addons/p5.sound.js", 2447 "line": 5426, 2448 "description": "<p>Constructor: <code>new p5.TriOsc()</code>.\nThis creates a Triangle Wave Oscillator and is\nequivalent to <code>new p5.Oscillator('triangle')\n</code> or creating a p5.Oscillator and then calling\nits method <code>setType('triangle')</code>.\nSee p5.Oscillator for methods.</p>\n", 2449 "is_constructor": 1, 2450 "extends": "p5.Oscillator", 2451 "params": [ 2452 { 2453 "name": "freq", 2454 "description": "<p>Set the frequency</p>\n", 2455 "type": "Number", 2456 "optional": true 2457 } 2458 ] 2459 }, 2460 "p5.SawOsc": { 2461 "name": "p5.SawOsc", 2462 "shortname": "p5.SawOsc", 2463 "classitems": [], 2464 "plugins": [], 2465 "extensions": [], 2466 "plugin_for": [], 2467 "extension_for": [], 2468 "module": "p5.sound", 2469 "submodule": "p5.sound", 2470 "namespace": "", 2471 "file": "lib/addons/p5.sound.js", 2472 "line": 5443, 2473 "description": "<p>Constructor: <code>new p5.SawOsc()</code>.\nThis creates a SawTooth Wave Oscillator and is\nequivalent to <code> new p5.Oscillator('sawtooth')\n</code> or creating a p5.Oscillator and then calling\nits method <code>setType('sawtooth')</code>.\nSee p5.Oscillator for methods.</p>\n", 2474 "is_constructor": 1, 2475 "extends": "p5.Oscillator", 2476 "params": [ 2477 { 2478 "name": "freq", 2479 "description": "<p>Set the frequency</p>\n", 2480 "type": "Number", 2481 "optional": true 2482 } 2483 ] 2484 }, 2485 "p5.SqrOsc": { 2486 "name": "p5.SqrOsc", 2487 "shortname": "p5.SqrOsc", 2488 "classitems": [], 2489 "plugins": [], 2490 "extensions": [], 2491 "plugin_for": [], 2492 "extension_for": [], 2493 "module": "p5.sound", 2494 "submodule": "p5.sound", 2495 "namespace": "", 2496 "file": "lib/addons/p5.sound.js", 2497 "line": 5460, 2498 "description": "<p>Constructor: <code>new p5.SqrOsc()</code>.\nThis creates a Square Wave Oscillator and is\nequivalent to <code> new p5.Oscillator('square')\n</code> or creating a p5.Oscillator and then calling\nits method <code>setType('square')</code>.\nSee p5.Oscillator for methods.</p>\n", 2499 "is_constructor": 1, 2500 "extends": "p5.Oscillator", 2501 "params": [ 2502 { 2503 "name": "freq", 2504 "description": "<p>Set the frequency</p>\n", 2505 "type": "Number", 2506 "optional": true 2507 } 2508 ] 2509 },
2510 "p5.Env": { 2511 "name": "p5.Env", 2512 "shortname": "p5.Env", 2513 "classitems": [], 2514 "plugins": [], 2515 "extensions": [], 2516 "plugin_for": [], 2517 "extension_for": [], 2518 "module": "p5.sound", 2519 "submodule": "p5.sound", 2520 "namespace": "", 2521 "file": "lib/addons/p5.sound.js", 2522 "line": 5917, 2523 "description": "<p>Envelopes are pre-defined amplitude distribution over time.\nTypically, envelopes are used to control the output volume\nof an object, a series of fades referred to as Attack, Decay,\nSustain and Release (\n<a href=\"https://upload.wikimedia.org/wikipedia/commons/e/ea/ADSR_parameter.svg\">ADSR</a>\n). Envelopes can also control other Web Audio Parametersâfor example, a p5.Env can\ncontrol an Oscillator's frequency like this: <code>osc.freq(env)</code>.</p>\n<p>Use <code><a href=\"#/p5.Env/setRange\">setRange</a></code> to change the attack/release level.\nUse <code><a href=\"#/p5.Env/setADSR\">setADSR</a></code> to change attackTime, decayTime, sustainPercent and releaseTime.</p>\n<p>Use the <code><a href=\"#/p5.Env/play\">play</a></code> method to play the entire envelope,\nthe <code><a href=\"#/p5.Env/ramp\">ramp</a></code> method for a pingable trigger,\nor <code><a href=\"#/p5.Env/triggerAttack\">triggerAttack</a></code>/\n<code><a href=\"#/p5.Env/triggerRelease\">triggerRelease</a></code> to trigger noteOn/noteOff.</p>", 2524 "is_constructor": 1, 2525 "example": [ 2526 "\n<div><code>\nvar attackLevel = 1.0;\nvar releaseLevel = 0;\n\nvar attackTime = 0.001\nvar decayTime = 0.2;\nvar susPercent = 0.2;\nvar releaseTime = 0.5;\n\nvar env, triOsc;\n\nfunction setup() {\n var cnv = createCanvas(100, 100);\n\n textAlign(CENTER);\n text('click to play', width/2, height/2);\n\n env = new p5.Env();\n env.setADSR(attackTime, decayTime, susPercent, releaseTime);\n env.setRange(attackLevel, releaseLevel);\n\n triOsc = new p5.Oscillator('triangle');\n triOsc.amp(env);\n triOsc.start();\n triOsc.freq(220);\n\n cnv.mousePressed(playEnv);\n}\n\nfunction playEnv(){\n env.play();\n}\n</code></div>" 2527 ] 2528 }, 2529 "p5.Pulse": { 2530 "name": "p5.Pulse", 2531 "shortname": "p5.Pulse", 2532 "classitems": [], 2533 "plugins": [], 2534 "extensions": [], 2535 "plugin_for": [], 2536 "extension_for": [], 2537 "module": "p5.sound", 2538 "submodule": "p5.sound", 2539 "namespace": "", 2540 "file": "lib/addons/p5.sound.js", 2541 "line": 6709, 2542 "description": "<p>Creates a Pulse object, an oscillator that implements\nPulse Width Modulation.\nThe pulse is created with two oscillators.\nAccepts a parameter for frequency, and to set the\nwidth between the pulses. See <a href=\"\nhttp://p5js.org/reference/#/p5.Oscillator\">\n<code>p5.Oscillator</code> for a full list of methods.</p>\n", 2543 "extends": "p5.Oscillator", 2544 "is_constructor": 1, 2545 "params": [ 2546 { 2547 "name": "freq", 2548 "description": "<p>Frequency in oscillations per second (Hz)</p>\n", 2549 "type": "Number", 2550 "optional": true 2551 }, 2552 { 2553 "name": "w", 2554 "description": "<p>Width between the pulses (0 to 1.0,\n defaults to 0)</p>\n", 2555 "type": "Number", 2556 "optional": true 2557 } 2558 ], 2559 "example": [ 2560 "\n<div><code>\nvar pulse;\nfunction setup() {\n background(0);\n\n // Create and start the pulse wave oscillator\n pulse = new p5.Pulse();\n pulse.amp(0.5);\n pulse.freq(220);\n pulse.start();\n}\n\nfunction draw() {\n var w = map(mouseX, 0, width, 0, 1);\n w = constrain(w, 0, 1);\n pulse.width(w)\n}\n</code></div>" 2561 ] 2562 }, 2563 "p5.Noise": { 2564 "name": "p5.Noise", 2565 "shortname": "p5.Noise", 2566 "classitems": [], 2567 "plugins": [], 2568 "extensions": [], 2569 "plugin_for": [], 2570 "extension_for": [], 2571 "module": "p5.sound", 2572 "submodule": "p5.sound", 2573 "namespace": "", 2574 "file": "lib/addons/p5.sound.js", 2575 "line": 6886, 2576 "description": "<p>Noise is a type of oscillator that generates a buffer with random values.</p>\n", 2577 "extends": "p5.Oscillator", 2578 "is_constructor": 1, 2579 "params": [ 2580 { 2581 "name": "type", 2582 "description": "<p>Type of noise can be 'white' (default),\n 'brown' or 'pink'.</p>\n", 2583 "type": "String" 2584 } 2585 ] 2586 },
2587 "p5.AudioIn": { 2588 "name": "p5.AudioIn", 2589 "shortname": "p5.AudioIn", 2590 "classitems": [], 2591 "plugins": [], 2592 "extensions": [], 2593 "plugin_for": [], 2594 "extension_for": [], 2595 "module": "p5.sound", 2596 "submodule": "p5.sound", 2597 "namespace": "", 2598 "file": "lib/addons/p5.sound.js", 2599 "line": 7075, 2600 "description": "<p>Get audio from an input, i.e. your computer's microphone.</p>\n\n<p>Turn the mic on/off with the start() and stop() methods. When the mic\nis on, its volume can be measured with getLevel or by connecting an\nFFT object.</p>\n\n<p>If you want to hear the AudioIn, use the .connect() method.\nAudioIn does not connect to p5.sound output by default to prevent\nfeedback.</p>\n\n<p><em>Note: This uses the <a href=\"http://caniuse.com/stream\">getUserMedia/\nStream</a> API, which is not supported by certain browsers. Access in Chrome browser\nis limited to localhost and https, but access over http may be limited.</em></p>", 2601 "is_constructor": 1, 2602 "params": [ 2603 { 2604 "name": "errorCallback", 2605 "description": "<p>A function to call if there is an error\n accessing the AudioIn. For example,\n Safari and iOS devices do not\n currently allow microphone access.</p>\n", 2606 "type": "Function", 2607 "optional": true 2608 } 2609 ], 2610 "example": [ 2611 "\n<div><code>\nvar mic;\nfunction setup(){\n mic = new p5.AudioIn()\n mic.start();\n}\nfunction draw(){\n background(0);\n micLevel = mic.getLevel();\n ellipse(width/2, constrain(height-micLevel*height*5, 0, height), 10, 10);\n}\n</code></div>" 2612 ] 2613 }, 2614 "p5.Effect": { 2615 "name": "p5.Effect", 2616 "shortname": "p5.Effect", 2617 "classitems": [], 2618 "plugins": [], 2619 "extensions": [], 2620 "plugin_for": [], 2621 "extension_for": [], 2622 "module": "p5.sound", 2623 "submodule": "p5.sound", 2624 "namespace": "", 2625 "file": "lib/addons/p5.sound.js", 2626 "line": 7970, 2627 "description": "<p>Effect is a base class for audio effects in p5. <br>\nThis module handles the nodes and methods that are\ncommon and useful for current and future effects.</p>\n<p>This class is extended by <a href=\"reference/#/p5.Distortion\">p5.Distortion</a>,\n<a href=\"reference/#/p5.Compressor\">p5.Compressor</a>,\n<a href=\"reference/#/p5.Delay\">p5.Delay</a>,\n<a href=\"reference/#/p5.Filter\">p5.Filter</a>,\n<a href=\"reference/#/p5.Reverb\">p5.Reverb</a>.</p>\n", 2628 "is_constructor": 1, 2629 "params": [ 2630 { 2631 "name": "ac", 2632 "description": "<p>Reference to the audio context of the p5 object</p>\n", 2633 "type": "Object", 2634 "optional": true 2635 }, 2636 { 2637 "name": "input", 2638 "description": "<p>Gain Node effect wrapper</p>\n", 2639 "type": "AudioNode", 2640 "optional": true 2641 }, 2642 { 2643 "name": "output", 2644 "description": "<p>Gain Node effect wrapper</p>\n", 2645 "type": "AudioNode", 2646 "optional": true 2647 }, 2648 { 2649 "name": "_drywet", 2650 "description": "<p>Tone.JS CrossFade node (defaults to value: 1)</p>\n", 2651 "type": "Object", 2652 "optional": true 2653 }, 2654 { 2655 "name": "wet", 2656 "description": "<p>Effects that extend this class should connect\n to the wet signal to this gain node, so that dry and wet\n signals are mixed properly.</p>\n", 2657 "type": "AudioNode", 2658 "optional": true 2659 } 2660 ] 2661 },
2662 "p5.Filter": { 2663 "name": "p5.Filter", 2664 "shortname": "p5.Filter", 2665 "classitems": [], 2666 "plugins": [], 2667 "extensions": [], 2668 "plugin_for": [], 2669 "extension_for": [], 2670 "module": "p5.sound", 2671 "submodule": "p5.sound", 2672 "namespace": "", 2673 "file": "lib/addons/p5.sound.js", 2674 "line": 8102, 2675 "description": "<p><p>A p5.Filter uses a Web Audio Biquad Filter to filter\nthe frequency response of an input source. Subclasses\ninclude:</p></p>\n<ul>\n<li><a href=\"/reference/#/p5.LowPass\"><code>p5.LowPass</code></a>:\nAllows frequencies below the cutoff frequency to pass through,\nand attenuates frequencies above the cutoff.<br/></li>\n<li><a href=\"/reference/#/p5.HighPass\"><code>p5.HighPass</code></a>:\nThe opposite of a lowpass filter. <br/></li>\n<li><a href=\"/reference/#/p5.BandPass\"><code>p5.BandPass</code></a>:\nAllows a range of frequencies to pass through and attenuates\nthe frequencies below and above this frequency range.<br/></li>\n</ul>\n<p>The <code>.res()</code> method controls either width of the\nbandpass, or resonance of the low/highpass cutoff frequency.</p>\n<p>This class extends <a href = \"/reference/#/p5.Effect\">p5.Effect</a>.\nMethods <a href = \"/reference/#/p5.Effect/amp\">amp()</a>, <a href = \"/reference/#/p5.Effect/chain\">chain()</a>,\n<a href = \"/reference/#/p5.Effect/drywet\">drywet()</a>, <a href = \"/reference/#/p5.Effect/connect\">connect()</a>, and\n<a href = \"/reference/#/p5.Effect/disconnect\">disconnect()</a> are available.</p>\n", 2676 "extends": "p5.Effect", 2677 "is_constructor": 1, 2678 "params": [ 2679 { 2680 "name": "type", 2681 "description": "<p>'lowpass' (default), 'highpass', 'bandpass'</p>\n", 2682 "type": "String", 2683 "optional": true 2684 } 2685 ], 2686 "example": [ 2687 "\n<div><code>\nvar fft, noise, filter;\n\nfunction setup() {\n fill(255, 40, 255);\n\n filter = new p5.BandPass();\n\n noise = new p5.Noise();\n // disconnect unfiltered noise,\n // and connect to filter\n noise.disconnect();\n noise.connect(filter);\n noise.start();\n\n fft = new p5.FFT();\n}\n\nfunction draw() {\n background(30);\n\n // set the BandPass frequency based on mouseX\n var freq = map(mouseX, 0, width, 20, 10000);\n filter.freq(freq);\n // give the filter a narrow band (lower res = wider bandpass)\n filter.res(50);\n\n // draw filtered spectrum\n var spectrum = fft.analyze();\n noStroke();\n for (var i = 0; i < spectrum.length; i++) {\n var x = map(i, 0, spectrum.length, 0, width);\n var h = -height + map(spectrum[i], 0, 255, height, 0);\n rect(x, height, width/spectrum.length, h);\n }\n\n isMouseOverCanvas();\n}\n\nfunction isMouseOverCanvas() {\n var mX = mouseX, mY = mouseY;\n if (mX > 0 && mX < width && mY < height && mY > 0) {\n noise.amp(0.5, 0.2);\n } else {\n noise.amp(0, 0.2);\n }\n}\n</code></div>" 2688 ] 2689 }, 2690 "p5.LowPass": { 2691 "name": "p5.LowPass", 2692 "shortname": "p5.LowPass", 2693 "classitems": [], 2694 "plugins": [], 2695 "extensions": [], 2696 "plugin_for": [], 2697 "extension_for": [], 2698 "module": "p5.sound", 2699 "submodule": "p5.sound", 2700 "namespace": "", 2701 "file": "lib/addons/p5.sound.js", 2702 "line": 8332, 2703 "description": "<p>Constructor: <code>new p5.LowPass()</code> Filter.\nThis is the same as creating a p5.Filter and then calling\nits method <code>setType('lowpass')</code>.\nSee p5.Filter for methods.</p>\n", 2704 "is_constructor": 1, 2705 "extends": "p5.Filter" 2706 }, 2707 "p5.HighPass": { 2708 "name": "p5.HighPass", 2709 "shortname": "p5.HighPass", 2710 "classitems": [], 2711 "plugins": [], 2712 "extensions": [], 2713 "plugin_for": [], 2714 "extension_for": [], 2715 "module": "p5.sound", 2716 "submodule": "p5.sound", 2717 "namespace": "", 2718 "file": "lib/addons/p5.sound.js", 2719 "line": 8346, 2720 "description": "<p>Constructor: <code>new p5.HighPass()</code> Filter.\nThis is the same as creating a p5.Filter and then calling\nits method <code>setType('highpass')</code>.\nSee p5.Filter for methods.</p>\n", 2721 "is_constructor": 1, 2722 "extends": "p5.Filter" 2723 },
2724 "p5.BandPass": { 2725 "name": "p5.BandPass", 2726 "shortname": "p5.BandPass", 2727 "classitems": [], 2728 "plugins": [], 2729 "extensions": [], 2730 "plugin_for": [], 2731 "extension_for": [], 2732 "module": "p5.sound", 2733 "submodule": "p5.sound", 2734 "namespace": "", 2735 "file": "lib/addons/p5.sound.js", 2736 "line": 8360, 2737 "description": "<p>Constructor: <code>new p5.BandPass()</code> Filter.\nThis is the same as creating a p5.Filter and then calling\nits method <code>setType('bandpass')</code>.\nSee p5.Filter for methods.</p>\n", 2738 "is_constructor": 1, 2739 "extends": "p5.Filter" 2740 }, 2741 "p5.EQ": { 2742 "name": "p5.EQ", 2743 "shortname": "p5.EQ", 2744 "classitems": [], 2745 "plugins": [], 2746 "extensions": [], 2747 "plugin_for": [], 2748 "extension_for": [], 2749 "module": "p5.sound", 2750 "submodule": "p5.sound", 2751 "namespace": "", 2752 "file": "lib/addons/p5.sound.js", 2753 "line": 8429, 2754 "description": "<p>p5.EQ is an audio effect that performs the function of a multiband\naudio equalizer. Equalization is used to adjust the balance of\nfrequency compoenents of an audio signal. This process is commonly used\nin sound production and recording to change the waveform before it reaches\na sound output device. EQ can also be used as an audio effect to create\ninteresting distortions by filtering out parts of the spectrum. p5.EQ is\nbuilt using a chain of Web Audio Biquad Filter Nodes and can be\ninstantiated with 3 or 8 bands. Bands can be added or removed from\nthe EQ by directly modifying p5.EQ.bands (the array that stores filters).</p>\n<p>This class extends <a href = \"/reference/#/p5.Effect\">p5.Effect</a>.\nMethods <a href = \"/reference/#/p5.Effect/amp\">amp()</a>, <a href = \"/reference/#/p5.Effect/chain\">chain()</a>,\n<a href = \"/reference/#/p5.Effect/drywet\">drywet()</a>, <a href = \"/reference/#/p5.Effect/connect\">connect()</a>, and\n<a href = \"/reference/#/p5.Effect/disconnect\">disconnect()</a> are available.</p>\n", 2755 "is_constructor": 1, 2756 "extends": "p5.Effect", 2757 "params": [ 2758 { 2759 "name": "_eqsize", 2760 "description": "<p>Constructor will accept 3 or 8, defaults to 3</p>\n", 2761 "type": "Number", 2762 "optional": true 2763 } 2764 ], 2765 "return": { 2766 "description": "p5.EQ object", 2767 "type": "Object" 2768 }, 2769 "example": [ 2770 "\n<div><code>\nvar eq;\nvar band_names;\nvar band_index;\n\nvar soundFile, play;\n\nfunction preload() {\n soundFormats('mp3', 'ogg');\n soundFile = loadSound('assets/beat');\n}\n\nfunction setup() {\n eq = new p5.EQ(3);\n soundFile.disconnect();\n eq.process(soundFile);\n\n band_names = ['lows','mids','highs'];\n band_index = 0;\n play = false;\n textAlign(CENTER);\n}\n\nfunction draw() {\n background(30);\n noStroke();\n fill(255);\n text('click to kill',50,25);\n\n fill(255, 40, 255);\n textSize(26);\n text(band_names[band_index],50,55);\n\n fill(255);\n textSize(9);\n text('space = play/pause',50,80);\n}\n\n//If mouse is over canvas, cycle to the next band and kill the frequency\nfunction mouseClicked() {\n for (var i = 0; i < eq.bands.length; i++) {\n eq.bands[i].gain(0);\n }\n eq.bands[band_index].gain(-40);\n if (mouseX > 0 && mouseX < width && mouseY < height && mouseY > 0) {\n band_index === 2 ? band_index = 0 : band_index++;\n }\n}\n\n//use space bar to trigger play / pause\nfunction keyPressed() {\n if (key===' ') {\n play = !play\n play ? soundFile.loop() : soundFile.pause();\n }\n}\n</code></div>" 2771 ] 2772 }, 2773 "p5.Panner3D": { 2774 "name": "p5.Panner3D", 2775 "shortname": "p5.Panner3D", 2776 "classitems": [], 2777 "plugins": [], 2778 "extensions": [], 2779 "plugin_for": [], 2780 "extension_for": [], 2781 "module": "p5.sound", 2782 "submodule": "p5.sound", 2783 "namespace": "", 2784 "file": "lib/addons/p5.sound.js", 2785 "line": 8619, 2786 "description": "<p>Panner3D is based on the <a title=\"Web Audio Panner docs\" href=\n\"https://developer.mozilla.org/en-US/docs/Web/API/PannerNode\">\nWeb Audio Spatial Panner Node</a>.\nThis panner is a spatial processing node that allows audio to be positioned\nand oriented in 3D space.</p>\n<p>The position is relative to an <a title=\"Web Audio Listener docs\" href=\n\"https://developer.mozilla.org/en-US/docs/Web/API/AudioListener\">\nAudio Context Listener</a>, which can be accessed\nby <code>p5.soundOut.audiocontext.listener</code></p>\n", 2787 "is_constructor": 1 2788 },
2789 "p5.Delay": { 2790 "name": "p5.Delay", 2791 "shortname": "p5.Delay", 2792 "classitems": [], 2793 "plugins": [], 2794 "extensions": [], 2795 "plugin_for": [], 2796 "extension_for": [], 2797 "module": "p5.sound", 2798 "submodule": "p5.sound", 2799 "namespace": "", 2800 "file": "lib/addons/p5.sound.js", 2801 "line": 9068, 2802 "description": "<p>Delay is an echo effect. It processes an existing sound source,\nand outputs a delayed version of that sound. The p5.Delay can\nproduce different effects depending on the delayTime, feedback,\nfilter, and type. In the example below, a feedback of 0.5 (the\ndefaul value) will produce a looping delay that decreases in\nvolume by 50% each repeat. A filter will cut out the high\nfrequencies so that the delay does not sound as piercing as the\noriginal source.</p>\n<p>This class extends <a href = \"/reference/#/p5.Effect\">p5.Effect</a>.\nMethods <a href = \"/reference/#/p5.Effect/amp\">amp()</a>, <a href = \"/reference/#/p5.Effect/chain\">chain()</a>,\n<a href = \"/reference/#/p5.Effect/drywet\">drywet()</a>, <a href = \"/reference/#/p5.Effect/connect\">connect()</a>, and\n<a href = \"/reference/#/p5.Effect/disconnect\">disconnect()</a> are available.</p>\n", 2803 "extends": "p5.Effect", 2804 "is_constructor": 1, 2805 "example": [ 2806 "\n<div><code>\nvar noise, env, delay;\n\nfunction setup() {\n background(0);\n noStroke();\n fill(255);\n textAlign(CENTER);\n text('click to play', width/2, height/2);\n\n noise = new p5.Noise('brown');\n noise.amp(0);\n noise.start();\n\n delay = new p5.Delay();\n\n // delay.process() accepts 4 parameters:\n // source, delayTime, feedback, filter frequency\n // play with these numbers!!\n delay.process(noise, .12, .7, 2300);\n\n // play the noise with an envelope,\n // a series of fades ( time / value pairs )\n env = new p5.Env(.01, 0.2, .2, .1);\n}\n\n// mouseClick triggers envelope\nfunction mouseClicked() {\n // is mouse over canvas?\n if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {\n env.play(noise);\n }\n}\n</code></div>" 2807 ] 2808 }, 2809 "p5.Reverb": { 2810 "name": "p5.Reverb", 2811 "shortname": "p5.Reverb", 2812 "classitems": [], 2813 "plugins": [], 2814 "extensions": [], 2815 "plugin_for": [], 2816 "extension_for": [], 2817 "module": "p5.sound", 2818 "submodule": "p5.sound", 2819 "namespace": "", 2820 "file": "lib/addons/p5.sound.js", 2821 "line": 9345, 2822 "description": "<p>Reverb adds depth to a sound through a large number of decaying\nechoes. It creates the perception that sound is occurring in a\nphysical space. The p5.Reverb has paramters for Time (how long does the\nreverb last) and decayRate (how much the sound decays with each echo)\nthat can be set with the .set() or .process() methods. The p5.Convolver\nextends p5.Reverb allowing you to recreate the sound of actual physical\nspaces through convolution.</p>\n<p>This class extends <a href = \"/reference/#/p5.Effect\">p5.Effect</a>.\nMethods <a href = \"/reference/#/p5.Effect/amp\">amp()</a>, <a href = \"/reference/#/p5.Effect/chain\">chain()</a>,\n<a href = \"/reference/#/p5.Effect/drywet\">drywet()</a>, <a href = \"/reference/#/p5.Effect/connect\">connect()</a>, and\n<a href = \"/reference/#/p5.Effect/disconnect\">disconnect()</a> are available.</p>\n", 2823 "extends": "p5.Effect", 2824 "is_constructor": 1, 2825 "example": [ 2826 "\n<div><code>\nvar soundFile, reverb;\nfunction preload() {\n soundFile = loadSound('assets/Damscray_DancingTiger.mp3');\n}\n\nfunction setup() {\n reverb = new p5.Reverb();\n soundFile.disconnect(); // so we'll only hear reverb...\n\n // connect soundFile to reverb, process w/\n // 3 second reverbTime, decayRate of 2%\n reverb.process(soundFile, 3, 2);\n soundFile.play();\n}\n</code></div>" 2827 ] 2828 }, 2829 "p5.Convolver": { 2830 "name": "p5.Convolver", 2831 "shortname": "p5.Convolver", 2832 "classitems": [], 2833 "plugins": [], 2834 "extensions": [], 2835 "plugin_for": [], 2836 "extension_for": [], 2837 "module": "p5.sound", 2838 "submodule": "p5.sound", 2839 "namespace": "", 2840 "file": "lib/addons/p5.sound.js", 2841 "line": 9505, 2842 "description": "<p>p5.Convolver extends p5.Reverb. It can emulate the sound of real\nphysical spaces through a process called <a href=\"\nhttps://en.wikipedia.org/wiki/Convolution_reverb#Real_space_simulation\">\nconvolution</a>.</p>\n\n<p>Convolution multiplies any audio input by an "impulse response"\nto simulate the dispersion of sound over time. The impulse response is\ngenerated from an audio file that you provide. One way to\ngenerate an impulse response is to pop a balloon in a reverberant space\n
2842and record the echo. Convolution can also be used to experiment with\nsound.</p>\n\n<p>Use the method <code>createConvolution(path)</code> to instantiate a\np5.Convolver with a path to your impulse response audio file.</p>", 2843 "extends": "p5.Effect", 2844 "is_constructor": 1, 2845 "params": [ 2846 { 2847 "name": "path", 2848 "description": "<p>path to a sound file</p>\n", 2849 "type": "String" 2850 }, 2851 { 2852 "name": "callback", 2853 "description": "<p>function to call when loading succeeds</p>\n", 2854 "type": "Function", 2855 "optional": true 2856 }, 2857 { 2858 "name": "errorCallback", 2859 "description": "<p>function to call if loading fails.\n This function will receive an error or\n XMLHttpRequest object with information\n about what went wrong.</p>\n", 2860 "type": "Function", 2861 "optional": true 2862 } 2863 ], 2864 "example": [ 2865 "\n<div><code>\nvar cVerb, sound;\nfunction preload() {\n // We have both MP3 and OGG versions of all sound assets\n soundFormats('ogg', 'mp3');\n\n // Try replacing 'bx-spring' with other soundfiles like\n // 'concrete-tunnel' 'small-plate' 'drum' 'beatbox'\n cVerb = createConvolver('assets/bx-spring.mp3');\n\n // Try replacing 'Damscray_DancingTiger' with\n // 'beat', 'doorbell', lucky_dragons'\n sound = loadSound('assets/Damscray_DancingTiger.mp3');\n}\n\nfunction setup() {\n // disconnect from master output...\n sound.disconnect();\n\n // ...and process with cVerb\n // so that we only hear the convolution\n cVerb.process(sound);\n\n sound.play();\n}\n</code></div>" 2866 ] 2867 }, 2868 "p5.Phrase": { 2869 "name": "p5.Phrase", 2870 "shortname": "p5.Phrase", 2871 "classitems": [], 2872 "plugins": [], 2873 "extensions": [], 2874 "plugin_for": [], 2875 "extension_for": [], 2876 "module": "p5.sound", 2877 "submodule": "p5.sound", 2878 "namespace": "", 2879 "file": "lib/addons/p5.sound.js", 2880 "line": 10057, 2881 "description": "<p>A phrase is a pattern of musical events over time, i.e.\na series of notes and rests.</p>\n\n<p>Phrases must be added to a p5.Part for playback, and\neach part can play multiple phrases at the same time.\nFor example, one Phrase might be a kick drum, another\ncould be a snare, and another could be the bassline.</p>\n\n<p>The first parameter is a name so that the phrase can be\nmodified or deleted later. The callback is a a function that\nthis phrase will call at every stepâfor example it might be\ncalled <code>playNote(value){}</code>. The array determines\nwhich value is passed into the callback at each step of the\nphrase. It can be numbers, an object with multiple numbers,\nor a zero (0) indicates a rest so the callback won't be called).</p>", 2882 "is_constructor": 1, 2883 "params": [ 2884 { 2885 "name": "name", 2886 "description": "<p>Name so that you can access the Phrase.</p>\n", 2887 "type": "String" 2888 }, 2889 { 2890 "name": "callback", 2891 "description": "<p>The name of a function that this phrase\n will call. Typically it will play a sound,\n and accept two parameters: a time at which\n to play the sound (in seconds from now),\n and a value from the sequence array. The\n time should be passed into the play() or\n start() method to ensure precision.</p>\n", 2892 "type": "Function" 2893 }, 2894 { 2895 "name": "sequence", 2896 "description": "<p>Array of values to pass into the callback\n at each step of the phrase.</p>\n", 2897 "type": "Array" 2898 } 2899 ], 2900 "example": [ 2901 "\n<div><code>\nvar mySound, myPhrase, myPart;\nvar pattern = [1,0,0,2,0,2,0,0];\nvar msg = 'click to play';\n\nfunction preload() {\n mySound = loadSound('assets/beatbox.mp3');\n}\n\nfunction setup() {\n noStroke();\n fill(255);\n textAlign(CENTER);\n masterVolume(0.1);
2901\n\n myPhrase = new p5.Phrase('bbox', makeSound, pattern);\n myPart = new p5.Part();\n myPart.addPhrase(myPhrase);\n myPart.setBPM(60);\n}\n\nfunction draw() {\n background(0);\n text(msg, width/2, height/2);\n}\n\nfunction makeSound(time, playbackRate) {\n mySound.rate(playbackRate);\n mySound.play(time);\n}\n\nfunction mouseClicked() {\n if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {\n myPart.start();\n msg = 'playing pattern';\n }\n}\n\n</code></div>" 2902 ] 2903 }, 2904 "p5.Part": { 2905 "name": "p5.Part", 2906 "shortname": "p5.Part", 2907 "classitems": [], 2908 "plugins": [], 2909 "extensions": [], 2910 "plugin_for": [], 2911 "extension_for": [], 2912 "module": "p5.sound", 2913 "submodule": "p5.sound", 2914 "namespace": "", 2915 "file": "lib/addons/p5.sound.js", 2916 "line": 10142, 2917 "description": "<p>A p5.Part plays back one or more p5.Phrases. Instantiate a part\nwith steps and tatums. By default, each step represents 1/16th note.</p>\n\n<p>See p5.Phrase for more about musical timing.</p>", 2918 "is_constructor": 1, 2919 "params": [ 2920 { 2921 "name": "steps", 2922 "description": "<p>Steps in the part</p>\n", 2923 "type": "Number", 2924 "optional": true 2925 }, 2926 { 2927 "name": "tatums", 2928 "description": "<p>Divisions of a beat (default is 1/16, a quarter note)</p>\n", 2929 "type": "Number", 2930 "optional": true 2931 } 2932 ], 2933 "example": [ 2934 "\n<div><code>\nvar box, drum, myPart;\nvar boxPat = [1,0,0,2,0,2,0,0];\nvar drumPat = [0,1,1,0,2,0,1,0];\nvar msg = 'click to play';\n\nfunction preload() {\n box = loadSound('assets/beatbox.mp3');\n drum = loadSound('assets/drum.mp3');\n}\n\nfunction setup() {\n noStroke();\n fill(255);\n textAlign(CENTER);\n masterVolume(0.1);\n\n var boxPhrase = new p5.Phrase('box', playBox, boxPat);\n var drumPhrase = new p5.Phrase('drum', playDrum, drumPat);\n myPart = new p5.Part();\n myPart.addPhrase(boxPhrase);\n myPart.addPhrase(drumPhrase);\n myPart.setBPM(60);\n masterVolume(0.1);\n}\n\nfunction draw() {\n background(0);\n text(msg, width/2, height/2);\n}\n\nfunction playBox(time, playbackRate) {\n box.rate(playbackRate);\n box.play(time);\n}\n\nfunction playDrum(time, playbackRate) {\n drum.rate(playbackRate);\n drum.play(time);\n}\n\nfunction mouseClicked() {\n if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {\n myPart.start();\n msg = 'playing part';\n }\n}\n</code></div>" 2935 ] 2936 }, 2937 "p5.Score": { 2938 "name": "p5.Score", 2939 "shortname": "p5.Score", 2940 "classitems": [], 2941 "plugins": [], 2942 "extensions": [], 2943 "plugin_for": [], 2944 "extension_for": [], 2945 "module": "p5.sound", 2946 "submodule": "p5.sound", 2947 "namespace": "", 2948 "file": "lib/addons/p5.sound.js", 2949 "line": 10396, 2950 "description": "<p>A Score consists of a series of Parts. The parts will\nbe played back in order. For example, you could have an\nA part, a B part, and a C part, and play them back in this order\n<code>new p5.Score(a, a, b, a, c)</code></p>\n", 2951 "is_constructor": 1, 2952 "params": [ 2953 { 2954 "name": "parts", 2955 "description": "<p>One or multiple parts, to be played in sequence.</p>\n", 2956 "type": "p5.Part", 2957 "optional": true, 2958 "multiple": true 2959 } 2960 ] 2961 }, 2962 "p5.SoundLoop": { 2963 "name": "p5.SoundLoop", 2964 "shortname": "p5.SoundLoop", 2965 "classitems": [], 2966 "plugins": [], 2967 "extensions": [], 2968 "plugin_for": [], 2969 "extension_for": [], 2970 "module": "p5.sound", 2971 "submodule": "p5.sound", 2972 "namespace": "", 2973 "file": "lib/addons/p5.sound.js", 2974 "line": 10527, 2975 "description": "<p>SoundLoop</p>\n", 2976 "is_constructor": 1, 2977 "params": [ 2978 { 2979 "name": "callback", 2980 "description": "<p>this function will be called on each iteration of theloop</p>\n", 2981 "type": "Function" 2982 }, 2983 { 2984 "name": "interval", 2985 "description": "<p>amount of time or beats for each iteration of the loop\n defaults to 1</p>\n", 2986 "type": "Number|String", 2987 "optional": true 2988 } 2989 ], 2990 "example": [ 2991 "\n<div><code>\nvar click;\nvar looper1;\n\nfunction preload() {\n click = loadSound('assets/drum.mp3');\n}\n\nfunction setup() {\n //the looper's callback is passed the timeFromNow\n //this value should be used as a reference point from\n //which to schedule sounds\n looper1 = new p5.SoundLoop(function(timeFromNow){\n click.play(timeFromNow);\n background(255 * (looper1.iterations % 2));\n }, 2);\n\n //stop after 10 iteratios;\n looper1.maxIterations = 10;\n //start the loop\n looper1.start();\n}\n</code></div>" 2992 ] 2993 },
2994 "p5.Compressor": { 2995 "name": "p5.Compressor", 2996 "shortname": "p5.Compressor", 2997 "classitems": [], 2998 "plugins": [], 2999 "extensions": [], 3000 "plugin_for": [], 3001 "extension_for": [], 3002 "module": "p5.sound", 3003 "submodule": "p5.sound", 3004 "namespace": "", 3005 "file": "lib/addons/p5.sound.js", 3006 "line": 10786, 3007 "description": "<p>Compressor is an audio effect class that performs dynamics compression\non an audio input source. This is a very commonly used technique in music\nand sound production. Compression creates an overall louder, richer,\nand fuller sound by lowering the volume of louds and raising that of softs.\nCompression can be used to avoid clipping (sound distortion due to\npeaks in volume) and is especially useful when many sounds are played\nat once. Compression can be used on indivudal sound sources in addition\nto the master output.</p>\n<p>This class extends <a href = \"/reference/#/p5.Effect\">p5.Effect</a>.\nMethods <a href = \"/reference/#/p5.Effect/amp\">amp()</a>, <a href = \"/reference/#/p5.Effect/chain\">chain()</a>,\n<a href = \"/reference/#/p5.Effect/drywet\">drywet()</a>, <a href = \"/reference/#/p5.Effect/connect\">connect()</a>, and\n<a href = \"/reference/#/p5.Effect/disconnect\">disconnect()</a> are available.</p>\n", 3008 "is_constructor": 1, 3009 "extends": "p5.Effect" 3010 }, 3011 "p5.SoundRecorder": { 3012 "name": "p5.SoundRecorder", 3013 "shortname": "p5.SoundRecorder", 3014 "classitems": [], 3015 "plugins": [], 3016 "extensions": [], 3017 "plugin_for": [], 3018 "extension_for": [], 3019 "module": "p5.sound", 3020 "submodule": "p5.sound", 3021 "namespace": "", 3022 "file": "lib/addons/p5.sound.js", 3023 "line": 10994, 3024 "description": "<p>
3024Record sounds for playback and/or to save as a .wav file.\nThe p5.SoundRecorder records all sound output from your sketch,\nor can be assigned a specific source with setInput().</p>\n<p>The record() method accepts a p5.SoundFile as a parameter.\nWhen playback is stopped (either after the given amount of time,\nor with the stop() method), the p5.SoundRecorder will send its\nrecording to that p5.SoundFile for playback.</p>", 3025 "is_constructor": 1, 3026 "example": [ 3027 "\n<div><code>\nvar mic, recorder, soundFile;\nvar state = 0;\n\nfunction setup() {\n background(200);\n // create an audio in\n mic = new p5.AudioIn();\n\n // prompts user to enable their browser mic\n mic.start();\n\n // create a sound recorder\n recorder = new p5.SoundRecorder();\n\n // connect the mic to the recorder\n recorder.setInput(mic);\n\n // this sound file will be used to\n // playback & save the recording\n soundFile = new p5.SoundFile();\n\n text('keyPress to record', 20, 20);\n}\n\nfunction keyPressed() {\n // make sure user enabled the mic\n if (state === 0 && mic.enabled) {\n\n // record to our p5.SoundFile\n recorder.record(soundFile);\n\n background(255,0,0);\n text('Recording!', 20, 20);\n state++;\n }\n else if (state === 1) {\n background(0,255,0);\n\n // stop recorder and\n // send result to soundFile\n recorder.stop();\n\n text('Stopped', 20, 20);\n state++;\n }\n\n else if (state === 2) {\n soundFile.play(); // play the result!\n save(soundFile, 'mySound.wav');\n state++;\n }\n}\n</div></code>" 3028 ] 3029 }, 3030 "p5.PeakDetect": { 3031 "name": "p5.PeakDetect", 3032 "shortname": "p5.PeakDetect", 3033 "classitems": [], 3034 "plugins": [], 3035 "extensions": [], 3036 "plugin_for": [], 3037 "extension_for": [], 3038 "module": "p5.sound", 3039 "submodule": "p5.sound", 3040 "namespace": "", 3041 "file": "lib/addons/p5.sound.js", 3042 "line": 11283, 3043 "description": "<p>PeakDetect works in conjunction with p5.FFT to\nlook for onsets in some or all of the frequency spectrum.\n</p>\n<p>\nTo use p5.PeakDetect, call <code>update</code> in the draw loop\nand pass in a p5.FFT object.\n</p>\n<p>\nYou can listen for a specific part of the frequency spectrum by\nsetting the range between <code>freq1</code> and <code>freq2</code>.\n</p>\n\n<p><code>threshold</code> is the threshold for detecting a peak,\nscaled between 0 and 1. It is logarithmic, so 0.1 is half as loud\nas 1.0.</p>\n\n<p>\nThe update method is meant to be run in the draw loop, and\n<b>frames</b> determines how many loops must pass before\nanother peak can be detected.\nFor example, if the frameRate() = 60, you could detect the beat of a\n120 beat-per-minute song with this equation:\n<code> framesPerPeak = 60 / (estimatedBPM / 60 );</code>\n</p>\n\n<p>\nBased on example contribtued by @b2renger, and a simple beat detection\nexplanation by <a href=\"a\nhref="http://www.airtightinteractive.com/2013/10/making-audio-reactive-visuals/"\ntarget="_blank"\">a\nhref="http://www.airtightinteractive.com/2013/10/making-audio-reactive-visuals/"\ntarget="_blank"</a>Felix Turner</a>.\n</p>", 3044 "is_constructor": 1, 3045 "params": [ 3046 { 3047 "name": "freq1", 3048 "description": "<p>lowFrequency - defaults to 20Hz</p>\n", 3049 "type": "Number", 3050 "optional": true 3051 }, 3052 { 3053 "name": "freq2", 3054 "description": "<p>highFrequency - defaults to 20000 Hz</p>\n", 3055 "type": "Number", 3056 "optional": true 3057 }, 3058 { 3059 "name": "threshold", 3060 "description": "<p>Threshold for detecting a beat between 0 and 1\n scaled logarithmically where 0.1 is 1/2 the loudness\n of 1.0. Defaults to 0.35.
3060</p>\n", 3061 "type": "Number", 3062 "optional": true 3063 }, 3064 { 3065 "name": "framesPerPeak", 3066 "description": "<p>Defaults to 20.</p>\n", 3067 "type": "Number", 3068 "optional": true 3069 } 3070 ], 3071 "example": [ 3072 "\n<div><code>\n\nvar cnv, soundFile, fft, peakDetect;\nvar ellipseWidth = 10;\n\nfunction setup() {\n background(0);\n noStroke();\n fill(255);\n textAlign(CENTER);\n\n soundFile = loadSound('assets/beat.mp3');\n\n // p5.PeakDetect requires a p5.FFT\n fft = new p5.FFT();\n peakDetect = new p5.PeakDetect();\n\n}\n\nfunction draw() {\n background(0);\n text('click to play/pause', width/2, height/2);\n\n // peakDetect accepts an fft post-analysis\n fft.analyze();\n peakDetect.update(fft);\n\n if ( peakDetect.isDetected ) {\n ellipseWidth = 50;\n } else {\n ellipseWidth *= 0.95;\n }\n\n ellipse(width/2, height/2, ellipseWidth, ellipseWidth);\n}\n\n// toggle play/stop when canvas is clicked\nfunction mouseClicked() {\n if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {\n if (soundFile.isPlaying() ) {\n soundFile.stop();\n } else {\n soundFile.play();\n }\n }\n}\n</code></div>" 3073 ] 3074 }, 3075 "p5.Gain": { 3076 "name": "p5.Gain", 3077 "shortname": "p5.Gain", 3078 "classitems": [], 3079 "plugins": [], 3080 "extensions": [], 3081 "plugin_for": [], 3082 "extension_for": [], 3083 "module": "p5.sound", 3084 "submodule": "p5.sound", 3085 "namespace": "", 3086 "file": "lib/addons/p5.sound.js", 3087 "line": 11503, 3088 "description": "<p>A gain node is usefull to set the relative volume of sound.\nIt's typically used to build mixers.</p>\n", 3089 "is_constructor": 1, 3090 "example": [ 3091 "\n<div><code>\n\n // load two soundfile and crossfade beetween them\n var sound1,sound2;\n var gain1, gain2, gain3;\n\n function preload(){\n soundFormats('ogg', 'mp3');\n sound1 = loadSound('../_files/Damscray_01');\n sound2 = loadSound('../_files/beat.mp3');\n }\n\n function setup() {\n createCanvas(400,200);\n\n // create a 'master' gain to which we will connect both soundfiles\n gain3 = new p5.Gain();\n gain3.connect();\n\n // setup first sound for playing\n sound1.rate(1);\n sound1.loop();\n sound1.disconnect(); // diconnect from p5 output\n\n gain1 = new p5.Gain(); // setup a gain node\n gain1.setInput(sound1); // connect the first sound to its input\n gain1.connect(gain3); // connect its output to the 'master'\n\n sound2.rate(1);\n sound2.disconnect();\n sound2.loop();\n\n gain2 = new p5.Gain();\n gain2.setInput(sound2);\n gain2.connect(gain3);\n\n }\n\n function draw(){\n background(180);\n\n // calculate the horizontal distance beetween the mouse and the right of the screen\n var d = dist(mouseX,0,width,0);\n\n // map the horizontal position of the mouse to values useable for volume control of sound1\n var vol1 = map(mouseX,0,width,0,1);\n var vol2 = 1-vol1; // when sound1 is loud, sound2 is quiet and vice versa\n\n gain1.amp(vol1,0.5,0);\n gain2.amp(vol2,0.5,0);\n\n // map the vertical position of the mouse to values useable for 'master volume control'\n var vol3 = map(mouseY,0,height,0,1);\n gain3.amp(vol3,0.5,0);\n }\n</code></div>\n" 3092 ] 3093 }, 3094 "p5.AudioVoice": { 3095 "name": "p5.AudioVoice", 3096 "shortname": "p5.AudioVoice", 3097 "classitems": [], 3098 "plugins": [], 3099 "extensions": [], 3100 "plugin_for": [], 3101 "extension_for": [], 3102 "module": "p5.sound", 3103 "submodule": "p5.sound", 3104 "namespace": "", 3105 "file": "lib/addons/p5.sound.js", 3106 "line": 11638, 3107 "description": "<p>Base class for monophonic synthesizers. Any extensions of this class\nshould follow the API and implement the methods below in order to\nremain compatible with p5.PolySynth();</p>\n", 3108 "is_constructor": 1 3109 },
3110 "p5.MonoSynth": { 3111 "name": "p5.MonoSynth", 3112 "shortname": "p5.MonoSynth", 3113 "classitems": [], 3114 "plugins": [], 3115 "extensions": [], 3116 "plugin_for": [], 3117 "extension_for": [], 3118 "module": "p5.sound", 3119 "submodule": "p5.sound", 3120 "namespace": "", 3121 "file": "lib/addons/p5.sound.js", 3122 "line": 11711, 3123 "description": "<p>An MonoSynth is used as a single voice for sound synthesis.\nThis is a class to be used in conjonction with the PolySynth\nclass. Custom synthetisers should be built inheriting from\nthis class.</p>\n", 3124 "is_constructor": 1, 3125 "example": [ 3126 "\n<div><code>\nvar monosynth;\nvar x;\n\nfunction setup() {\n monosynth = new p5.MonoSynth();\n monosynth.loadPreset('simpleBass');\n monosynth.play(45,1,x=0,1);\n monosynth.play(49,1,x+=1,0.25);\n monosynth.play(50,1,x+=0.25,0.25);\n monosynth.play(49,1,x+=0.5,0.25);\n monosynth.play(50,1,x+=0.25,0.25);\n}\n</code></div>" 3127 ] 3128 }, 3129 "p5.PolySynth": { 3130 "name": "p5.PolySynth", 3131 "shortname": "p5.PolySynth", 3132 "classitems": [], 3133 "plugins": [], 3134 "extensions": [], 3135 "plugin_for": [], 3136 "extension_for": [], 3137 "module": "p5.sound", 3138 "submodule": "p5.sound", 3139 "namespace": "", 3140 "file": "lib/addons/p5.sound.js", 3141 "line": 11943, 3142 "description": "<p>An AudioVoice is used as a single voice for sound synthesis.\nThe PolySynth class holds an array of AudioVoice, and deals\nwith voices allocations, with setting notes to be played, and\nparameters to be set.</p>\n", 3143 "is_constructor": 1, 3144 "params": [ 3145 { 3146 "name": "synthVoice", 3147 "description": "<p>A monophonic synth voice inheriting\n the AudioVoice class. Defaults to p5.MonoSynth</p>\n", 3148 "type": "Number", 3149 "optional": true 3150 }, 3151 { 3152 "name": "polyValue", 3153 "description": "<p>Number of voices, defaults to 8;</p>\n", 3154 "type": "Number", 3155 "optional": true 3156 } 3157 ], 3158 "example": [ 3159 "\n<div><code>\nvar polysynth;\nfunction setup() {\n polysynth = new p5.PolySynth();\n polysynth.play(53,1,0,3);\n polysynth.play(60,1,0,2.9);\n polysynth.play(69,1,0,3);\n polysynth.play(71,1,0,3);\n polysynth.play(74,1,0,3);\n}\n</code></div>\n" 3160 ] 3161 }, 3162 "p5.Distortion": { 3163 "name": "p5.Distortion", 3164 "shortname": "p5.Distortion", 3165 "classitems": [], 3166 "plugins": [], 3167 "extensions": [], 3168 "plugin_for": [], 3169 "extension_for": [], 3170 "module": "p5.sound", 3171 "submodule": "p5.sound", 3172 "namespace": "", 3173 "file": "lib/addons/p5.sound.js", 3174 "line": 12243, 3175 "description": "<p>A Distortion effect created with a Waveshaper Node,\nwith an approach adapted from\n<a href=\"http://stackoverflow.com/questions/22312841/waveshaper-node-in-webaudio-how-to-emulate-distortion\">Kevin Ennis</a></p>\n<p>This class extends <a href = \"/reference/#/p5.Effect\">p5.Effect</a>.\nMethods <a href = \"/reference/#/p5.Effect/amp\">amp()</a>, <a href = \"/reference/#/p5.Effect/chain\">chain()</a>,\n<a href = \"/reference/#/p5.Effect/drywet\">drywet()</a>, <a href = \"/reference/#/p5.Effect/connect\">connect()</a>, and\n<a href = \"/reference/#/p5.Effect/disconnect\">disconnect()</a> are available.</p>\n", 3176 "extends": "p5.Effect", 3177 "is_constructor": 1, 3178 "params": [ 3179 { 3180 "name": "amount", 3181 "description": "<p>Unbounded distortion amount.\n Normal values range from 0-1.</p>\n", 3182 "type": "Number", 3183 "optional": true, 3184 "optdefault": "0.25" 3185 }, 3186 { 3187 "name": "oversample", 3188 "description": "<p>'none', '2x', or '4x'.</p>\n", 3189 "type": "String", 3190 "optional": true, 3191 "optdefault": "'none'" 3192 } 3193 ] 3194 } 3195 }, 3196 "elements": {}, 3197 "classitems": [ 3198 { 3199 "file": "src/color/color_conversion.js", 3200 "line": 10, 3201 "description": "<p>Conversions adapted from <a href=\"http://www.easyrgb.com/en/math.php\">http://www.easyrgb.com/en/math.php</a>.</p>\n<p>In these functions, hue is always in the range [0,1); all other components\nare in the range [0,1]. 'Brightness' and 'value' are used interchangeably.</p>\n", 3202 "class": "p5", 3203 "module": "Conversion", 3204 "submodule": "Color Conversion" 3205 }, 3206 { 3207 "file": "src/color/color_conversion.js", 3208 "line": 20, 3209 "description": "<p>Convert an HSBA array to HSLA.</p>\n", 3210 "class": "p5", 3211 "module": "Conversion", 3212 "submodule": "Color Conversion" 3213 }, 3214 { 3215 "file": "src/color/color_conversion.js", 3216 "line": 46, 3217 "description": "<p>Convert an HSBA array to RGBA.</p>\n", 3218 "class": "p5", 3219 "module": "Conversion", 3220 "submodule": "Color Conversion" 3221 }, 3222 { 3223 "file": "src/color/color_conversion.js", 3224 "line": 101, 3225 "description": "<p>Convert an HSLA array to HSBA.</p>\n", 3226 "class": "p5", 3227 "module": "Conversion", 3228 "submodule": "Color Conversion" 3229 }, 3230 { 3231 "file": "src/color/color_conversion.js", 3232 "line": 124, 3233 "description": "<p>Convert an HSLA array to RGBA.</p>\n<p>We need to change basis from HSLA to something that can be more easily be\nprojected onto RGBA. We will choose hue and brightness as our first two\ncomponents, and pick a convenient third one ('zest') so that we don't need\nto calculate formal HSBA saturation.</p>\n", 3234 "class": "p5", 3235 "module": "Conversion", 3236 "submodule": "Color Conversion" 3237 }, 3238 { 3239 "file": "src/color/color_conversion.js", 3240 "line": 188, 3241 "description": "<p>Convert an RGBA array to HSBA.</p>\n", 3242 "class": "p5", 3243 "module": "Conversion", 3244 "submodule": "Color Conversion" 3245 }, 3246 { 3247 "file": "src/color/color_conversion.js", 3248 "line": 227, 3249 "description": "<p>Convert an RGBA array to HSLA.</p>\n", 3250 "class": "p5", 3251 "module": "Conversion", 3252 "submodule": "Color Conversion" 3253 }, 3254 { 3255 "file": "src/color/creating_reading.js", 3256 "line": 16, 3257 "description": "<p>Extracts the alpha value from a color or pixel array.</p>\n", 3258 "itemtype": "method", 3259 "name": "alpha", 3260 "params": [ 3261 { 3262 "name": "color", 3263 "description": "<p>p5.Color object, color components,\n or CSS color</p>\n", 3264 "type": "p5.Color|Number[]|String" 3265 } 3266 ], 3267 "return": { 3268 "description": "the alpha value", 3269 "type": "Number" 3270 }, 3271 "example": [ 3272 "\n<div>\n<code>\nnoStroke();\nvar c = color(0, 126, 255, 102);\nfill(c);\nrect(15, 15, 35, 70);\nvar value = alpha(c); // Sets 'value' to 102\nfill(value);\nrect(50, 15, 35, 70);\n</code>\n</div>" 3273 ], 3274 "alt": "Left half of canvas light blue and right half light charcoal grey.\nLeft half of canvas light purple and right half a royal blue.\nLeft half of canvas salmon pink and the right half white.\nYellow rect in middle right of canvas, with 55 pixel width and height.\nYellow ellipse in top left canvas, black ellipse in bottom right,both 80x80.\nBright fuschia rect in middle of canvas, 60 pixel width and height.\nTwo bright green rects on opposite sides of the canvas, both 45x80.\nFour blue rects in each corner of the canvas, each are 35x35.\nBright sea green rect on left and darker rect on right of canvas, both 45x80.\nDark green rect on left and light green rect on right of canvas, both 45x80.\nDark blue rect on left and light teal rect on right of canvas, both 45x80.\nblue rect on left and green on right, both with black outlines & 35x60.\nsalmon pink rect on left and black on right, both 35x60.\n4 rects, tan, brown, brownish purple and purple, with white outlines & 20x60.\nlight pastel green rect on left and dark grey rect on right, both 35x60.\nyellow rect on left and red rect on right, both with black outlines & 35x60.\ngrey canvas\ndeep pink rect on left and grey rect on right, both 35x60.", 3275 "class": "p5", 3276 "module": "Color", 3277 "submodule": "Creating & Reading" 3278 }, 3279 { 3280 "file": "src/color/creating_reading.js", 3281 "line": 61, 3282 "description": "<p>Extracts the blue value from a color or pixel array.</p>\n", 3283 "itemtype": "method", 3284 "name": "blue", 3285 "params": [ 3286 { 3287 "name": "color", 3288 "description": "<p>p5.Color object, color components,\n or CSS color</p>\n", 3289 "type": "p5.Color|Number[]|String" 3290 } 3291 ], 3292 "return": { 3293 "description": "the blue value", 3294 "type": "Number" 3295 }, 3296 "example": [ 3297 "\n<div>\n<code>\nvar c = color(175, 100, 220); // Define color 'c'\nfill(c); // Use color variable 'c' as fill color\nrect(15, 20, 35, 60); // Draw left rectangle\n\nvar blueValue = blue(c); // Get blue in 'c'\nprint(blueValue); // Prints \"220.0\"\nfill(0, 0, blueValue); // Use 'blueValue' in new fill\nrect(50, 20, 35, 60); // Draw right rectangle\n</code>\n</div>" 3298 ], 3299 "alt": "Left half of canvas light purple and right half a royal blue.", 3300 "class": "p5", 3301 "module": "Color", 3302 "submodule": "Creating & Reading" 3303 }, 3304 { 3305 "file": "src/color/creating_reading.js", 3306 "line": 91, 3307 "description": "<p>Extracts the HSB brightness value from a color or pixel array.</p>\n", 3308 "itemtype": "method", 3309 "name": "brightness", 3310 "params": [ 3311 { 3312 "name": "color", 3313 "description": "<p>p5.Color object, color components,\n or CSS color</p>\n", 3314 "type": "p5.Color|Number[]|String" 3315 } 3316 ], 3317 "return": { 3318 "description": "the brightness value", 3319 "type": "Number" 3320 }, 3321 "example": [ 3322 "\n<div>\n<code>\nnoStroke();\ncolorMode(HSB, 255);\nvar c = color(0, 126, 255);\nfill(c);\nrect(15, 20, 35, 60);\nvar value = brightness(c); // Sets 'value' to 255\nfill(value);\nrect(50, 20, 35, 60);\n</code>\n</div>" 3323 ], 3324 "alt": "Left half of canvas salmon pink and the right half white.", 3325 "class": "p5", 3326 "module": "Color", 3327 "submodule": "Creating & Reading" 3328 }, 3329 { 3330 "file": "src/color/creating_reading.js", 3331 "line": 121, 3332 "description": "<p>Creates colors for storing in variables of the color datatype. The\nparameters are interpreted as RGB or HSB values depending on the\ncurrent colorMode(). The default mode is RGB values from 0 to 255\nand, therefore, the function call color(255, 204, 0) will return a\nbright yellow color.\n<br><br>\nNote that if only one value is provided to color(), it will be interpreted\nas a grayscale value. Add a second value, and it will be used for alpha\ntransparency. When three values are specified, they are interpreted as\neither RGB or HSB values. Adding a fourth value applies alpha\ntransparency.\n<br><br>
3332\nIf a single string argument is provided, RGB, RGBA and Hex CSS color\nstrings and all named color strings are supported. In this case, an alpha\nnumber value as a second argument is not supported, the RGBA form should be\nused.</p>\n", 3333 "itemtype": "method", 3334 "name": "color", 3335 "return": { 3336 "description": "resulting color", 3337 "type": "p5.Color" 3338 }, 3339 "example": [ 3340 "\n<div>\n<code>\nvar c = color(255, 204, 0); // Define color 'c'\nfill(c); // Use color variable 'c' as fill color\nnoStroke(); // Don't draw a stroke around shapes\nrect(30, 20, 55, 55); // Draw rectangle\n</code>\n</div>\n\n<div>\n<code>\nvar c = color(255, 204, 0); // Define color 'c'\nfill(c); // Use color variable 'c' as fill color\nnoStroke(); // Don't draw a stroke around shapes\nellipse(25, 25, 80, 80); // Draw left circle\n\n// Using only one value with color()\n// generates a grayscale value.\nc = color(65); // Update 'c' with grayscale value\nfill(c); // Use updated 'c' as fill color\nellipse(75, 75, 80, 80); // Draw right circle\n</code>\n</div>\n\n<div>\n<code>\n// Named SVG & CSS colors may be used,\nvar c = color('magenta');\nfill(c); // Use 'c' as fill color\nnoStroke(); // Don't draw a stroke around shapes\nrect(20, 20, 60, 60); // Draw rectangle\n</code>\n</div>\n\n<div>\n<code>\n// as can hex color codes:\nnoStroke(); // Don't draw a stroke around shapes\nvar c = color('#0f0');\nfill(c); // Use 'c' as fill color\nrect(0, 10, 45, 80); // Draw rectangle\n\nc = color('#00ff00');\nfill(c); // Use updated 'c' as fill color\nrect(55, 10, 45, 80); // Draw rectangle\n</code>\n</div>\n\n<div>\n<code>\n// RGB and RGBA color strings are also supported:\n// these all set to the same color (solid blue)\nvar c;\nnoStroke(); // Don't draw a stroke around shapes\nc = color('rgb(0,0,255)');\nfill(c); // Use 'c' as fill color\nrect(10, 10, 35, 35); // Draw rectangle\n\nc = color('rgb(0%, 0%, 100%)');\nfill(c); // Use updated 'c' as fill color\nrect(55, 10, 35, 35); // Draw rectangle\n\nc = color('rgba(0, 0, 255, 1)');\nfill(c); // Use updated 'c' as fill color\nrect(10, 55, 35, 35); // Draw rectangle\n\nc = color('rgba(0%, 0%, 100%, 1)');\nfill(c); // Use updated 'c' as fill color\nrect(55, 55, 35, 35); // Draw rectangle\n</code>\n</div>\n\n<div>\n<code>\n// HSL color is also supported and can be specified\n// by value\nvar c;\nnoStroke(); // Don't draw a stroke around shapes\nc = color('hsl(160, 100%, 50%)');\nfill(c); // Use 'c' as fill color\nrect(0, 10, 45, 80); // Draw rectangle\n\nc = color('hsla(160, 100%, 50%, 0.5)');\nfill(c); // Use updated 'c' as fill color\nrect(55, 10, 45, 80); // Draw rectangle\n</code>\n</div>\n\n<div>\n<code>\n// HSB color is also supported and can be specified\n// by value\nvar c;\nnoStroke(); // Don't draw a stroke around shapes\nc = color('hsb(160, 100%, 50%)');\nfill(c); // Use 'c' as fill color\nrect(0, 10, 45, 80); // Draw rectangle\n\nc = color('hsba(160, 100%, 50%, 0.5)');\nfill(c); // Use updated 'c' as fill color\nrect(55, 10, 45, 80); // Draw rectangle\n</code>\n</div>\n\n<div>\n<code>\nvar c; // Declare color 'c'\nnoStroke(); // Don't draw a stroke around shapes\n\n// If no colorMode is specified, then the\n// default of RGB with scale of 0-255 is used.\nc = color(50, 55, 100); // Create a color for 'c'\nfill(c); // Use color variable 'c' as fill color\nrect(0, 10, 45, 80); // Draw left rect\n\ncolorMode(HSB, 100); // Use HSB with scale of 0-100\nc = color(50, 55, 100); // Update 'c' with new color\nfill(c); // Use updated 'c' as fill color\nrect(55, 10, 45, 80); // Draw right rect\n</code>\n</div>" 3341 ], 3342 "alt": "Yellow rect in middle right of canvas, with 55 pixel width and height.\nYellow ellipse in top left of canvas, black ellipse in bottom right,both 80x80.\nBright fuschia rect in middle of canvas, 60 pixel width and height.\nTwo bright green rects on opposite sides of the canvas, both 45x80.\nFour blue rects in each corner of the canvas, each are 35x35.\nBright sea green rect on left and darker rect on right of canvas, both 45x80.\nDark green rect on left and lighter green rect on right of canvas, both 45x80.\nDark blue rect on left and light teal rect on right of canvas, both 45x80.", 3343 "class": "p5", 3344 "module": "Color", 3345 "submodule": "Creating & Reading", 3346 "overloads": [ 3347 { 3348 "line": 121, 3349 "params": [ 3350 { 3351 "name": "gray", 3352 "description": "<p>number specifying value between white\n and black.</p>\n", 3353 "type": "Number" 3354 }, 3355 { 3356 "name": "alpha", 3357 "description": "<p>alpha value relative to current color range\n (default is 0-255)</p>\n", 3358 "type": "Number", 3359 "optional": true 3360 } 3361 ], 3362 "return": { 3363 "description": "resulting color", 3364 "type": "p5.Color" 3365 } 3366 }, 3367 { 3368 "line": 280, 3369 "params": [ 3370 { 3371 "name": "v1", 3372 "description": "<p>red or hue value relative to\n the current color range</p>\n", 3373 "type": "Number" 3374 }, 3375 { 3376 "name": "v2", 3377 "description": "<p>
3377green or saturation value\n relative to the current color range</p>\n", 3378 "type": "Number" 3379 }, 3380 { 3381 "name": "v3", 3382 "description": "<p>blue or brightness value\n relative to the current color range</p>\n", 3383 "type": "Number" 3384 }, 3385 { 3386 "name": "alpha", 3387 "description": "", 3388 "type": "Number", 3389 "optional": true 3390 } 3391 ], 3392 "return": { 3393 "description": "", 3394 "type": "p5.Color" 3395 } 3396 }, 3397 { 3398 "line": 292, 3399 "params": [ 3400 { 3401 "name": "value", 3402 "description": "<p>a color string</p>\n", 3403 "type": "String" 3404 } 3405 ], 3406 "return": { 3407 "description": "", 3408 "type": "p5.Color" 3409 } 3410 }, 3411 { 3412 "line": 297, 3413 "params": [ 3414 { 3415 "name": "values", 3416 "description": "<p>an array containing the red,green,blue &\n and alpha components of the color</p>\n", 3417 "type": "Number[]" 3418 } 3419 ], 3420 "return": { 3421 "description": "", 3422 "type": "p5.Color" 3423 } 3424 }, 3425 { 3426 "line": 303, 3427 "params": [ 3428 { 3429 "name": "color", 3430 "description": "", 3431 "type": "p5.Color" 3432 } 3433 ], 3434 "return": { 3435 "description": "", 3436 "type": "p5.Color" 3437 } 3438 } 3439 ] 3440 }, 3441 { 3442 "file": "src/color/creating_reading.js", 3443 "line": 319, 3444 "description": "<p>Extracts the green value from a color or pixel array.</p>\n", 3445 "itemtype": "method", 3446 "name": "green", 3447 "params": [ 3448 { 3449 "name": "color", 3450 "description": "<p>p5.Color object, color components,\n or CSS color</p>\n", 3451 "type": "p5.Color|Number[]|String" 3452 } 3453 ], 3454 "return": { 3455 "description": "the green value", 3456 "type": "Number" 3457 }, 3458 "example": [ 3459 "\n<div>\n<code>\nvar c = color(20, 75, 200); // Define color 'c'\nfill(c); // Use color variable 'c' as fill color\nrect(15, 20, 35, 60); // Draw left rectangle\n\nvar greenValue = green(c); // Get green in 'c'\nprint(greenValue); // Print \"75.0\"\nfill(0, greenValue, 0); // Use 'greenValue' in new fill\nrect(50, 20, 35, 60); // Draw right rectangle\n</code>\n</div>" 3460 ], 3461 "alt": "blue rect on left and green on right, both with black outlines & 35x60.", 3462 "class": "p5", 3463 "module": "Color", 3464 "submodule": "Creating & Reading" 3465 }, 3466 { 3467 "file": "src/color/creating_reading.js", 3468 "line": 350, 3469 "description": "<p>Extracts the hue value from a color or pixel array.</p>\n<p>Hue exists in both HSB and HSL. This function will return the\nHSB-normalized hue when supplied with an HSB color object (or when supplied\nwith a pixel array while the color mode is HSB), but will default to the\nHSL-normalized hue otherwise. (The values will only be different if the\nmaximum hue setting for each system is different.)</p>\n", 3470 "itemtype": "method", 3471 "name": "hue", 3472 "params": [ 3473 { 3474 "name": "color", 3475 "description": "<p>p5.Color object, color components,\n or CSS color</p>\n", 3476 "type": "p5.Color|Number[]|String" 3477 } 3478 ], 3479 "return": { 3480 "description": "the hue", 3481 "type": "Number" 3482 }, 3483 "example": [ 3484 "\n<div>\n<code>\nnoStroke();\ncolorMode(HSB, 255);\nvar c = color(0, 126, 255);\nfill(c);\nrect(15, 20, 35, 60);\nvar value = hue(c); // Sets 'value' to \"0\"\nfill(value);\nrect(50, 20, 35, 60);\n</code>\n</div>" 3485 ], 3486 "alt": "salmon pink rect on left and black on right, both 35x60.", 3487 "class": "p5", 3488 "module": "Color", 3489 "submodule": "Creating & Reading" 3490 }, 3491 { 3492 "file": "src/color/creating_reading.js", 3493 "line": 387, 3494 "description": "<p>Blends two colors to find a third color somewhere between them. The amt\nparameter is the amount to interpolate between the two values where 0.0\nequal to the first color, 0.1 is very near the first color, 0.5 is halfway\nin between, etc. An amount below 0 will be treated as 0. Likewise, amounts\nabove 1 will be capped at 1. This is different from the behavior of lerp(),\nbut necessary because otherwise numbers outside the range will produce\nstrange and unexpected colors.\n<br><br>\nThe way that colours are interpolated depends on the current color mode.</p>\n", 3495 "itemtype": "method", 3496 "name": "lerpColor", 3497 "params": [ 3498 { 3499 "name": "c1", 3500 "description": "<p>interpolate from this color</p>\n", 3501 "type": "p5.Color" 3502 }, 3503 { 3504 "name": "c2", 3505 "description": "<p>interpolate to this color</p>\n", 3506 "type": "p5.Color" 3507 }, 3508 { 3509 "name": "amt", 3510 "description": "<p>number between 0 and 1</p>\n", 3511 "type": "Number" 3512 } 3513 ], 3514 "return": { 3515 "description": "interpolated color", 3516 "type": "p5.Color" 3517 }, 3518 "example": [ 3519 "\n<div>\n<code>\ncolorMode(RGB);
3519\nstroke(255);\nbackground(51);\nvar from = color(218, 165, 32);\nvar to = color(72, 61, 139);\ncolorMode(RGB); // Try changing to HSB.\nvar interA = lerpColor(from, to, 0.33);\nvar interB = lerpColor(from, to, 0.66);\nfill(from);\nrect(10, 20, 20, 60);\nfill(interA);\nrect(30, 20, 20, 60);\nfill(interB);\nrect(50, 20, 20, 60);\nfill(to);\nrect(70, 20, 20, 60);\n</code>\n</div>" 3520 ], 3521 "alt": "4 rects one tan, brown, brownish purple, purple, with white outlines & 20x60", 3522 "class": "p5", 3523 "module": "Color", 3524 "submodule": "Creating & Reading" 3525 }, 3526 { 3527 "file": "src/color/creating_reading.js", 3528 "line": 484, 3529 "description": "<p>Extracts the HSL lightness value from a color or pixel array.</p>\n", 3530 "itemtype": "method", 3531 "name": "lightness", 3532 "params": [ 3533 { 3534 "name": "color", 3535 "description": "<p>p5.Color object, color components,\n or CSS color</p>\n", 3536 "type": "p5.Color|Number[]|String" 3537 } 3538 ], 3539 "return": { 3540 "description": "the lightness", 3541 "type": "Number" 3542 }, 3543 "example": [ 3544 "\n<div>\n<code>\nnoStroke();\ncolorMode(HSL);\nvar c = color(156, 100, 50, 1);\nfill(c);\nrect(15, 20, 35, 60);\nvar value = lightness(c); // Sets 'value' to 50\nfill(value);\nrect(50, 20, 35, 60);\n</code>\n</div>" 3545 ], 3546 "alt": "light pastel green rect on left and dark grey rect on right, both 35x60.", 3547 "class": "p5", 3548 "module": "Color", 3549 "submodule": "Creating & Reading" 3550 }, 3551 { 3552 "file": "src/color/creating_reading.js", 3553 "line": 514, 3554 "description": "<p>Extracts the red value from a color or pixel array.</p>\n", 3555 "itemtype": "method", 3556 "name": "red", 3557 "params": [ 3558 { 3559 "name": "color", 3560 "description": "<p>p5.Color object, color components,\n or CSS color</p>\n", 3561 "type": "p5.Color|Number[]|String" 3562 } 3563 ], 3564 "return": { 3565 "description": "the red value", 3566 "type": "Number" 3567 }, 3568 "example": [ 3569 "\n<div>\n<code>\nvar c = color(255, 204, 0); // Define color 'c'\nfill(c); // Use color variable 'c' as fill color\nrect(15, 20, 35, 60); // Draw left rectangle\n\nvar redValue = red(c); // Get red in 'c'\nprint(redValue); // Print \"255.0\"\nfill(redValue, 0, 0); // Use 'redValue' in new fill\nrect(50, 20, 35, 60); // Draw right rectangle\n</code>\n</div>\n\n<div>\n<code>\ncolorMode(RGB, 255);\nvar c = color(127, 255, 0);\ncolorMode(RGB, 1);\nvar myColor = red(c);\nprint(myColor);\n</code>\n</div>" 3570 ], 3571 "alt": "yellow rect on left and red rect on right, both with black outlines and 35x60.\ngrey canvas", 3572 "class": "p5", 3573 "module": "Color", 3574 "submodule": "Creating & Reading" 3575 }, 3576 { 3577 "file": "src/color/creating_reading.js", 3578 "line": 554, 3579 "description": "<p>Extracts the saturation value from a color or pixel array.</p>\n<p>Saturation is scaled differently in HSB and HSL. This function will return\nthe HSB saturation when supplied with an HSB color object (or when supplied\nwith a pixel array while the color mode is HSB), but will default to the\nHSL saturation otherwise.</p>\n", 3580 "itemtype": "method", 3581 "name": "saturation", 3582 "params": [ 3583 { 3584 "name": "color", 3585 "description": "<p>p5.Color object, color components,\n or CSS color</p>\n", 3586 "type": "p5.Color|Number[]|String" 3587 } 3588 ], 3589 "return": { 3590 "description": "the saturation value", 3591 "type": "Number" 3592 }, 3593 "example": [ 3594 "\n<div>\n<code>\nnoStroke();\ncolorMode(HSB, 255);\nvar c = color(0, 126, 255);\nfill(c);\nrect(15, 20, 35, 60);\nvar value = saturation(c); // Sets 'value' to 126\nfill(value);\nrect(50, 20, 35, 60);\n</code>\n</div>" 3595 ], 3596 "alt": "deep pink rect on left and grey rect on right, both 35x60.", 3597 "class": "p5", 3598 "module": "Color", 3599 "submodule": "Creating & Reading" 3600 }, 3601 { 3602 "file": "src/color/p5.Color.js", 3603 "line": 52, 3604 "description": "<p>This function returns the color formatted as a string. This can be useful\nfor debugging, or for using p5.js with other libraries.</p>\n", 3605 "itemtype": "method", 3606 "name": "toString", 3607 "params": [ 3608 { 3609 "name": "format", 3610 "description": "<p>How the color string will be formatted.\nLeaving this empty formats the string as rgba(r, g, b, a).\n'#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", 3611 "type": "String", 3612 "optional": true 3613 } 3614 ], 3615 "return": { 3616 "description": "the formatted string", 3617 "type": "String" 3618 }, 3619 "example": [ 3620 "\n<div>\n<code>\nvar myColor;\nfunction setup() {\n createCanvas(200, 200);
3620\n stroke(255);\n myColor = color(100, 100, 250);\n fill(myColor);\n}\n\nfunction draw() {\n text(myColor.toString(), 10, 10);\n text(myColor.toString('#rrggbb'), 10, 95);\n text(myColor.toString('rgba%'), 10, 180);\n}\n</code>\n</div>" 3621 ], 3622 "alt": "canvas with text representation of color", 3623 "class": "p5.Color", 3624 "module": "Color", 3625 "submodule": "Creating & Reading" 3626 }, 3627 { 3628 "file": "src/color/p5.Color.js", 3629 "line": 247, 3630 "itemtype": "method", 3631 "name": "setRed", 3632 "params": [ 3633 { 3634 "name": "red", 3635 "description": "<p>the new red value</p>\n", 3636 "type": "Number" 3637 } 3638 ], 3639 "example": [ 3640 "\n<div>\n<code>\nvar backgroundColor;\n\nfunction setup() {\n backgroundColor = color(100, 50, 150);\n}\n\nfunction draw() {\n backgroundColor.setRed(128 + 128 * sin(millis() / 1000));\n background(backgroundColor);\n}\n</code>\n</div>" 3641 ], 3642 "alt": "canvas with gradually changing background color", 3643 "class": "p5.Color", 3644 "module": "Color", 3645 "submodule": "Creating & Reading" 3646 }, 3647 { 3648 "file": "src/color/p5.Color.js", 3649 "line": 274, 3650 "itemtype": "method", 3651 "name": "setGreen", 3652 "params": [ 3653 { 3654 "name": "green", 3655 "description": "<p>the new green value</p>\n", 3656 "type": "Number" 3657 } 3658 ], 3659 "example": [ 3660 "\n<div>\n<code>\nvar backgroundColor;\n\nfunction setup() {\n backgroundColor = color(100, 50, 150);\n}\n\nfunction draw() {\n backgroundColor.setGreen(128 + 128 * sin(millis() / 1000));\n background(backgroundColor);\n}\n</code>\n</div>" 3661 ], 3662 "alt": "canvas with gradually changing background color", 3663 "class": "p5.Color", 3664 "module": "Color", 3665 "submodule": "Creating & Reading" 3666 }, 3667 { 3668 "file": "src/color/p5.Color.js", 3669 "line": 301, 3670 "itemtype": "method", 3671 "name": "setBlue", 3672 "params": [ 3673 { 3674 "name": "blue", 3675 "description": "<p>the new blue value</p>\n", 3676 "type": "Number" 3677 } 3678 ], 3679 "example": [ 3680 "\n<div>\n<code>\nvar backgroundColor;\n\nfunction setup() {\n backgroundColor = color(100, 50, 150);\n}\n\nfunction draw() {\n backgroundColor.setBlue(128 + 128 * sin(millis() / 1000));\n background(backgroundColor);\n}\n</code>\n</div>" 3681 ], 3682 "alt": "canvas with gradually changing background color", 3683 "class": "p5.Color", 3684 "module": "Color", 3685 "submodule": "Creating & Reading" 3686 }, 3687 { 3688 "file": "src/color/p5.Color.js", 3689 "line": 328, 3690 "itemtype": "method", 3691 "name": "setAlpha", 3692 "params": [ 3693 { 3694 "name": "alpha", 3695 "description": "<p>the new alpha value</p>\n", 3696 "type": "Number" 3697 } 3698 ], 3699 "example": [ 3700 "\n<div>\n<code>\nvar squareColor;\n\nfunction setup() {\n ellipseMode(CORNERS);\n strokeWeight(4);\n squareColor = color(100, 50, 150);\n}\n\nfunction draw() {\n background(255);\n\n noFill();\n stroke(0);\n ellipse(10, 10, width - 10, height - 10);\n\n squareColor.setAlpha(128 + 128 * sin(millis() / 1000));\n fill(squareColor);\n noStroke();\n rect(13, 13, width - 26, height - 26);\n}\n</code>\n</div>" 3701 ], 3702 "alt": "circle behind a square with gradually changing opacity", 3703 "class": "p5.Color", 3704 "module": "Color", 3705 "submodule": "Creating & Reading" 3706 }, 3707 { 3708 "file": "src/color/p5.Color.js", 3709 "line": 406, 3710 "description": "<p>Hue is the same in HSB and HSL, but the maximum value may be different.\nThis function will return the HSB-normalized saturation when supplied with\nan HSB color object, but will default to the HSL-normalized saturation\notherwise.</p>\n", 3711 "class": "p5.Color", 3712 "module": "Color", 3713 "submodule": "Creating & Reading" 3714 }, 3715 { 3716 "file": "src/color/p5.Color.js", 3717 "line": 437, 3718 "description": "<p>Saturation is scaled differently in HSB and HSL. This function will return\nthe HSB saturation when supplied with an HSB color object, but will default\nto the HSL saturation otherwise.</p>\n", 3719 "class": "p5.Color", 3720 "module": "Color", 3721 "submodule": "Creating & Reading" 3722 }, 3723 { 3724 "file": "src/color/p5.Color.js", 3725 "line": 456, 3726 "description": "<p>CSS named colors.</p>\n", 3727 "class": "p5.Color", 3728 "module": "Color", 3729 "submodule": "Creating & Reading" 3730 }, 3731 { 3732 "file": "src/color/p5.Color.js", 3733 "line": 609, 3734 "description": "<p>These regular expressions are used to build up the patterns for matching\nviable CSS color strings: fragmenting the regexes in this way increases the\nlegibility and comprehensibility of the code.</p>\n<p>Note that RGB values of .9 are not parsed by IE, but are supported here for\ncolor string consistency.</p>\n", 3735 "class": "p5.Color", 3736 "module": "Color", 3737 "submodule": "Creating & Reading" 3738 }, 3739 { 3740 "file": "src/color/p5.Color.js", 3741 "line": 622, 3742 "description": "<p>Full color string patterns. The capture groups are necessary.</p>\n", 3743 "class": "p5.Color", 3744 "module": "Color", 3745 "submodule": "Creating & Reading" 3746 }, 3747 { 3748 "file": "src/color/p5.Color.js", 3749 "line": 976, 3750 "description": "<p>For HSB and HSL, interpret the gray level as a brightness/lightness\nvalue (they are equivalent when chroma is zero). For RGB, normalize the\ngray level according to the blue maximum.</p>\n", 3751 "class": "p5.Color", 3752 "module": "Color", 3753 "submodule": "Creating & Reading" 3754 }, 3755 { 3756 "file": "src/color/setting.js", 3757 "line": 15, 3758 "description": "<p>The background() function sets the color used for the background of the\np5.js canvas. The default background is light gray. This function is\ntypically used within draw() to clear the display window at the beginning\nof each frame, but it can be used inside setup() to set the background on\nthe first frame of animation or if the background need only be set once.\n<br><br>\nThe color is either specified in terms of the RGB, HSB, or HSL color\ndepending on the current colorMode. (The default color space is RGB, with\neach value in the range from 0 to 255). The alpha range by default is also 0 to 255.\n<br><br>
3758\nIf a single string argument is provided, RGB, RGBA and Hex CSS color strings\nand all named color strings are supported. In this case, an alpha number\nvalue as a second argument is not supported, the RGBA form should be used.\n<br><br>\nA p5.Color object can also be provided to set the background color.\n<br><br>\nA p5.Image can also be provided to set the background image.</p>\n", 3759 "itemtype": "method", 3760 "name": "background", 3761 "chainable": 1, 3762 "example": [ 3763 "\n<div>\n<code>\n// Grayscale integer value\nbackground(51);\n</code>\n</div>\n\n<div>\n<code>\n// R, G & B integer values\nbackground(255, 204, 0);\n</code>\n</div>\n\n<div>\n<code>\n// H, S & B integer values\ncolorMode(HSB);\nbackground(255, 204, 100);\n</code>\n</div>\n\n<div>\n<code>\n// Named SVG/CSS color string\nbackground('red');\n</code>\n</div>\n\n<div>\n<code>\n// three-digit hexadecimal RGB notation\nbackground('#fae');\n</code>\n</div>\n\n<div>\n<code>\n// six-digit hexadecimal RGB notation\nbackground('#222222');\n</code>\n</div>\n\n<div>\n<code>\n// integer RGB notation\nbackground('rgb(0,255,0)');\n</code>\n</div>\n\n<div>\n<code>\n// integer RGBA notation\nbackground('rgba(0,255,0, 0.25)');\n</code>\n</div>\n\n<div>\n<code>\n// percentage RGB notation\nbackground('rgb(100%,0%,10%)');\n</code>\n</div>\n\n<div>\n<code>\n// percentage RGBA notation\nbackground('rgba(100%,0%,100%,0.5)');\n</code>\n</div>\n\n<div>\n<code>\n// p5 Color object\nbackground(color(0, 0, 255));\n</code>\n</div>" 3764 ], 3765 "alt": "canvas with darkest charcoal grey background.\ncanvas with yellow background.\ncanvas with royal blue background.\ncanvas with red background.\ncanvas with pink background.\ncanvas with black background.\ncanvas with bright green background.\ncanvas with soft green background.\ncanvas with red background.\ncanvas with light purple background.\ncanvas with blue background.", 3766 "class": "p5", 3767 "module": "Color", 3768 "submodule": "Setting", 3769 "overloads": [ 3770 { 3771 "line": 15, 3772 "params": [ 3773 { 3774 "name": "color", 3775 "description": "<p>any value created by the color() function</p>\n", 3776 "type": "p5.Color" 3777 } 3778 ], 3779 "chainable": 1 3780 }, 3781 { 3782 "line": 131, 3783 "params": [ 3784 { 3785 "name": "colorstring", 3786 "description": "<p>color string, possible formats include: integer\n rgb() or rgba(), percentage rgb() or rgba(),\n 3-digit hex, 6-digit hex</p>\n", 3787 "type": "String" 3788 }, 3789 { 3790 "name": "a", 3791 "description": "<p>opacity of the background relative to current\n color range (default is 0-255)</p>\n", 3792 "type": "Number", 3793 "optional": true 3794 } 3795 ], 3796 "chainable": 1 3797 }, 3798 { 3799 "line": 141, 3800 "params": [ 3801 { 3802 "name": "gray", 3803 "description": "<p>specifies a value between white and black</p>\n", 3804 "type": "Number" 3805 }, 3806 { 3807 "name": "a", 3808 "description": "", 3809 "type": "Number", 3810 "optional": true 3811 } 3812 ], 3813 "chainable": 1 3814 }, 3815 { 3816 "line": 148, 3817 "params": [ 3818 { 3819 "name": "v1", 3820 "description": "<p>red or hue value (depending on the current color\n mode)</p>\n", 3821 "type": "Number" 3822 }, 3823 { 3824 "name": "v2", 3825 "description": "<p>green or saturation value (depending on the current\n color mode)</p>\n", 3826 "type": "Number" 3827 }, 3828 { 3829 "name": "v3", 3830 "description": "<p>blue or brightness value (depending on the current\n color mode)</p>\n", 3831 "type": "Number" 3832 }, 3833 { 3834 "name": "a", 3835 "description": "", 3836 "type": "Number", 3837 "optional": true 3838 } 3839 ], 3840 "chainable": 1 3841 }, 3842 { 3843 "line": 160,
3844 "params": [ 3845 { 3846 "name": "values", 3847 "description": "<p>an array containing the red,green,blue &\n and alpha components of the color</p>\n", 3848 "type": "Number[]" 3849 } 3850 ], 3851 "chainable": 1 3852 }, 3853 { 3854 "line": 167, 3855 "params": [ 3856 { 3857 "name": "image", 3858 "description": "<p>image created with loadImage() or createImage(),\n to set as background\n (must be same size as the sketch window)</p>\n", 3859 "type": "p5.Image" 3860 }, 3861 { 3862 "name": "a", 3863 "description": "", 3864 "type": "Number", 3865 "optional": true 3866 } 3867 ], 3868 "chainable": 1 3869 } 3870 ] 3871 }, 3872 { 3873 "file": "src/color/setting.js", 3874 "line": 185, 3875 "description": "<p>Clears the pixels within a buffer. This function only works on p5.Canvas\nobjects created with the createCanvas() function; it won't work with the\nmain display window. Unlike the main graphics context, pixels in\nadditional graphics areas created with createGraphics() can be entirely\nor partially transparent. This function clears everything to make all of\nthe pixels 100% transparent.</p>\n", 3876 "itemtype": "method", 3877 "name": "clear", 3878 "chainable": 1, 3879 "example": [ 3880 "\n<div>\n<code>\n// Clear the screen on mouse press.\nfunction setup() {\n createCanvas(100, 100);\n}\n\nfunction draw() {\n ellipse(mouseX, mouseY, 20, 20);\n}\n\nfunction mousePressed() {\n clear();\n}\n</code>\n</div>" 3881 ], 3882 "alt": "20x20 white ellipses are continually drawn at mouse x and y coordinates.", 3883 "class": "p5", 3884 "module": "Color", 3885 "submodule": "Setting" 3886 }, 3887 { 3888 "file": "src/color/setting.js", 3889 "line": 223, 3890 "description": "<p>colorMode() changes the way p5.js interprets color data. By default, the\nparameters for fill(), stroke(), background(), and color() are defined by\nvalues between 0 and 255 using the RGB color model. This is equivalent to\nsetting colorMode(RGB, 255). Setting colorMode(HSB) lets you use the HSB\nsystem instead. By default, this is colorMode(HSB, 360, 100, 100, 1). You\ncan also use HSL.\n<br><br>\nNote: existing color objects remember the mode that they were created in,\nso you can change modes as you like without affecting their appearance.</p>\n", 3891 "itemtype": "method", 3892 "name": "colorMode", 3893 "chainable": 1, 3894 "example": [ 3895 "\n<div>\n<code>\nnoStroke();\ncolorMode(RGB, 100);\nfor (var i = 0; i < 100; i++) {\n for (var j = 0; j < 100; j++) {\n stroke(i, j, 0);\n point(i, j);\n }\n}\n</code>\n</div>\n\n<div>\n<code>\nnoStroke();\ncolorMode(HSB, 100);\nfor (var i = 0; i < 100; i++) {\n for (var j = 0; j < 100; j++) {\n stroke(i, j, 100);\n point(i, j);\n }\n}\n</code>\n</div>\n\n<div>\n<code>\ncolorMode(RGB, 255);\nvar c = color(127, 255, 0);\n\ncolorMode(RGB, 1);\nvar myColor = c._getRed();\ntext(myColor, 10, 10, 80, 80);\n</code>\n</div>\n\n<div>\n<code>\nnoFill();\ncolorMode(RGB, 255, 255, 255, 1);\nbackground(255);\n\nstrokeWeight(4);\nstroke(255, 0, 10, 0.3);\nellipse(40, 40, 50, 50);\nellipse(50, 50, 40, 40);\n</code>\n</div>" 3896 ], 3897 "alt": "Green to red gradient from bottom L to top R. shading originates from top left.\nRainbow gradient from left to right. Brightness increasing to white at top.\nunknown image.\n50x50 ellipse at middle L & 40x40 ellipse at center. Transluscent pink outlines.", 3898 "class": "p5", 3899 "module": "Color", 3900 "submodule": "Setting", 3901 "overloads": [ 3902 { 3903 "line": 223, 3904 "params": [ 3905 { 3906 "name": "mode", 3907 "description": "<p>either RGB, HSB or HSL, corresponding to\n Red/Green/Blue and Hue/Saturation/Brightness\n (or Lightness)</p>\n", 3908 "type": "Constant" 3909 }, 3910 { 3911 "name": "max", 3912 "description": "<p>range for all values</p>\n", 3913 "type": "Number", 3914 "optional": true 3915 } 3916 ], 3917 "chainable": 1 3918 }, 3919 { 3920 "line": 300, 3921 "params": [ 3922 { 3923 "name": "mode", 3924 "description": "", 3925 "type": "Constant" 3926 }, 3927 { 3928 "name": "max1", 3929 "description": "<p>range for the red or hue depending on the\n current color mode</p>\n", 3930 "type": "Number" 3931 }, 3932 { 3933 "name": "max2", 3934 "description": "<p>range for the green or saturation depending\n on the current color mode</p>\n", 3935 "type": "Number" 3936 }, 3937 { 3938 "name": "max3", 3939 "description": "<p>range for the blue or brightness/lighntess\n depending on the current color mode</p>\n", 3940 "type": "Number" 3941 }, 3942 { 3943 "name": "maxA", 3944 "description": "<p>range for the alpha</p>\n", 3945 "type": "Number", 3946 "optional": true 3947 } 3948 ], 3949 "chainable": 1 3950 } 3951 ] 3952 }, 3953 { 3954 "file": "src/color/setting.js", 3955 "line": 344, 3956 "description": "<p>Sets the color used to fill shapes. For example, if you run\nfill(204, 102, 0), all subsequent shapes will be filled with orange. This\ncolor is either specified in terms of the RGB or HSB color depending on\nthe current colorMode(). (The default color space is RGB, with each value\nin the range from 0 to 255). The alpha range by default is also 0 to 255.\n<br><br>
3956\nIf a single string argument is provided, RGB, RGBA and Hex CSS color strings\nand all named color strings are supported. In this case, an alpha number\nvalue as a second argument is not supported, the RGBA form should be used.\n<br><br>\nA p5 Color object can also be provided to set the fill color.</p>\n", 3957 "itemtype": "method", 3958 "name": "fill", 3959 "chainable": 1, 3960 "example": [ 3961 "\n<div>\n<code>\n// Grayscale integer value\nfill(51);\nrect(20, 20, 60, 60);\n</code>\n</div>\n\n<div>\n<code>\n// R, G & B integer values\nfill(255, 204, 0);\nrect(20, 20, 60, 60);\n</code>\n</div>\n\n<div>\n<code>\n// H, S & B integer values\ncolorMode(HSB);\nfill(255, 204, 100);\nrect(20, 20, 60, 60);\n</code>\n</div>\n\n<div>\n<code>\n// Named SVG/CSS color string\nfill('red');\nrect(20, 20, 60, 60);\n</code>\n</div>\n\n<div>\n<code>\n// three-digit hexadecimal RGB notation\nfill('#fae');\nrect(20, 20, 60, 60);\n</code>\n</div>\n\n<div>\n<code>\n// six-digit hexadecimal RGB notation\nfill('#222222');\nrect(20, 20, 60, 60);\n</code>\n</div>\n\n<div>\n<code>\n// integer RGB notation\nfill('rgb(0,255,0)');\nrect(20, 20, 60, 60);\n</code>\n</div>\n\n<div>\n<code>\n// integer RGBA notation\nfill('rgba(0,255,0, 0.25)');\nrect(20, 20, 60, 60);\n</code>\n</div>\n\n<div>\n<code>\n// percentage RGB notation\nfill('rgb(100%,0%,10%)');\nrect(20, 20, 60, 60);\n</code>\n</div>\n\n<div>\n<code>\n// percentage RGBA notation\nfill('rgba(100%,0%,100%,0.5)');\nrect(20, 20, 60, 60);\n</code>\n</div>\n\n<div>\n<code>\n// p5 Color object\nfill(color(0, 0, 255));\nrect(20, 20, 60, 60);\n</code>\n</div>" 3962 ], 3963 "alt": "60x60 dark charcoal grey rect with black outline in center of canvas.\n60x60 yellow rect with black outline in center of canvas.\n60x60 royal blue rect with black outline in center of canvas.\n60x60 red rect with black outline in center of canvas.\n60x60 pink rect with black outline in center of canvas.\n60x60 black rect with black outline in center of canvas.\n60x60 light green rect with black outline in center of canvas.\n60x60 soft green rect with black outline in center of canvas.\n60x60 red rect with black outline in center of canvas.\n60x60 dark fushcia rect with black outline in center of canvas.\n60x60 blue rect with black outline in center of canvas.", 3964 "class": "p5", 3965 "module": "Color", 3966 "submodule": "Setting", 3967 "overloads": [ 3968 { 3969 "line": 344, 3970 "params": [ 3971 { 3972 "name": "v1", 3973 "description": "<p>red or hue value relative to\n the current color range</p>\n", 3974 "type": "Number" 3975 }, 3976 { 3977 "name": "v2", 3978 "description": "<p>green or saturation value\n relative to the current color range</p>\n", 3979 "type": "Number" 3980 }, 3981 { 3982 "name": "v3", 3983 "description": "<p>blue or brightness value\n relative to the current color range</p>\n", 3984 "type": "Number" 3985 }, 3986 { 3987 "name": "alpha", 3988 "description": "", 3989 "type": "Number", 3990 "optional": true 3991 } 3992 ], 3993 "chainable": 1 3994 }, 3995 { 3996 "line": 469, 3997 "params": [ 3998 { 3999 "name": "value", 4000 "description": "<p>a color string</p>\n", 4001 "type": "String" 4002 } 4003 ], 4004 "chainable": 1 4005 }, 4006 { 4007 "line": 475, 4008 "params": [ 4009 { 4010 "name": "gray", 4011 "description": "<p>a gray value</p>\n", 4012 "type": "Number" 4013 }, 4014 { 4015 "name": "alpha", 4016 "description": "", 4017 "type": "Number", 4018 "optional": true 4019 } 4020 ], 4021 "chainable": 1 4022 }, 4023 { 4024 "line": 482, 4025 "params": [ 4026 { 4027 "name": "values", 4028 "description": "<p>an array containing the red,green,blue &\n and alpha components of the color</p>\n", 4029 "type": "Number[]" 4030 } 4031 ], 4032 "chainable": 1 4033 }, 4034 { 4035 "line": 489, 4036 "params": [ 4037 { 4038 "name": "color", 4039 "description": "<p>the fill color</p>\n", 4040 "type": "p5.Color" 4041 } 4042 ], 4043 "chainable": 1 4044 } 4045 ] 4046 }, 4047 { 4048 "file": "src/color/setting.js", 4049 "line": 501, 4050 "description": "<p>Disables filling geometry. If both noStroke() and noFill() are called,\nnothing will be drawn to the screen.</p>\n", 4051 "itemtype": "method", 4052 "name": "noFill", 4053 "chainable": 1, 4054 "example": [ 4055 "\n<div>\n<code>\nrect(15, 10, 55, 55);\nnoFill();\nrect(20, 20, 60, 60);\n</code>\n</div>\n\n<div modernizr='webgl'>\n<code>\nfunction setup() {\n createCanvas(100, 100, WEBGL);\n}\n\nfunction draw() {\n background(0);\n noFill();\n stroke(100, 100, 240);\n rotateX(frameCount * 0.01);\n rotateY(frameCount * 0.01);\n box(45, 45, 45);\n}\n</code>\n</div>" 4056 ], 4057 "alt": "white rect top middle and noFill rect center. Both 60x60 with black outlines.\nblack canvas with purple cube wireframe spinning", 4058 "class": "p5", 4059 "module": "Color", 4060 "submodule": "Setting" 4061 }, 4062 { 4063 "file": "src/color/setting.js", 4064 "line": 542, 4065 "description": "<p>Disables drawing the stroke (outline). If both noStroke() and noFill()\nare c
4065alled, nothing will be drawn to the screen.</p>\n", 4066 "itemtype": "method", 4067 "name": "noStroke", 4068 "chainable": 1, 4069 "example": [ 4070 "\n<div>\n<code>\nnoStroke();\nrect(20, 20, 60, 60);\n</code>\n</div>\n\n<div modernizr='webgl'>\n<code>\nfunction setup() {\n createCanvas(100, 100, WEBGL);\n}\n\nfunction draw() {\n background(0);\n noStroke();\n fill(240, 150, 150);\n rotateX(frameCount * 0.01);\n rotateY(frameCount * 0.01);\n box(45, 45, 45);\n}\n</code>\n</div>" 4071 ], 4072 "alt": "60x60 white rect at center. no outline.\nblack canvas with pink cube spinning", 4073 "class": "p5", 4074 "module": "Color", 4075 "submodule": "Setting" 4076 }, 4077 { 4078 "file": "src/color/setting.js", 4079 "line": 582, 4080 "description": "<p>Sets the color used to draw lines and borders around shapes. This color\nis either specified in terms of the RGB or HSB color depending on the\ncurrent colorMode() (the default color space is RGB, with each value in\nthe range from 0 to 255). The alpha range by default is also 0 to 255.\n<br><br>\nIf a single string argument is provided, RGB, RGBA and Hex CSS color\nstrings and all named color strings are supported. In this case, an alpha\nnumber value as a second argument is not supported, the RGBA form should be\nused.\n<br><br>\nA p5 Color object can also be provided to set the stroke color.</p>\n", 4081 "itemtype": "method", 4082 "name": "stroke", 4083 "chainable": 1, 4084 "example": [ 4085 "\n<div>\n<code>\n// Grayscale integer value\nstrokeWeight(4);\nstroke(51);\nrect(20, 20, 60, 60);\n</code>\n</div>\n\n<div>\n<code>\n// R, G & B integer values\nstroke(255, 204, 0);\nstrokeWeight(4);\nrect(20, 20, 60, 60);\n</code>\n</div>\n\n<div>\n<code>\n// H, S & B integer values\ncolorMode(HSB);\nstrokeWeight(4);\nstroke(255, 204, 100);\nrect(20, 20, 60, 60);\n</code>\n</div>\n\n<div>\n<code>\n// Named SVG/CSS color string\nstroke('red');\nstrokeWeight(4);\nrect(20, 20, 60, 60);\n</code>\n</div>\n\n<div>\n<code>\n// three-digit hexadecimal RGB notation\nstroke('#fae');\nstrokeWeight(4);\nrect(20, 20, 60, 60);\n</code>\n</div>\n\n<div>\n<code>\n// six-digit hexadecimal RGB notation\nstroke('#222222');\nstrokeWeight(4);\nrect(20, 20, 60, 60);\n</code>\n</div>\n\n<div>\n<code>\n// integer RGB notation\nstroke('rgb(0,255,0)');\nstrokeWeight(4);\nrect(20, 20, 60, 60);\n</code>\n</div>\n\n<div>\n<code>\n// integer RGBA notation\nstroke('rgba(0,255,0,0.25)');\nstrokeWeight(4);\nrect(20, 20, 60, 60);\n</code>\n</div>\n\n<div>\n<code>\n// percentage RGB notation\nstroke('rgb(100%,0%,10%)');\nstrokeWeight(4);\nrect(20, 20, 60, 60);\n</code>\n</div>\n\n<div>\n<code>\n// percentage RGBA notation\nstroke('rgba(100%,0%,100%,0.5)');\nstrokeWeight(4);\nrect(20, 20, 60, 60);\n</code>\n</div>\n\n<div>\n<code>\n// p5 Color object\nstroke(color(0, 0, 255));\nstrokeWeight(4);\nrect(20, 20, 60, 60);\n</code>\n</div>" 4086 ], 4087 "alt": "60x60 white rect at center. Dark charcoal grey outline.\n60x60 white rect at center. Yellow outline.\n60x60 white rect at center. Royal blue outline.\n60x60 white rect at center. Red outline.\n60x60 white rect at center. Pink outline.\n60x60 white rect at center. Black outline.\n60x60 white rect at center. Bright green outline.\n60x60 white rect at center. Soft green outline.\n60x60 white rect at center. Red outline.\n60x60 white rect at center. Dark fushcia outline.\n60x60 white rect at center. Blue outline.", 4088 "class": "p5", 4089 "module": "Color", 4090 "submodule": "Setting", 4091 "overloads": [ 4092 { 4093 "line": 582, 4094 "params": [ 4095 { 4096 "name": "v1", 4097 "description": "<p>red or hue value relative to\n the current color range</p>\n", 4098 "type": "Number" 4099 }, 4100 { 4101 "name": "v2", 4102 "description": "<p>
4102green or saturation value\n relative to the current color range</p>\n", 4103 "type": "Number" 4104 }, 4105 { 4106 "name": "v3", 4107 "description": "<p>blue or brightness value\n relative to the current color range</p>\n", 4108 "type": "Number" 4109 }, 4110 { 4111 "name": "alpha", 4112 "description": "", 4113 "type": "Number", 4114 "optional": true 4115 } 4116 ], 4117 "chainable": 1 4118 }, 4119 { 4120 "line": 721, 4121 "params": [ 4122 { 4123 "name": "value", 4124 "description": "<p>a color string</p>\n", 4125 "type": "String" 4126 } 4127 ], 4128 "chainable": 1 4129 }, 4130 { 4131 "line": 727, 4132 "params": [ 4133 { 4134 "name": "gray", 4135 "description": "<p>a gray value</p>\n", 4136 "type": "Number" 4137 }, 4138 { 4139 "name": "alpha", 4140 "description": "", 4141 "type": "Number", 4142 "optional": true 4143 } 4144 ], 4145 "chainable": 1 4146 }, 4147 { 4148 "line": 734, 4149 "params": [ 4150 { 4151 "name": "values", 4152 "description": "<p>an array containing the red,green,blue &\n and alpha components of the color</p>\n", 4153 "type": "Number[]" 4154 } 4155 ], 4156 "chainable": 1 4157 }, 4158 { 4159 "line": 741, 4160 "params": [ 4161 { 4162 "name": "color", 4163 "description": "<p>the stroke color</p>\n", 4164 "type": "p5.Color" 4165 } 4166 ], 4167 "chainable": 1 4168 } 4169 ] 4170 }, 4171 { 4172 "file": "src/core/2d_primitives.js", 4173 "line": 16, 4174 "description": "<p>Draw an arc to the screen. If called with only x, y, w, h, start, and\nstop, the arc will be drawn and filled as an open pie segment. If a mode parameter is provided, the arc\nwill be filled like an open semi-circle (OPEN) , a closed semi-circle (CHORD), or as a closed pie segment (PIE). The\norigin may be changed with the ellipseMode() function.<br><br>\nNote that drawing a full circle (ex: 0 to TWO_PI) will appear blank\nbecause 0 and TWO_PI are the same position on the unit circle. The\nbest way to handle this is by using the ellipse() function instead\nto create a closed ellipse, and to use the arc() function\nonly to draw parts of an ellipse.</p>\n", 4175 "itemtype": "method", 4176 "name": "arc", 4177 "params": [ 4178 { 4179 "name": "x", 4180 "description": "<p>x-coordinate of the arc's ellipse</p>\n", 4181 "type": "Number" 4182 }, 4183 { 4184 "name": "y", 4185 "description": "<p>y-coordinate of the arc's ellipse</p>\n", 4186 "type": "Number" 4187 }, 4188 { 4189 "name": "w", 4190 "description": "<p>width of the arc's ellipse by default</p>\n", 4191 "type": "Number" 4192 }, 4193 { 4194 "name": "h", 4195 "description": "<p>height of the arc's ellipse by default</p>\n", 4196 "type": "Number" 4197 }, 4198 { 4199 "name": "start", 4200 "description": "<p>angle to start the arc, specified in radians</p>\n", 4201 "type": "Number" 4202 }, 4203 { 4204 "name": "stop", 4205 "description": "<p>angle to stop the arc, specified in radians</p>\n", 4206 "type": "Number" 4207 }, 4208 { 4209 "name": "mode", 4210 "description": "<p>optional parameter to determine the way of drawing\n the arc. either CHORD, PIE or OPEN</p>\n", 4211 "type": "Constant", 4212 "optional": true 4213 } 4214 ], 4215 "chainable": 1, 4216 "example": [ 4217 "\n<div>\n<code>\narc(50, 55, 50, 50, 0, HALF_PI);\nnoFill();\narc(50, 55, 60, 60, HALF_PI, PI);\narc(50, 55, 70, 70, PI, PI + QUARTER_PI);\narc(50, 55, 80, 80, PI + QUARTER_PI, TWO_PI);\n</code>\n</div>\n\n<div>\n<code>\narc(50, 50, 80, 80, 0, PI + QUARTER_PI);\n</code>\n</div>\n\n<div>\n<code>\narc(50, 50, 80, 80, 0, PI + QUARTER_PI, OPEN);\n</code>\n</div>\n\n<div>\n<code>\narc(50, 50, 80, 80, 0, PI + QUARTER_PI, CHORD);\n</code>\n</div>\n\n<div>\n<code>\narc(50, 50, 80, 80, 0, PI + QUARTER_PI, PIE);\n</code>\n</div>" 4218 ], 4219 "alt": "shattered outline of an ellipse with a quarter of a white circle bottom-right.\nwhite ellipse with top right quarter missing.\nwhite ellipse with black outline with top right missing.\nwhite ellipse with top right missing with black outline around shape.\nwhite ellipse with top right quarter missing with black outline around the shape.", 4220 "class": "p5", 4221 "module": "Shape", 4222 "submodule": "2D Primitives" 4223 }, 4224 { 4225 "file": "src/core/2d_primitives.js", 4226 "line": 133, 4227 "description": "<p>Draws an ellipse (oval) to the screen. An ellipse with equal width and\nheight is a circle. By default, the first two parameters set the location,\nand the third and fourth parameters set the shape'
4227s width and height. If\nno height is specified, the value of width is used for both the width and\nheight. If a negative height or width is specified, the absolute value is taken.\nThe origin may be changed with the ellipseMode() function.</p>\n", 4228 "itemtype": "method", 4229 "name": "ellipse", 4230 "chainable": 1, 4231 "example": [ 4232 "\n<div>\n<code>\nellipse(56, 46, 55, 55);\n</code>\n</div>" 4233 ], 4234 "alt": "white ellipse with black outline in middle-right of canvas that is 55x55.", 4235 "class": "p5", 4236 "module": "Shape", 4237 "submodule": "2D Primitives", 4238 "overloads": [ 4239 { 4240 "line": 133, 4241 "params": [ 4242 { 4243 "name": "x", 4244 "description": "<p>x-coordinate of the ellipse.</p>\n", 4245 "type": "Number" 4246 }, 4247 { 4248 "name": "y", 4249 "description": "<p>y-coordinate of the ellipse.</p>\n", 4250 "type": "Number" 4251 }, 4252 { 4253 "name": "w", 4254 "description": "<p>width of the ellipse.</p>\n", 4255 "type": "Number" 4256 }, 4257 { 4258 "name": "h", 4259 "description": "<p>height of the ellipse.</p>\n", 4260 "type": "Number", 4261 "optional": true 4262 } 4263 ], 4264 "chainable": 1 4265 }, 4266 { 4267 "line": 158, 4268 "params": [ 4269 { 4270 "name": "x", 4271 "description": "", 4272 "type": "Number" 4273 }, 4274 { 4275 "name": "y", 4276 "description": "", 4277 "type": "Number" 4278 }, 4279 { 4280 "name": "w", 4281 "description": "", 4282 "type": "Number" 4283 }, 4284 { 4285 "name": "h", 4286 "description": "", 4287 "type": "Number" 4288 }, 4289 { 4290 "name": "detail", 4291 "description": "<p>number of radial sectors to draw</p>\n", 4292 "type": "Integer" 4293 } 4294 ] 4295 } 4296 ] 4297 }, 4298 { 4299 "file": "src/core/2d_primitives.js", 4300 "line": 188, 4301 "description": "<p>Draws a line (a direct path between two points) to the screen. The version\nof line() with four parameters draws the line in 2D. To color a line, use\nthe stroke() function. A line cannot be filled, therefore the fill()\nfunction will not affect the color of a line. 2D lines are drawn with a\nwidth of one pixel by default, but this can be changed with the\nstrokeWeight(
4301) function.</p>\n", 4302 "itemtype": "method", 4303 "name": "line", 4304 "chainable": 1, 4305 "example": [ 4306 "\n<div>\n<code>\nline(30, 20, 85, 75);\n</code>\n</div>\n\n<div>\n<code>\nline(30, 20, 85, 20);\nstroke(126);\nline(85, 20, 85, 75);\nstroke(255);\nline(85, 75, 30, 75);\n</code>\n</div>" 4307 ], 4308 "alt": "line 78 pixels long running from mid-top to bottom-right of canvas.\n3 lines of various stroke sizes. Form top, bottom and right sides of a square.", 4309 "class": "p5", 4310 "module": "Shape", 4311 "submodule": "2D Primitives", 4312 "overloads": [ 4313 { 4314 "line": 188, 4315 "params": [ 4316 { 4317 "name": "x1", 4318 "description": "<p>the x-coordinate of the first point</p>\n", 4319 "type": "Number" 4320 }, 4321 { 4322 "name": "y1", 4323 "description": "<p>the y-coordinate of the first point</p>\n", 4324 "type": "Number" 4325 }, 4326 { 4327 "name": "x2", 4328 "description": "<p>the x-coordinate of the second point</p>\n", 4329 "type": "Number" 4330 }, 4331 { 4332 "name": "y2", 4333 "description": "<p>the y-coordinate of the second point</p>\n", 4334 "type": "Number" 4335 } 4336 ], 4337 "chainable": 1 4338 }, 4339 { 4340 "line": 224, 4341 "params": [ 4342 { 4343 "name": "x1", 4344 "description": "", 4345 "type": "Number" 4346 }, 4347 { 4348 "name": "y1", 4349 "description": "", 4350 "type": "Number" 4351 }, 4352 { 4353 "name": "z1", 4354 "description": "<p>the z-coordinate of the first point</p>\n", 4355 "type": "Number" 4356 }, 4357 { 4358 "name": "x2", 4359 "description": "", 4360 "type": "Number" 4361 }, 4362 { 4363 "name": "y2", 4364 "description": "", 4365 "type": "Number" 4366 }, 4367 { 4368 "name": "z2", 4369 "description": "<p>the z-coordinate of the second point</p>\n", 4370 "type": "Number" 4371 } 4372 ], 4373 "chainable": 1 4374 } 4375 ] 4376 }, 4377 { 4378 "file": "src/core/2d_primitives.js", 4379 "line": 244, 4380 "description": "<p>Draws a point, a coordinate in space at the dimension of one pixel.\nThe first parameter is the horizontal value for the point, the second\nvalue is the vertical value for the point. The color of the point is\ndetermined by the current stroke.</p>\n", 4381 "itemtype": "method", 4382 "name": "point", 4383 "params": [ 4384 { 4385 "name": "x", 4386 "description": "<p>the x-coordinate</p>\n", 4387 "type": "Number" 4388 }, 4389 { 4390 "name": "y", 4391 "description": "<p>the y-coordinate</p>\n", 4392 "type": "Number" 4393 }, 4394 { 4395 "name": "z", 4396 "description": "<p>the z-coordinate (for WEBGL mode)</p>\n", 4397 "type": "Number", 4398 "optional": true 4399 } 4400 ], 4401 "chainable": 1, 4402 "example": [ 4403 "\n<div>\n<code>\npoint(30, 20);\npoint(85, 20);\npoint(85, 75);\npoint(30, 75);\n</code>\n</div>" 4404 ], 4405 "alt": "4 points centered in the middle-right of the canvas.", 4406 "class": "p5", 4407 "module": "Shape", 4408 "submodule": "2D Primitives" 4409 }, 4410 { 4411 "file": "src/core/2d_primitives.js", 4412 "line": 279, 4413 "description": "<p>Draw a quad. A quad is a quadrilateral, a four sided polygon. It is\nsimilar to a rectangle, but the angles between its edges are not\nconstrained to
4413ninety degrees. The first pair of parameters (x1,y1)\nsets the first vertex and the subsequent pairs should proceed\nclockwise or counter-clockwise around the defined shape.</p>\n", 4414 "itemtype": "method", 4415 "name": "quad", 4416 "chainable": 1, 4417 "example": [ 4418 "\n<div>\n<code>\nquad(38, 31, 86, 20, 69, 63, 30, 76);\n</code>\n</div>" 4419 ], 4420 "alt": "irregular white quadrilateral shape with black outline mid-right of canvas.", 4421 "class": "p5", 4422 "module": "Shape", 4423 "submodule": "2D Primitives", 4424 "overloads": [ 4425 { 4426 "line": 279, 4427 "params": [ 4428 { 4429 "name": "x1", 4430 "description": "<p>the x-coordinate of the first point</p>\n", 4431 "type": "Number" 4432 }, 4433 { 4434 "name": "y1", 4435 "description": "<p>the y-coordinate of the first point</p>\n", 4436 "type": "Number" 4437 }, 4438 { 4439 "name": "x2", 4440 "description": "<p>the x-coordinate of the second point</p>\n", 4441 "type": "Number" 4442 }, 4443 { 4444 "name": "y2", 4445 "description": "<p>the y-coordinate of the second point</p>\n", 4446 "type": "Number" 4447 }, 4448 { 4449 "name": "x3", 4450 "description": "<p>the x-coordinate of the third point</p>\n", 4451 "type": "Number" 4452 }, 4453 { 4454 "name": "y3", 4455 "description": "<p>the y-coordinate of the third point</p>\n", 4456 "type": "Number" 4457 }, 4458 { 4459 "name": "x4", 4460 "description": "<p>the x-coordinate of the fourth point</p>\n", 4461 "type": "Number" 4462 }, 4463 { 4464 "name": "y4", 4465 "description": "<p>the y-coordinate of the fourth point</p>\n", 4466 "type": "Number" 4467 } 4468 ], 4469 "chainable": 1 4470 }, 4471 { 4472 "line": 307, 4473 "params": [ 4474 { 4475 "name": "x1", 4476 "description": "", 4477 "type": "Number" 4478 }, 4479 { 4480 "name": "y1", 4481 "description": "", 4482 "type": "Number" 4483 }, 4484 { 4485 "name": "z1", 4486 "description": "", 4487 "type": "Number" 4488 }, 4489 { 4490 "name": "x2", 4491 "description": "", 4492 "type": "Number" 4493 }, 4494 { 4495 "name": "y2", 4496 "description": "", 4497 "type": "Number" 4498 }, 4499 { 4500 "name": "z2", 4501 "description": "", 4502 "type": "Number" 4503 }, 4504 { 4505 "name": "x3", 4506 "description": "", 4507 "type": "Number" 4508 }, 4509 { 4510 "name": "y3", 4511 "description": "", 4512 "type": "Number" 4513 }, 4514 { 4515 "name": "z3", 4516 "description": "", 4517 "type": "Number" 4518 }, 4519 { 4520 "name": "x4", 4521 "description": "", 4522 "type": "Number" 4523 }, 4524 { 4525 "name": "y4", 4526 "description": "", 4527 "type": "Number" 4528 }, 4529 { 4530 "name": "z4", 4531 "description": "", 4532 "type": "Number" 4533 } 4534 ], 4535 "chainable": 1 4536 } 4537 ] 4538 }, 4539 { 4540 "file": "src/core/2d_primitives.js", 4541 "line": 333, 4542 "description": "<p>Draws a rectangle to the screen. A rectangle is a four-sided shape with\nevery angle at ninety degrees. By default, the first two parameters set\nthe location of the upper-left corner, the third sets the width, and the\nfourth sets the height. The way these parameters are interpreted, however,\nmay be changed with the rectMode() function.\n<br><br>\nThe fifth, sixth, seventh and eighth parameters, if specified,\ndetermine corner radius for the top-right, top-left, lower-right and\nlower-left corners, respectively. An omitted corner radius parameter is set\nto the value of the previously specified radius value in the parameter list.</p>\n", 4543 "itemtype": "method", 4544 "name": "rect", 4545 "chainable": 1, 4546 "example": [ 4547 "\n<div>\n<code>\n// Draw a rectangle at location (30, 20) with a width and height of 55.\nrect(30, 20, 55, 55);\n</code>\n</div>\n\n<div>\n<code>\n// Draw a rectangle with rounded corners, each having a radius of 20.\nrect(30, 20, 55, 55, 20);\n</code>\n</div>\n\n<div>\n<code>\n// Draw a rectangle with rounded corners having the following radii:\n// top-left = 20, top-right = 15, bottom-right = 10, bottom-left = 5.\nrect(30, 20, 55, 55, 20, 15, 10, 5);\n</code>\n</div>" 4548 ], 4549 "alt": "55x55 white rect with black outline in mid-right of canvas.\n55x55 white rect with black outline and rounded edges in mid-right of canvas.\n55x55 white rect with black outline and rounded edges of different radii.", 4550 "class": "p5", 4551 "module": "Shape", 4552 "submodule": "2D Primitives", 4553 "overloads": [ 4554 { 4555 "line": 333, 4556 "params": [ 4557 { 4558 "name": "x", 4559 "description": "<p>x-coordinate of the rectangle.</p>\n", 4560 "type": "Number" 4561 }, 4562 { 4563 "name": "y", 4564 "description": "<p>y-coordinate of the rectangle.</p>\n", 4565 "type": "Number" 4566 }, 4567 { 4568 "name": "w", 4569 "description": "<p>width of the rectangle.</p>\n", 4570 "type": "Number" 4571 }, 4572 { 4573 "name": "h", 4574 "description": "<p>height of the rectangle.</p>\n", 4575 "type": "Number" 4576 }, 4577 { 4578 "name": "tl", 4579 "description": "<p>optional radius of top-left corner.</p>\n", 4580 "type": "Number", 4581 "optional": true 4582 }, 4583 { 4584 "name": "tr", 4585 "description": "<p>optional radius of top-right corner.</p>\n", 4586 "type": "Number", 4587 "optional": true 4588 }, 4589 { 4590 "name": "br", 4591 "description": "<p>optional radius of bottom-right corner.</p>\n", 4592 "type": "Number", 4593 "optional": true 4594 }, 4595 { 4596 "name": "bl", 4597 "description": "<p>optional radius of bottom-left corner.</p>\n", 4598 "type": "Number", 4599 "optional": true 4600 } 4601 ], 4602 "chainable": 1 4603 }, 4604 { 4605 "line": 383, 4606 "params": [ 4607 { 4608 "name": "x", 4609 "description": "", 4610 "type": "Number" 4611 }, 4612 { 4613 "name": "y", 4614 "description": "", 4615 "type": "Number" 4616 }, 4617 { 4618 "name": "w", 4619 "description": "", 4620 "type": "Number" 4621 }, 4622 { 4623 "name": "h", 4624 "description": "", 4625 "type": "Number" 4626 }, 4627 { 4628 "name": "detailX", 4629 "description": "<p>number of segments in the x-direction</p>\n", 4630 "type": "Integer", 4631 "optional": true 4632 }, 4633 { 4634 "name": "detailY", 4635 "description": "<p>number of segments in the y-direction</p>\n", 4636 "type": "Integer", 4637 "optional": true 4638 } 4639 ], 4640 "chainable": 1 4641 } 4642 ] 4643 }, 4644 { 4645 "file": "src/core/2d_primitives.js", 4646 "line": 416, 4647 "description": "<p>A triangle is a plane created by connecting three points. The first two\narguments specify the first point, the middle two arguments specify the\nsecond point, and the last two arguments specify the third point.</p>\n", 4648 "itemtype": "method", 4649 "name": "triangle", 4650 "params": [ 4651 { 4652 "name": "x1", 4653 "description": "<p>x-coordinate of the first point</p>\n", 4654 "type": "Number" 4655 }, 4656 { 4657 "name": "y1", 4658 "description": "<p>y-coordinate of the first point</p>\n", 4659 "type": "Number" 4660 }, 4661 { 4662 "name": "x2", 4663 "description": "<p>x-coordinate of the second point</p>\n", 4664 "type": "Number" 4665 }, 4666 { 4667 "name": "y2", 4668 "description": "<p>y-coordinate of the second point</p>\n", 4669 "type": "Number" 4670 }, 4671 { 4672 "name": "x3", 4673 "description": "<p>x-coordinate of the third point</p>\n", 4674 "type": "Number" 4675 }, 4676 { 4677 "name": "y3", 4678 "description": "<p>y-coordinate of the third point</p>\n", 4679 "type": "Number" 4680 } 4681 ], 4682 "chainable": 1, 4683 "example": [ 4684 "\n<div>\n<code>\ntriangle(30, 75, 58, 20, 86, 75);\n</code>\n</div>" 4685 ], 4686 "alt": "white triangle with black outline in mid-right of canvas.", 4687 "class": "p5", 4688 "module": "Shape", 4689 "submodule": "2D Primitives" 4690 }, 4691 { 4692 "file": "src/core/attributes.js", 4693 "line": 14, 4694 "description": "<p>Modifies the location from which ellipses are drawn by changing the way\nin which parameters given to ellipse() are interpreted.\n<br><br>\nThe default mode is ellipseMode(CENTER), which interprets the first two\nparameters of ellipse() as the shape's center point, while the third and\nfourth parameters are its width and height.\n<br><br>\nellipseMode(RADIUS) also uses the first two parameters of ellipse() as\nthe shape's center point, but uses the third and fourth parameters to\nspecify half of the shapes's width and height.\n<br><br>\nellipseMode(CORNER) interprets the first two parameters of ellipse() as\nthe upper-left corner of the shape, while the third and fourth parameters\nare its width and height.\n<br><br>\nellipseMode(CORNERS) interprets the first two parameters of ellipse() as\nthe location of one corner of the ellipse's bounding box, and the third\nand fourth parameters as the location of the opposite corner.\n<br><br>\nThe parameter must be written in ALL CAPS because Javascript is a\ncase-sensitive language.</p>\n", 4695 "itemtype": "method", 4696 "name": "ellipseMode", 4697 "params": [ 4698 { 4699 "name": "mode", 4700 "description": "<p>either CENTER, RADIUS, CORNER, or CORNERS</p>\n", 4701 "type": "Constant" 4702 } 4703 ], 4704 "chainable": 1, 4705 "example": [ 4706 "\n<div>\n<code>\nellipseMode(RADIUS); // Set ellipseMode to RADIUS\nfill(255); // Set fill to white\nellipse(50, 50, 30, 30); // Draw white ellipse using RADIUS mode\n\nellipseMode(CENTER); // Set ellipseMode to CENTER\nfill(100); // Set fill to gray\nellipse(50, 50, 30, 30); // Draw gray ellipse using CENTER mode\n</code>\n</div>\n\n<div>\n<code>\nellipseMode(CORNER); // Set ellipseMode is CORNER\nfill(255); // Set fill to white\nellipse(25, 25, 50, 50); // Draw white ellipse using CORNER mode\n\nellipseMode(CORNERS); // Set ellipseMode to CORNERS\nfill(100); // Set fill to gray\nellipse(25, 25, 50, 50); // Draw gray ellipse using CORNERS mode\n</code>\n</div>" 4707 ], 4708 "alt": "60x60 white ellipse and 30x30 grey ellipse with black outlines at center.\n60x60 white ellipse @center and 30x30 grey ellipse top-right, black outlines.", 4709 "class": "p5", 4710 "module": "Shape", 4711 "submodule": "Attributes"
4712 }, 4713 { 4714 "file": "src/core/attributes.js", 4715 "line": 83, 4716 "description": "<p>Draws all geometry with jagged (aliased) edges. Note that smooth() is\nactive by default, so it is necessary to call noSmooth() to disable\nsmoothing of geometry, images, and fonts.</p>\n", 4717 "itemtype": "method", 4718 "name": "noSmooth", 4719 "chainable": 1, 4720 "example": [ 4721 "\n<div>\n<code>\nbackground(0);\nnoStroke();\nsmooth();\nellipse(30, 48, 36, 36);\nnoSmooth();\nellipse(70, 48, 36, 36);\n</code>\n</div>" 4722 ], 4723 "alt": "2 pixelated 36x36 white ellipses to left & right of center, black background", 4724 "class": "p5", 4725 "module": "Shape", 4726 "submodule": "Attributes" 4727 }, 4728 { 4729 "file": "src/core/attributes.js", 4730 "line": 111, 4731 "description": "<p>Modifies the location from which rectangles are drawn by changing the way\nin which parameters given to rect() are interpreted.\n<br><br>\nThe default mode is rectMode(CORNER), which interprets the first two\nparameters of rect() as the upper-left corner of the shape, while the\nthird and fourth parameters are its width and height.\n<br><br>\nrectMode(CORNERS) interprets the first two parameters of rect() as the\nlocation of one corner, and the third and fourth parameters as the\nlocation of the opposite corner.\n<br><br>\nrectMode(CENTER) interprets the first two parameters of rect() as the\nshape's center point, while the third and fourth parameters are its\nwidth and height.\n<br><br>\nrectMode(RADIUS) also uses the first two parameters of rect() as the\nshape's center point, but uses the third and fourth parameters to specify\nhalf of the shapes's width and height.\n<br><br>\nThe parameter must be written in ALL CAPS because Javascript is a\ncase-sensitive language.</p>\n", 4732 "itemtype": "method", 4733 "name": "rectMode", 4734 "params": [ 4735 { 4736 "name": "mode", 4737 "description": "<p>either CORNER, CORNERS, CENTER, or RADIUS</p>\n", 4738 "type": "Constant" 4739 } 4740 ], 4741 "chainable": 1, 4742 "example": [ 4743 "\n<div>\n<code>\nrectMode(CORNER); // Default rectMode is CORNER\nfill(255); // Set fill to white\nrect(25, 25, 50, 50); // Draw white rect using CORNER mode\n\nrectMode(CORNERS); // Set rectMode to CORNERS\nfill(100); // Set fill to gray\nrect(25, 25, 50, 50); // Draw gray rect using CORNERS mode\n</code>\n</div>\n\n<div>\n<code>\nrectMode(RADIUS); // Set rectMode to RADIUS\nfill(255); // Set fill to white\nrect(50, 50, 30, 30); // Draw white rect using RADIUS mode\n\nrectMode(CENTER); // Set rectMode to CENTER\nfill(100); // Set fill to gray\nrect(50, 50, 30, 30); // Draw gray rect using CENTER mode\n</code>\n</div>" 4744 ], 4745 "alt": "50x50 white rect at center and 25x25 grey rect in the top left of the other.\n50x50 white rect at center and 25x25 grey rect in the center of the other.", 4746 "class": "p5", 4747 "module": "Shape", 4748 "submodule": "Attributes"
4749 }, 4750 { 4751 "file": "src/core/attributes.js", 4752 "line": 180, 4753 "description": "<p>Draws all geometry with smooth (anti-aliased) edges. smooth() will also\nimprove image quality of resized images. Note that smooth() is active by\ndefault; noSmooth() can be used to disable smoothing of geometry,\nimages, and fonts.</p>\n", 4754 "itemtype": "method", 4755 "name": "smooth", 4756 "chainable": 1, 4757 "example": [ 4758 "\n<div>\n<code>\nbackground(0);\nnoStroke();\nsmooth();\nellipse(30, 48, 36, 36);\nnoSmooth();\nellipse(70, 48, 36, 36);\n</code>\n</div>" 4759 ], 4760 "alt": "2 pixelated 36x36 white ellipses one left one right of center. On black.", 4761 "class": "p5", 4762 "module": "Shape", 4763 "submodule": "Attributes" 4764 }, 4765 { 4766 "file": "src/core/attributes.js", 4767 "line": 209, 4768 "description": "<p>Sets the style for rendering line endings. These ends are either squared,\nextended, or rounded, each of which specified with the corresponding\nparameters: SQUARE, PROJECT, and ROUND. The default cap is ROUND.</p>\n", 4769 "itemtype": "method", 4770 "name": "strokeCap", 4771 "params": [ 4772 { 4773 "name": "cap", 4774 "description": "<p>either SQUARE, PROJECT, or ROUND</p>\n", 4775 "type": "Constant" 4776 } 4777 ], 4778 "chainable": 1, 4779 "example": [ 4780 "\n<div>\n<code>\nstrokeWeight(12.0);\nstrokeCap(ROUND);\nline(20, 30, 80, 30);\nstrokeCap(SQUARE);\nline(20, 50, 80, 50);\nstrokeCap(PROJECT);\nline(20, 70, 80, 70);\n</code>\n</div>" 4781 ], 4782 "alt": "3 lines. Top line: rounded ends, mid: squared, bottom:longer squared ends.", 4783 "class": "p5", 4784 "module": "Shape", 4785 "submodule": "Attributes"
4786 }, 4787 { 4788 "file": "src/core/attributes.js", 4789 "line": 246, 4790 "description": "<p>Sets the style of the joints which connect line segments. These joints\nare either mitered, beveled, or rounded and specified with the\ncorresponding parameters MITER, BEVEL, and ROUND. The default joint is\nMITER.</p>\n", 4791 "itemtype": "method", 4792 "name": "strokeJoin", 4793 "params": [ 4794 { 4795 "name": "join", 4796 "description": "<p>either MITER, BEVEL, ROUND</p>\n", 4797 "type": "Constant" 4798 } 4799 ], 4800 "chainable": 1, 4801 "example": [ 4802 "\n<div>\n<code>\nnoFill();\nstrokeWeight(10.0);\nstrokeJoin(MITER);\nbeginShape();\nvertex(35, 20);\nvertex(65, 50);\nvertex(35, 80);\nendShape();\n</code>\n</div>\n\n<div>\n<code>\nnoFill();\nstrokeWeight(10.0);\nstrokeJoin(BEVEL);\nbeginShape();\nvertex(35, 20);\nvertex(65, 50);\nvertex(35, 80);\nendShape();\n</code>\n</div>\n\n<div>\n<code>\nnoFill();\nstrokeWeight(10.0);\nstrokeJoin(ROUND);\nbeginShape();\nvertex(35, 20);\nvertex(65, 50);\nvertex(35, 80);\nendShape();\n</code>\n</div>" 4803 ], 4804 "alt": "Right-facing arrowhead shape with pointed tip in center of canvas.\nRight-facing arrowhead shape with flat tip in center of canvas.\nRight-facing arrowhead shape with rounded tip in center of canvas.", 4805 "class": "p5", 4806 "module": "Shape", 4807 "submodule": "Attributes"
4808 }, 4809 { 4810 "file": "src/core/attributes.js", 4811 "line": 313, 4812 "description": "<p>Sets the width of the stroke used for lines, points, and the border\naround shapes. All widths are set in units of pixels.</p>\n", 4813 "itemtype": "method", 4814 "name": "strokeWeight", 4815 "params": [ 4816 { 4817 "name": "weight", 4818 "description": "<p>the weight (in pixels) of the stroke</p>\n", 4819 "type": "Number" 4820 } 4821 ], 4822 "chainable": 1, 4823 "example": [ 4824 "\n<div>\n<code>\nstrokeWeight(1); // Default\nline(20, 20, 80, 20);\nstrokeWeight(4); // Thicker\nline(20, 40, 80, 40);\nstrokeWeight(10); // Beastly\nline(20, 70, 80, 70);\n</code>\n</div>" 4825 ], 4826 "alt": "3 horizontal black lines. Top line: thin, mid: medium, bottom:thick.", 4827 "class": "p5", 4828 "module": "Shape", 4829 "submodule": "Attributes" 4830 }, 4831 { 4832 "file": "src/core/canvas.js", 4833 "line": 1, 4834 "requires": [ 4835 "constants" 4836 ], 4837 "class": "p5", 4838 "module": "Shape" 4839 }, 4840 { 4841 "file": "src/core/constants.js", 4842 "line": 13, 4843 "itemtype": "property", 4844 "name": "P2D", 4845 "type": "String", 4846 "final": 1, 4847 "class": "p5", 4848 "module": "Constants", 4849 "submodule": "Constants" 4850 }, 4851 { 4852 "file": "src/core/constants.js", 4853 "line": 18, 4854 "itemtype": "property", 4855 "name": "WEBGL", 4856 "type": "String", 4857 "final": 1, 4858 "class": "p5", 4859 "module": "Constants", 4860 "submodule": "Constants" 4861 }, 4862 { 4863 "file": "src/core/constants.js", 4864 "line": 34, 4865 "description": "<p>HALF_PI is a mathematical constant with the value\n1.57079632679489661923. It is half the ratio of the\ncircumference of a circle to its diameter. It is useful in\ncombination with the trigonometric functions sin() and cos().</p>\n", 4866 "itemtype": "property", 4867 "name": "HALF_PI", 4868 "type": "Number", 4869 "final": 1, 4870 "example": [ 4871 "\n<div><code>\narc(50, 50, 80, 80, 0, HALF_PI);\n</code></div>" 4872 ], 4873 "alt": "80x80 white quarter-circle with curve toward bottom right of canvas.", 4874 "class": "p5", 4875 "module": "Constants", 4876 "submodule": "Constants" 4877 }, 4878 { 4879 "file": "src/core/constants.js", 4880 "line": 53, 4881 "description": "<p>PI is a mathematical constant with the value\n3.14159265358979323846. It is the ratio of the circumference\nof a circle to its diameter. It is useful in combination with\nthe trigonometric functions sin() and cos().</p>\n", 4882 "itemtype": "property", 4883 "name": "PI", 4884 "type": "Number", 4885 "final": 1, 4886 "example": [ 4887 "\n<div><code>\narc(50, 50, 80, 80, 0, PI);\n</code></div>" 4888 ], 4889 "alt": "white half-circle with curve toward bottom of canvas.", 4890 "class": "p5", 4891 "module": "Constants", 4892 "submodule": "Constants" 4893 }, 4894 { 4895 "file": "src/core/constants.js", 4896 "line": 72, 4897 "description": "<p>QUARTER_PI is a mathematical constant with the value 0.7853982.\nIt is one quarter the ratio of the circumference of a circle to\nits diameter. It is useful in combination with the trigonometric\nfunctions sin() and cos().</p>\n", 4898 "itemtype": "property", 4899 "name": "QUARTER_PI", 4900 "type": "Number", 4901 "final": 1, 4902 "example": [ 4903 "\n<div><code>\narc(50, 50, 80, 80, 0, QUARTER_PI);\n</code></div>" 4904 ], 4905 "alt": "white eighth-circle rotated about 40 degrees with curve bottom right canvas.", 4906 "class": "p5", 4907 "module": "Constants", 4908 "submodule": "Constants" 4909 }, 4910 { 4911 "file": "src/core/constants.js", 4912 "line": 91, 4913 "description": "<p>TAU is an alias for TWO_PI, a mathematical constant with the\nvalue 6.28318530717958647693. It is twice the ratio of the\ncircumference of a circle to its diameter. It is useful in\ncombination with the trigonometric functions sin() and cos().</p>\n", 4914 "itemtype": "property", 4915 "name": "TAU", 4916 "type": "Number", 4917 "final": 1, 4918 "example": [ 4919 "\n<div><code>\narc(50, 50, 80, 80, 0, TAU);\n</code></div>" 4920 ], 4921 "alt": "80x80 white ellipse shape in center of canvas.", 4922 "class": "p5", 4923 "module": "Constants", 4924 "submodule": "Constants" 4925 }, 4926 { 4927 "file": "src/core/constants.js", 4928 "line": 110, 4929 "description": "<p>TWO_PI is a mathematical constant with the value\n6.28318530717958647693. It is twice the ratio of the\ncircumference of a circle to its diameter. It is useful in\ncombination with the trigonometric functions sin() and cos().</p>\n", 4930 "itemtype": "property", 4931 "name": "TWO_PI", 4932 "type": "Number", 4933 "final": 1, 4934 "example": [ 4935 "\n<div><code>\narc(50, 50, 80, 80, 0, TWO_PI);\n</code></div>" 4936 ], 4937 "alt": "80x80 white ellipse shape in center of canvas.", 4938 "class": "p5", 4939 "module": "Constants", 4940 "submodule": "Constants" 4941 }, 4942 { 4943 "file": "src/core/constants.js", 4944 "line": 129, 4945 "description": "<p>Constant to be used with angleMode() function, to set the mode which\np5.js interprates and calculates angles (either DEGREES or RADIANS).</p>\n", 4946 "itemtype": "property", 4947 "name": "DEGREES", 4948 "type": "String", 4949 "final": 1, 4950 "example": [ 4951 "\n<div class='norender'><code>\nfunction setup() {\n angleMode(DEGREES);\n}\n</code></div>" 4952 ], 4953 "class": "p5", 4954 "module": "Constants", 4955 "submodule": "Constants" 4956 }, 4957 { 4958 "file": "src/core/constants.js", 4959 "line": 143, 4960 "description": "<p>Constant to be used with angleMode() function, to set the mode which\np5.js interprates and calculates angles (either RADIANS or DEGREES).</p>\n", 4961 "itemtype": "property", 4962 "name": "RADIANS", 4963 "type": "String", 4964 "final": 1, 4965 "example": [ 4966 "\n<div class='norender'><code>\nfunction setup() {\n angleMode(RADIANS);\n}\n</code></div>" 4967 ], 4968 "class": "p5", 4969 "module": "Constants", 4970 "submodule": "Constants" 4971 }, 4972 { 4973 "file": "src/core/constants.js", 4974 "line": 161, 4975 "itemtype": "property", 4976 "name": "CORNER", 4977 "type": "String", 4978 "final": 1, 4979 "class": "p5", 4980 "module": "Constants", 4981 "submodule": "Constants" 4982 }, 4983 { 4984 "file": "src/core/constants.js", 4985 "line": 166, 4986 "itemtype": "property", 4987 "name": "CORNERS", 4988 "type": "String", 4989 "final": 1, 4990 "class": "p5", 4991 "module": "Constants", 4992 "submodule": "Constants" 4993 }, 4994 { 4995 "file": "src/core/constants.js", 4996 "line": 171, 4997 "itemtype": "property", 4998 "name": "RADIUS", 4999 "type": "String", 5000 "final": 1, 5001 "class": "p5", 5002 "module": "Constants", 5003 "submodule": "Constants" 5004 }, 5005 { 5006 "file": "src/core/constants.js", 5007 "line": 176, 5008 "itemtype": "property", 5009 "name": "RIGHT", 5010 "type": "String", 5011 "final": 1, 5012 "class": "p5", 5013 "module": "Constants", 5014 "submodule": "Constants" 5015 }, 5016 { 5017 "file": "src/core/constants.js", 5018 "line": 181, 5019 "itemtype": "property", 5020 "name": "LEFT", 5021 "type": "String", 5022 "final": 1, 5023 "class": "p5", 5024 "module": "Constants", 5025 "submodule": "Constants" 5026 }, 5027 { 5028 "file": "src/core/constants.js", 5029 "line": 186, 5030 "itemtype": "property", 5031 "name": "CENTER", 5032 "type": "String", 5033 "final": 1, 5034 "class": "p5", 5035 "module": "Constants", 5036 "submodule": "Constants" 5037 }, 5038 { 5039 "file": "src/core/constants.js", 5040 "line": 191, 5041 "itemtype": "property", 5042 "name": "TOP", 5043 "type": "String", 5044 "final": 1, 5045 "class": "p5", 5046 "module": "Constants", 5047 "submodule": "Constants" 5048 }, 5049 { 5050 "file": "src/core/constants.js", 5051 "line": 196, 5052 "itemtype": "property", 5053 "name": "BOTTOM", 5054 "type": "String", 5055 "final": 1, 5056 "class": "p5", 5057 "module": "Constants", 5058 "submodule": "Constants" 5059 }, 5060 { 5061 "file": "src/core/constants.js", 5062 "line": 201, 5063 "itemtype": "property", 5064 "name": "BASELINE", 5065 "type": "String", 5066 "final": 1, 5067 "default": "alphabetic", 5068 "class": "p5", 5069 "module": "Constants", 5070 "submodule": "Constants" 5071 }, 5072 { 5073 "file": "src/core/constants.js", 5074 "line": 207, 5075 "itemtype": "property", 5076 "name": "POINTS", 5077 "type": "Number", 5078 "final": 1, 5079 "default": "0x0000", 5080 "class": "p5", 5081 "module": "Constants", 5082 "submodule": "Constants" 5083 }, 5084 { 5085 "file": "src/core/constants.js", 5086 "line": 213, 5087 "itemtype": "property", 5088 "name": "LINES", 5089 "type": "Number", 5090 "final": 1, 5091 "default": "0x0001", 5092 "class": "p5", 5093 "module": "Constants", 5094 "submodule": "Constants" 5095 }, 5096 { 5097 "file": "src/core/constants.js", 5098 "line": 219, 5099 "itemtype": "property", 5100 "name": "LINE_STRIP", 5101 "type": "Number", 5102 "final": 1, 5103 "default": "0x0003", 5104 "class": "p5", 5105 "module": "Constants", 5106 "submodule": "Constants" 5107 }, 5108 { 5109 "file": "src/core/constants.js", 5110 "line": 225, 5111 "itemtype": "property", 5112 "name": "LINE_LOOP", 5113 "type": "Number", 5114 "final": 1, 5115 "default": "0x0002", 5116 "class": "p5", 5117 "module": "Constants", 5118 "submodule": "Constants" 5119 }, 5120 { 5121 "file": "src/core/constants.js", 5122 "line": 231, 5123 "itemtype": "property", 5124 "name": "TRIANGLES", 5125 "type": "Number", 5126 "final": 1, 5127 "default": "0x0004", 5128 "class": "p5", 5129 "module": "Constants", 5130 "submodule": "Constants" 5131 }, 5132 { 5133 "file": "src/core/constants.js", 5134 "line": 237, 5135 "itemtype": "property", 5136 "name": "TRIANGLE_FAN", 5137 "type": "Number", 5138 "final": 1, 5139 "default": "0x0006", 5140 "class": "p5", 5141 "module": "Constants", 5142 "submodule": "Constants" 5143 }, 5144 { 5145 "file": "src/core/constants.js", 5146 "line": 243, 5147 "itemtype": "property", 5148 "name": "TRIANGLE_STRIP", 5149 "type": "Number", 5150 "final": 1, 5151 "default": "0x0005", 5152 "class": "p5", 5153 "module": "Constants", 5154 "submodule": "Constants" 5155 }, 5156 { 5157 "file": "src/core/constants.js", 5158 "line": 249, 5159 "itemtype": "property", 5160 "name": "QUADS", 5161 "type": "String", 5162 "final": 1, 5163 "class": "p5", 5164 "module": "Constants", 5165 "submodule": "Constants" 5166 }, 5167 { 5168 "file": "src/core/constants.js", 5169 "line": 254, 5170 "itemtype": "property", 5171 "name": "QUAD_STRIP", 5172 "type": "String", 5173 "final": 1, 5174 "default": "quad_strip", 5175 "class": "p5", 5176 "module": "Constants", 5177 "submodule": "Constants" 5178 }, 5179 { 5180 "file": "src/core/constants.js", 5181 "line": 260, 5182 "itemtype": "property", 5183 "name": "CLOSE", 5184 "type": "String", 5185 "final": 1, 5186 "class": "p5", 5187 "module": "Constants", 5188 "submodule": "Constants" 5189 }, 5190 { 5191 "file": "src/core/constants.js", 5192 "line": 265, 5193 "itemtype": "property", 5194 "name": "OPEN", 5195 "type": "String", 5196 "final": 1, 5197 "class": "p5", 5198 "module": "Constants", 5199 "submodule": "Constants" 5200 }, 5201 { 5202 "file": "src/core/constants.js", 5203 "line": 270, 5204 "itemtype": "property", 5205 "name": "CHORD", 5206 "type": "String", 5207 "final": 1, 5208 "class": "p5", 5209 "module": "Constants", 5210 "submodule": "Constants" 5211 }, 5212 { 5213 "file": "src/core/constants.js", 5214 "line": 275, 5215 "itemtype": "property", 5216 "name": "PIE", 5217 "type": "String", 5218 "final": 1, 5219 "class": "p5", 5220 "module": "Constants", 5221 "submodule": "Constants" 5222 }, 5223 { 5224 "file": "src/core/constants.js", 5225 "line": 280, 5226 "itemtype": "property", 5227 "name": "PROJECT", 5228 "type": "String", 5229 "final": 1, 5230 "default": "square", 5231 "class": "p5", 5232 "module": "Constants", 5233 "submodule": "Constants" 5234 }, 5235 { 5236 "file": "src/core/constants.js", 5237 "line": 286, 5238 "itemtype": "property", 5239 "name": "SQUARE", 5240 "type": "String", 5241 "final": 1, 5242 "default": "butt", 5243 "class": "p5", 5244 "module": "Constants", 5245 "submodule": "Constants" 5246 }, 5247 { 5248 "file": "src/core/constants.js", 5249 "line": 292, 5250 "itemtype": "property", 5251 "name": "ROUND", 5252 "type": "String", 5253 "final": 1, 5254 "class": "p5", 5255 "module": "Constants", 5256 "submodule": "Constants" 5257 }, 5258 { 5259 "file": "src/core/constants.js", 5260 "line": 297, 5261 "itemtype": "property", 5262 "name": "BEVEL", 5263 "type": "String", 5264 "final": 1, 5265 "class": "p5", 5266 "module": "Constants", 5267 "submodule": "Constants" 5268 }, 5269 { 5270 "file": "src/core/constants.js", 5271 "line": 302, 5272 "itemtype": "property", 5273 "name": "MITER", 5274 "type": "String", 5275 "final": 1, 5276 "class": "p5", 5277 "module": "Constants", 5278 "submodule": "Constants" 5279 }, 5280 { 5281 "file": "src/core/constants.js", 5282 "line": 309, 5283 "itemtype": "property", 5284 "name": "RGB", 5285 "type": "String", 5286 "final": 1, 5287 "class": "p5", 5288 "module": "Constants", 5289 "submodule": "Constants" 5290 }, 5291 { 5292 "file": "src/core/constants.js", 5293 "line": 314, 5294 "itemtype": "property", 5295 "name": "HSB", 5296 "type": "String", 5297 "final": 1, 5298 "class": "p5", 5299 "module": "Constants", 5300 "submodule": "Constants" 5301 }, 5302
5302 { 5303 "file": "src/core/constants.js", 5304 "line": 319, 5305 "itemtype": "property", 5306 "name": "HSL", 5307 "type": "String", 5308 "final": 1, 5309 "class": "p5", 5310 "module": "Constants", 5311 "submodule": "Constants" 5312 }, 5313 { 5314 "file": "src/core/constants.js", 5315 "line": 345, 5316 "itemtype": "property", 5317 "name": "BLEND", 5318 "type": "String", 5319 "final": 1, 5320 "default": "source-over", 5321 "class": "p5", 5322 "module": "Constants", 5323 "submodule": "Constants" 5324 }, 5325 { 5326 "file": "src/core/constants.js", 5327 "line": 351, 5328 "itemtype": "property", 5329 "name": "ADD", 5330 "type": "String", 5331 "final": 1, 5332 "default": "lighter", 5333 "class": "p5", 5334 "module": "Constants", 5335 "submodule": "Constants" 5336 }, 5337 { 5338 "file": "src/core/constants.js", 5339 "line": 359, 5340 "itemtype": "property", 5341 "name": "DARKEST", 5342 "type": "String", 5343 "final": 1, 5344 "class": "p5", 5345 "module": "Constants", 5346 "submodule": "Constants" 5347 }, 5348 { 5349 "file": "src/core/constants.js", 5350 "line": 364, 5351 "itemtype": "property", 5352 "name": "LIGHTEST", 5353 "type": "String", 5354 "final": 1, 5355 "default": "lighten", 5356 "class": "p5", 5357 "module": "Constants", 5358 "submodule": "Constants" 5359 }, 5360 { 5361 "file": "src/core/constants.js", 5362 "line": 370, 5363 "itemtype": "property", 5364 "name": "DIFFERENCE", 5365 "type": "String", 5366 "final": 1, 5367 "class": "p5", 5368 "module": "Constants", 5369 "submodule": "Constants" 5370 }, 5371 { 5372 "file": "src/core/constants.js", 5373 "line": 375, 5374 "itemtype": "property", 5375 "name": "EXCLUSION", 5376 "type": "String", 5377 "final": 1, 5378 "class": "p5", 5379 "module": "Constants", 5380 "submodule": "Constants" 5381 }, 5382 { 5383 "file": "src/core/constants.js", 5384 "line": 380, 5385 "itemtype": "property", 5386 "name": "MULTIPLY", 5387 "type": "String", 5388 "final": 1, 5389 "class": "p5", 5390 "module": "Constants", 5391 "submodule": "Constants" 5392 }, 5393 { 5394 "file": "src/core/constants.js", 5395 "line": 385, 5396 "itemtype": "property", 5397 "name": "SCREEN", 5398 "type": "String", 5399 "final": 1, 5400 "class": "p5", 5401 "module": "Constants", 5402 "submodule": "Constants" 5403 }, 5404 { 5405 "file": "src/core/constants.js", 5406 "line": 390, 5407 "itemtype": "property", 5408 "name": "REPLACE", 5409 "type": "String", 5410 "final": 1, 5411 "default": "copy", 5412 "class": "p5", 5413 "module": "Constants", 5414 "submodule": "Constants" 5415 }, 5416 { 5417 "file": "src/core/constants.js", 5418 "line": 396, 5419 "itemtype": "property", 5420 "name": "OVERLAY", 5421 "type": "String", 5422 "final": 1, 5423 "class": "p5", 5424 "module": "Constants", 5425 "submodule": "Constants" 5426 }, 5427 { 5428 "file": "src/core/constants.js", 5429 "line": 401, 5430 "itemtype": "property", 5431 "name": "HARD_LIGHT", 5432 "type": "String", 5433 "final": 1, 5434 "class": "p5", 5435 "module": "Constants", 5436 "submodule": "Constants" 5437 }, 5438 { 5439 "file": "src/core/constants.js", 5440 "line": 406, 5441 "itemtype": "property", 5442 "name": "SOFT_LIGHT", 5443 "type": "String", 5444 "final": 1, 5445 "class": "p5", 5446 "module": "Constants", 5447 "submodule": "Constants" 5448 }, 5449 { 5450 "file": "src/core/constants.js", 5451 "line": 411, 5452 "itemtype": "property", 5453 "name": "DODGE", 5454 "type": "String", 5455 "final": 1, 5456 "default": "color-dodge", 5457 "class": "p5", 5458 "module": "Constants", 5459 "submodule": "Constants" 5460 }, 5461 { 5462 "file": "src/core/constants.js", 5463 "line": 417, 5464 "itemtype": "property", 5465 "name": "BURN", 5466 "type": "String", 5467 "final": 1, 5468 "default": "color-burn", 5469 "class": "p5", 5470 "module": "Constants", 5471 "submodule": "Constants" 5472 }, 5473 { 5474 "file": "src/core/constants.js", 5475 "line": 425, 5476 "itemtype": "property", 5477 "name": "THRESHOLD", 5478 "type": "String", 5479 "final": 1, 5480 "class": "p5", 5481 "module": "Constants", 5482 "submodule": "Constants" 5483 }, 5484 { 5485 "file": "src/core/constants.js", 5486 "line": 430, 5487 "itemtype": "property", 5488 "name": "GRAY", 5489 "type": "String", 5490 "final": 1, 5491 "class": "p5", 5492 "module": "Constants", 5493 "submodule": "Constants" 5494 }, 5495 { 5496 "file": "src/core/constants.js", 5497 "line": 435, 5498 "itemtype": "property", 5499 "name": "OPAQUE", 5500 "type": "String", 5501 "final": 1, 5502 "class": "p5", 5503 "module": "Constants", 5504 "submodule": "Constants" 5505 }, 5506 { 5507 "file": "src/core/constants.js", 5508 "line": 440, 5509 "itemtype": "property", 5510 "name": "INVERT", 5511 "type": "String", 5512 "final": 1, 5513 "class": "p5", 5514 "module": "Constants", 5515 "submodule": "Constants" 5516 }, 5517 { 5518 "file": "src/core/constants.js", 5519 "line": 445, 5520 "itemtype": "property", 5521 "name": "POSTERIZE", 5522 "type": "String", 5523 "final": 1, 5524 "class": "p5", 5525 "module": "Constants", 5526 "submodule": "Constants" 5527 }, 5528 { 5529 "file": "src/core/constants.js", 5530 "line": 450, 5531 "itemtype": "property", 5532 "name": "DILATE", 5533 "type": "String", 5534 "final": 1, 5535 "class": "p5", 5536 "module": "Constants", 5537 "submodule": "Constants" 5538 }, 5539 { 5540 "file": "src/core/constants.js", 5541 "line": 455, 5542 "itemtype": "property", 5543 "name": "ERODE", 5544 "type": "String", 5545 "final": 1, 5546 "class": "p5", 5547 "module": "Constants", 5548 "submodule": "Constants" 5549 }, 5550 { 5551 "file": "src/core/constants.js", 5552 "line": 460, 5553 "itemtype": "property", 5554 "name": "BLUR", 5555 "type": "String", 5556 "final": 1, 5557 "class": "p5", 5558 "module": "Constants", 5559 "submodule": "Constants" 5560 }, 5561 { 5562 "file": "src/core/constants.js", 5563 "line": 467, 5564 "itemtype": "property", 5565 "name": "NORMAL", 5566 "type": "String", 5567 "final": 1, 5568 "class": "p5", 5569 "module": "Constants", 5570 "submodule": "Constants" 5571 }, 5572 { 5573 "file": "src/core/constants.js", 5574 "line": 472, 5575 "itemtype": "property", 5576 "name": "ITALIC", 5577 "type": "String", 5578 "final": 1, 5579 "class": "p5", 5580 "module": "Constants", 5581 "submodule": "Constants" 5582 }, 5583 { 5584 "file": "src/core/constants.js", 5585 "line": 477, 5586 "itemtype": "property", 5587 "name": "BOLD", 5588 "type": "String", 5589 "final": 1, 5590 "class": "p5", 5591 "module": "Constants", 5592 "submodule": "Constants" 5593 }, 5594 { 5595 "file": "src/core/constants.js", 5596 "line": 501, 5597 "itemtype": "property", 5598 "name": "LANDSCAPE", 5599 "type": "String", 5600 "final": 1, 5601 "class": "p5", 5602 "module": "Constants", 5603 "submodule": "Constants" 5604 }, 5605 { 5606 "file": "src/core/constants.js", 5607 "line": 506, 5608 "itemtype": "property", 5609 "name": "PORTRAIT", 5610 "type": "String", 5611 "final": 1, 5612 "class": "p5", 5613 "module": "Constants", 5614 "submodule": "Constants" 5615 }, 5616 { 5617 "file": "src/core/core.js", 5618 "line": 49, 5619 "description": "<p>Called directly before setup(), the preload() function is used to handle\nasynchronous loading of external files in a blocking way. If a preload \nfunction is defined, setup() will wait until any load calls within have\nfinished. Nothing besides load calls (loadImage, loadJSON, loadFont,\nloadStrings, etc.) should be inside preload function. If asynchronous\nloading is preferred, the load methods can instead be called in setup()\nor anywhere else with the use of a callback parameter.\n<br><br>\nBy default the text "loading..." will be displayed. To make your own\nloading page, include an HTML element with id "p5_loading" in your\npage. More information <a href=\"http://bit.ly/2kQ6Nio\">here</a>.</p>\n", 5620 "itemtype": "method", 5621 "name": "preload", 5622 "example": [ 5623 "\n<div><code>\nvar img;\nvar c;\nfunction preload() {\n // preload() runs once\n img = loadImage('assets/laDefense.jpg');\n}\n\nfunction setup() {\n // setup() waits until preload() is done\n img.loadPixels();\n // get color of middle pixel\n c = img.get(img.width / 2, img.height / 2);\n}\n\nfunction draw() {\n background(c);\n image(img, 25, 25, 50, 50);\n}\n</code></div>" 5624 ], 5625 "alt": "nothing displayed", 5626 "class": "p5", 5627 "module": "Structure", 5628 "submodule": "Structure" 5629 }, 5630 { 5631 "file": "src/core/core.js", 5632 "line": 90, 5633 "description": "<p>The setup() function is called once when the program starts. It's used to\ndefine initial environment properties such as screen size and background\ncolor and to load media such as images and fonts as the program starts.\nThere can only be one setup() function for each program and it shouldn't\nbe called again after its initial execution.\n<br><br>\nNote: Variables declared within setup() are not accessible within other\nfunctions, including draw().</p>\n", 5634 "itemtype": "method", 5635 "name": "setup", 5636 "example": [ 5637 "\n<div><code>\nvar a = 0;\n\nfunction setup() {\n background(0);\n noStroke();\n fill(102);\n}\n\nfunction draw() {\n rect(a++ % width, 10, 2, 80);\n}\n</code></div>" 5638 ], 5639 "alt": "nothing displayed", 5640 "class": "p5", 5641 "module": "Structure", 5642 "submodule": "Structure" 5643 }, 5644 { 5645 "file": "src/core/core.js", 5646 "line": 121, 5647 "description": "<p>Called directly after setup(), the draw() function continuously executes\nthe lines of code contained inside its block until the program is stopped\nor noLoop() is called. Note if noLoop() is called
5647in setup(), draw() will\nstill be executed once before stopping. draw() is called automatically and\nshould never be called explicitly.\n<br><br>\nIt should always be controlled with noLoop(), redraw() and loop(). After\nnoLoop() stops the code in draw() from executing, redraw() causes the\ncode inside draw() to execute once, and loop() will cause the code\ninside draw() to resume executing continuously.\n<br><br>\nThe number of times draw() executes in each second may be controlled with\nthe frameRate() function.\n<br><br>\nThere can only be one draw() function for each sketch, and draw() must\nexist if you want the code to run continuously, or to process events such\nas mousePressed(). Sometimes, you might have an empty call to draw() in\nyour program, as shown in the above example.\n<br><br>\nIt is important to note that the drawing coordinate system will be reset\nat the beginning of each draw() call. If any transformations are performed\nwithin draw() (ex: scale, rotate, translate), their effects will be\nundone at the beginning of draw(), so transformations will not accumulate\nover time. On the other hand, styling applied (ex: fill, stroke, etc) will\nremain in effect.</p>\n", 5648 "itemtype": "method", 5649 "name": "draw", 5650 "example": [ 5651 "\n<div><code>\nvar yPos = 0;\nfunction setup() {\n // setup() runs once\n frameRate(30);\n}\nfunction draw() {\n // draw() loops forever, until stopped\n background(204);\n yPos = yPos - 1;\n if (yPos < 0) {\n yPos = height;\n }\n line(0, yPos, width, yPos);\n}\n</code></div>" 5652 ], 5653 "alt": "nothing displayed", 5654 "class": "p5", 5655 "module": "Structure", 5656 "submodule": "Structure" 5657 }, 5658 { 5659 "file": "src/core/core.js", 5660 "line": 407, 5661 "description": "<p>Removes the entire p5 sketch. This will remove the canvas and any\nelements created by p5.js. It will also stop the draw loop and unbind\nany properties or methods from the window global scope. It will\nleave a variable p5 in case you wanted to create a new p5 sketch.\nIf you like, you can set p5 = null to erase it. While all functions and\nvariables and objects created by the p5 library will be removed, any\nother global variables created by your code will remain.</p>\n", 5662 "itemtype": "method", 5663 "name": "remove", 5664 "example": [ 5665 "\n<div class='norender'><code>\nfunction draw() {\n ellipse(50, 50, 10, 10);\n}\n\nfunction mousePressed() {\n remove(); // remove whole sketch on mouse press\n}\n</code></div>" 5666 ], 5667 "alt": "nothing displayed", 5668 "class": "p5", 5669 "module": "Structure", 5670 "submodule": "Structure" 5671 }, 5672 { 5673 "file": "src/core/curves.js", 5674 "line": 13, 5675 "description": "<p>Draws a cubic Bezier curve on the screen. These curves are defined by a\nseries of anchor and control points. The first two parameters specify\nthe first anchor point and the last two parameters specify the other\nanchor point, which become the first and last points on the curve. The\nmiddle parameters specify the two control points which define the shape\nof the curve. Approximately speaking, control points "pull" the curve\ntowards them.<br /><br />Bezier curves were developed by French\nautomotive engineer Pierre Bezier, and are commonly used in computer\ngraphics to define gently sloping curves. See also curve().</p>\n", 5676 "itemtype": "method", 5677 "name": "bezier", 5678 "chainable": 1, 5679 "example": [ 5680 "\n<div>\n<code>\nnoFill();\nstroke(255, 102, 0);\nline(85, 20, 10, 10);\nline(90, 90, 15, 80);\nstroke(0, 0, 0);\nbezier(85, 20, 10, 10, 90, 90, 15, 80);\n</code>\n</div>\n\n<div>\n<code>\nbackground(0, 0, 0);\nnoFill();\nstroke(255);\nbezier(250, 250, 0, 100, 100, 0, 100, 0, 0, 0, 100, 0);\n</code>\n</div>" 5681 ], 5682 "alt": "stretched black s-shape in center with orange lines extending from end points.\
5682nstretched black s-shape with 10 5x5 white ellipses along the shape.\nstretched black s-shape with 7 5x5 ellipses and orange lines along the shape.\nstretched black s-shape with 17 small orange lines extending from under shape.\nhorseshoe shape with orange ends facing left and black curved center.\nhorseshoe shape with orange ends facing left and black curved center.\nLine shaped like right-facing arrow,points move with mouse-x and warp shape.\nhorizontal line that hooks downward on the right and 13 5x5 ellipses along it.\nright curving line mid-right of canvas with 7 short lines radiating from it.", 5683 "class": "p5", 5684 "module": "Shape", 5685 "submodule": "Curves", 5686 "overloads": [ 5687 { 5688 "line": 13, 5689 "params": [ 5690 { 5691 "name": "x1", 5692 "description": "<p>x-coordinate for the first anchor point</p>\n", 5693 "type": "Number" 5694 }, 5695 { 5696 "name": "y1", 5697 "description": "<p>y-coordinate for the first anchor point</p>\n", 5698 "type": "Number" 5699 }, 5700 { 5701 "name": "x2", 5702 "description": "<p>x-coordinate for the first control point</p>\n", 5703 "type": "Number" 5704 }, 5705 { 5706 "name": "y2", 5707 "description": "<p>y-coordinate for the first control point</p>\n", 5708 "type": "Number" 5709 }, 5710 { 5711 "name": "x3", 5712 "description": "<p>x-coordinate for the second control point</p>\n", 5713 "type": "Number" 5714 }, 5715 { 5716 "name": "y3", 5717 "description": "<p>y-coordinate for the second control point</p>\n", 5718 "type": "Number" 5719 }, 5720 { 5721 "name": "x4", 5722 "description": "<p>x-coordinate for the second anchor point</p>\n", 5723 "type": "Number" 5724 }, 5725 { 5726 "name": "y4", 5727 "description": "<p>y-coordinate for the second anchor point</p>\n", 5728 "type": "Number" 5729 } 5730 ], 5731 "chainable": 1 5732 }, 5733 { 5734 "line": 66, 5735 "params": [ 5736 { 5737 "name": "x1", 5738 "description": "", 5739 "type": "Number" 5740 }, 5741 { 5742 "name": "y1", 5743 "description": "", 5744 "type": "Number" 5745 }, 5746 { 5747 "name": "z1", 5748 "description": "<p>z-coordinate for the first anchor point</p>\n", 5749 "type": "Number" 5750 }, 5751 { 5752 "name": "x2", 5753 "description": "", 5754 "type": "Number" 5755 }, 5756 { 5757 "name": "y2", 5758 "description": "", 5759 "type": "Number" 5760 }, 5761 { 5762 "name": "z2", 5763 "description": "<p>z-coordinate for the first control point</p>\n", 5764 "type": "Number" 5765 }, 5766 { 5767 "name": "x3", 5768 "description": "", 5769 "type": "Number" 5770 }, 5771 { 5772 "name": "y3", 5773 "description": "", 5774 "type": "Number" 5775 }, 5776 { 5777 "name": "z3", 5778 "description": "<p>z-coordinate for the second control point</p>\n", 5779 "type": "Number" 5780 }, 5781 { 5782 "name": "x4", 5783 "description": "", 5784 "type": "Number" 5785 }, 5786 { 5787 "name": "y4", 5788 "description": "", 5789 "type": "Number" 5790 }, 5791 { 5792 "name": "z4", 5793 "description": "<p>z-coordinate for the second anchor point</p>\n", 5794 "type": "Number" 5795 } 5796 ], 5797 "chainable": 1 5798 } 5799 ] 5800 }, 5801 { 5802 "file": "src/core/curves.js", 5803 "line": 92, 5804 "description": "<p>Sets the resolution at which Beziers display.</p>\n<p>The default value is 20.</p>\n<p>This function is only useful when using the WEBGL renderer\nas the default canvas renderer does not use this information.</p>\n", 5805 "itemtype": "method", 5806 "name": "bezierDetail", 5807 "params": [ 5808 { 5809 "name": "detail", 5810 "description": "<p>resolution of the curves</p>\n", 5811 "type": "Number" 5812 } 5813 ], 5814 "chainable": 1, 5815 "example": [ 5816 "\n<div modernizr='webgl'>\n<code>\nfunction setup() {\n createCanvas(100, 100, WEBGL);\n noFill();\n\n bezierDetail(5);\n}\n\nfunction draw() {\n background(200);\n\n // prettier-ignore\n bezier(-40, -40, 0,\n 90, -40, 0,\n -90, 40, 0,\n 40, 40, 0);\n}\n</code>\n</div>" 5817 ], 5818 "alt": "stretched black s-shape with a low level of bezier detail", 5819 "class": "p5", 5820 "module": "Shape", 5821 "submodule": "Curves" 5822 }, 5823 { 5824 "file": "src/core/curves.js", 5825 "line": 135, 5826 "description": "<p>Evaluates the Bezier at position t for points a, b, c, d.\nThe parameters a and d are the first and last points\non the curve, and b and c are the control points.\
5826nThe final parameter t varies between 0 and 1.\nThis can be done once with the x coordinates and a second time\nwith the y coordinates to get the location of a bezier curve at t.</p>\n", 5827 "itemtype": "method", 5828 "name": "bezierPoint", 5829 "params": [ 5830 { 5831 "name": "a", 5832 "description": "<p>coordinate of first point on the curve</p>\n", 5833 "type": "Number" 5834 }, 5835 { 5836 "name": "b", 5837 "description": "<p>coordinate of first control point</p>\n", 5838 "type": "Number" 5839 }, 5840 { 5841 "name": "c", 5842 "description": "<p>coordinate of second control point</p>\n", 5843 "type": "Number" 5844 }, 5845 { 5846 "name": "d", 5847 "description": "<p>coordinate of second point on the curve</p>\n", 5848 "type": "Number" 5849 }, 5850 { 5851 "name": "t", 5852 "description": "<p>value between 0 and 1</p>\n", 5853 "type": "Number" 5854 } 5855 ], 5856 "return": { 5857 "description": "the value of the Bezier at position t", 5858 "type": "Number" 5859 }, 5860 "example": [ 5861 "\n<div>\n<code>\nnoFill();\nvar x1 = 85,\n x2 = 10,\n x3 = 90,\n x4 = 15;\nvar y1 = 20,\n y2 = 10,\n y3 = 90,\n y4 = 80;\nbezier(x1, y1, x2, y2, x3, y3, x4, y4);\nfill(255);\nvar steps = 10;\nfor (var i = 0; i <= steps; i++) {\n var t = i / steps;\n var x = bezierPoint(x1, x2, x3, x4, t);\n var y = bezierPoint(y1, y2, y3, y4, t);\n ellipse(x, y, 5, 5);\n}\n</code>\n</div>" 5862 ], 5863 "alt": "stretched black s-shape with 17 small orange lines extending from under shape.", 5864 "class": "p5", 5865 "module": "Shape", 5866 "submodule": "Curves" 5867 }, 5868 { 5869 "file": "src/core/curves.js", 5870 "line": 190, 5871 "description": "<p>Evaluates the tangent to the Bezier at position t for points a, b, c, d.\nThe parameters a and d are the first and last points\non the curve, and b and c are the control points.\nThe final parameter t varies between 0 and 1.</p>\n", 5872 "itemtype": "method", 5873 "name": "bezierTangent", 5874 "params": [ 5875 { 5876 "name": "a", 5877 "description": "<p>coordinate of first point on the curve</p>\n", 5878 "type": "Number" 5879 }, 5880 { 5881 "name": "b", 5882 "description": "<p>coordinate of first control point</p>\n", 5883 "type": "Number" 5884 }, 5885 { 5886 "name": "c", 5887 "description": "<p>coordinate of second control point</p>\n", 5888 "type": "Number" 5889 }, 5890 { 5891 "name": "d", 5892 "description": "<p>coordinate of second point on the curve</p>\n", 5893 "type": "Number" 5894 }, 5895 { 5896 "name": "t", 5897 "description": "<p>value between 0 and 1</p>\n", 5898 "type": "Number" 5899 } 5900 ], 5901 "return": { 5902 "description": "the tangent at position t", 5903 "type": "Number" 5904 }, 5905 "example": [ 5906 "\n<div>\n<code>\nnoFill();\nbezier(85, 20, 10, 10, 90, 90, 15, 80);\nvar steps = 6;\nfill(255);\nfor (var i = 0; i <= steps; i++) {\n var t = i / steps;\n // Get the location of the point\n var x = bezierPoint(85, 10, 90, 15, t);\n var y = bezierPoint(20, 10, 90, 80, t);\n // Get the tangent points\n var tx = bezierTangent(85, 10, 90, 15, t);\n var ty = bezierTangent(20, 10, 90, 80, t);\n // Calculate an angle from the tangent points\n var a = atan2(ty, tx);\n a += PI;\n stroke(255, 102, 0);\n line(x, y, cos(a) * 30 + x, sin(a) * 30 + y);\n // The following line of code makes a line\n // inverse of the above line\n //line(x, y, cos(a)*-30 + x, sin(a)*-30 + y);\n stroke(0);\n ellipse(x, y, 5, 5);\n}\n</code>\n</div>\n\n<div>\n<code>\nnoFill();\nbezier(85, 20, 10, 10, 90, 90, 15, 80);\nstroke(255, 102, 0);\nvar steps = 16;\nfor (var i = 0; i <= steps;
5906 i++) {\n var t = i / steps;\n var x = bezierPoint(85, 10, 90, 15, t);\n var y = bezierPoint(20, 10, 90, 80, t);\n var tx = bezierTangent(85, 10, 90, 15, t);\n var ty = bezierTangent(20, 10, 90, 80, t);\n var a = atan2(ty, tx);\n a -= HALF_PI;\n line(x, y, cos(a) * 8 + x, sin(a) * 8 + y);\n}\n</code>\n</div>" 5907 ], 5908 "alt": "s-shaped line with 17 short orange lines extending from underside of shape", 5909 "class": "p5", 5910 "module": "Shape", 5911 "submodule": "Curves" 5912 }, 5913 { 5914 "file": "src/core/curves.js", 5915 "line": 269, 5916 "description": "<p>Draws a curved line on the screen between two points, given as the\nmiddle four parameters. The first two parameters are a control point, as\nif the curve came from this point even though it's not drawn. The last\ntwo parameters similarly describe the other control point. <br /><br />\nLonger curves can be created by putting a series of curve() functions\ntogether or using curveVertex(). An additional function called\ncurveTightness() provides control for the visual quality of the curve.\nThe curve() function is an implementation of Catmull-Rom splines.</p>\n", 5917 "itemtype": "method", 5918 "name": "curve", 5919 "chainable": 1, 5920 "example": [ 5921 "\n<div>\n<code>\nnoFill();\nstroke(255, 102, 0);\ncurve(5, 26, 5, 26, 73, 24, 73, 61);\nstroke(0);\ncurve(5, 26, 73, 24, 73, 61, 15, 65);\nstroke(255, 102, 0);\ncurve(73, 24, 73, 61, 15, 65, 15, 65);\n</code>\n</div>\n<div>\n<code>\n// Define the curve points as JavaScript objects\nvar p1 = { x: 5, y: 26 },\n p2 = { x: 73, y: 24 };\nvar p3 = { x: 73, y: 61 },\n p4 = { x: 15, y: 65 };\nnoFill();\nstroke(255, 102, 0);\ncurve(p1.x, p1.y, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y);\nstroke(0);\ncurve(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y);\nstroke(255, 102, 0);\ncurve(p2.x, p2.y, p3.x, p3.y, p4.x, p4.y, p4.x, p4.y);\n</code>\n</div>\n<div>\n<code>\nnoFill();\nstroke(255, 102, 0);\ncurve(5, 26, 0, 5, 26, 0, 73, 24, 0, 73, 61, 0);\nstroke(0);\ncurve(5, 26, 0, 73, 24, 0, 73, 61, 0, 15, 65, 0);\nstroke(255, 102, 0);\ncurve(73, 24, 0, 73, 61, 0, 15, 65, 0, 15, 65, 0);\n</code>\n</div>" 5922 ], 5923 "alt": "horseshoe shape with orange ends facing left and black curved center.\nhorseshoe shape with orange ends facing left and black curved center.\ncurving black and orange lines.", 5924 "class": "p5", 5925 "module": "Shape", 5926 "submodule": "Curves", 5927 "overloads": [ 5928 { 5929 "line": 269, 5930 "params": [ 5931 { 5932 "name": "x1", 5933 "description": "<p>x-coordinate for the beginning control point</p>\n", 5934 "type": "Number" 5935 }, 5936 { 5937 "name": "y1", 5938 "description": "<p>y-coordinate for the beginning control point</p>\n", 5939 "type": "Number" 5940 }, 5941 { 5942 "name": "x2", 5943 "description": "<p>x-coordinate for the first point</p>\n", 5944 "type": "Number" 5945 }, 5946 { 5947 "name": "y2", 5948 "description": "<p>y-coordinate for the first point</p>\n", 5949 "type": "Number" 5950 }, 5951 { 5952 "name": "x3", 5953 "description": "<p>x-coordinate for the second point</p>\n", 5954 "type": "Number" 5955 }, 5956 { 5957 "name": "y3", 5958 "description": "<p>y-coordinate for the second point</p>\n", 5959 "type": "Number" 5960 }, 5961 { 5962 "name": "x4", 5963 "description": "<p>x-coordinate for the ending control point</p>\n", 5964 "type": "Number" 5965 }, 5966 { 5967 "name": "y4", 5968 "description": "<p>y-coordinate for the ending control point</p>\n", 5969 "type": "Number" 5970 } 5971 ], 5972 "chainable": 1 5973 }, 5974 { 5975 "line": 334, 5976 "params": [ 5977 { 5978 "name": "x1", 5979 "description": "", 5980 "type": "Number" 5981 }, 5982 { 5983 "name": "y1", 5984 "description": "", 5985 "type": "Number" 5986 }, 5987 { 5988 "name": "z1", 5989 "description": "<p>z-coordinate for the beginning control point</p>\n", 5990 "type": "Number" 5991 }, 5992 { 5993 "name": "x2", 5994 "description": "", 5995 "type": "Number" 5996 }, 5997 { 5998 "name": "y2", 5999 "description": "", 6000 "type": "Number" 6001 }, 6002 { 6003 "name": "z2", 6004 "description": "<p>z-coordinate for the first point</p>\n", 6005 "type": "Number" 6006 }, 6007 { 6008 "name": "x3", 6009 "description": "", 6010 "type": "Number" 6011 }, 6012 { 6013 "name": "y3", 6014 "description": "", 6015 "type": "Number" 6016 }, 6017 { 6018 "name": "z3", 6019 "description": "<p>z-coordinate for the second point</p>\n", 6020 "type": "Number" 6021 }, 6022 { 6023 "name": "x4", 6024 "description": "", 6025 "type": "Number" 6026 }, 6027 { 6028 "name": "y4", 6029 "description": "", 6030 "type": "Number" 6031 }, 6032 { 6033 "name": "z4", 6034 "description": "<p>z-coordinate for the ending control point</p>\n", 6035 "type": "Number" 6036 } 6037 ], 6038 "chainable": 1 6039 } 6040 ] 6041 }, 6042 { 6043 "file": "src/core/curves.js", 6044 "line": 360, 6045 "description": "<p>Sets the resolution at which curves display.</p>\n<p>The default value is 20.</p>\n<p>This function is only useful when using the WEBGL renderer\nas the default canvas renderer does not use this\ninformation.</p>\n", 6046 "itemtype": "method", 6047 "name": "curveDetail", 6048 "params": [ 6049 { 6050 "name": "resolution", 6051 "description": "<p>of the curves</p>\n", 6052 "type": "Number" 6053 } 6054 ], 6055 "chainable": 1, 6056 "example": [ 6057 "\n<div modernizr='webgl'>\n<code>\nfunction setup() {\n createCanvas(100, 100, WEBGL);\n\n curveDetail(5);\n}\nfunction draw() {\n background(200);\n\n // prettier-ignore\n curve( 250, 600, 0,\n -30, 40, 0,\n 30, 30, 0,\n -250, 600, 0);\n}\n</code>\n</div>" 6058 ], 6059 "alt": "white arch shape with a low level of curve detail.", 6060 "class": "p5", 6061 "module": "Shape", 6062 "submodule": "Curves" 6063 }, 6064 { 6065 "file": "src/core/curves.js", 6066 "line": 402, 6067 "description": "<p>
6067Modifies the quality of forms created with curve() and curveVertex().\nThe parameter tightness determines how the curve fits to the vertex\npoints. The value 0.0 is the default value for tightness (this value\ndefines the curves to be Catmull-Rom splines) and the value 1.0 connects\nall the points with straight lines. Values within the range -5.0 and 5.0\nwill deform the curves but will leave them recognizable and as values\nincrease in magnitude, they will continue to deform.</p>\n", 6068 "itemtype": "method", 6069 "name": "curveTightness", 6070 "params": [ 6071 { 6072 "name": "amount", 6073 "description": "<p>of deformation from the original vertices</p>\n", 6074 "type": "Number" 6075 } 6076 ], 6077 "chainable": 1, 6078 "example": [ 6079 "\n<div>\n<code>\n// Move the mouse left and right to see the curve change\n\nfunction setup() {\n createCanvas(100, 100);\n noFill();\n}\n\nfunction draw() {\n background(204);\n var t = map(mouseX, 0, width, -5, 5);\n curveTightness(t);\n beginShape();\n curveVertex(10, 26);\n curveVertex(10, 26);\n curveVertex(83, 24);\n curveVertex(83, 61);\n curveVertex(25, 65);\n curveVertex(25, 65);\n endShape();\n}\n</code>\n</div>" 6080 ], 6081 "alt": "Line shaped like right-facing arrow,points move with mouse-x and warp shape.", 6082 "class": "p5", 6083 "module": "Shape", 6084 "submodule": "Curves" 6085 }, 6086 { 6087 "file": "src/core/curves.js", 6088 "line": 448, 6089 "description": "<p>Evaluates the curve at position t for points a, b, c, d.\nThe parameter t varies between 0 and 1, a and d are points\non the curve, and b and c are the control points.\nThis can be done once with the x coordinates and a second time\nwith the y coordinates to get the location of a curve at t.</p>\n", 6090 "itemtype": "method", 6091 "name": "curvePoint", 6092 "params": [ 6093 { 6094 "name": "a", 6095 "description": "<p>coordinate of first point on the curve</p>\n", 6096 "type": "Number" 6097 }, 6098 { 6099 "name": "b", 6100 "description": "<p>coordinate of first control point</p>\n", 6101 "type": "Number" 6102 }, 6103 { 6104 "name": "c", 6105 "description": "<p>coordinate of second control point</p>\n", 6106 "type": "Number" 6107 }, 6108 { 6109 "name": "d", 6110 "description": "<p>coordinate of second point on the curve</p>\n", 6111 "type": "Number" 6112 }, 6113 { 6114 "name": "t", 6115 "description": "<p>value between 0 and 1</p>\n", 6116 "type": "Number" 6117 } 6118 ], 6119 "return": { 6120 "description": "bezier value at position t", 6121 "type": "Number" 6122 }, 6123 "example": [ 6124 "\n<div>\n<code>\nnoFill();\ncurve(5, 26, 5, 26, 73, 24, 73, 61);\ncurve(5, 26, 73, 24, 73, 61, 15, 65);\nfill(255);\nellipseMode(CENTER);\nvar steps = 6;\nfor (var i = 0; i <= steps; i++) {\n var t = i / steps;\n var x = curvePoint(5, 5, 73, 73, t);\n var y = curvePoint(26, 26, 24, 61, t);\n ellipse(x, y, 5, 5);\n x = curvePoint(5, 73, 73, 15, t);\n y = curvePoint(26, 24, 61, 65, t);\n ellipse(x, y, 5, 5);\n}\n</code>\n</div>\n\nline hooking down to right-bottom with 13 5x5 white ellipse points" 6125 ], 6126 "class": "p5", 6127 "module": "Shape", 6128 "submodule": "Curves" 6129 }, 6130 { 6131 "file": "src/core/curves.js", 6132 "line": 497, 6133 "description": "<p>Evaluates the tangent to the curve at position t for points a, b, c, d.\nThe parameter t varies between 0 and 1, a and d are points on the curve,\nand b and c are the control points.</p>\n", 6134 "itemtype": "method", 6135 "name": "curveTangent", 6136 "params": [ 6137 { 6138 "name": "a", 6139 "description": "<p>coordinate of first point on the curve</p>\n", 6140 "type": "Number" 6141 }, 6142 { 6143 "name": "b", 6144 "description": "<p>coordinate of first control point</p>\n", 6145 "type": "Number" 6146 }, 6147 { 6148 "name": "c", 6149 "description": "<p>coordinate of second control point</p>\n", 6150 "type": "Number" 6151 }, 6152 { 6153 "name": "d", 6154 "description": "<p>coordinate of second point on the curve</p>\n", 6155 "type": "Number" 6156 }, 6157 { 6158 "name": "t", 6159 "description": "<p>value between 0 and 1</p>\n", 6160 "type": "Number" 6161 } 6162 ], 6163 "return": { 6164 "description": "the tangent at position t", 6165 "type": "Number" 6166 }, 6167 "example": [ 6168 "\n<div>\n<code>\nnoFill();\ncurve(5, 26, 73, 24, 73, 61, 15, 65);\nvar steps = 6;\nfor (var i = 0; i <= steps;
6168 i++) {\n var t = i / steps;\n var x = curvePoint(5, 73, 73, 15, t);\n var y = curvePoint(26, 24, 61, 65, t);\n //ellipse(x, y, 5, 5);\n var tx = curveTangent(5, 73, 73, 15, t);\n var ty = curveTangent(26, 24, 61, 65, t);\n var a = atan2(ty, tx);\n a -= PI / 2.0;\n line(x, y, cos(a) * 8 + x, sin(a) * 8 + y);\n}\n</code>\n</div>" 6169 ], 6170 "alt": "right curving line mid-right of canvas with 7 short lines radiating from it.", 6171 "class": "p5", 6172 "module": "Shape", 6173 "submodule": "Curves" 6174 }, 6175 { 6176 "file": "src/core/environment.js", 6177 "line": 22, 6178 "description": "<p>The print() function writes to the console area of your browser.\nThis function is often helpful for looking at the data a program is\nproducing. This function creates a new line of text for each call to\nthe function. Individual elements can be\nseparated with quotes ("") and joined with the addition operator (+).</p>\n", 6179 "itemtype": "method", 6180 "name": "print", 6181 "params": [ 6182 { 6183 "name": "contents", 6184 "description": "<p>any combination of Number, String, Object, Boolean,\n Array to print</p>\n", 6185 "type": "Any" 6186 } 6187 ], 6188 "example": [ 6189 "\n<div><code class='norender'>\nvar x = 10;\nprint('The value of x is ' + x);\n// prints \"The value of x is 10\"\n</code></div>" 6190 ], 6191 "alt": "default grey canvas", 6192 "class": "p5", 6193 "module": "Environment", 6194 "submodule": "Environment" 6195 }, 6196 { 6197 "file": "src/core/environment.js", 6198 "line": 49, 6199 "description": "<p>The system variable frameCount contains the number of frames that have\nbeen displayed since the program started. Inside setup() the value is 0,\nafter the first iteration of draw it is 1, etc.</p>\n", 6200 "itemtype": "property", 6201 "name": "frameCount", 6202 "type": "Integer", 6203 "readonly": "", 6204 "example": [ 6205 "\n <div><code>\nfunction setup() {\n frameRate(30);\n textSize(20);\n textSize(30);\n textAlign(CENTER);\n}\n\nfunction draw() {\n background(200);\n text(frameCount, width / 2, height / 2);\n}\n</code></div>" 6206 ], 6207 "alt": "numbers rapidly counting upward with frame count set to 30.", 6208 "class": "p5", 6209 "module": "Environment", 6210 "submodule": "Environment" 6211 }, 6212 { 6213 "file": "src/core/environment.js", 6214 "line": 77, 6215 "description": "<p>Confirms if the window a p5.js program is in is "focused," meaning that\nthe sketch will accept mouse or keyboard input. This variable is\n"true" if the window is focused and "false" if not.</p>\n", 6216 "itemtype": "property", 6217 "name": "focused", 6218 "type": "Boolean", 6219 "readonly": "", 6220 "example": [ 6221 "\n<div><code>\n// To demonstrate, put two windows side by side.\n// Click on the window that the p5 sketch isn't in!\nfunction draw() {\n background(200);\n noStroke();\n fill(0, 200, 0);\n ellipse(25, 25, 50, 50);\n\n if (!focused) {\n // or \"if (focused === false)\"\n stroke(200, 0, 0);\n line(0, 0, 100, 100);\n line(100, 0, 0, 100);\n }\n}\n</code></div>" 6222 ], 6223 "alt": "green 50x50 ellipse at top left. Red X covers canvas when page focus changes", 6224 "class": "p5", 6225 "module": "Environment", 6226 "submodule": "Environment" 6227 }, 6228 { 6229 "file": "src/core/environment.js", 6230 "line": 109, 6231 "description": "<p>Sets the cursor to a predefined symbol or an image, or makes it visible\nif already hidden. If you are trying to set an image as the cursor, the\nrecommended size is 16x16 or 32x32 pixels. It is not possible to load an\nimage as the cursor if you are exporting your program for the Web, and n
6231ot\nall MODES work with all browsers. The values for parameters x and y must\nbe less than the dimensions of the image.</p>\n", 6232 "itemtype": "method", 6233 "name": "cursor", 6234 "params": [ 6235 { 6236 "name": "type", 6237 "description": "<p>either ARROW, CROSS, HAND, MOVE, TEXT, or\n WAIT, or path for image</p>\n", 6238 "type": "String|Constant" 6239 }, 6240 { 6241 "name": "x", 6242 "description": "<p>the horizontal active spot of the cursor</p>\n", 6243 "type": "Number", 6244 "optional": true 6245 }, 6246 { 6247 "name": "y", 6248 "description": "<p>the vertical active spot of the cursor</p>\n", 6249 "type": "Number", 6250 "optional": true 6251 } 6252 ], 6253 "example": [ 6254 "\n<div><code>\n// Move the mouse left and right across the image\n// to see the cursor change from a cross to a hand\nfunction draw() {\n line(width / 2, 0, width / 2, height);\n if (mouseX < 50) {\n cursor(CROSS);\n } else {\n cursor(HAND);\n }\n}\n</code></div>" 6255 ], 6256 "alt": "horizontal line divides canvas. cursor on left is a cross, right is hand.", 6257 "class": "p5", 6258 "module": "Environment", 6259 "submodule": "Environment" 6260 }, 6261 { 6262 "file": "src/core/environment.js", 6263 "line": 170, 6264 "description": "<p>Specifies the number of frames to be displayed every second. For example,\nthe function call frameRate(30) will attempt to refresh 30 times a second.\nIf the processor is not fast enough to maintain the specified rate, the\nframe rate will not be achieved. Setting the frame rate within setup() is\nrecommended. The default rate is 60 frames per second. This is the same as\nsetFrameRate(val).\n<br><br>\nCalling frameRate() with no arguments returns the current framerate. The\ndraw function must run at least once before it will return a value. This\nis the same as getFrameRate().\n<br><br>\nCalling frameRate() with arguments that are not of the type numbers\nor are non positive also returns current framerate.</p>\n", 6265 "itemtype": "method", 6266 "name": "frameRate", 6267 "chainable": 1, 6268 "example": [ 6269 "\n\n<div><code>\nvar rectX = 0;\nvar fr = 30; //starting FPS\nvar clr;\n\nfunction setup() {\n background(200);\n frameRate(fr); // Attempt to refresh at starting FPS\n clr = color(255, 0, 0);\n}\n\nfunction draw() {\n background(200);\n rectX = rectX += 1; // Move Rectangle\n\n if (rectX >= width) {\n // If you go off screen.\n if (fr === 30) {\n clr = color(0, 0, 255);\n fr = 10;\n frameRate(fr); // make frameRate 10 FPS\n } else {\n clr = color(255, 0, 0);\n fr = 30;\n frameRate(fr); // make frameRate 30 FPS\n }\n rectX = 0;\n }\n fill(clr);\n rect(rectX, 40, 20, 20);\n}\n</code></div>" 6270 ], 6271 "alt": "blue rect moves left to right, followed by red rect moving faster. Loops.", 6272 "class": "p5", 6273 "module": "Environment", 6274 "submodule": "Environment", 6275 "overloads": [ 6276 { 6277 "line": 170, 6278 "params": [ 6279 { 6280 "name": "fps", 6281 "description": "<p>number of frames to be displayed every second</p>\n", 6282 "type": "Number" 6283 } 6284 ], 6285 "chainable": 1 6286 }, 6287 { 6288 "line": 228, 6289 "params": [], 6290 "return": { 6291 "description": "current frameRate", 6292 "type": "Number" 6293 } 6294 } 6295 ] 6296 }, 6297 { 6298 "file": "src/core/environment.js", 6299 "line": 268, 6300 "description": "<p>Hides the cursor from view.</p>\n", 6301 "itemtype": "method", 6302 "name": "noCursor", 6303 "example": [ 6304 "\n<div><code>\nfunction setup() {\n noCursor();\n}\n\nfunction draw() {\n background(200);\n ellipse(mouseX, mouseY, 10, 10);\n}\n</code></div>" 6305 ], 6306 "alt": "cursor becomes 10x 10 white ellipse the moves with mouse x and y.", 6307 "class": "p5", 6308 "module": "Environment", 6309 "submodule": "Environment" 6310 }, 6311 { 6312 "file": "src/core/environment.js", 6313 "line": 293, 6314 "description": "<p>System variable that stores the width of the entire screen display. This\nis used to run a full-screen program on any display size.</p>\n", 6315 "itemtype": "property", 6316 "name": "displayWidth", 6317 "type": "Number", 6318 "readonly": "", 6319 "example": [ 6320 "\n<div class=\"norender\"><code>\ncreateCanvas(displayWidth, displayHeight);\n</code></div>" 6321 ], 6322 "alt": "cursor becomes 10x 10 white ellipse the moves with mouse x and y.", 6323 "class": "p5", 6324 "module": "Environment", 6325 "submodule": "Environment" 6326 }, 6327 { 6328 "file": "src/core/environment.js", 6329 "line": 310, 6330 "description": "<p>System variable that stores the height of the entire screen display. This\nis used to run a full-screen program on any display size.</p>\n", 6331 "itemtype": "property", 6332 "name": "displayHeight", 6333 "type": "Number", 6334 "readonly": "", 6335 "example": [ 6336 "\n<div class=\"norender\"><code>\ncreateCanvas(displayWidth, displayHeight);\n</code></div>" 6337 ],
6338 "alt": "no display.", 6339 "class": "p5", 6340 "module": "Environment", 6341 "submodule": "Environment" 6342 }, 6343 { 6344 "file": "src/core/environment.js", 6345 "line": 327, 6346 "description": "<p>System variable that stores the width of the inner window, it maps to\nwindow.innerWidth.</p>\n", 6347 "itemtype": "property", 6348 "name": "windowWidth", 6349 "type": "Number", 6350 "readonly": "", 6351 "example": [ 6352 "\n<div class=\"norender\"><code>\ncreateCanvas(windowWidth, windowHeight);\n</code></div>" 6353 ], 6354 "alt": "no display.", 6355 "class": "p5", 6356 "module": "Environment", 6357 "submodule": "Environment" 6358 }, 6359 { 6360 "file": "src/core/environment.js", 6361 "line": 343, 6362 "description": "<p>System variable that stores the height of the inner window, it maps to\nwindow.innerHeight.</p>\n", 6363 "itemtype": "property", 6364 "name": "windowHeight", 6365 "type": "Number", 6366 "readonly": "", 6367 "example": [ 6368 "\n<div class=\"norender\"><code>\ncreateCanvas(windowWidth, windowHeight);\n</code></div>" 6369 ], 6370 "alt": "no display.", 6371 "class": "p5", 6372 "module": "Environment", 6373 "submodule": "Environment" 6374 }, 6375 { 6376 "file": "src/core/environment.js", 6377 "line": 359, 6378 "description": "<p>The windowResized() function is called once every time the browser window\nis resized. This is a good place to resize the canvas or do any other\nadjustments to accommodate the new window size.</p>\n", 6379 "itemtype": "method", 6380 "name": "windowResized", 6381 "example": [ 6382 "\n<div class=\"norender\"><code>\nfunction setup() {\n createCanvas(windowWidth, windowHeight);\n}\n\nfunction draw() {\n background(0, 100, 200);\n}\n\nfunction windowResized() {\n resizeCanvas(windowWidth, windowHeight);\n}\n</code></div>" 6383 ], 6384 "alt": "no display.", 6385 "class": "p5", 6386 "module": "Environment", 6387 "submodule": "Environment" 6388 }, 6389 { 6390 "file": "src/core/environment.js", 6391 "line": 413, 6392 "description": "<p>System variable that stores the width of the drawing canvas. This value\nis set by the first parameter of the createCanvas() function.\nFor example, the function call createCanvas(320, 240) sets the width\nvariable to the value 320. The value of width defaults to 100 if\ncreateCanvas() is not used in a program.</p>\n", 6393 "itemtype": "property", 6394 "name": "width", 6395 "type": "Number", 6396 "readonly": "", 6397 "class": "p5", 6398 "module": "Environment", 6399 "submodule": "Environment" 6400 }, 6401 { 6402 "file": "src/core/environment.js", 6403 "line": 425, 6404 "description": "<p>System variable that stores the height of the drawing canvas. This value\nis set by the second parameter of the createCanvas() function. For\nexample, the function call createCanvas(320, 240) sets the height\nvariable to the value 240. The value of height defaults to 100 if\ncreateCanvas() is not used in a program.</p>\n", 6405 "itemtype": "property", 6406 "name": "height", 6407 "type": "Number", 6408 "readonly": "", 6409 "class": "p5", 6410 "module": "Environment", 6411 "submodule": "Environment" 6412 }, 6413 { 6414 "file": "src/core/environment.js", 6415 "line": 437, 6416 "description": "<p>If argument is given, sets the sketch to fullscreen or not based on the\nvalue of the argument. If no argument is given, returns the current\nfullscreen state. Note that due to browser restrictions this can only\nbe called on user input, for example, on mouse press like the example\nbelow.</p>\n", 6417 "itemtype": "method", 6418 "name": "fullscreen", 6419 "params": [ 6420 { 6421 "name": "val", 6422 "description": "<p>whether the sketch should be in fullscreen mode\nor not</p>\n", 6423 "type": "Boolean", 6424 "optional": true 6425 } 6426 ], 6427 "return": { 6428 "description": "current fullscreen state", 6429 "type": "Boolean" 6430 }, 6431 "example": [ 6432 "\n<div>\n<code>\n// Clicking in the box toggles fullscreen on and off.\nfunction setup() {\n background(200);\n}\nfunction mousePressed() {\n if (mouseX > 0 && mouseX < 100 && mouseY > 0 && mouseY < 100) {\n var fs = fullscreen();\n fullscreen(!fs);\n }\n}\n</code>\n</div>" 6433 ],
6434 "alt": "no display.", 6435 "class": "p5", 6436 "module": "Environment", 6437 "submodule": "Environment" 6438 }, 6439 { 6440 "file": "src/core/environment.js", 6441 "line": 488, 6442 "description": "<p>Sets the pixel scaling for high pixel density displays. By default\npixel density is set to match display density, call pixelDensity(1)\nto turn this off. Calling pixelDensity() with no arguments returns\nthe current pixel density of the sketch.</p>\n", 6443 "itemtype": "method", 6444 "name": "pixelDensity", 6445 "params": [ 6446 { 6447 "name": "val", 6448 "description": "<p>whether or how much the sketch should scale</p>\n", 6449 "type": "Number", 6450 "optional": true 6451 } 6452 ], 6453 "return": { 6454 "description": "current pixel density of the sketch", 6455 "type": "Number" 6456 }, 6457 "example": [ 6458 "\n<div>\n<code>\nfunction setup() {\n pixelDensity(1);\n createCanvas(100, 100);\n background(200);\n ellipse(width / 2, height / 2, 50, 50);\n}\n</code>\n</div>\n<div>\n<code>\nfunction setup() {\n pixelDensity(3.0);\n createCanvas(100, 100);\n background(200);\n ellipse(width / 2, height / 2, 50, 50);\n}\n</code>\n</div>" 6459 ], 6460 "alt": "fuzzy 50x50 white ellipse with black outline in center of canvas.\nsharp 50x50 white ellipse with black outline in center of canvas.", 6461 "class": "p5", 6462 "module": "Environment", 6463 "submodule": "Environment" 6464 }, 6465 { 6466 "file": "src/core/environment.js", 6467 "line": 534, 6468 "description": "<p>Returns the pixel density of the current display the sketch is running on.</p>\n", 6469 "itemtype": "method", 6470 "name": "displayDensity", 6471 "return": { 6472 "description": "current pixel density of the display", 6473 "type": "Number" 6474 }, 6475 "example": [ 6476 "\n<div>\n<code>\nfunction setup() {\n var density = displayDensity();\n pixelDensity(density);\n createCanvas(100, 100);\n background(200);\n ellipse(width / 2, height / 2, 50, 50);\n}\n</code>\n</div>" 6477 ], 6478 "alt": "50x50 white ellipse with black outline in center of canvas.", 6479 "class": "p5", 6480 "module": "Environment", 6481 "submodule": "Environment" 6482 }, 6483 { 6484 "file": "src/core/environment.js", 6485 "line": 591, 6486 "description": "<p>Gets the current URL.</p>\n", 6487 "itemtype": "method", 6488 "name": "getURL", 6489 "return": { 6490 "description": "url", 6491 "type": "String" 6492 }, 6493 "example": [ 6494 "\n<div>\n<code>\nvar url;\nvar x = 100;\n\nfunction setup() {\n fill(0);\n noStroke();\n url = getURL();\n}\n\nfunction draw() {\n background(200);\n text(url, x, height / 2);\n x--;\n}\n</code>\n</div>" 6495 ], 6496 "alt": "current url (http://p5js.org/reference/#/p5/getURL) moves right to left.", 6497 "class": "p5", 6498 "module": "Environment", 6499 "submodule": "Environment" 6500 }, 6501 { 6502 "file": "src/core/environment.js", 6503 "line": 622, 6504 "description": "<p>Gets the current URL path as an array.</p>\n", 6505 "itemtype": "method", 6506 "name": "getURLPath", 6507 "return": { 6508 "description": "path components", 6509 "type": "String[]" 6510 }, 6511 "example": [ 6512 "\n<div class='norender'><code>\nfunction setup() {\n var urlPath = getURLPath();\n for (var i = 0; i < urlPath.length; i++) {\n text(urlPath[i], 10, i * 20 + 20);\n }\n}\n</code></div>" 6513 ], 6514 "alt": "no display", 6515 "class": "p5", 6516 "module": "Environment", 6517 "submodule": "Environment" 6518 }, 6519 { 6520 "file": "src/core/environment.js", 6521 "line": 645, 6522 "description": "<p>Gets the current URL params as an Object.</p>\n", 6523 "itemtype": "method", 6524 "name": "getURLParams", 6525 "return": { 6526 "description": "URL params", 6527 "type": "Object" 6528 }, 6529 "example": [ 6530 "\n<div class='norender notest'>\n<code>\n// Example: http://p5js.org?year=2014&month=May&day=15\n\nfunction setup() {\n var params = getURLParams();\n text(params.day, 10, 20);\n text(params.month, 10, 40);\n text(params.year, 10, 60);\n}\n</code>\n</div>" 6531 ],
6532 "alt": "no display.", 6533 "class": "p5", 6534 "module": "Environment", 6535 "submodule": "Environment" 6536 }, 6537 { 6538 "file": "src/core/error_helpers.js", 6539 "line": 1, 6540 "requires": [ 6541 "core" 6542 ], 6543 "class": "p5", 6544 "module": "Environment" 6545 }, 6546 { 6547 "file": "src/core/error_helpers.js", 6548 "line": 405, 6549 "description": "<p>Validates parameters\nparam {String} func the name of the function\nparam {Array} args user input arguments</p>\n<p>example:\n var a;\n ellipse(10,10,a,5);\nconsole ouput:\n "It looks like ellipse received an empty variable in spot #2."</p>\n<p>example:\n ellipse(10,"foo",5,5);\nconsole output:\n "ellipse was expecting a number for parameter #1,\n received "foo" instead."</p>\n", 6550 "class": "p5", 6551 "module": "Environment" 6552 }, 6553 { 6554 "file": "src/core/error_helpers.js", 6555 "line": 457, 6556 "description": "<p>Prints out all the colors in the color pallete with white text.\nFor color blindness testing.</p>\n", 6557 "class": "p5", 6558 "module": "Environment" 6559 }, 6560 { 6561 "file": "src/core/p5.Element.js", 6562 "line": 26, 6563 "description": "<p>Underlying HTML element. All normal HTML methods can be called on this.</p>\n", 6564 "example": [ 6565 "\n<div>\n<code>\ncreateCanvas(300, 500);\nbackground(0, 0, 0, 0);\nvar input = createInput();\ninput.position(20, 225);\nvar inputElem = new p5.Element(input.elt);\ninputElem.style('width:450px;');\ninputElem.value('some string');\n</code>\n</div>" 6566 ], 6567 "itemtype": "property", 6568 "name": "elt", 6569 "readonly": "", 6570 "class": "p5.Element", 6571 "module": "DOM", 6572 "submodule": "DOM" 6573 }, 6574 { 6575 "file": "src/core/p5.Element.js", 6576 "line": 51, 6577 "description": "<p>Attaches the element to the parent specified. A way of setting\n the container for the element. Accepts either a string ID, DOM\n node, or p5.Element. If no arguments given, parent node is returned.\n For more ways to position the canvas, see the\n <a href='https://github.com/processing/p5.js/wiki/Positioning-your-canvas'>\n positioning the canvas</a> wiki page.</p>\n", 6578 "itemtype": "method", 6579 "name": "parent", 6580 "chainable": 1, 6581 "example": [ 6582 "\n <div class=\"norender notest\"><code>\n // in the html file:\n // <div id=\"myContainer\"></div>\n// in the js file:\n var cnv = createCanvas(100, 100);\n cnv.parent('myContainer');\n </code></div>\n <div class='norender'><code>\n var div0 = createDiv('this is the parent');\n var div1 = createDiv('this is the child');\n div1.parent(div0); // use p5.Element\n </code></div>\n <div class='norender'><code>\n var div0 = createDiv('this is the parent');\n div0.id('apples');\n var div1 = createDiv('this is the child');\n div1.parent('apples'); // use id\n </code></div>\n <div class='norender notest'><code>\n var elt = document.getElementById('myParentDiv');\n var div1 = createDiv('this is the child');\n div1.parent(elt);
6582 // use element from page\n </code></div>" 6583 ], 6584 "alt": "no display.", 6585 "class": "p5.Element", 6586 "module": "DOM", 6587 "submodule": "DOM", 6588 "overloads": [ 6589 { 6590 "line": 51, 6591 "params": [ 6592 { 6593 "name": "parent", 6594 "description": "<p>the ID, DOM node, or p5.Element\n of desired parent element</p>\n", 6595 "type": "String|p5.Element|Object" 6596 } 6597 ], 6598 "chainable": 1 6599 }, 6600 { 6601 "line": 94, 6602 "params": [], 6603 "return": { 6604 "description": "", 6605 "type": "p5.Element" 6606 } 6607 } 6608 ] 6609 }, 6610 { 6611 "file": "src/core/p5.Element.js", 6612 "line": 116, 6613 "description": "<p>Sets the ID of the element. If no ID argument is passed in, it instead\n returns the current ID of the element.</p>\n", 6614 "itemtype": "method", 6615 "name": "id", 6616 "chainable": 1, 6617 "example": [ 6618 "\n <div class='norender'><code>\n function setup() {\n var cnv = createCanvas(100, 100);\n // Assigns a CSS selector ID to\n // the canvas element.\n cnv.id('mycanvas');\n }\n </code></div>" 6619 ], 6620 "alt": "no display.", 6621 "class": "p5.Element", 6622 "module": "DOM", 6623 "submodule": "DOM", 6624 "overloads": [ 6625 { 6626 "line": 116, 6627 "params": [ 6628 { 6629 "name": "id", 6630 "description": "<p>ID of the element</p>\n", 6631 "type": "String" 6632 } 6633 ], 6634 "chainable": 1 6635 }, 6636 { 6637 "line": 138, 6638 "params": [], 6639 "return": { 6640 "description": "the id of the element", 6641 "type": "String" 6642 } 6643 } 6644 ] 6645 }, 6646 { 6647 "file": "src/core/p5.Element.js", 6648 "line": 153, 6649 "description": "<p>Adds given class to the element. If no class argument is passed in, it\n instead returns a string containing the current class(es) of the element.</p>\n", 6650 "itemtype": "method", 6651 "name": "class", 6652 "chainable": 1, 6653 "example": [ 6654 "\n <div class='norender'><code>\n function setup() {\n var cnv = createCanvas(100, 100);\n // Assigns a CSS selector class 'small'\n // to the canvas element.\n cnv.class('small');\n }\n </code></div>" 6655 ], 6656 "alt": "no display.", 6657 "class": "p5.Element", 6658 "module": "DOM", 6659 "submodule": "DOM", 6660 "overloads": [ 6661 { 6662 "line": 153, 6663 "params": [ 6664 { 6665 "name": "class", 6666 "description": "<p>class to add</p>\n", 6667 "type": "String" 6668 } 6669 ], 6670 "chainable": 1 6671 }, 6672 { 6673 "line": 175, 6674 "params": [], 6675 "return": { 6676 "description": "the class of the element", 6677 "type": "String" 6678 } 6679 } 6680 ] 6681 }, 6682 { 6683 "file": "src/core/p5.Element.js", 6684 "line": 188, 6685 "description": "<p>The .mousePressed() function is called once after every time a\nmouse button is pressed over the element. This can be used to\nattach element specific event listeners.</p>\n", 6686 "itemtype": "method", 6687 "name": "mousePressed", 6688 "params": [ 6689 { 6690 "name": "fxn", 6691 "description": "<p>function to be fired when mouse is\n pressed over the element.\n if <code>false</code> is passed instead, the previously\n firing function will no longer fire.</p>\n", 6692 "type": "Function|Boolean" 6693 } 6694 ], 6695 "chainable": 1, 6696 "example": [ 6697 "\n<div class='norender'><code>\nvar cnv;\nvar d;\nvar g;\nfunction setup() {\n cnv = createCanvas(100, 100);\n cnv.mousePressed(changeGray); // attach listener for\n // canvas click only\n d = 10;\n g = 100;\n}\n\nfunction draw() {\n background(g);\n ellipse(width / 2, height / 2, d, d);\n}
6697\n\n// this function fires with any click anywhere\nfunction mousePressed() {\n d = d + 10;\n}\n\n// this function fires only when cnv is clicked\nfunction changeGray() {\n g = random(0, 255);\n}\n</code></div>" 6698 ], 6699 "alt": "no display.", 6700 "class": "p5.Element", 6701 "module": "DOM", 6702 "submodule": "DOM" 6703 }, 6704 { 6705 "file": "src/core/p5.Element.js", 6706 "line": 238, 6707 "description": "<p>The .doubleClicked() function is called once after every time a\nmouse button is pressed twice over the element. This can be used to\nattach element and action specific event listeners.</p>\n", 6708 "itemtype": "method", 6709 "name": "doubleClicked", 6710 "params": [ 6711 { 6712 "name": "fxn", 6713 "description": "<p>function to be fired when mouse is\n double clicked over the element.\n if <code>false</code> is passed instead, the previously\n firing function will no longer fire.</p>\n", 6714 "type": "Function|Boolean" 6715 } 6716 ], 6717 "return": { 6718 "description": "", 6719 "type": "p5.Element" 6720 }, 6721 "example": [ 6722 "\n<div class='norender'><code>\nvar cnv;\nvar d;\nvar g;\nfunction setup() {\n cnv = createCanvas(100, 100);\n cnv.doubleClicked(changeGray); // attach listener for\n // canvas double click only\n d = 10;\n g = 100;\n}\n\nfunction draw() {\n background(g);\n ellipse(width / 2, height / 2, d, d);\n}\n\n// this function fires with any double click anywhere\nfunction doubleClicked() {\n d = d + 10;\n}\n\n// this function fires only when cnv is double clicked\nfunction changeGray() {\n g = random(0, 255);\n}\n</code></div>" 6723 ], 6724 "alt": "no display.", 6725 "class": "p5.Element", 6726 "module": "DOM", 6727 "submodule": "DOM" 6728 }, 6729 { 6730 "file": "src/core/p5.Element.js", 6731 "line": 287, 6732 "description": "<p>The .mouseWheel() function is called once after every time a\nmouse wheel is scrolled over the element. This can be used to\nattach element specific event listeners.\n<br><br>\nThe function accepts a callback function as argument which will be executed\nwhen the <code>wheel</code> event is triggered on the element, the callback function is\npassed one argument <code>event</code>. The <code>event.deltaY</code> property returns negative\nvalues if the mouse wheel is rotated up or away from the user and positive\nin the other direction. The <code>event.deltaX</code> does the same as <code>event.deltaY</code>\nexcept it reads the horizontal wheel scroll of the mouse wheel.\n<br><br>\nOn OS X with "natural" scrolling enabled, the <code>event.deltaY</code> values are\nreversed.</p>\n", 6733 "itemtype": "method", 6734 "name": "mouseWheel", 6735 "params": [ 6736 { 6737 "name": "fxn", 6738 "description": "<p>function to be fired when mouse is\n scrolled over the element.\n if <code>false</code> is passed instead, the previously\n firing function will no longer fire.</p>\n", 6739 "type": "Function|Boolean" 6740 } 6741 ], 6742 "chainable": 1, 6743 "example": [ 6744 "\n<div class='norender'><code>\nvar cnv;\nvar d;\nvar g;\nfunction setup() {\n cnv = createCanvas(100, 100);\n cnv.mouseWheel(changeSize); // attach listener for\n // activity on canvas only\n d = 10;\n g = 100;\n}\n\nfunction draw() {\n background(g);\n ellipse(width / 2, height / 2, d, d);\n}\n\n// this function fires with mousewheel movement\n// anywhere on screen\nfunction mouseWheel() {\n g = g + 10;\n}\n\n// this function fires with mousewheel movement\n// over canvas only\nfunction changeSize(event) {\n if (event.deltaY > 0) {\n d = d + 10;\n } else {\n d = d - 10;\n }\n}\n</code></div>" 6745 ],
6746 "alt": "no display.", 6747 "class": "p5.Element", 6748 "module": "DOM", 6749 "submodule": "DOM" 6750 }, 6751 { 6752 "file": "src/core/p5.Element.js", 6753 "line": 353, 6754 "description": "<p>The .mouseReleased() function is called once after every time a\nmouse button is released over the element. This can be used to\nattach element specific event listeners.</p>\n", 6755 "itemtype": "method", 6756 "name": "mouseReleased", 6757 "params": [ 6758 { 6759 "name": "fxn", 6760 "description": "<p>function to be fired when mouse is\n released over the element.\n if <code>false</code> is passed instead, the previously\n firing function will no longer fire.</p>\n", 6761 "type": "Function|Boolean" 6762 } 6763 ], 6764 "chainable": 1, 6765 "example": [ 6766 "\n<div class='norender'><code>\nvar cnv;\nvar d;\nvar g;\nfunction setup() {\n cnv = createCanvas(100, 100);\n cnv.mouseReleased(changeGray); // attach listener for\n // activity on canvas only\n d = 10;\n g = 100;\n}\n\nfunction draw() {\n background(g);\n ellipse(width / 2, height / 2, d, d);\n}\n\n// this function fires after the mouse has been\n// released\nfunction mouseReleased() {\n d = d + 10;\n}\n\n// this function fires after the mouse has been\n// released while on canvas\nfunction changeGray() {\n g = random(0, 255);\n}\n</code></div>" 6767 ], 6768 "alt": "no display.", 6769 "class": "p5.Element", 6770 "module": "DOM", 6771 "submodule": "DOM" 6772 }, 6773 { 6774 "file": "src/core/p5.Element.js", 6775 "line": 406, 6776 "description": "<p>The .mouseClicked() function is called once after a mouse button is\npressed and released over the element. This can be used to\nattach element specific event listeners.</p>\n", 6777 "itemtype": "method", 6778 "name": "mouseClicked", 6779 "params": [ 6780 { 6781 "name": "fxn", 6782 "description": "<p>function to be fired when mouse is\n clicked over the element.\n if <code>false</code> is passed instead, the previously\n firing function will no longer fire.</p>\n", 6783 "type": "Function|Boolean" 6784 } 6785 ], 6786 "chainable": 1, 6787 "example": [ 6788 "\n<div class=\"norender\">\n<code>\nvar cnv;\nvar d;\nvar g;\n\nfunction setup() {\n cnv = createCanvas(100, 100);\n cnv.mouseClicked(changeGray); // attach listener for\n // activity on canvas only\n d = 10;\n g = 100;\n}\n\nfunction draw() {\n background(g);\n ellipse(width / 2, height / 2, d, d);\n}\n\n// this function fires after the mouse has been\n// clicked anywhere\nfunction mouseClicked() {\n d = d + 10;\n}\n\n// this function fires after the mouse has been\n// clicked on canvas\nfunction changeGray() {\n g = random(0, 255);\n}\n</code>\n</div>" 6789 ], 6790 "alt": "no display.", 6791 "class": "p5.Element", 6792 "module": "DOM", 6793 "submodule": "DOM" 6794 }, 6795 { 6796 "file": "src/core/p5.Element.js", 6797 "line": 460, 6798 "description": "<p>The .mouseMoved() function is called once every time a\nmouse moves over the element. This can be used to attach an\nelement specific event listener.</p>\n", 6799 "itemtype": "method", 6800 "name": "mouseMoved", 6801 "params": [ 6802 { 6803 "name": "fxn", 6804 "description": "<p>function to be fired when a mouse moves\n over the element.\n if <code>false</code> is passed instead, the previously\n firing function will no longer fire.</p>\n", 6805 "type": "Function|Boolean" 6806 } 6807 ], 6808 "chainable": 1, 6809 "example": [ 6810 "\n<div class='norender'><code>\nvar cnv;\nvar d = 30;\nvar g;\nfunction setup() {\n cnv = createCanvas(100, 100);
6810\n cnv.mouseMoved(changeSize); // attach listener for\n // activity on canvas only\n d = 10;\n g = 100;\n}\n\nfunction draw() {\n background(g);\n fill(200);\n ellipse(width / 2, height / 2, d, d);\n}\n\n// this function fires when mouse moves anywhere on\n// page\nfunction mouseMoved() {\n g = g + 5;\n if (g > 255) {\n g = 0;\n }\n}\n\n// this function fires when mouse moves over canvas\nfunction changeSize() {\n d = d + 2;\n if (d > 100) {\n d = 0;\n }\n}\n</code></div>" 6811 ], 6812 "alt": "no display.", 6813 "class": "p5.Element", 6814 "module": "DOM", 6815 "submodule": "DOM" 6816 }, 6817 { 6818 "file": "src/core/p5.Element.js", 6819 "line": 519, 6820 "description": "<p>The .mouseOver() function is called once after every time a\nmouse moves onto the element. This can be used to attach an\nelement specific event listener.</p>\n", 6821 "itemtype": "method", 6822 "name": "mouseOver", 6823 "params": [ 6824 { 6825 "name": "fxn", 6826 "description": "<p>function to be fired when a mouse moves\n onto the element.\n if <code>false</code> is passed instead, the previously\n firing function will no longer fire.</p>\n", 6827 "type": "Function|Boolean" 6828 } 6829 ], 6830 "chainable": 1, 6831 "example": [ 6832 "\n<div class='norender'><code>\nvar cnv;\nvar d;\nfunction setup() {\n cnv = createCanvas(100, 100);\n cnv.mouseOver(changeGray);\n d = 10;\n}\n\nfunction draw() {\n ellipse(width / 2, height / 2, d, d);\n}\n\nfunction changeGray() {\n d = d + 10;\n if (d > 100) {\n d = 0;\n }\n}\n</code></div>" 6833 ], 6834 "alt": "no display.", 6835 "class": "p5.Element", 6836 "module": "DOM", 6837 "submodule": "DOM" 6838 }, 6839 { 6840 "file": "src/core/p5.Element.js", 6841 "line": 562, 6842 "description": "<p>The .changed() function is called when the value of an\nelement changes.\nThis can be used to attach an element specific event listener.</p>\n", 6843 "itemtype": "method", 6844 "name": "changed", 6845 "params": [ 6846 { 6847 "name": "fxn", 6848 "description": "<p>function to be fired when the value of\n an element changes.\n if <code>false</code> is passed instead, the previously\n firing function will no longer fire.</p>\n", 6849 "type": "Function|Boolean" 6850 } 6851 ], 6852 "chainable": 1, 6853 "example": [ 6854 "\n<div><code>\nvar sel;\n\nfunction setup() {\n textAlign(CENTER);\n background(200);\n sel = createSelect();\n sel.position(10, 10);\n sel.option('pear');\n sel.option('kiwi');\n sel.option('grape');\n sel.changed(mySelectEvent);\n}\n\nfunction mySelectEvent() {\n var item = sel.value();\n background(200);\n text(\"it's a \" + item + '!', 50, 50);\n}\n</code></div>\n<div><code>\nvar checkbox;\nvar cnv;\n\nfunction setup() {\n checkbox = createCheckbox(' fill');\n checkbox.changed(changeFill);\n cnv = createCanvas(100, 100);\n cnv.position(0, 30);\n noFill();\n}\n\nfunction draw() {\n background(200);\n ellipse(50, 50, 50, 50);\n}\n\nfunction changeFill() {\n if (checkbox.checked()) {\n fill(0);\n } else {\n noFill();\n }\n}\n</code></div>" 6855 ], 6856 "alt": "dropdown: pear, kiwi, grape. When selected text \"its a\" + selection shown.", 6857 "class": "p5.Element", 6858 "module": "DOM", 6859 "submodule": "DOM" 6860 }, 6861 { 6862 "file": "src/core/p5.Element.js", 6863 "line": 629, 6864 "description": "<p>The .input() function is called when any user input is\ndetected with an element. The input event is often used\nto detect keystrokes in a input element, or changes on a\nsl
6864ider element. This can be used to attach an element specific\nevent listener.</p>\n", 6865 "itemtype": "method", 6866 "name": "input", 6867 "params": [ 6868 { 6869 "name": "fxn", 6870 "description": "<p>function to be fired when any user input is\n detected within the element.\n if <code>false</code> is passed instead, the previously\n firing function will no longer fire.</p>\n", 6871 "type": "Function|Boolean" 6872 } 6873 ], 6874 "chainable": 1, 6875 "example": [ 6876 "\n<div class='norender'><code>\n// Open your console to see the output\nfunction setup() {\n var inp = createInput('');\n inp.input(myInputEvent);\n}\n\nfunction myInputEvent() {\n console.log('you are typing: ', this.value());\n}\n</code></div>" 6877 ], 6878 "alt": "no display.", 6879 "class": "p5.Element", 6880 "module": "DOM", 6881 "submodule": "DOM" 6882 }, 6883 { 6884 "file": "src/core/p5.Element.js", 6885 "line": 664, 6886 "description": "<p>The .mouseOut() function is called once after every time a\nmouse moves off the element. This can be used to attach an\nelement specific event listener.</p>\n", 6887 "itemtype": "method", 6888 "name": "mouseOut", 6889 "params": [ 6890 { 6891 "name": "fxn", 6892 "description": "<p>function to be fired when a mouse\n moves off of an element.\n if <code>false</code> is passed instead, the previously\n firing function will no longer fire.</p>\n", 6893 "type": "Function|Boolean" 6894 } 6895 ], 6896 "chainable": 1, 6897 "example": [ 6898 "\n<div class='norender'><code>\nvar cnv;\nvar d;\nfunction setup() {\n cnv = createCanvas(100, 100);\n cnv.mouseOut(changeGray);\n d = 10;\n}\n\nfunction draw() {\n ellipse(width / 2, height / 2, d, d);\n}\n\nfunction changeGray() {\n d = d + 10;\n if (d > 100) {\n d = 0;\n }\n}\n</code></div>" 6899 ], 6900 "alt": "no display.", 6901 "class": "p5.Element", 6902 "module": "DOM", 6903 "submodule": "DOM" 6904 }, 6905 { 6906 "file": "src/core/p5.Element.js", 6907 "line": 706, 6908 "description": "<p>The .touchStarted() function is called once after every time a touch is\nregistered. This can be used to attach element specific event listeners.</p>\n", 6909 "itemtype": "method", 6910 "name": "touchStarted", 6911 "params": [ 6912 { 6913 "name": "fxn", 6914 "description": "<p>function to be fired when a touch\n starts over the element.\n if <code>false</code> is passed instead, the previously\n firing function will no longer fire.</p>\n", 6915 "type": "Function|Boolean" 6916 } 6917 ], 6918 "chainable": 1, 6919 "example": [ 6920 "\n<div class='norender'><code>\nvar cnv;\nvar d;\nvar g;\nfunction setup() {\n cnv = createCanvas(100, 100);\n cnv.touchStarted(changeGray); // attach listener for\n // canvas click only\n d = 10;\n g = 100;\n}\n\nfunction draw() {\n background(g);\n ellipse(width / 2, height / 2, d, d);\n}\n\n// this function fires with any touch anywhere\nfunction touchStarted() {\n d = d + 10;\n}\n\n// this function fires only when cnv is clicked\nfunction changeGray() {\n g = random(0, 255);\n}\n</code></div>" 6921 ], 6922 "alt": "no display.", 6923 "class": "p5.Element", 6924 "module": "DOM", 6925 "submodule": "DOM" 6926 }, 6927 { 6928 "file": "src/core/p5.Element.js", 6929 "line": 755, 6930 "description": "<p>The .touchMoved() function is called once after every time a touch move is\nregistered. This can be used to attach element specific event listeners.</p>\n", 6931 "itemtype": "method", 6932 "name": "touchMoved", 6933 "params": [ 6934 { 6935 "name": "fxn", 6936 "description": "<p>function to be fired when a touch moves over\n the element.\n if <code>false</code> is passed instead, the previously\n firing function will no longer fire.</p>\n", 6937 "type": "Function|Boolean" 6938 } 6939 ], 6940 "chainable": 1, 6941 "example": [ 6942 "\n<div class='norender'><code>\nvar cnv;\nvar g;\nfunction setup() {\n cnv = createCanvas(100, 100);\n cnv.touchMoved(changeGray); // attach listener for\n // canvas click only\n g = 100;\n}\n\nfunction draw() {\n background(g);\n}\n\n// this function fires only when cnv is clicked\nfunction changeGray() {\n g = random(0, 255);\n}\n</code></div>" 6943 ],
6944 "alt": "no display.", 6945 "class": "p5.Element", 6946 "module": "DOM", 6947 "submodule": "DOM" 6948 }, 6949 { 6950 "file": "src/core/p5.Element.js", 6951 "line": 796, 6952 "description": "<p>The .touchEnded() function is called once after every time a touch is\nregistered. This can be used to attach element specific event listeners.</p>\n", 6953 "itemtype": "method", 6954 "name": "touchEnded", 6955 "params": [ 6956 { 6957 "name": "fxn", 6958 "description": "<p>function to be fired when a touch ends\n over the element.\n if <code>false</code> is passed instead, the previously\n firing function will no longer fire.</p>\n", 6959 "type": "Function|Boolean" 6960 } 6961 ], 6962 "chainable": 1, 6963 "example": [ 6964 "\n<div class='norender'><code>\nvar cnv;\nvar d;\nvar g;\nfunction setup() {\n cnv = createCanvas(100, 100);\n cnv.touchEnded(changeGray); // attach listener for\n // canvas click only\n d = 10;\n g = 100;\n}\n\nfunction draw() {\n background(g);\n ellipse(width / 2, height / 2, d, d);\n}\n\n// this function fires with any touch anywhere\nfunction touchEnded() {\n d = d + 10;\n}\n\n// this function fires only when cnv is clicked\nfunction changeGray() {\n g = random(0, 255);\n}\n</code></div>" 6965 ], 6966 "alt": "no display.", 6967 "class": "p5.Element", 6968 "module": "DOM", 6969 "submodule": "DOM" 6970 }, 6971 { 6972 "file": "src/core/p5.Element.js", 6973 "line": 846, 6974 "description": "<p>The .dragOver() function is called once after every time a\nfile is dragged over the element. This can be used to attach an\nelement specific event listener.</p>\n", 6975 "itemtype": "method", 6976 "name": "dragOver", 6977 "params": [ 6978 { 6979 "name": "fxn", 6980 "description": "<p>function to be fired when a file is\n dragged over the element.\n if <code>false</code> is passed instead, the previously\n firing function will no longer fire.</p>\n", 6981 "type": "Function|Boolean" 6982 } 6983 ], 6984 "chainable": 1, 6985 "example": [ 6986 "\n<div><code>\n// To test this sketch, simply drag a\n// file over the canvas\nfunction setup() {\n var c = createCanvas(100, 100);\n background(200);\n textAlign(CENTER);\n text('Drag file', width / 2, height / 2);\n c.dragOver(dragOverCallback);\n}\n\n// This function will be called whenever\n// a file is dragged over the canvas\nfunction dragOverCallback() {\n background(240);\n text('Dragged over', width / 2, height / 2);\n}\n</code></div>" 6987 ], 6988 "alt": "nothing displayed", 6989 "class": "p5.Element", 6990 "module": "DOM", 6991 "submodule": "DOM" 6992 }, 6993 { 6994 "file": "src/core/p5.Element.js", 6995 "line": 884, 6996 "description": "<p>The .dragLeave() function is called once after every time a\ndragged file leaves the element area. This can be used to attach an\nelement specific event listener.</p>\n", 6997 "itemtype": "method", 6998 "name": "dragLeave", 6999 "params": [ 7000 { 7001 "name": "fxn", 7002 "description": "<p>function to be fired when a file is\n dragged off the element.\n if <code>false</code> is passed instead, the previously\n firing function will no longer fire.</p>\n", 7003 "type": "Function|Boolean" 7004 } 7005 ], 7006 "chainable": 1, 7007 "example": [ 7008 "\n<div><code>\n// To test this sketch, simply drag a file\n// over and then out of the canvas area\nfunction setup() {\n var c = createCanvas(100, 100);\n background(200);\n textAlign(CENTER);\n text('Drag file', width / 2, height / 2);\n c.dragLeave(dragLeaveCallback);\n}\n\n// This function will be called whenever\n// a file is dragged out of the canvas\nfunction dragLeaveCallback() {\n background(240);\n text('Dragged off', width / 2, height / 2);\n}\n</code></div>" 7009 ], 7010 "alt": "nothing displayed", 7011 "class": "p5.Element", 7012 "module": "DOM", 7013 "submodule": "DOM" 7014 }, 7015 { 7016 "file": "src/core/p5.Element.js", 7017 "line": 922, 7018 "description": "<p>The .drop() function is called for each file dropped on the element.\nIt requires a callback that is passed a p5.File object. You can\noptionally pass two callbacks, the first one (required) is triggered\nfor each file dropped when the file is loaded. The second (optional)\nis triggered just once when a file (or files) are dropped.</p>\n", 7019 "itemtype": "method", 7020 "name": "drop", 7021 "params": [ 7022 { 7023 "name": "callback", 7024 "description": "<p>callback triggered when files are dropped.</p>\n", 7025 "type": "Function" 7026 }, 7027 { 7028 "name": "fxn", 7029 "description": "<p>callback to receive loaded file.</p>\n", 7030 "type": "Function", 7031 "optional": true 7032 } 7033 ], 7034 "chainable": 1, 7035 "example": [ 7036 "\n<div><code>\nfunction setup() {\n var c = createCanvas(100, 100);\n background(200);\n textAlign(CENTER);\n text('drop image', width / 2, height / 2);\n c.drop(gotFile);\n}\n\nfunction gotFile(file) {\n var img = createImg(file.data).hide();\n // Draw the image onto the canvas\n image(img, 0, 0, width, height);\n}\n</code></div>" 7037 ], 7038 "alt": "Canvas turns into whatever image is dragged/dropped onto it.", 7039 "class": "p5.Element", 7040 "module": "DOM", 7041 "submodule": "DOM" 7042 }, 7043 { 7044 "file": "src/core/p5.Element.js", 7045 "line": 1057, 7046 "description": "<p>Helper fxn for sharing pixel methods</p>\n", 7047 "class": "p5.Element", 7048 "module": "DOM", 7049 "submodule": "DOM" 7050 }, 7051 { 7052 "file": "src/core/p5.Graphics.js", 7053 "line": 65, 7054 "description": "<p>Removes a Graphics object from the page and frees any resources\nassociated with it.</p>\n", 7055 "itemtype": "method", 7056 "name": "remove", 7057 "example": [ 7058 "\n<div class='norender'><code>\nvar bg;\nfunction setup() {\n bg = createCanvas(100, 100);\n bg.background(0);\n image(bg, 0, 0);\n bg.remove();\n}\n</code></div>\n\n<div><code>\nvar bg;\nfunction setup() {\n pixelDensity(1);\n createCanvas(100, 100);
7058\n stroke(255);\n fill(0);\n\n // create and draw the background image\n bg = createGraphics(100, 100);\n bg.background(200);\n bg.ellipse(50, 50, 80, 80);\n}\nfunction draw() {\n var t = millis() / 1000;\n // draw the background\n if (bg) {\n image(bg, frameCount % 100, 0);\n image(bg, frameCount % 100 - 100, 0);\n }\n // draw the foreground\n var p = p5.Vector.fromAngle(t, 35).add(50, 50);\n ellipse(p.x, p.y, 30);\n}\nfunction mouseClicked() {\n // remove the background\n if (bg) {\n bg.remove();\n bg = null;\n }\n}\n</code></div>" 7059 ], 7060 "alt": "no image\na multi-colored circle moving back and forth over a scrolling background.", 7061 "class": "p5.Graphics", 7062 "module": "Rendering", 7063 "submodule": "Rendering" 7064 }, 7065 { 7066 "file": "src/core/p5.Renderer.js", 7067 "line": 113, 7068 "description": "<p>Resize our canvas element.</p>\n", 7069 "class": "p5.Renderer", 7070 "module": "Rendering", 7071 "submodule": "Rendering" 7072 }, 7073 { 7074 "file": "src/core/p5.Renderer.js", 7075 "line": 182, 7076 "description": "<p>Helper fxn to check font type (system or otf)</p>\n", 7077 "class": "p5.Renderer", 7078 "module": "Rendering", 7079 "submodule": "Rendering" 7080 }, 7081 { 7082 "file": "src/core/p5.Renderer.js", 7083 "line": 235, 7084 "description": "<p>Helper fxn to measure ascent and descent.\nAdapted from <a href=\"http://stackoverflow.com/a/25355178\">http://stackoverflow.com/a/25355178</a></p>\n", 7085 "class": "p5.Renderer", 7086 "module": "Rendering", 7087 "submodule": "Rendering" 7088 }, 7089 { 7090 "file": "src/core/p5.Renderer2D.js", 7091 "line": 10, 7092 "description": "<p>p5.Renderer2D\nThe 2D graphics canvas renderer class.\nextends p5.Renderer</p>\n", 7093 "class": "p5", 7094 "module": "Rendering" 7095 }, 7096 { 7097 "file": "src/core/p5.Renderer2D.js", 7098 "line": 395, 7099 "description": "<p>Generate a cubic Bezier representing an arc on the unit circle of total\nangle <code>size</code> radians, beginning <code>start</code> radians above the x-axis. Up to\nfour of these curves are combined to make a full arc.</p>\n<p>See www.joecridge.me/bezier.pdf for an explanation of the method.</p>\n", 7100 "class": "p5", 7101 "module": "Rendering" 7102 }, 7103 { 7104 "file": "src/core/rendering.js", 7105 "line": 17, 7106 "description": "<p>Creates a canvas element in the document, and sets the dimensions of it\nin pixels. This method should be called only once at the start of setup.\nCalling createCanvas more than once in a sketch will result in very\nunpredictable behavior. If you want more than one drawing canvas\nyou could use createGraphics (hidden by default but it can be shown).\n<br><br>\nThe system variables width and height are set by the parameters passed\nto this function. If createCanvas() is not used, the window will be\ngiven a default size of 100x100 pixels.\n<br><br>\nFor more ways to position the canvas, see the\n<a href='https://github.com/processing/p5.js/wiki/Positioning-your-canvas'>\npositioning the canvas</a> wiki page.</p>\n", 7107 "itemtype": "method", 7108 "name": "createCanvas", 7109 "params": [ 7110 { 7111 "name": "w", 7112 "description": "<p>width of the canvas</p>\n", 7113 "type": "Number" 7114 }, 7115 { 7116 "name": "h", 7117 "description": "<p>height of the canvas</p>\n", 7118 "type": "Number" 7119 }, 7120 { 7121 "name": "renderer", 7122 "description": "<p>either P2D or WEBGL</p>\n", 7123 "type": "Constant", 7124 "optional": true 7125 } 7126 ], 7127 "return": { 7128 "description": "", 7129 "type": "p5.Renderer" 7130 }, 7131 "example": [ 7132 "\n<div>\n<code>\nfunction setup() {\n createCanvas(100, 50);\n background(153);\n line(0, 0, width, height);\n}\n</code>\n</div>" 7133 ], 7134 "alt": "Black line extending from top-left of canvas to bottom right.", 7135 "class": "p5", 7136 "module": "Rendering", 7137 "submodule": "Rendering" 7138 }, 7139 { 7140 "file": "src/core/rendering.js", 7141 "line": 119, 7142 "description": "<p>Resizes the canvas to given width and height. The canvas will be cleared\nand draw will be called immediately, allowing the sketch to re-render itself\nin the resized canvas.</p>\n", 7143 "itemtype": "method", 7144 "name": "resizeCanvas", 7145 "params": [ 7146 { 7147 "name": "w", 7148 "description": "<p>width of the canvas</p>\n", 7149 "type": "Number" 7150 }, 7151 { 7152 "name": "h", 7153 "description": "<p>height of the canvas</p>\n", 7154 "type": "Number" 7155 }, 7156 { 7157 "name": "noRedraw", 7158 "description": "<p>don't redraw the canvas immediately</p>\n", 7159 "type": "Boolean", 7160 "optional": true 7161 } 7162 ], 7163 "example": [ 7164 "\n<div class=\"norender\"><code>\nfunction setup() {\n createCanvas(windowWidth, windowHeight);\n}\n\nfunction draw() {\n background(0, 100, 200);\n}\n\nfunction windowResized() {\n resizeCanvas(windowWidth, windowHeight);\n}\n</code></div>" 7165 ], 7166 "alt": "No image displayed.", 7167 "class": "p5", 7168 "module": "Rendering", 7169 "submodule": "Rendering" 7170 }, 7171 { 7172 "file": "src/core/rendering.js", 7173 "line": 172, 7174 "description": "<p>Removes the default canvas for a p5 sketch that doesn't\nrequire a canvas</p>\n", 7175 "itemtype": "method", 7176 "name": "noCanvas", 7177 "example": [ 7178 "\n<div>\n<code>\nfunction setup() {\n noCanvas();\n}\n</code>\n</div>" 7179 ], 7180 "alt": "no image displayed", 7181 "class": "p5", 7182 "module": "Rendering", 7183 "submodule": "Rendering" 7184 }, 7185 { 7186 "file": "src/core/rendering.js", 7187 "line": 195, 7188 "description": "<p>Creates and returns a new p5.Renderer object. Use this class if you need\nto draw into an off-screen graphics buffer. The two parameters define the\nwidth and height in pixels.</p>\n", 7189 "itemtype": "method", 7190 "name": "createGraphics", 7191 "params": [ 7192 { 7193 "name": "w", 7194 "description": "<p>width of the offscreen graphics buffer</p>\n", 7195 "type": "Number" 7196 }, 7197 { 7198 "name": "h", 7199 "description": "<p>height of the offscreen graphics buffer</p>\n", 7200 "type": "Number" 7201 }, 7202 { 7203 "name": "renderer", 7204 "description": "<p>either P2D or WEBGL\nundefined defaults to p2d</p>\n", 7205 "type": "Constant", 7206 "optional": true 7207 } 7208 ], 7209 "return": { 7210 "description": "offscreen graphics buffer", 7211 "type": "p5.Graphics" 7212 }, 7213 "example": [ 7214 "\n<div>\n<code>\nvar pg;\nfunction setup() {\n createCanvas(100, 100);\n pg = createGraphics(100, 100);\n}\nfunction draw() {\n background(200);\n pg.background(100);\n pg.noStroke();\n pg.ellipse(pg.width / 2, pg.height / 2, 50, 50);\n image(pg, 50, 50);\n image(pg, 0, 0, 50, 50);\n}\n</code>\n</div>" 7215 ], 7216 "alt": "4 grey squares alternating light and dark grey. White quarter circle mid-left.", 7217 "class": "p5", 7218 "module": "Rendering", 7219 "submodule": "Rendering" 7220 }, 7221 { 7222 "file": "src/core/rendering.js", 7223 "line": 234, 7224 "description": "<p>Blends the pixels in the display window according to the defined mode.\nThere is a choice of the following modes to blend the source pixels (A)\nwith the ones of pixels already in the display window (B):</p>\n<ul>\n<li><code>BLEND</code> - linear interpolation of colours: C =\nA*factor + B. This is the default blending mode.</li>\n<li><code>ADD</code> - sum of A and B</li>\n<li><code>DARKEST</code> - only the darkest colour succeeds: C =\nmin(A*factor, B).</li>\n<li><code>LIGHTEST</code> - only the lightest colour succeeds: C =\nmax(A*factor, B).</li>\n<li><code>DIFFERENCE</code> - subtract colors from underlying image.</li>\n<li><code>EXCLUSION</code> - similar to <code>DIFFERENCE</code>, but less\nextreme.</li>\n<li><code>MULTIPLY</code> - multiply the colors, result will always be\ndarker.</li>\n<li><code>SCREEN</code> - opposite multiply, uses inverse values of the\ncolors.</li>\n<li><code>REPLACE</code> - the pixels entirely replace the others and\ndon'
7224t utilize alpha (transparency) values.</li>\n<li><code>OVERLAY</code> - mix of <code>MULTIPLY</code> and <code>SCREEN\n</code>. Multiplies dark values, and screens light values.</li>\n<li><code>HARD_LIGHT</code> - <code>SCREEN</code> when greater than 50%\ngray, <code>MULTIPLY</code> when lower.</li>\n<li><code>SOFT_LIGHT</code> - mix of <code>DARKEST</code> and\n<code>LIGHTEST</code>. Works like <code>OVERLAY</code>, but not as harsh.\n</li>\n<li><code>DODGE</code> - lightens light tones and increases contrast,\nignores darks.</li>\n<li><code>BURN</code> - darker areas are applied, increasing contrast,\nignores lights.</li>\n</ul>", 7225 "itemtype": "method", 7226 "name": "blendMode", 7227 "params": [ 7228 { 7229 "name": "mode", 7230 "description": "<p>blend mode to set for canvas.\n either BLEND, DARKEST, LIGHTEST, DIFFERENCE, MULTIPLY,\n EXCLUSION, SCREEN, REPLACE, OVERLAY, HARD_LIGHT,\n SOFT_LIGHT, DODGE, BURN, ADD or NORMAL</p>\n", 7231 "type": "Constant" 7232 } 7233 ], 7234 "example": [ 7235 "\n<div>\n<code>\nblendMode(LIGHTEST);\nstrokeWeight(30);\nstroke(80, 150, 255);\nline(25, 25, 75, 75);\nstroke(255, 50, 50);\nline(75, 25, 25, 75);\n</code>\n</div>\n<div>\n<code>\nblendMode(MULTIPLY);\nstrokeWeight(30);\nstroke(80, 150, 255);\nline(25, 25, 75, 75);\nstroke(255, 50, 50);\nline(75, 25, 25, 75);\n</code>\n</div>" 7236 ], 7237 "alt": "translucent image thick red & blue diagonal rounded lines intersecting center\nThick red & blue diagonal rounded lines intersecting center. dark at overlap", 7238 "class": "p5", 7239 "module": "Rendering", 7240 "submodule": "Rendering" 7241 }, 7242 { 7243 "file": "src/core/shim.js", 7244 "line": 70, 7245 "description": "<p>shim for Uint8ClampedArray.slice\n(allows arrayCopy to work with pixels[])\nwith thanks to <a href=\"http://halfpapstudios.com/blog/tag/html5-canvas/\">http://halfpapstudios.com/blog/tag/html5-canvas/</a>\nEnumerable set to false to protect for...in from\nUint8ClampedArray.prototype pollution.</p>\n", 7246 "class": "p5", 7247 "module": "Rendering" 7248 }, 7249 { 7250 "file": "src/core/structure.js", 7251 "line": 15, 7252 "description": "<p>Stops p5.js from continuously executing the code within draw().\nIf loop() is called, the code in draw() begins to run continuously again.\nIf using noLoop() in setup(), it should be the last line inside the block.\n<br><br>\nWhen noLoop() is used, it's not possible to manipulate or access the\nscreen inside event handling functions such as mousePressed() or\nkeyPressed(). Instead, use those functions to call redraw() or loop(),\nwhich will run draw(), which can update the screen properly. This means\nthat when noLoop() has been called, no drawing can happen, and functions\nlike saveFrame() or loadPixels() may not be used.\n<br><br>\nNote that if the sketch is resized, redraw() will be called to update\nthe sketch, even after noLoop() has been specified. Otherwise, the sketch\nwould enter an odd state until loop() was called.</p>\n", 7253 "itemtype": "method", 7254 "name": "noLoop", 7255 "example": [ 7256 "\n<div><code>\nfunction setup() {\n createCanvas(100, 100);\n background(200);\n noLoop();\n}\n\nfunction draw() {\n line(10, 10, 90, 90);\n}\n</code></div>\n\n<div><code>\nvar x = 0;\nfunction setup() {\n createCanvas(100, 100);\n}\n\nfunction draw() {\n background(204);\n x = x + 0.1;\n if (x > width) {\n x = 0;\n }\n line(x, 0, x, height);\n}\n\nfunction mousePressed() {\n noLoop();\n}\n\nfunction mouseReleased() {\n loop();\n}\n</code></div>" 7257 ], 7258 "alt": "113 pixel long line extending from top-left to bottom right of canvas.\nhorizontal line moves slowly from left. Loops but stops on mouse press.", 7259 "class": "p5", 7260 "module": "Structure", 7261 "submodule": "Structure" 7262 }, 7263 { 7264 "file": "src/core/structure.js", 7265 "line": 77, 7266 "description": "<p>By default, p5.js loops through draw() continuously, executing the code\nwithin it. However, the draw() loop may be stopped by calling noLoop().\nIn that case, the draw() loop can be resumed with loop().</p>\n", 7267 "itemtype": "method", 7268 "name": "loop", 7269 "example": [ 7270 "\n<div><code>\nvar x = 0;\nfunction setup() {\n createCanvas(100, 100);\n noLoop();\n}\n\nfunction draw() {\n background(204);\n x = x + 0.1;\n if (x > width) {\n x = 0;\n }\n line(x, 0, x, height);\n}\n\nfunction mousePressed() {\n loop();\n}\n\nfunction mouseReleased() {\n noLoop();\n}\n</code></div>" 7271 ], 7272 "alt": "horizontal line moves slowly from left. Loops but stops on mouse press.", 7273 "class": "p5", 7274 "module": "Structure", 7275 "submodule": "Structure" 7276 }, 7277 { 7278 "file": "src/core/structure.js", 7279 "line": 132, 7280 "description": "<p>The push() function saves the current drawing style settings and\ntransformations, while pop() restores these settings. Note that these\nfunctions are always used together. They allow you to change the style\nand transformation settings and later return to what you had. When a new\nstate is started with push(), it builds on the current style and transform\ninformation. The push() and pop() functions can be embedded to provide\nmore control. (See the second example for a demonstration.)\n<br><br>\npush() stores information related to the current transformation state\nand style settings controlled by the following functions: fill(),\nstroke(), tint(), strokeWeight(
7280), strokeCap(), strokeJoin(),\nimageMode(), rectMode(), ellipseMode(), colorMode(), textAlign(),\ntextFont(), textMode(), textSize(), textLeading().</p>\n", 7281 "itemtype": "method", 7282 "name": "push", 7283 "example": [ 7284 "\n<div>\n<code>\nellipse(0, 50, 33, 33); // Left circle\n\npush(); // Start a new drawing state\nstrokeWeight(10);\nfill(204, 153, 0);\ntranslate(50, 0);\nellipse(0, 50, 33, 33); // Middle circle\npop(); // Restore original state\n\nellipse(100, 50, 33, 33); // Right circle\n</code>\n</div>\n<div>\n<code>\nellipse(0, 50, 33, 33); // Left circle\n\npush(); // Start a new drawing state\nstrokeWeight(10);\nfill(204, 153, 0);\nellipse(33, 50, 33, 33); // Left-middle circle\n\npush(); // Start another new drawing state\nstroke(0, 102, 153);\nellipse(66, 50, 33, 33); // Right-middle circle\npop(); // Restore previous state\n\npop(); // Restore original state\n\nellipse(100, 50, 33, 33); // Right circle\n</code>\n</div>" 7285 ], 7286 "alt": "Gold ellipse + thick black outline @center 2 white ellipses on left and right.\n2 Gold ellipses left black right blue stroke. 2 white ellipses on left+right.", 7287 "class": "p5", 7288 "module": "Structure", 7289 "submodule": "Structure" 7290 }, 7291 { 7292 "file": "src/core/structure.js", 7293 "line": 197, 7294 "description": "<p>The push() function saves the current drawing style settings and\ntransformations, while pop() restores these settings. Note that these\nfunctions are always used together. They allow you to change the style\nand transformation settings and later return to what you had. When a new\nstate is started with push(), it builds on the current style and transform\ninformation. The push() and pop() functions can be embedded to provide\nmore control. (See the second example for a demonstration.)\n<br><br>\npush() stores information related to the current transformation state\nand style settings controlled by the following functions: fill(),\nstroke(), tint(), strokeWeight(
7294), strokeCap(), strokeJoin(),\nimageMode(), rectMode(), ellipseMode(), colorMode(), textAlign(),\ntextFont(), textMode(), textSize(), textLeading().</p>\n", 7295 "itemtype": "method", 7296 "name": "pop", 7297 "example": [ 7298 "\n<div>\n<code>\nellipse(0, 50, 33, 33); // Left circle\n\npush(); // Start a new drawing state\ntranslate(50, 0);\nstrokeWeight(10);\nfill(204, 153, 0);\nellipse(0, 50, 33, 33); // Middle circle\npop(); // Restore original state\n\nellipse(100, 50, 33, 33); // Right circle\n</code>\n</div>\n<div>\n<code>\nellipse(0, 50, 33, 33); // Left circle\n\npush(); // Start a new drawing state\nstrokeWeight(10);\nfill(204, 153, 0);\nellipse(33, 50, 33, 33); // Left-middle circle\n\npush(); // Start another new drawing state\nstroke(0, 102, 153);\nellipse(66, 50, 33, 33); // Right-middle circle\npop(); // Restore previous state\n\npop(); // Restore original state\n\nellipse(100, 50, 33, 33); // Right circle\n</code>\n</div>" 7299 ], 7300 "alt": "Gold ellipse + thick black outline @center 2 white ellipses on left and right.\n2 Gold ellipses left black right blue stroke. 2 white ellipses on left+right.", 7301 "class": "p5", 7302 "module": "Structure", 7303 "submodule": "Structure" 7304 }, 7305 { 7306 "file": "src/core/structure.js", 7307 "line": 271, 7308 "description": "<p>Executes the code within draw() one time. This functions allows the\n program to update the display window only when necessary, for example\n when an event registered by mousePressed() or keyPressed() occurs.\n <br><br>\n In structuring a program, it only makes sense to call redraw() within\n events such as mousePressed(). This is because redraw() does not run\n draw() immediately (it only sets a flag that indicates an update is\n needed).\n <br><br>\n The redraw() function does not work properly when called inside draw().\n To enable/disable animations, use loop() and noLoop().\n <br><br>\n In addition you can set the number of redraws per method call. Just\n add an integer as single parameter for the number of redraws.</p>\n", 7309 "itemtype": "method", 7310 "name": "redraw", 7311 "params": [ 7312 { 7313 "name": "n", 7314 "description": "<p>Redraw for n-times. The default value is 1.</p>\n", 7315 "type": "Integer", 7316 "optional": true 7317 } 7318 ], 7319 "example": [ 7320 "\n <div><code>\n var x = 0;\nfunction setup() {\n createCanvas(100, 100);\n noLoop();\n }\nfunction draw() {\n background(204);\n line(x, 0, x, height);\n }\nfunction mousePressed() {\n x += 1;\n redraw();\n }\n </code></div>\n<div class='norender'><code>\n var x = 0;\nfunction setup() {\n createCanvas(100, 100);\n noLoop();\n }\nfunction draw() {\n background(204);\n x += 1;\n line(x, 0, x, height);\n }\nfunction mousePressed() {\n redraw(5);\n }\n </code></div>" 7321 ], 7322 "alt": "black line on far left of canvas\n black line on far left of canvas", 7323 "class": "p5", 7324 "module": "Structure", 7325 "submodule": "Structure" 7326 }, 7327 { 7328 "file": "src/core/transform.js", 7329 "line": 13, 7330 "description": "<p>Multiplies the current matrix by the one specified through the parameters.\nThis is a powerful operation that can perform the equivalent of translate,\nscale, shear and rotate all at once. You can learn more about transformation\nmatrices on <a href=\"https://en.wikipedia.org/wiki/Transformation_matrix\">\nWikipedia</a>.</p>\n<p>The naming of the arguments here follows the naming of the <a href=\n\"https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-transform\">\nWHATWG specification</a> and corresponds to a\ntransformation matrix of the\nform:</p>\n<blockquote>\n<p><img style=\"max-width: 150px\" src=\"assets/transformation-matrix.png\"\nalt=\"The transformation matrix used when applyMatrix is called\"/></p>\n</blockquote>\n", 7331 "itemtype": "method", 7332 "name": "applyMatrix", 7333 "params": [ 7334 { 7335 "name": "a", 7336 "description": "<p>numbers which define the 2x3 matrix to be multiplied</p>\n", 7337 "type": "Number" 7338 }, 7339 { 7340 "name": "b", 7341 "description": "<p>numbers which define the 2x3 matrix to be multiplied</p>\n", 7342 "type": "Number" 7343 }, 7344 { 7345 "name": "c", 7346 "description": "<p>numbers which define the 2x3 matrix to be multiplied</p>\n", 7347 "type": "Number" 7348 }, 7349 { 7350 "name": "d", 7351 "description": "<p>numbers which define the 2x3 matrix to be multiplied</p>\n", 7352 "type": "Number" 7353 }, 7354 { 7355 "name": "e", 7356 "description": "<p>numbers which define the 2x3 matrix to be multiplied</p>\n", 7357 "type": "Number" 7358 }, 7359 { 7360 "name": "f", 7361 "description": "<p>numbers which define the 2x3 matrix to be multiplied</p>\n", 7362 "type": "Number" 7363 } 7364 ], 7365 "chainable": 1, 7366 "example": [ 7367 "\n<div>\n<code>\nfunction setup() {\n frameRate(10);\n rectMode(CENTER);\n}\n\nfunction draw() {\n var step = frameCount % 20;\n background(200);\n // Equivalent to translate(x, y);\n applyMatrix(1, 0, 0, 1, 40 + step, 50);\n rect(0, 0, 50, 50);\n}\n</code>\n</div>\n<div>\n<code>\nfunction setup() {\n frameRate(10);\n rectMode(CENTER);\n}\n\nfunction draw() {\n var step = frameCount % 20;\n background(200);\n translate(50, 50);\n // Equivalent to scale(x, y);\n applyMatrix(1 / step, 0, 0, 1 / step, 0, 0);\n rect(0, 0, 50, 50);\n}\n</code>\n</div>\n<div>\n<code>\nfunction setup() {\n frameRate(10);\n rectMode(CENTER);\n}\n\nfunction draw() {\n var step = frameCount % 20;\n var angle = map(step, 0, 20, 0, TWO_PI);\n var cos_a = cos(angle);\n var sin_a = sin(angle);\n background(200);\n translate(50, 50);\n // Equivalent to rotate(angle);
7367\n applyMatrix(cos_a, sin_a, -sin_a, cos_a, 0, 0);\n rect(0, 0, 50, 50);\n}\n</code>\n</div>\n<div>\n<code>\nfunction setup() {\n frameRate(10);\n rectMode(CENTER);\n}\n\nfunction draw() {\n var step = frameCount % 20;\n var angle = map(step, 0, 20, -PI / 4, PI / 4);\n background(200);\n translate(50, 50);\n // equivalent to shearX(angle);\n var shear_factor = 1 / tan(PI / 2 - angle);\n applyMatrix(1, 0, shear_factor, 1, 0, 0);\n rect(0, 0, 50, 50);\n}\n</code>\n</div>" 7368 ], 7369 "alt": "A rectangle translating to the right\nA rectangle shrinking to the center\nA rectangle rotating clockwise about the center\nA rectangle shearing", 7370 "class": "p5", 7371 "module": "Transform", 7372 "submodule": "Transform" 7373 }, 7374 { 7375 "file": "src/core/transform.js", 7376 "line": 135, 7377 "description": "<p>Replaces the current matrix with the identity matrix.</p>\n", 7378 "itemtype": "method", 7379 "name": "resetMatrix", 7380 "chainable": 1, 7381 "example": [ 7382 "\n<div>\n<code>\ntranslate(50, 50);\napplyMatrix(0.5, 0.5, -0.5, 0.5, 0, 0);\nrect(0, 0, 20, 20);\n// Note that the translate is also reset.\nresetMatrix();\nrect(0, 0, 20, 20);\n</code>\n</div>" 7383 ], 7384 "alt": "A rotated retangle in the center with another at the top left corner", 7385 "class": "p5", 7386 "module": "Transform", 7387 "submodule": "Transform" 7388 }, 7389 { 7390 "file": "src/core/transform.js", 7391 "line": 161, 7392 "description": "<p>Rotates a shape the amount specified by the angle parameter. This\nfunction accounts for angleMode, so angles can be entered in either\nRADIANS or DEGREES.\n<br><br>\nObjects are always rotated around their relative position to the\norigin and positive numbers rotate objects in a clockwise direction.\nTransformations apply to everything that happens after and subsequent\ncalls to the function accumulates the effect. For example, calling\nrotate(HALF_PI) and then rotate(HALF_PI) is the same as rotate(PI).\nAll tranformations are reset when draw() begins again.\n<br><br>\nTechnically, rotate() multiplies the current transformation matrix\nby a rotation matrix. This function can be further controlled by\nthe push() and pop().</p>\n", 7393 "itemtype": "method", 7394 "name": "rotate", 7395 "params": [ 7396 { 7397 "name": "angle", 7398 "description": "<p>the angle of rotation, specified in radians\n or degrees, depending on current angleMode</p>\n", 7399 "type": "Number" 7400 }, 7401 { 7402 "name": "axis", 7403 "description": "<p>(in 3d) the axis to rotate around</p>\n", 7404 "type": "p5.Vector|Number[]", 7405 "optional": true 7406 } 7407 ], 7408 "chainable": 1, 7409 "example": [ 7410 "\n<div>\n<code>\ntranslate(width / 2, height / 2);\nrotate(PI / 3.0);\nrect(-26, -26, 52, 52);\n</code>\n</div>" 7411 ], 7412 "alt": "white 52x52 rect with black outline at center rotated counter 45 degrees", 7413 "class": "p5", 7414 "module": "Transform", 7415 "submodule": "Transform" 7416 }, 7417 { 7418 "file": "src/core/transform.js", 7419 "line": 201, 7420 "description": "<p>Rotates around X axis.</p>\n", 7421 "itemtype": "method", 7422 "name": "rotateX", 7423 "params": [ 7424 { 7425 "name": "angle", 7426 "description": "<p>the angle of rotation, specified in radians\n or degrees, depending on current angleMode</p>\n", 7427 "type": "Number" 7428 } 7429 ], 7430 "chainable": 1, 7431 "example": [ 7432 "\n<div modernizr='webgl'>\n<code>\nfunction setup() {\n createCanvas(100, 100, WEBGL);\n}\nfunction draw() {\n background(255);\n rotateX(millis() / 1000);\n box();\n}\n</code>\n</div>" 7433 ], 7434 "alt": "3d box rotating around the x axis.", 7435 "class": "p5", 7436 "module": "Transform", 7437 "submodule": "Transform" 7438 }, 7439 { 7440 "file": "src/core/transform.js", 7441 "line": 231, 7442 "description": "<p>
7442Rotates around Y axis.</p>\n", 7443 "itemtype": "method", 7444 "name": "rotateY", 7445 "params": [ 7446 { 7447 "name": "angle", 7448 "description": "<p>the angle of rotation, specified in radians\n or degrees, depending on current angleMode</p>\n", 7449 "type": "Number" 7450 } 7451 ], 7452 "chainable": 1, 7453 "example": [ 7454 "\n<div modernizr='webgl'>\n<code>\nfunction setup() {\n createCanvas(100, 100, WEBGL);\n}\nfunction draw() {\n background(255);\n rotateY(millis() / 1000);\n box();\n}\n</code>\n</div>" 7455 ], 7456 "alt": "3d box rotating around the y axis.", 7457 "class": "p5", 7458 "module": "Transform", 7459 "submodule": "Transform" 7460 }, 7461 { 7462 "file": "src/core/transform.js", 7463 "line": 261, 7464 "description": "<p>Rotates around Z axis. Webgl mode only.</p>\n", 7465 "itemtype": "method", 7466 "name": "rotateZ", 7467 "params": [ 7468 { 7469 "name": "angle", 7470 "description": "<p>the angle of rotation, specified in radians\n or degrees, depending on current angleMode</p>\n", 7471 "type": "Number" 7472 } 7473 ], 7474 "chainable": 1, 7475 "example": [ 7476 "\n<div modernizr='webgl'>\n<code>\nfunction setup() {\n createCanvas(100, 100, WEBGL);\n}\nfunction draw() {\n background(255);\n rotateZ(millis() / 1000);\n box();\n}\n</code>\n</div>" 7477 ], 7478 "alt": "3d box rotating around the z axis.", 7479 "class": "p5", 7480 "module": "Transform", 7481 "submodule": "Transform" 7482 }, 7483 { 7484 "file": "src/core/transform.js", 7485 "line": 291, 7486 "description": "<p>Increases or decreases the size of a shape by expanding and contracting\nvertices. Objects always scale from their relative origin to the\ncoordinate system. Scale values are specified as decimal percentages.\nFor example, the function call scale(2.0) increases the dimension of a\nshape by 200%.\n<br><br>\nTransformations apply to everything that happens after and subsequent\ncalls to the function multiply the effect. For example, calling scale(2.0)\nand then scale(1.5) is the same as scale(3.0). If scale() is called\nwithin draw(), the transformation is reset when the loop begins again.\n<br><br>\nUsing this function with the z parameter is only available in WEBGL mode.\nThis function can be further controlled with push() and pop().</p>\n", 7487 "itemtype": "method", 7488 "name": "scale", 7489 "chainable": 1, 7490 "example": [ 7491 "\n<div>\n<code>\ntranslate(width / 2, height / 2);\nrotate(PI / 3.0);\nrect(-26, -26, 52, 52);\n</code>\n</div>\n\n<div>\n<code>\nrect(30, 20, 50, 50);\nscale(0.5, 1.3);\nrect(30, 20, 50, 50);\n</code>\n</div>" 7492 ], 7493 "alt": "white 52x52 rect with black outline at center rotated counter 45 degrees\n2 white rects with black outline- 1 50x50 at center. other 25x65 bottom left", 7494 "class": "p5", 7495 "module": "Transform", 7496 "submodule": "Transform", 7497 "overloads": [ 7498 { 7499 "line": 291, 7500 "params": [ 7501 { 7502 "name": "s", 7503 "description": "<p>percent to scale the object, or percentage to\n scale the object in the x-axis if multiple arguments\n are given</p>\n", 7504 "type": "Number|p5.Vector|Number[]" 7505 }, 7506 { 7507 "name": "y", 7508 "description": "<p>percent to scale the object in the y-axis</p>\n", 7509 "type": "Number", 7510 "optional": true 7511 }, 7512 { 7513 "name": "z", 7514 "description": "<p>percent to scale the object in the z-axis (webgl only)</p>\n", 7515 "type": "Number", 7516 "optional": true 7517 } 7518 ], 7519 "chainable": 1 7520 }, 7521 { 7522 "line": 336, 7523 "params": [ 7524 { 7525 "name": "scales", 7526 "description": "<p>per-axis percents to scale the object</p>\n", 7527 "type": "p5.Vector|Number[]" 7528 } 7529 ], 7530 "chainable": 1 7531 } 7532 ] 7533 }, 7534 { 7535 "file": "src/core/transform.js", 7536 "line": 366, 7537 "description": "<p>Shears a shape around the x-axis the amount specified by the angle\nparameter. Angles should be specified in the current angleMode.\nObjects are always sheared around their relative position to the origin\nand positive numbers shear objects in a clockwise direction.\n<br><br>\nTransformations apply to everything that happens after and subsequent\ncalls to the function accumulates the effect. For example, calling\nshearX(PI/2) and then shearX(PI/2) is the same as shearX(PI).\nIf shearX() is called within the draw(), the transformation is reset when\nthe loop begins again.\n<br><br>\nTechnically, shearX() multiplies the current transformation matrix by a\nrotation matrix. This function can be further controlled by the\npush() and pop() functions.</p>\n", 7538 "itemtype": "method", 7539 "name": "shearX", 7540 "params": [ 7541 { 7542 "name": "angle", 7543 "description": "<p>angle of shear specified in radians or degrees,\n depending on current angleMode</p>\n", 7544 "type": "Number" 7545 } 7546 ], 7547 "chainable": 1, 7548 "example": [ 7549 "\n<div>\n<code>\ntranslate(width / 4, height / 4);\nshearX(PI / 4.0);\nrect(0, 0, 30, 30);\n</code>\n</div>" 7550 ], 7551 "alt": "white irregular quadrilateral with black outline at top middle.", 7552 "class": "p5", 7553 "module": "Transform", 7554 "submodule": "Transform" 7555 }, 7556 { 7557 "file": "src/core/transform.js", 7558 "line": 405, 7559 "description": "<p>Shears a shape around the y-axis the amount specified by the angle\nparameter. Angles should be specified in the current angleMode. Objects\nare always sheared around their relative position to the origin and\npositive numbers shear objects in a clockwise direction.\n<br><br>\nTransformations apply to everything that happens after and subsequent\ncalls to the function accumulates the effect. For example, calling\nshearY(PI/2) and then shearY(PI/2) is the same as shearY(PI). If\nshearY() is called within the draw(), the transformation is reset when\nthe loop begins again.\n<br><br>\nTechnically, shearY() multiplies the current transformation matrix by a\nrotation matrix. This function can be further controlled by the\npush() and pop() functions.</p>\n", 7560 "itemtype": "method", 7561 "name": "shearY", 7562 "params": [ 7563 { 7564 "name": "angle", 7565 "description": "<p>angle of shear specified in radians or degrees,\n depending on current angleMode</p>\n", 7566 "type": "Number" 7567 } 7568 ], 7569 "chainable": 1, 7570 "example": [ 7571 "\n<div>\n<code>\ntranslate(width / 4, height / 4);\nshearY(PI / 4.0);\nrect(0, 0, 30, 30);\n</code>\n</div>" 7572 ], 7573 "alt": "white irregular quadrilateral with black outline at middle bottom.", 7574 "class": "p5", 7575 "module": "Transform", 7576 "submodule": "Transform" 7577 }, 7578 { 7579 "file": "src/core/transform.js", 7580 "line": 444, 7581 "description": "<p>Specifies an amount to displace objects within the display window.\nThe x parameter specifies left/right translation, the y parameter\nspecifies up/down translation.\n<br><br>\nTransformations are cumulative and apply to everything that happens after\nand subsequent calls to the function accumulates the effect. For example,\ncalling translate(50, 0) and then translate(20, 0) is the same as\ntranslate(70, 0). If translate() is called within draw(), the\ntransformation is reset when the loop begins again. This function can be\nfurther
7581controlled by using push() and pop().</p>\n", 7582 "itemtype": "method", 7583 "name": "translate", 7584 "chainable": 1, 7585 "example": [ 7586 "\n<div>\n<code>\ntranslate(30, 20);\nrect(0, 0, 55, 55);\n</code>\n</div>\n\n<div>\n<code>\nrect(0, 0, 55, 55); // Draw rect at original 0,0\ntranslate(30, 20);\nrect(0, 0, 55, 55); // Draw rect at new 0,0\ntranslate(14, 14);\nrect(0, 0, 55, 55); // Draw rect at new 0,0\n</code>\n</div>\n\n\n<div>\n<code>\nfunction draw() {\n background(200);\n rectMode(CENTER);\n translate(width / 2, height / 2);\n translate(p5.Vector.fromAngle(millis() / 1000, 40));\n rect(0, 0, 20, 20);\n}\n</code>\n</div>" 7587 ], 7588 "alt": "white 55x55 rect with black outline at center right.\n3 white 55x55 rects with black outlines at top-l, center-r and bottom-r.\na 20x20 white rect moving in a circle around the canvas", 7589 "class": "p5", 7590 "module": "Transform", 7591 "submodule": "Transform", 7592 "overloads": [ 7593 { 7594 "line": 444, 7595 "params": [ 7596 { 7597 "name": "x", 7598 "description": "<p>left/right translation</p>\n", 7599 "type": "Number" 7600 }, 7601 { 7602 "name": "y", 7603 "description": "<p>up/down translation</p>\n", 7604 "type": "Number" 7605 }, 7606 { 7607 "name": "z", 7608 "description": "<p>forward/backward translation (webgl only)</p>\n", 7609 "type": "Number", 7610 "optional": true 7611 } 7612 ], 7613 "chainable": 1 7614 }, 7615 { 7616 "line": 498, 7617 "params": [ 7618 { 7619 "name": "vector", 7620 "description": "<p>the vector to translate by</p>\n", 7621 "type": "p5.Vector" 7622 } 7623 ], 7624 "chainable": 1 7625 } 7626 ] 7627 }, 7628 { 7629 "file": "src/core/vertex.js", 7630 "line": 22, 7631 "description": "<p>Use the beginContour() and endContour() functions to create negative\nshapes within shapes such as the center of the letter 'O'. beginContour()\nbegins recording vertices for the shape and endContour() stops recording.\nThe vertices that define a negative shape must "wind" in the opposite\ndirection from the exterior shape. First draw vertices for the exterior\nclockwise order, then for internal shapes, draw vertices\nshape in counter-clockwise.\n<br><br>\nThese functions can only be used within a beginShape()/endShape() pair and\ntransformations such as translate(), rotate(), and scale() do not work\nwithin a beginContour()/endContour() pair. It is also not possible to use\nother shapes, such as ellipse() or rect() within.</p>\n", 7632 "itemtype": "method", 7633 "name": "beginContour", 7634 "chainable": 1, 7635 "example": [ 7636 "\n<div>\n<code>\ntranslate(50, 50);\nstroke(255, 0, 0);\nbeginShape();\n// Exterior part of shape, clockwise winding\nvertex(-40, -40);\nvertex(40, -40);\nvertex(40, 40);\nvertex(-40, 40);\n// Interior part of shape, counter-clockwise winding\nbeginContour();\nvertex(-20, -20);\nvertex(-20, 20);\nvertex(20, 20);\nvertex(20, -20);\nendContour();\nendShape(CLOSE);\n</code>\n</div>" 7637 ], 7638 "alt": "white rect and smaller grey rect with red outlines in center of canvas.", 7639 "class": "p5", 7640 "module": "Shape", 7641 "submodule": "Vertex" 7642 }, 7643 { 7644 "file": "src/core/vertex.js", 7645 "line": 70, 7646 "description": "<p>Using the beginShape() and endShape() functions allow creating more\ncomplex forms. beginShape() begins recording vertices for a shape and\nendShape() stops recording. The value of the kind parameter tells it which\ntypes of shapes to create from the provided vertices. With no mode\nspecified, the shape can be any irregular polygon.\n<br><br>\nThe parameters available for beginShape() are POINTS, LINES, TRIANGLES,\nTRIANGLE_FAN, TRIANGLE_STRIP, QUADS, and QUAD_STRIP. After calling the\nbeginShape() function, a series of vertex() commands must follow. To stop\ndrawing the shape, call endShape(). Each shape will be outlined with the\ncurrent stroke color and filled with the fill color.\n<br><br>\nTransformations such as translate(), rotate(), and scale() do not work\nwithin beginShape(). It is also not possible to use other shapes, such as\nellipse() or rect() within beginShape().</p>\n", 7647 "itemtype": "method", 7648 "name": "beginShape", 7649 "params": [ 7650 { 7651 "name": "kind", 7652 "description": "<p>either POINTS, LINES, TRIANGLES, TRIANGLE_FAN\n TRIANGLE_STRIP, QUADS, or QUAD_STRIP</p>\n", 7653 "type": "Constant", 7654 "optional": true 7655 } 7656 ], 7657 "chainable": 1, 7658 "example": [ 7659 "\n<div>\n<code>\nbeginShape();\nvertex(30, 20);\nvertex(85, 20);
7659\nvertex(85, 75);\nvertex(30, 75);\nendShape(CLOSE);\n</code>\n</div>\n\n<div>\n<code>\nbeginShape(POINTS);\nvertex(30, 20);\nvertex(85, 20);\nvertex(85, 75);\nvertex(30, 75);\nendShape();\n</code>\n</div>\n\n<div>\n<code>\nbeginShape(LINES);\nvertex(30, 20);\nvertex(85, 20);\nvertex(85, 75);\nvertex(30, 75);\nendShape();\n</code>\n</div>\n\n<div>\n<code>\nnoFill();\nbeginShape();\nvertex(30, 20);\nvertex(85, 20);\nvertex(85, 75);\nvertex(30, 75);\nendShape();\n</code>\n</div>\n\n<div>\n<code>\nnoFill();\nbeginShape();\nvertex(30, 20);\nvertex(85, 20);\nvertex(85, 75);\nvertex(30, 75);\nendShape(CLOSE);\n</code>\n</div>\n\n<div>\n<code>\nbeginShape(TRIANGLES);\nvertex(30, 75);\nvertex(40, 20);\nvertex(50, 75);\nvertex(60, 20);\nvertex(70, 75);\nvertex(80, 20);\nendShape();\n</code>\n</div>\n\n<div>\n<code>\nbeginShape(TRIANGLE_STRIP);\nvertex(30, 75);\nvertex(40, 20);\nvertex(50, 75);\nvertex(60, 20);\nvertex(70, 75);\nvertex(80, 20);\nvertex(90, 75);\nendShape();\n</code>\n</div>\n\n<div>\n<code>\nbeginShape(TRIANGLE_FAN);\nvertex(57.5, 50);\nvertex(57.5, 15);\nvertex(92, 50);\nvertex(57.5, 85);\nvertex(22, 50);\nvertex(57.5, 15);\nendShape();\n</code>\n</div>\n\n<div>\n<code>\nbeginShape(QUADS);\nvertex(30, 20);\nvertex(30, 75);\nvertex(50, 75);\nvertex(50, 20);\nvertex(65, 20);\nvertex(65, 75);\nvertex(85, 75);\nvertex(85, 20);\nendShape();\n</code>\n</div>\n\n<div>\n<code>\nbeginShape(QUAD_STRIP);\nvertex(30, 20);\nvertex(30, 75);\nvertex(50, 20);\nvertex(50, 75);\nvertex(65, 20);\nvertex(65, 75);\nvertex(85, 20);\nvertex(85, 75);\nendShape();\n</code>\n</div>\n\n<div>\n<code>\nbeginShape();\nvertex(20, 20);\nvertex(40, 20);\nvertex(40, 40);\nvertex(60, 40);\nvertex(60, 60);\nvertex(20, 60);\nendShape(CLOSE);\n</code>\n</div>" 7660 ], 7661 "alt": "white square-shape with black outline in middle-right of canvas.\n4 black points in a square shape in middle-right of canvas.\n2 horizontal black lines. In the top-right and bottom-right of canvas.\n3 line shape with horizontal on top, vertical in middle and horizontal bottom.\nsquare line shape in middle-right of canvas.\n2 white triangle shapes mid-right canvas. left one pointing up and right down.\n5 horizontal interlocking and alternating white triangles in mid-right canvas.\n4 interlocking white triangles in 45 degree rotated square-shape.\n2 white rectangle shapes in mid-right canvas. Both 20x55.\n3 side-by-side white rectangles center rect is smaller in mid-right canvas.\nThick white l-shape with black outline mid-top-left of canvas.", 7662 "class": "p5", 7663 "module": "Shape", 7664 "submodule": "Vertex" 7665 }, 7666 { 7667 "file": "src/core/vertex.js", 7668 "line": 270, 7669 "description": "<p>Specifies vertex coordinates for Bezier curves. Each call to\nbezierVertex() defines the position of two control points and\none anchor point of a Bezier curve, adding a new segment to a\nline or shape.\n<br><br>\nThe first time bezierVertex() is used within a\nbeginShape() call, it must be prefaced with a call to vertex()\nto set the first anchor point. This function must be used between\nbeginShape() and endShape() and only when there is no MODE\nparameter specified to beginShape().</p>\n", 7670 "itemtype": "method", 7671 "name": "bezierVertex", 7672 "params": [ 7673 { 7674 "name": "x2", 7675 "description": "<p>x-coordinate for the first control point</p>\n", 7676 "type": "Number" 7677 }, 7678 { 7679 "name": "y2", 7680 "description": "<p>y-coordinate for the first control point</p>\n", 7681 "type": "Number" 7682 }, 7683 { 7684 "name": "x3", 7685 "description": "<p>x-coordinate for the second control point</p>\n", 7686 "type": "Number" 7687 }, 7688 { 7689 "name": "y3", 7690 "description": "<p>y-coordinate for the second control point</p>\n", 7691 "type": "Number" 7692 }, 7693 { 7694 "name": "x4", 7695 "description": "<p>
7695x-coordinate for the anchor point</p>\n", 7696 "type": "Number" 7697 }, 7698 { 7699 "name": "y4", 7700 "description": "<p>y-coordinate for the anchor point</p>\n", 7701 "type": "Number" 7702 } 7703 ], 7704 "chainable": 1, 7705 "example": [ 7706 "\n<div>\n<code>\nstrokeWeight(5);\npoint(30, 20);\npoint(80, 20);\npoint(80, 75);\npoint(30, 75);\n\nstrokeWeight(1);\nnoFill();\nbeginShape();\nvertex(30, 20);\nbezierVertex(80, 20, 80, 75, 30, 75);\nendShape();\n</code>\n</div>\n\n<div>\n<code>\nstrokeWeight(5);\npoint(30, 20);\npoint(80, 20);\npoint(80, 75);\npoint(30, 75);\n\nstroke(244, 122, 158);\npoint(50, 80);\npoint(60, 25);\npoint(30, 20);\n\nstroke(0);\nstrokeWeight(1);\nbeginShape();\nvertex(30, 20);\nbezierVertex(80, 20, 80, 75, 30, 75);\nbezierVertex(50, 80, 60, 25, 30, 20);\nendShape();\n</code>\n</div>" 7707 ], 7708 "alt": "crescent-shaped line in middle of canvas. Points facing left.\nwhite crescent shape in middle of canvas. Points facing left.", 7709 "class": "p5", 7710 "module": "Shape", 7711 "submodule": "Vertex" 7712 }, 7713 { 7714 "file": "src/core/vertex.js", 7715 "line": 356, 7716 "description": "<p>Specifies vertex coordinates for curves. This function may only\nbe used between beginShape() and endShape() and only when there\nis no MODE parameter specified to beginShape().\n<br><br>\nThe first and last points in a series of curveVertex() lines will be used to\nguide the beginning and end of a the curve. A minimum of four\npoints is required to draw a tiny curve between the second and\nthird points. Adding a fifth point with curveVertex() will draw\nthe curve between the second, third, and fourth points. The\ncurveVertex() function is an implementation of Catmull-Rom\nsplines.</p>\n", 7717 "itemtype": "method", 7718 "name": "curveVertex", 7719 "params": [ 7720 { 7721 "name": "x", 7722 "description": "<p>x-coordinate of the vertex</p>\n", 7723 "type": "Number" 7724 }, 7725 { 7726 "name": "y", 7727 "description": "<p>y-coordinate of the vertex</p>\n", 7728 "type": "Number" 7729 } 7730 ], 7731 "chainable": 1, 7732 "example": [ 7733 "\n<div>\n<code>\nstrokeWeight(5);\npoint(84, 91);\npoint(68, 19);\npoint(21, 17);\npoint(32, 91);\nstrokeWeight(1);\n\nnoFill();\nbeginShape();\ncurveVertex(84, 91);\ncurveVertex(84, 91);\ncurveVertex(68, 19);\ncurveVertex(21, 17);\ncurveVertex(32, 91);\ncurveVertex(32, 91);\nendShape();\n</code>\n</div>" 7734 ], 7735 "alt": "Upside-down u-shape line, mid canvas. left point extends beyond canvas view.", 7736 "class": "p5", 7737 "module": "Shape", 7738 "submodule": "Vertex" 7739 }, 7740 { 7741 "file": "src/core/vertex.js", 7742 "line": 407, 7743 "description": "<p>Use the beginContour() and endContour() functions to create negative\nshapes within shapes such as the center of the letter 'O'. beginContour()\nbegins recording vertices for the shape and endContour() stops recording.\nThe vertices that define a negative shape must "wind" in the opposite\ndirection from the exterior shape. First draw vertices for the exterior\nclockwise order, then for internal shapes, draw vertices\nshape in counter-clockwise.\n<br><br>\nThese functions can only be used within a beginShape()/endShape() pair and\ntransformations such as translate(), rotate(), and scale() do not work\nwithin a beginContour()/endContour() pair. It is also not possible to use\nother shapes, such as ellipse() or rect() within.</p>\n", 7744 "itemtype": "method", 7745 "name": "endContour", 7746 "chainable": 1, 7747 "example": [ 7748 "\n<div>\n<code>\ntranslate(50, 50);\nstroke(255, 0, 0);\nbeginShape();\n// Exterior part of shape, clockwise winding\nvertex(-40, -40);\nvertex(40, -40);\nvertex(40, 40);\nvertex(-40, 40);\n// Interior part of shape, counter-clockwise winding\nbeginContour();\nvertex(-20, -20);\nvertex(-20, 20);\nvertex(20, 20);\nvertex(20, -20);\nendContour();\nendShape(CLOSE);\n</code>\n</div>" 7749 ], 7750 "alt": "white rect and smaller grey rect with red outlines in center of canvas.", 7751 "class": "p5", 7752 "module": "Shape", 7753 "submodule": "Vertex" 7754 }, 7755 { 7756 "file": "src/core/vertex.js", 7757 "line": 467, 7758 "description": "<p>The endShape() function is the companion to beginShape() and may only be\ncalled after beginShape(). When endshape() is called, all of image data\ndefined since the previous call to beginShape() is written into the image\nbuffer. The constant CLOSE as the value for the MODE parameter to close\nthe shape (to connect the beginning and the end).</p>\n", 7759 "itemtype": "method", 7760 "name": "endShape", 7761 "params": [ 7762 { 7763 "name": "mode", 7764 "description": "<p>use CLOSE to close the shape</p>\n", 7765 "type": "Constant", 7766 "optional": true 7767 } 7768 ], 7769 "chainable": 1, 7770 "example": [ 7771 "\n<div>\n<code>\nnoFill();\n\nbeginShape();\nvertex(20, 20);\nvertex(45, 20);\nvertex(45, 80);\nendShape(CLOSE);\n\nbeginShape();\nvertex(50, 20);\nvertex(75, 20);\nvertex(75, 80);\nendShape();\n</code>\n</div>" 7772 ], 7773 "alt": "Triangle line shape with smallest interior angle on bottom and upside-
7773down L.", 7774 "class": "p5", 7775 "module": "Shape", 7776 "submodule": "Vertex" 7777 }, 7778 { 7779 "file": "src/core/vertex.js", 7780 "line": 553, 7781 "description": "<p>Specifies vertex coordinates for quadratic Bezier curves. Each call to\nquadraticVertex() defines the position of one control points and one\nanchor point of a Bezier curve, adding a new segment to a line or shape.\nThe first time quadraticVertex() is used within a beginShape() call, it\nmust be prefaced with a call to vertex() to set the first anchor point.\nThis function must be used between beginShape() and endShape() and only\nwhen there is no MODE parameter specified to beginShape().</p>\n", 7782 "itemtype": "method", 7783 "name": "quadraticVertex", 7784 "params": [ 7785 { 7786 "name": "cx", 7787 "description": "<p>x-coordinate for the control point</p>\n", 7788 "type": "Number" 7789 }, 7790 { 7791 "name": "cy", 7792 "description": "<p>y-coordinate for the control point</p>\n", 7793 "type": "Number" 7794 }, 7795 { 7796 "name": "x3", 7797 "description": "<p>x-coordinate for the anchor point</p>\n", 7798 "type": "Number" 7799 }, 7800 { 7801 "name": "y3", 7802 "description": "<p>y-coordinate for the anchor point</p>\n", 7803 "type": "Number" 7804 } 7805 ], 7806 "chainable": 1, 7807 "example": [ 7808 "\n<div>\n<code>\nstrokeWeight(5);\npoint(20, 20);\npoint(80, 20);\npoint(50, 50);\n\nnoFill();\nstrokeWeight(1);\nbeginShape();\nvertex(20, 20);\nquadraticVertex(80, 20, 50, 50);\nendShape();\n</code>\n</div>\n\n<div>\n<code>\nstrokeWeight(5);\npoint(20, 20);\npoint(80, 20);\npoint(50, 50);\n\npoint(20, 80);\npoint(80, 80);\npoint(80, 60);\n\nnoFill();\nstrokeWeight(1);\nbeginShape();\nvertex(20, 20);\nquadraticVertex(80, 20, 50, 50);\nquadraticVertex(20, 80, 80, 80);\nvertex(80, 60);\nendShape();\n</code>\n</div>" 7809 ], 7810 "alt": "arched-shaped black line with 4 pixel thick stroke weight.\nbackwards s-shaped black line with 4 pixel thick stroke weight.", 7811 "class": "p5", 7812 "module": "Shape", 7813 "submodule": "Vertex" 7814 }, 7815 { 7816 "file": "src/core/vertex.js", 7817 "line": 645, 7818 "description": "<p>All shapes are constructed by connecting a series of vertices. vertex()\nis used to specify the vertex coordinates for points, lines, triangles,\nquads, and polygons. It is used exclusively within the beginShape() and\nendShape() functions.</p>\n", 7819 "itemtype": "method", 7820 "name": "vertex", 7821 "chainable": 1, 7822 "example": [ 7823 "\n<div>\n<code>\nstrokeWeight(3);\nbeginShape(POINTS);\nvertex(30, 20);\nvertex(85, 20);\nvertex(85, 75);\nvertex(30, 75);\nendShape();\n</code>\n</div>" 7824 ], 7825 "alt": "8 points making 4 lines", 7826 "class": "p5", 7827 "module": "Shape", 7828 "submodule": "Vertex", 7829 "overloads": [ 7830 { 7831 "line": 645, 7832 "params": [ 7833 { 7834 "name": "x", 7835 "description": "<p>x-coordinate of the vertex</p>\n", 7836 "type": "Number" 7837 }, 7838 { 7839 "name": "y", 7840 "description": "<p>y-coordinate of the vertex</p>\n", 7841 "type": "Number" 7842 } 7843 ], 7844 "chainable": 1 7845 }, 7846 { 7847 "line": 732, 7848 "params": [ 7849 { 7850 "name": "x", 7851 "description": "", 7852 "type": "Number" 7853 }, 7854 { 7855 "name": "y", 7856 "description": "", 7857 "type": "Number" 7858 }, 7859 { 7860 "name": "z", 7861 "description": "<p>z-coordinate of the vertex</p>\n", 7862 "type": "Number", 7863 "optional": true 7864 }, 7865 { 7866 "name": "u", 7867 "description": "<p>the vertex's texture u-coordinate</p>\n", 7868 "type": "Number", 7869 "optional": true 7870 }, 7871 { 7872 "name": "v", 7873 "description": "<p>the vertex's texture v-coordinate</p>\n", 7874 "type": "Number", 7875 "optional": true 7876 } 7877 ] 7878 } 7879 ] 7880 }, 7881 { 7882 "file": "src/data/p5.TypedDict.js", 7883 "line": 16, 7884 "description": "<p>Creates a new instance of p5.StringDict using the key, value pair\n or object you provide.</p>\n", 7885 "itemtype": "method", 7886 "name": "createStringDict", 7887 "return": { 7888 "description": "", 7889 "type": "p5.StringDict" 7890 }, 7891 "example": [ 7892 "\n <div class=\"norender\">\n <code>\n function setup() {\n var myDictionary = createStringDict('p5', 'js');\n print(myDictionary.hasKey('p5')); // logs true to console\n }\n </code></div>" 7893 ], 7894 "class": "p5", 7895 "module": "Data", 7896 "submodule": "Dictionary", 7897 "overloads": [ 7898 { 7899 "line": 16, 7900 "params": [ 7901 { 7902 "name": "key", 7903 "description": "", 7904 "type": "String" 7905 }, 7906 { 7907 "name": "value", 7908 "description": "", 7909 "type": "String" 7910 } 7911 ], 7912 "return": { 7913 "description": "", 7914 "type": "p5.StringDict" 7915 } 7916 }, 7917 { 7918 "line": 36, 7919 "params": [ 7920 { 7921 "name": "object", 7922 "description": "<p>object</p>\n", 7923 "type": "Object" 7924 } 7925 ], 7926 "return": { 7927 "description": "", 7928 "type": "p5.StringDict" 7929 } 7930 } 7931 ] 7932 }, 7933 { 7934 "file": "src/data/p5.TypedDict.js", 7935 "line": 47, 7936 "description": "<p>Creates a new instance of p5.NumberDict using the key, value pair\n or object you provide.</p>\n", 7937 "itemtype": "method", 7938 "name": "createNumberDict", 7939 "return": { 7940 "description": "", 7941 "type": "p5.NumberDict" 7942 }, 7943 "example": [ 7944 "\n <div class=\"norender\">\n <code>\n function setup() {\n var myDictionary = createNumberDict(100, 42);\n print(myDictionary.hasKey(100)); // logs true to console\n }\n </code></div>" 7945 ], 7946 "class": "p5", 7947 "module": "Data", 7948 "submodule": "Dictionary", 7949 "overloads": [ 7950 { 7951 "line": 47, 7952 "params": [ 7953 { 7954 "name": "key", 7955 "description": "", 7956 "type": "Number" 7957 }, 7958 { 7959 "name": "value", 7960 "description": "", 7961 "type": "Number" 7962 } 7963 ], 7964 "return": { 7965 "description": "", 7966 "type": "p5.NumberDict" 7967 } 7968 }, 7969 { 7970 "line": 67, 7971 "params": [ 7972 { 7973 "name": "object", 7974 "description": "<p>object</p>\n", 7975 "type": "Object" 7976 } 7977 ], 7978 "return": { 7979 "description": "", 7980 "type": "p5.NumberDict" 7981 } 7982 } 7983 ] 7984 }, 7985 { 7986 "file": "src/data/p5.TypedDict.js", 7987 "line": 97, 7988 "description": "<p>Returns the number of key-value pairs currently in Dictionary object</p>\n", 7989 "itemtype": "method", 7990 "name": "size", 7991 "return": { 7992 "description": "the number of key-value pairs in Dictionary object", 7993 "type": "Integer" 7994 }, 7995 "example": [ 7996 "\n<div class=\"norender\">\n<code>\nfunction setup() {\n var myDictionary = createNumberDict(1, 10);\n myDictionary.create(2, 20);\n myDictionary.create(3, 30);\n print(myDictionary.size()); // value of amt is 3\n}\n</code></div>\n" 7997 ], 7998 "class": "p5.TypedDict", 7999 "module": "Data", 8000 "submodule": "Dictionary" 8001 }, 8002 { 8003 "file": "src/data/p5.TypedDict.js", 8004 "line": 119, 8005 "description": "<p>Returns true if key exists in Dictionary\notherwise returns false</p>\n", 8006 "itemtype": "method", 8007 "name": "hasKey", 8008 "params": [ 8009 { 8010 "name": "key", 8011 "description": "<p>that you want to access</p>\n", 8012 "type": "Number|String" 8013 } 8014 ], 8015 "return": { 8016 "description": "whether that key exists in Dictionary", 8017 "type": "Boolean" 8018 }, 8019 "example": [ 8020 "\n<div class=\"norender\">\n<code>\nfunction setup() {\n var myDictionary = createStringDict('p5', 'js');\n print(myDictionary.hasKey('p5')); // logs true to console\n}\n</code></div>\n" 8021 ], 8022 "class": "p5.TypedDict", 8023 "module": "Data", 8024 "submodule": "Dictionary" 8025 }, 8026 { 8027 "file": "src/data/p5.TypedDict.js", 8028 "line": 142, 8029 "description": "<p>Returns value stored at supplied key.</p>\n", 8030 "itemtype": "method", 8031 "name": "get", 8032 "params": [ 8033 { 8034 "name": "key", 8035 "description": "<p>that you want to access</p>\n", 8036 "type": "Number|String" 8037 } 8038 ], 8039 "return": { 8040 "description": "the value stored at that key", 8041 "type": "Number|String" 8042 }, 8043 "example": [ 8044 "\n<div class=\"norender\">\n<code>\nfunction setup() {\n var myDictionary = createStringDict('p5', 'js');\n var myValue = myDictionary.get('p5');\n print(myValue === 'js'); // logs true to console\n}\n</code></div>\n" 8045 ], 8046 "class": "p5.TypedDict", 8047 "module": "Data", 8048 "submodule": "Dictionary" 8049 }, 8050 { 8051 "file": "src/data/p5.TypedDict.js", 8052 "line": 169, 8053 "description": "<p>Changes the value of key if in it already exists in\nin the Dictionary otherwise makes a new key-value pair</p>\n", 8054 "itemtype": "method", 8055 "name": "set", 8056 "params": [ 8057 { 8058 "name": "key", 8059 "description": "", 8060 "type": "Number|String" 8061 }, 8062 { 8063 "name": "value", 8064 "description": "", 8065 "type": "Number|String" 8066 } 8067 ], 8068 "example": [ 8069 "\n<div class=\"norender\">\n<code>\nfunction setup() {\n var myDictionary = createStringDict('p5', 'js');\n myDictionary.set('p5', 'JS');\n myDictionary.print();\n // above logs \"key: p5 - value: JS\" to console\n}\n</code></div>\n" 8070 ], 8071 "class": "p5.TypedDict", 8072 "module": "Data", 8073 "submodule": "Dictionary" 8074 }, 8075 { 8076 "file": "src/data/p5.TypedDict.js", 8077 "line": 198, 8078 "description": "<p>private helper function to handle the user passing objects in\nduring construction or calls to create()</p>\n", 8079 "class": "p5.TypedDict", 8080 "module": "Data", 8081 "submodule": "Dictionary" 8082 }, 8083 { 8084 "file": "src/data/p5.TypedDict.js", 8085 "line": 209, 8086 "description": "<p>Creates a key-value pair in the Dictionary</p>\n", 8087 "itemtype": "method", 8088 "name": "create", 8089 "example": [ 8090 "\n<div class=\"norender\">\n<code>\nfunction setup() {\n var myDictionary = createStringDict('p5', 'js');\n myDictionary.create('happy', 'coding');\n myDictionary.print();\n // above logs \"key: p5 - value: js, key: happy - value: coding\" to console\n}\n</code></div>" 8091 ], 8092 "class": "p5.TypedDict", 8093 "module": "Data", 8094 "submodule": "Dictionary", 8095 "overloads": [ 8096 { 8097 "line": 209, 8098 "params": [ 8099 { 8100 "name": "key", 8101 "description": "", 8102 "type": "Number|String" 8103 }, 8104 { 8105 "name": "value", 8106 "description": "", 8107 "type": "Number|String" 8108 } 8109 ] 8110 }, 8111 { 8112 "line": 227, 8113 "params": [ 8114 { 8115 "name": "obj", 8116 "description": "<p>key/value pair</p>\n", 8117 "type": "Object" 8118 } 8119 ] 8120 } 8121 ] 8122 }, 8123 { 8124 "file": "src/data/p5.TypedDict.js", 8125 "line": 245, 8126 "description": "<p>Empties Dictionary of all key-value pairs</p>\n", 8127 "itemtype": "method", 8128 "name": "clear", 8129 "example": [ 8130 "\n<div class=\"norender\">\n<code>\nfunction setup() {\n var myDictionary = createStringDict('p5', 'js');\n print(myDictionary.hasKey('p5')); // prints 'true'\n myDictionary.clear();\n print(myDictionary.hasKey('p5')); // prints 'false'\n}\n</code>\n</div>" 8131 ], 8132 "class": "p5.TypedDict", 8133 "module": "Data", 8134 "submodule": "Dictionary" 8135 }, 8136 { 8137 "file": "src/data/p5.TypedDict.js", 8138 "line": 265, 8139 "description": "<p>Removes a key-value pair in the Dictionary</p>\n", 8140 "itemtype": "method", 8141 "name": "remove", 8142 "params": [ 8143 { 8144 "name": "key", 8145 "description": "<p>for the pair to remove</p>\n", 8146 "type": "Number|String" 8147 } 8148 ], 8149 "example": [ 8150 "\n<div class=\"norender\">\n<code>\nfunction setup() {\n var myDictionary = createStringDict('p5', 'js');\n myDictionary.create('happy', 'coding');\n myDictionary.print();\n // above logs \"key: p5 - value: js, key: happy - value: coding\" to console\n myDictionary.remove('p5');\n myDictionary.print();\n // above logs \"key: happy value: coding\" to console\n}\n</code></div>\n" 8151 ], 8152 "class": "p5.Typed
8152Dict", 8153 "module": "Data", 8154 "submodule": "Dictionary" 8155 }, 8156 { 8157 "file": "src/data/p5.TypedDict.js", 8158 "line": 295, 8159 "description": "<p>Logs the list of items currently in the Dictionary to the console</p>\n", 8160 "itemtype": "method", 8161 "name": "print", 8162 "example": [ 8163 "\n<div class=\"norender\">\n<code>\nfunction setup() {\n var myDictionary = createStringDict('p5', 'js');\n myDictionary.create('happy', 'coding');\n myDictionary.print();\n // above logs \"key: p5 - value: js, key: happy - value: coding\" to console\n}\n</code>\n</div>" 8164 ], 8165 "class": "p5.TypedDict", 8166 "module": "Data", 8167 "submodule": "Dictionary" 8168 }, 8169 { 8170 "file": "src/data/p5.TypedDict.js", 8171 "line": 319, 8172 "description": "<p>Converts the Dictionary into a CSV file for local\nstorage.</p>\n", 8173 "itemtype": "method", 8174 "name": "saveTable", 8175 "example": [ 8176 "\n<div>\n<code>\ncreateButton('save')\n .position(10, 10)\n .mousePressed(function() {\n createStringDict({\n john: 1940,\n paul: 1942,\n george: 1943,\n ringo: 1940\n }).saveTable('beatles');\n });\n</code>\n</div>" 8177 ], 8178 "class": "p5.TypedDict", 8179 "module": "Data", 8180 "submodule": "Dictionary" 8181 }, 8182 { 8183 "file": "src/data/p5.TypedDict.js", 8184 "line": 352, 8185 "description": "<p>Converts the Dictionary into a JSON file for local\nstorage.</p>\n", 8186 "itemtype": "method", 8187 "name": "saveJSON", 8188 "example": [ 8189 "\n<div>\n<code>\ncreateButton('save')\n .position(10, 10)\n .mousePressed(function() {\n createStringDict({\n john: 1940,\n paul: 1942,\n george: 1943,\n ringo: 1940\n }).saveJSON('beatles');\n });\n</code>\n</div>" 8190 ], 8191 "class": "p5.TypedDict", 8192 "module": "Data", 8193 "submodule": "Dictionary" 8194 }, 8195 { 8196 "file": "src/data/p5.TypedDict.js", 8197 "line": 378, 8198 "description": "<p>private helper function to ensure that the user passed in valid\nvalues for the Dictionary type</p>\n", 8199 "class": "p5.TypedDict", 8200 "module": "Data", 8201 "submodule": "Dictionary" 8202 }, 8203 { 8204 "file": "src/data/p5.TypedDict.js", 8205 "line": 423, 8206 "description": "<p>private helper function to ensure that the user passed in valid\nvalues for the Dictionary type</p>\n", 8207 "class": "p5.NumberDict", 8208 "module": "Data", 8209 "submodule": "Dictionary" 8210 }, 8211 { 8212 "file": "src/data/p5.TypedDict.js", 8213 "line": 432, 8214 "description": "<p>Add to a value stored at a certain key\nThe sum is stored in that location in the Dictionary.</p>\n", 8215 "itemtype": "method", 8216 "name": "add", 8217 "params": [ 8218 { 8219 "name": "Key", 8220 "description": "<p>for value you wish to add to</p>\n", 8221 "type": "Number" 8222 }, 8223 { 8224 "name": "Amount", 8225 "description": "<p>to add to the value</p>\n", 8226 "type": "Number" 8227 } 8228 ], 8229 "example": [ 8230 "\n<div class='norender'>\n<code>\nfunction setup() {\n var myDictionary = createNumberDict(2, 5);\n myDictionary.add(2, 2);\n console.log(myDictionary.get(2)); // logs 7 to console.\n}\n</code></div>\n\n" 8231 ], 8232 "class": "p5.NumberDict", 8233 "module": "Data", 8234 "submodule": "Dictionary" 8235 }, 8236 { 8237 "file": "src/data/p5.TypedDict.js", 8238 "line": 460, 8239 "description": "<p>Subtract from a value stored at a certain key\nThe difference is stored in that location in the Dictionary.</p>\n", 8240 "itemtype": "method", 8241 "name": "sub", 8242 "params": [ 8243 { 8244 "name": "Key", 8245 "description": "<p>
8245for value you wish to subtract from</p>\n", 8246 "type": "Number" 8247 }, 8248 { 8249 "name": "Amount", 8250 "description": "<p>to subtract from the value</p>\n", 8251 "type": "Number" 8252 } 8253 ], 8254 "example": [ 8255 "\n<div class='norender'>\n<code>\nfunction setup() {\n var myDictionary = createNumberDict(2, 5);\n myDictionary.sub(2, 2);\n console.log(myDictionary.get(2)); // logs 3 to console.\n}\n</code></div>\n\n" 8256 ], 8257 "class": "p5.NumberDict", 8258 "module": "Data", 8259 "submodule": "Dictionary" 8260 }, 8261 { 8262 "file": "src/data/p5.TypedDict.js", 8263 "line": 484, 8264 "description": "<p>Multiply a value stored at a certain key\nThe product is stored in that location in the Dictionary.</p>\n", 8265 "itemtype": "method", 8266 "name": "mult", 8267 "params": [ 8268 { 8269 "name": "Key", 8270 "description": "<p>for value you wish to multiply</p>\n", 8271 "type": "Number" 8272 }, 8273 { 8274 "name": "Amount", 8275 "description": "<p>to multiply the value by</p>\n", 8276 "type": "Number" 8277 } 8278 ], 8279 "example": [ 8280 "\n<div class='norender'>\n<code>\nfunction setup() {\n var myDictionary = createNumberDict(2, 4);\n myDictionary.mult(2, 2);\n console.log(myDictionary.get(2)); // logs 8 to console.\n}\n</code></div>\n\n" 8281 ], 8282 "class": "p5.NumberDict", 8283 "module": "Data", 8284 "submodule": "Dictionary" 8285 }, 8286 { 8287 "file": "src/data/p5.TypedDict.js", 8288 "line": 512, 8289 "description": "<p>Divide a value stored at a certain key\nThe quotient is stored in that location in the Dictionary.</p>\n", 8290 "itemtype": "method", 8291 "name": "div", 8292 "params": [ 8293 { 8294 "name": "Key", 8295 "description": "<p>for value you wish to divide</p>\n", 8296 "type": "Number" 8297 }, 8298 { 8299 "name": "Amount", 8300 "description": "<p>to divide the value by</p>\n", 8301 "type": "Number" 8302 } 8303 ], 8304 "example": [ 8305 "\n<div class='norender'>\n<code>\nfunction setup() {\n var myDictionary = createNumberDict(2, 8);\n myDictionary.div(2, 2);\n console.log(myDictionary.get(2)); // logs 4 to console.\n}\n</code></div>\n\n" 8306 ], 8307 "class": "p5.NumberDict", 8308 "module": "Data", 8309 "submodule": "Dictionary" 8310 }, 8311 { 8312 "file": "src/data/p5.TypedDict.js", 8313 "line": 540, 8314 "description": "<p>private helper function for finding lowest or highest value\nthe argument 'flip' is used to flip the comparison arrow\nfrom 'less than' to 'greater than'</p>\n", 8315 "class": "p5.NumberDict", 8316 "module": "Data", 8317 "submodule": "Dictionary" 8318 }, 8319 { 8320 "file": "src/data/p5.TypedDict.js", 8321 "line": 563, 8322 "description": "<p>Return the lowest value.</p>\n", 8323 "itemtype": "method", 8324 "name": "minValue", 8325 "return": { 8326 "description": "", 8327 "type": "Number" 8328 }, 8329 "example": [ 8330 "\n<div class='norender'>\n<code>\nfunction setup() {\n var myDictionary = createNumberDict({ 2: -10, 4: 0.65, 1.2: 3 });\n var lowestValue = myDictionary.minValue(); // value is -10\n print(lowestValue);\n}\n</code></div>\n" 8331 ], 8332 "class": "p5.NumberDict", 8333 "module": "Data", 8334 "submodule": "Dictionary" 8335 }, 8336 { 8337 "file": "src/data/p5.TypedDict.js", 8338 "line": 584, 8339 "description": "<p>Return the highest value.</p>\n", 8340 "itemtype": "method", 8341 "name": "maxValue", 8342 "return": { 8343 "description": "", 8344 "type": "Number" 8345 }, 8346 "example": [ 8347 "\n<div class='norender'>\n<code>\nfunction setup() {\n var myDictionary = createNumberDict({ 2: -10, 4: 0.65, 1.2: 3 });\n var highestValue = myDictionary.maxValue(); // value is 3\n print(highestValue);\n}\n</code></div>\n" 8348 ], 8349 "class": "p5.NumberDict", 8350 "module": "Data", 8351 "submodule": "Dictionary" 8352 }, 8353 { 8354 "file": "src/data/p5.TypedDict.js", 8355 "line": 605, 8356 "description": "<p>private helper function for finding lowest or highest key\nthe argument 'flip' is used to flip the comparison arrow\nfrom 'less than' to 'greater than'</p>\n", 8357 "class": "p5.NumberDict", 8358 "module": "Data", 8359 "submodule": "Dictionary" 8360 }, 8361 { 8362 "file": "src/data/p5.TypedDict.js", 8363 "line": 628, 8364 "description": "<p>Return the lowest key.</p>\n", 8365 "itemtype": "method", 8366 "name": "minKey", 8367 "return": { 8368 "description": "", 8369 "type": "Number" 8370 }, 8371 "example": [ 8372 "\n<div class='norender'>\n<code>\nfunction setup() {\n var myDictionary = createNumberDict({ 2: 4, 4: 6, 1.2: 3 });\n var lowestKey = myDictionary.minKey(); // value is 1.2\n print(lowestKey);\n}\n</code></div>\n" 8373 ], 8374 "class": "p5.NumberDict", 8375 "module": "Data", 8376 "submodule": "Dictionary" 8377 }, 8378 { 8379 "file": "src/data/p5.TypedDict.js", 8380 "line": 649, 8381 "description": "<p>Return the highest key.</p>\n", 8382 "itemtype": "method", 8383 "name": "maxKey", 8384 "return": { 8385 "description": "", 8386 "type": "Number" 8387 }, 8388 "example": [ 8389 "\n<div class='norender'>\n<code>\nfunction setup() {\n var myDictionary = createNumberDict({ 2: 4, 4: 6, 1.2: 3 });\n var highestKey = myDictionary.maxKey(); // value is 4\n print(highestKey);\n}\n</code></div>\n" 8390 ], 8391 "class": "p5.NumberDict", 8392 "module": "Data", 8393 "submodule": "Dictionary" 8394 }, 8395 { 8396 "file": "src/events/acceleration.js", 8397 "line": 12, 8398 "description": "<p>The system variable deviceOrientation always contains the orientation of\nthe device. The value of this variable will either be set 'landscape'
8398\nor 'portrait'. If no data is available it will be set to 'undefined'.\neither LANDSCAPE or PORTRAIT.</p>\n", 8399 "itemtype": "property", 8400 "name": "deviceOrientation", 8401 "type": "Constant", 8402 "readonly": "", 8403 "class": "p5", 8404 "module": "Events", 8405 "submodule": "Acceleration" 8406 }, 8407 { 8408 "file": "src/events/acceleration.js", 8409 "line": 23, 8410 "description": "<p>The system variable accelerationX always contains the acceleration of the\ndevice along the x axis. Value is represented as meters per second squared.</p>\n", 8411 "itemtype": "property", 8412 "name": "accelerationX", 8413 "type": "Number", 8414 "readonly": "", 8415 "class": "p5", 8416 "module": "Events", 8417 "submodule": "Acceleration" 8418 }, 8419 { 8420 "file": "src/events/acceleration.js", 8421 "line": 32, 8422 "description": "<p>The system variable accelerationY always contains the acceleration of the\ndevice along the y axis. Value is represented as meters per second squared.</p>\n", 8423 "itemtype": "property", 8424 "name": "accelerationY", 8425 "type": "Number", 8426 "readonly": "", 8427 "class": "p5", 8428 "module": "Events", 8429 "submodule": "Acceleration" 8430 }, 8431 { 8432 "file": "src/events/acceleration.js", 8433 "line": 41, 8434 "description": "<p>The system variable accelerationZ always contains the acceleration of the\ndevice along the z axis. Value is represented as meters per second squared.</p>\n", 8435 "itemtype": "property", 8436 "name": "accelerationZ", 8437 "type": "Number", 8438 "readonly": "", 8439 "class": "p5", 8440 "module": "Events", 8441 "submodule": "Acceleration" 8442 }, 8443 { 8444 "file": "src/events/acceleration.js", 8445 "line": 50, 8446 "description": "<p>The system variable pAccelerationX always contains the acceleration of the\ndevice along the x axis in the frame previous to the current frame. Value\nis represented as meters per second squared.</p>\n", 8447 "itemtype": "property", 8448 "name": "pAccelerationX", 8449 "type": "Number", 8450 "readonly": "", 8451 "class": "p5", 8452 "module": "Events", 8453 "submodule": "Acceleration" 8454 }, 8455 { 8456 "file": "src/events/acceleration.js", 8457 "line": 60, 8458 "description": "<p>The system variable pAccelerationY always contains the acceleration of the\ndevice along the y axis in the frame previous to the current frame. Value\nis represented as meters per second squared.</p>\n", 8459 "itemtype": "property", 8460 "name": "pAccelerationY", 8461 "type": "Number", 8462 "readonly": "", 8463 "class": "p5", 8464 "module": "Events", 8465 "submodule": "Acceleration" 8466 }, 8467 { 8468 "file": "src/events/acceleration.js", 8469 "line": 70, 8470 "description": "<p>The system variable pAccelerationZ always contains the acceleration of the\ndevice along the z axis in the frame previous to the current frame. Value\nis represented as meters per second squared.</p>\n", 8471 "itemtype": "property", 8472 "name": "pAccelerationZ", 8473 "type": "Number", 8474 "readonly": "", 8475 "class": "p5", 8476 "module": "Events", 8477 "submodule": "Acceleration" 8478 }, 8479 { 8480 "file": "src/events/acceleration.js", 8481 "line": 91, 8482 "description": "<p>The system variable rotationX always contains the rotation of the\ndevice along the x axis. Value is represented as 0 to +/-180 degrees.\n<br><br>\nNote: The order the rotations are called is important, ie. if used\ntogether, it must be called in the order Z-X-Y or there might be\nunexpected behaviour.</p>\n", 8483 "example": [ 8484 "\n<div>\n<code>\nfunction setup() {\n createCanvas(100, 100, WEBGL);\n}\n\nfunction draw() {\n background(200);\n //rotateZ(radians(rotationZ));\n rotateX(radians(rotationX));\n //rotateY(radians(rotationY));\n box(200, 200, 200);\n}\n</code>\n</div>" 8485 ], 8486 "itemtype": "property", 8487 "name": "rotationX", 8488 "type": "Number", 8489 "readonly": "", 8490 "alt": "red horizontal line right, green vertical line bottom. black background.", 8491 "class": "p5", 8492 "module": "Events", 8493 "submodule": "Acceleration" 8494 }, 8495 { 8496 "file": "src/events/acceleration.js", 8497 "line": 125, 8498 "description": "<p>The system variable rotationY always contains the rotation of the\ndevice along the y axis. V
8498alue is represented as 0 to +/-90 degrees.\n<br><br>\nNote: The order the rotations are called is important, ie. if used\ntogether, it must be called in the order Z-X-Y or there might be\nunexpected behaviour.</p>\n", 8499 "example": [ 8500 "\n<div>\n<code>\nfunction setup() {\n createCanvas(100, 100, WEBGL);\n}\n\nfunction draw() {\n background(200);\n //rotateZ(radians(rotationZ));\n //rotateX(radians(rotationX));\n rotateY(radians(rotationY));\n box(200, 200, 200);\n}\n</code>\n</div>" 8501 ], 8502 "itemtype": "property", 8503 "name": "rotationY", 8504 "type": "Number", 8505 "readonly": "", 8506 "alt": "red horizontal line right, green vertical line bottom. black background.", 8507 "class": "p5", 8508 "module": "Events", 8509 "submodule": "Acceleration" 8510 }, 8511 { 8512 "file": "src/events/acceleration.js", 8513 "line": 158, 8514 "description": "<p>The system variable rotationZ always contains the rotation of the\ndevice along the z axis. Value is represented as 0 to 359 degrees.\n<br><br>\nUnlike rotationX and rotationY, this variable is available for devices\nwith a built-in compass only.\n<br><br>\nNote: The order the rotations are called is important, ie. if used\ntogether, it must be called in the order Z-X-Y or there might be\nunexpected behaviour.</p>\n", 8515 "example": [ 8516 "\n<div>\n<code>\nfunction setup() {\n createCanvas(100, 100, WEBGL);\n}\n\nfunction draw() {\n background(200);\n rotateZ(radians(rotationZ));\n //rotateX(radians(rotationX));\n //rotateY(radians(rotationY));\n box(200, 200, 200);\n}\n</code>\n</div>" 8517 ], 8518 "itemtype": "property", 8519 "name": "rotationZ", 8520 "type": "Number", 8521 "readonly": "", 8522 "alt": "red horizontal line right, green vertical line bottom. black background.", 8523 "class": "p5", 8524 "module": "Events", 8525 "submodule": "Acceleration" 8526 }, 8527 { 8528 "file": "src/events/acceleration.js", 8529 "line": 194, 8530 "description": "<p>The system variable pRotationX always contains the rotation of the\ndevice along the x axis in the frame previous to the current frame. Value\nis represented as 0 to +/-180 degrees.\n<br><br>\npRotationX can also be used with rotationX to determine the rotate\ndirection of the device along the X-axis.</p>\n", 8531 "example": [ 8532 "\n<div class='norender'>\n<code>\n// A simple if statement looking at whether\n// rotationX - pRotationX < 0 is true or not will be\n// sufficient for determining the rotate direction\n// in most cases.\n\n// Some extra logic is needed to account for cases where\n// the angles wrap around.\nvar rotateDirection = 'clockwise';\n\n// Simple range conversion to make things simpler.\n// This is not absolutely necessary but the logic\n// will be different in that case.\n\nvar rX = rotationX + 180;\nvar pRX = pRotationX + 180;\n\nif ((rX - pRX > 0 && rX - pRX < 270) || rX - pRX < -270) {\n rotateDirection = 'clockwise';\n} else if (rX - pRX < 0 || rX - pRX > 270) {\n rotateDirection = 'counter-clockwise';\n}\n\nprint(rotateDirection);\n</code>\n</div>" 8533 ], 8534 "alt": "no image to display.", 8535 "itemtype": "property", 8536 "name": "pRotationX", 8537 "type": "Number", 8538 "readonly": "", 8539 "class": "p5", 8540 "module": "Events", 8541 "submodule": "Acceleration" 8542 }, 8543 { 8544 "file": "src/events/acceleration.js", 8545 "line": 239, 8546 "description": "<p>The system variable pRotationY always contains the rotation of the\ndevice along the y axis in the frame previous to the current frame. Value\nis represented as 0 to +/-90 degrees.\n<br><br>\npRotationY can also be used with rotationY to determine the rotate\ndirection of the device along the Y-axis.</p>\n", 8547 "example": [ 8548 "\n<div class='norender'>\n<code>\n// A simple if statement looking at whether\n// rotationY - pRotationY < 0 is true or not will be\n// sufficient for determining the rotate direction\n// in most cases.\n\n// Some extra logic is needed to account for cases where\n// the angles wrap around.\nvar rotateDirection = 'clockwise';\n\n// Simple range conversion to make things simpler.\n// This is not absolutely necessary but the logic\n// will be different in that case.\n\nvar rY = rotationY + 180;\nvar pRY = pRotationY + 180;\n\nif ((rY - pRY > 0 && rY - pRY < 270) || rY - pRY < -270) {\n rotateDirection = 'clockwise';\n} else if (rY - pRY < 0 || rY - pRY > 270) {\n rotateDirection = 'counter-clockwise';\n}\nprint(rotateDirection);\n</code>\n</div>" 8549 ], 8550 "alt": "no image to display.", 8551 "itemtype": "property", 8552 "name": "pRotationY", 8553 "type": "Number", 8554 "readonly": "", 8555 "class": "p5", 8556 "module": "Events", 8557 "submodule": "Acceleration" 8558 }, 8559 { 8560 "file": "src/events/acceleration.js", 8561 "line": 283, 8562 "description": "<p>The system variable pRotationZ always contains the rotation of the\ndevice along the z axis in the frame previous to the current frame. Value\nis represented as 0 to 359 degrees.\n<br><br>\npRotationZ can also be used with rotationZ to determine the rotate\ndirection of the device along the Z-axis.</p>\n", 8563 "example": [ 8564 "\n<div class='norender'>\n<code>\n// A simple if statement looking at whether\n// rotationZ - pRotationZ < 0 is true or not will be\n// sufficient for determining the rotate direction\n// in most cases.\n\n// Some extra logic is needed to account for cases where\n// the angles wrap around.\nvar rotateDirection = 'clockwise';\n\nif (\n (rotationZ - pRotationZ > 0 && rotationZ - pRotationZ < 270) ||\n rotationZ - pRotationZ < -270\n) {\n rotateDirection = 'clockwise';\n} else if (rotationZ - pRotationZ < 0 || rotationZ - pRotationZ > 270) {\n rotateDirection = 'counter-clockwise';\n}\nprint(rotateDirection);\n</code>\n</div>" 8565 ], 8566 "alt": "no image to display.", 8567 "itemtype": "property", 8568 "name": "pRotationZ", 8569 "type": "Number", 8570 "readonly": "", 8571 "class": "p5", 8572 "module": "Events", 8573 "submodule": "Acceleration" 8574 }, 8575 { 8576 "file": "src/events/acceleration.js", 8577 "line": 341, 8578 "itemtype": "property", 8579 "name": "turnAxis", 8580 "type": "String", 8581 "readonly": "", 8582 "class": "p5", 8583 "module": "Events", 8584 "submodule": "Acceleration" 8585 }, 8586 { 8587 "file": "src/events/acceleration.js", 8588 "line": 350, 8589 "description": "<p>The setMoveThreshold() function is used to set the movement threshold for\nthe deviceMoved() function. The default threshold is set to 0.5.</p>\n", 8590 "itemtype": "method", 8591 "name": "setMoveThreshold", 8592 "params": [ 8593 { 8594 "name": "value", 8595 "description": "<p>The threshold value</p>\n", 8596 "type": "Number" 8597 } 8598 ], 8599 "class": "p5", 8600 "module": "Events", 8601 "submodule": "Acceleration" 8602 }, 8603 { 8604 "file": "src/events/acceleration.js", 8605 "line": 362, 8606 "description": "<p>The setShakeThreshold() function is used to set the movement threshold for\nthe deviceShaken() function. The default threshold is set to 30.</p>\n", 8607 "itemtype": "method", 8608 "name": "setShakeThreshold", 8609 "params": [ 8610 { 8611 "name": "value", 8612 "description": "<p>The threshold value</p>\n", 8613 "type": "Number" 8614 } 8615 ], 8616 "class": "p5", 8617 "module": "Events", 8618 "submodule": "Acceleration" 8619 }, 8620 { 8621 "file": "src/events/acceleration.js", 8622 "line": 374, 8623 "description": "<p>The deviceMoved() function is called when the device is moved by more than\nthe threshold value along X, Y or Z axis. The default threshold is set to\n0.5.</p>\n", 8624 "itemtype": "method", 8625 "name": "deviceMoved", 8626 "example": [ 8627 "\n<div class=\"norender\">\n<code>\n// Run this example on a mobile device\n// Move the device around\n// to change the value.\n\nvar value = 0;\nfunction draw() {\n fill(value);\n rect(25, 25, 50, 50);\n}
8627\nfunction deviceMoved() {\n value = value + 5;\n if (value > 255) {\n value = 0;\n }\n}\n</code>\n</div>" 8628 ], 8629 "alt": "50x50 black rect in center of canvas. turns white on mobile when device moves", 8630 "class": "p5", 8631 "module": "Events", 8632 "submodule": "Acceleration" 8633 }, 8634 { 8635 "file": "src/events/acceleration.js", 8636 "line": 405, 8637 "description": "<p>The deviceTurned() function is called when the device rotates by\nmore than 90 degrees continuously.\n<br><br>\nThe axis that triggers the deviceTurned() method is stored in the turnAxis\nvariable. The deviceTurned() method can be locked to trigger on any axis:\nX, Y or Z by comparing the turnAxis variable to 'X', 'Y' or 'Z'.</p>\n", 8638 "itemtype": "method", 8639 "name": "deviceTurned", 8640 "example": [ 8641 "\n<div class=\"norender\">\n<code>\n// Run this example on a mobile device\n// Rotate the device by 90 degrees\n// to change the value.\n\nvar value = 0;\nfunction draw() {\n fill(value);\n rect(25, 25, 50, 50);\n}\nfunction deviceTurned() {\n if (value === 0) {\n value = 255;\n } else if (value === 255) {\n value = 0;\n }\n}\n</code>\n</div>\n<div>\n<code>\n// Run this example on a mobile device\n// Rotate the device by 90 degrees in the\n// X-axis to change the value.\n\nvar value = 0;\nfunction draw() {\n fill(value);\n rect(25, 25, 50, 50);\n}\nfunction deviceTurned() {\n if (turnAxis === 'X') {\n if (value === 0) {\n value = 255;\n } else if (value === 255) {\n value = 0;\n }\n }\n}\n</code>\n</div>" 8642 ], 8643 "alt": "50x50 black rect in center of canvas. turns white on mobile when device turns\n50x50 black rect in center of canvas. turns white on mobile when x-axis turns", 8644 "class": "p5", 8645 "module": "Events", 8646 "submodule": "Acceleration" 8647 }, 8648 { 8649 "file": "src/events/acceleration.js", 8650 "line": 464, 8651 "description": "<p>The deviceShaken() function is called when the device total acceleration\nchanges of accelerationX and accelerationY values is more than\nthe threshold value. The default threshold is set to 30.</p>\n", 8652 "itemtype": "method", 8653 "name": "deviceShaken", 8654 "example": [ 8655 "\n<div class=\"norender\">\n<code>\n// Run this example on a mobile device\n// Shake the device to change the value.\n\nvar value = 0;\nfunction draw() {\n fill(value);\n rect(25, 25, 50, 50);\n}\nfunction deviceShaken() {\n value = value + 5;\n if (value > 255) {\n value = 0;\n }\n}\n</code>\n</div>" 8656 ], 8657 "alt": "50x50 black rect in center of canvas. turns white on mobile when device shakes", 8658 "class": "p5", 8659 "module": "Events", 8660 "submodule": "Acceleration" 8661 }, 8662 { 8663 "file": "src/events/keyboard.js", 8664 "line": 18, 8665 "description": "<p>The boolean system variable keyIsPressed is true if any key is pressed\nand false if no keys are pressed.</p>\n", 8666 "itemtype": "property", 8667 "name": "keyIsPressed", 8668 "type": "Boolean", 8669 "readonly": "", 8670 "example": [ 8671 "\n<div>\n<code>\nfunction draw() {\n if (keyIsPressed === true) {\n fill(0);\n } else {\n fill(255);\n }\n rect(25, 25, 50, 50);\n}\n</code>\n</div>" 8672 ], 8673 "alt": "50x50 white rect that turns black on keypress.", 8674 "class": "p5", 8675 "module": "Events", 8676 "submodule": "Keyboard" 8677 }, 8678 { 8679 "file": "src/events/keyboard.js", 8680 "line": 45, 8681 "description": "<p>The system variable key always contains the value of the most recent\nkey on the keyboard that was typed. To get the proper capitalization, it\nis best to use it within keyTyped(). For non-ASCII keys, use the keyCode\nvariable.</p>\n", 8682 "itemtype": "property", 8683 "name": "key", 8684 "type": "String", 8685 "readonly": "", 8686 "example": [ 8687 "\n<div><code>\n// Click any key to display it!\n// (Not Guaranteed to be Case Sensitive)\nfunction setup() {\n fill(245, 123, 158);\n textSize(50);\n}\n\nfunction draw() {\n background(200);\n text(key, 33, 65); // Display last key pressed.\n}\n</code></div>" 8688 ], 8689 "alt": "canvas displays any key value that is pressed in pink font.", 8690 "class": "p5", 8691 "module": "Events", 8692 "submodule": "Keyboard" 8693 }, 8694 { 8695 "file": "src/events/keyboard.js", 8696 "line": 74, 8697 "description": "<p>The variable keyCode is used to detect special keys such as BACKSPACE,\nDELETE, ENTE
8697R, RETURN, TAB, ESCAPE, SHIFT, CONTROL, OPTION, ALT, UP_ARROW,\nDOWN_ARROW, LEFT_ARROW, RIGHT_ARROW.\nYou can also check for custom keys by looking up the keyCode of any key\non a site like this: <a href=\"http://keycode.info/\">keycode.info</a>.</p>\n", 8698 "itemtype": "property", 8699 "name": "keyCode", 8700 "type": "Integer", 8701 "readonly": "", 8702 "example": [ 8703 "\n<div><code>\nvar fillVal = 126;\nfunction draw() {\n fill(fillVal);\n rect(25, 25, 50, 50);\n}\n\nfunction keyPressed() {\n if (keyCode === UP_ARROW) {\n fillVal = 255;\n } else if (keyCode === DOWN_ARROW) {\n fillVal = 0;\n }\n return false; // prevent default\n}\n</code></div>" 8704 ], 8705 "alt": "Grey rect center. turns white when up arrow pressed and black when down", 8706 "class": "p5", 8707 "module": "Events", 8708 "submodule": "Keyboard" 8709 }, 8710 { 8711 "file": "src/events/keyboard.js", 8712 "line": 107, 8713 "description": "<p>The keyPressed() function is called once every time a key is pressed. The\nkeyCode for the key that was pressed is stored in the keyCode variable.\n<br><br>\nFor non-ASCII keys, use the keyCode variable. You can check if the keyCode\nequals BACKSPACE, DELETE, ENTER, RETURN, TAB, ESCAPE, SHIFT, CONTROL,\nOPTION, ALT, UP_ARROW, DOWN_ARROW, LEFT_ARROW, RIGHT_ARROW.\n<br><br>\nFor ASCII keys that was pressed is stored in the key variable. However, it\ndoes not distinguish between uppercase and lowercase. For this reason, it\nis recommended to use keyTyped() to read the key variable, in which the\ncase of the variable will be distinguished.\n<br><br>\nBecause of how operating systems handle key repeats, holding down a key\nmay cause multiple calls to keyTyped() (and keyReleased() as well). The\nrate of repeat is set by the operating system and how each computer is\nconfigured.<br><br>\nBrowsers may have different default\nbehaviors attached to various key events. To prevent any default\nbehavior for this event, add "return false" to the end of the method.</p>\n", 8714 "itemtype": "method", 8715 "name": "keyPressed", 8716 "example": [ 8717 "\n<div>\n<code>\nvar value = 0;\nfunction draw() {\n fill(value);\n rect(25, 25, 50, 50);\n}\nfunction keyPressed() {\n if (value === 0) {\n value = 255;\n } else {\n value = 0;\n }\n}\n</code>\n</div>\n<div>\n<code>\nvar value = 0;\nfunction draw() {\n fill(value);\n rect(25, 25, 50, 50);\n}\nfunction keyPressed() {\n if (keyCode === LEFT_ARROW) {\n value = 255;\n } else if (keyCode === RIGHT_ARROW) {\n value = 0;\n }\n}\n</code>\n</div>\n<div class=\"norender\">\n<code>\nfunction keyPressed() {\n // Do something\n return false; // prevent any default behaviour\n}\n</code>\n</div>" 8718 ], 8719 "alt": "black rect center. turns white when key pressed and black when released\nblack rect center. turns white when left arrow pressed and black when right.", 8720 "class": "p5", 8721 "module": "Events", 8722 "submodule": "Keyboard" 8723 }, 8724 { 8725 "file": "src/events/keyboard.js", 8726 "line": 198, 8727 "description": "<p>The keyReleased() function is called once every time a key is released.\nSee key and keyCode for more information.<br><br>\nBrowsers may have different default\nbehaviors attached to various key events. To prevent any default\nbehavior for this event, add "return false" to the end of the method.</p>\n", 8728 "itemtype": "method", 8729 "name": "keyReleased", 8730 "example": [ 8731 "\n<div>\n<code>\nvar value = 0;\nfunction draw() {\n fill(value);\n rect(25, 25, 50, 50);\n}\nfunction keyReleased() {\n if (value === 0) {\n value = 255;\n } else {\n value = 0;\n }\n return false; // prevent any default behavior\n}\n</code>\n</div>" 8732 ], 8733 "alt": "black rect center. turns white when key pressed and black when pressed again", 8734 "class": "p5", 8735 "module": "Events", 8736 "submodule": "Keyboard" 8737 }, 8738 { 8739 "file": "src/events/keyboard.js", 8740 "line": 254, 8741 "description": "<p>The keyTyped() function is called once every time a key is pressed, but\naction keys such as Ctrl, Shift, and Alt are ignored. The most recent\nkey pressed will be stored in the key variable.\n<br><br>\nBecause of how operating systems handle key repeats, holding down a key\nwill cause multiple calls to keyTyped() (and keyReleased() as well). The\nrate of repeat is set by the operating system and how each computer is\nconfigured.<br><br>\nBrowsers may have different default behaviors attached to various key\nevents. To prevent any default behavior for this event, add "return false"\nto the end of the method.</p>\n", 8742 "itemtype": "method", 8743 "name": "keyTyped", 8744 "example": [ 8745 "\n<div>\n<code>\nvar value = 0;\nfunction draw() {\n fill(value);\n rect(25, 25, 50, 50);\n}\nfunction keyTyped() {\n if (key === 'a') {\n value = 255;\n } else if (key === 'b') {\n value = 0;\n }\n // uncomment to prevent any default behavior\n // return false;\n}\n</code>\n</div>" 8746 ], 8747 "alt": "black rect center. turns white when 'a' key typed and black when 'b' pressed", 8748 "class": "p5", 8749 "module": "Events", 8750 "submodule": "Keyboard" 8751 }, 8752 { 8753 "file": "src/events/keyboard.js", 8754 "line": 308, 8755 "description": "<p>The onblur function is called when the user is no longer focused\non the p5 element. Because the keyup events will not fire if the user is\nnot focused on the element we must assume all keys currently down have\nbeen released.</p>\n", 8756 "class": "p5", 8757 "module": "Events", 8758 "submodule": "Keyboard" 8759 }, 8760 { 8761 "file": "src/events/keyboard.js", 8762 "line": 318, 8763 "description": "<p>The keyIsDown() function checks if the key is currently down, i.e. pressed.\nIt can be used if you have an object that moves, and you want several keys\nto be able to affect its behaviour simultaneously, such as moving a\nsprite diagonally. You can put in any number representing the keyCode of\nthe key, or use any of the variable keyCode names listed\n<a href=\"http://p5js.org/reference/#p5/keyCode\">here</a>.</p>\n", 8764 "itemtype": "method", 8765 "name": "keyIsDown", 8766 "params": [ 8767 { 8768 "name": "code", 8769 "description": "<p>The key to check for.</p>\n", 8770 "type": "Number" 8771 } 8772 ], 8773 "return": { 8774 "description": "whether key is down or not", 8775 "type": "Boolean" 8776 }, 8777 "example": [ 8778 "\n<div><code>\nvar x = 100;\nvar y = 100;\n\nfunction setup() {\n createCanvas(512, 512);\n}\n\nfunction draw() {\n if (keyIsDown(LEFT_ARROW)) {\n x -= 5;\n }\n\n if (keyIsDown(RIGHT_ARROW)) {\n x += 5;\n }\n\n if (keyIsDown(UP_ARROW)) {\n y -= 5;\n }\n\n if (keyIsDown(DOWN_ARROW)) {\n y += 5;\n }\n\n clear();\n fill(255, 0, 0);\n ellipse(x, y, 50, 50);\n}\n</code></div>" 8779 ], 8780 "alt": "50x50 red ellipse moves left, right, up and down with arrow presses.", 8781 "class": "p5", 8782 "module": "Events", 8783 "submodule": "Keyboard" 8784 }, 8785 { 8786 "file": "src/events/mouse.js", 8787 "line": 22, 8788 "description": "<p>The system variable mouseX always contains the current horizontal\nposition of the mouse, relative to (0, 0) of the canvas. If touch is\nused instead of mouse input, mou
8788seX will hold the x value of the most\nrecent touch point.</p>\n", 8789 "itemtype": "property", 8790 "name": "mouseX", 8791 "type": "Number", 8792 "readonly": "", 8793 "example": [ 8794 "\n<div>\n<code>\n// Move the mouse across the canvas\nfunction draw() {\n background(244, 248, 252);\n line(mouseX, 0, mouseX, 100);\n}\n</code>\n</div>" 8795 ], 8796 "alt": "horizontal black line moves left and right with mouse x-position", 8797 "class": "p5", 8798 "module": "Events", 8799 "submodule": "Mouse" 8800 }, 8801 { 8802 "file": "src/events/mouse.js", 8803 "line": 48, 8804 "description": "<p>The system variable mouseY always contains the current vertical position\nof the mouse, relative to (0, 0) of the canvas. If touch is\nused instead of mouse input, mouseY will hold the y value of the most\nrecent touch point.</p>\n", 8805 "itemtype": "property", 8806 "name": "mouseY", 8807 "type": "Number", 8808 "readonly": "", 8809 "example": [ 8810 "\n<div>\n<code>\n// Move the mouse across the canvas\nfunction draw() {\n background(244, 248, 252);\n line(0, mouseY, 100, mouseY);\n}\n</code>\n</div>" 8811 ], 8812 "alt": "vertical black line moves up and down with mouse y-position", 8813 "class": "p5", 8814 "module": "Events", 8815 "submodule": "Mouse" 8816 }, 8817 { 8818 "file": "src/events/mouse.js", 8819 "line": 74, 8820 "description": "<p>The system variable pmouseX always contains the horizontal position of\nthe mouse or finger in the frame previous to the current frame, relative to\n(0, 0) of the canvas.</p>\n", 8821 "itemtype": "property", 8822 "name": "pmouseX", 8823 "type": "Number", 8824 "readonly": "", 8825 "example": [ 8826 "\n<div>\n<code>\n// Move the mouse across the canvas to leave a trail\nfunction setup() {\n //slow down the frameRate to make it more visible\n frameRate(10);\n}\n\nfunction draw() {\n background(244, 248, 252);\n line(mouseX, mouseY, pmouseX, pmouseY);\n print(pmouseX + ' -> ' + mouseX);\n}\n</code>\n</div>" 8827 ], 8828 "alt": "line trail is created from cursor movements. faster movement make longer line.", 8829 "class": "p5", 8830 "module": "Events", 8831 "submodule": "Mouse" 8832 }, 8833 { 8834 "file": "src/events/mouse.js", 8835 "line": 105, 8836 "description": "<p>The system variable pmouseY always contains the vertical position of the\nmouse or finger in the frame previous to the current frame, relative to\n(0, 0) of the canvas.</p>\n", 8837 "itemtype": "property", 8838 "name": "pmouseY", 8839 "type": "Number", 8840 "readonly": "", 8841 "example": [ 8842 "\n<div>\n<code>\nfunction draw() {\n background(237, 34, 93);\n fill(0);\n //draw a square only if the mouse is not moving\n if (mouseY === pmouseY && mouseX === pmouseX) {\n rect(20, 20, 60, 60);\n }\n\n print(pmouseY + ' -> ' + mouseY);\n}\n</code>\n</div>" 8843 ], 8844 "alt": "60x60 black rect center, fuschia background. rect flickers on mouse movement", 8845 "class": "p5", 8846 "module": "Events", 8847 "submodule": "Mouse" 8848 }, 8849 { 8850 "file": "src/events/mouse.js", 8851 "line": 135, 8852 "description": "<p>The system variable winMouseX always contains the current horizontal\nposition of the mouse, relative to (0, 0) of the window.</p>\n", 8853 "itemtype": "property", 8854 "name": "winMouseX", 8855 "type": "Number", 8856 "readonly": "", 8857 "example": [ 8858 "\n<div>\n<code>\nvar myCanvas;\n\nfunction setup() {\n //use a variable to store a pointer to the canvas\n myCanvas = createCanvas(100, 100);\n}\n\nfunction draw() {\n background(237, 34, 93);\n fill(0);\n\n //move the canvas to the horizontal mouse position\n //rela tive to the window\n myCanvas.position(winMouseX + 1, windowHeight / 2);\n\n //the y of the square is relative to the canvas\n rect(20, mouseY, 60, 60);\n}\n</code>\n</div>" 8859 ], 8860 "alt": "60x60 black rect y moves with mouse y and fuschia canvas moves with mouse x", 8861 "class": "p5", 8862 "module": "Events", 8863 "submodule": "Mouse" 8864 }, 8865 { 8866 "file": "src/events/mouse.js", 8867 "line": 172, 8868 "description": "<p>The system variable winMouseY always contains the current vertical\nposition of the mouse, relative to (0, 0) of the window.</p>\n", 8869 "itemtype": "property", 8870 "name": "winMouseY", 8871 "type": "Number", 8872 "readonly": "", 8873 "example": [ 8874 "\n<div>\n<code>\nvar myCanvas;\n\nfunction setup() {\n //use a variable to store a pointer to the canvas\n myCanvas = createCanvas(100, 100);\n}\n\nfunction draw() {\n background(237, 34, 93);\n fill(0);\n\n //move the canvas to the vertical mouse position\n //rel ative to the window\n myCanvas.position(windowWidth / 2, winMouseY
8874+ 1);\n\n //the x of the square is relative to the canvas\n rect(mouseX, 20, 60, 60);\n}\n</code>\n</div>" 8875 ], 8876 "alt": "60x60 black rect x moves with mouse x and fuschia canvas y moves with mouse y", 8877 "class": "p5", 8878 "module": "Events", 8879 "submodule": "Mouse" 8880 }, 8881 { 8882 "file": "src/events/mouse.js", 8883 "line": 209, 8884 "description": "<p>The system variable pwinMouseX always contains the horizontal position\nof the mouse in the frame previous to the current frame, relative to\n(0, 0) of the window.</p>\n", 8885 "itemtype": "property", 8886 "name": "pwinMouseX", 8887 "type": "Number", 8888 "readonly": "", 8889 "example": [ 8890 "\n<div>\n<code>\nvar myCanvas;\n\nfunction setup() {\n //use a variable to store a pointer to the canvas\n myCanvas = createCanvas(100, 100);\n noStroke();\n fill(237, 34, 93);\n}\n\nfunction draw() {\n clear();\n //the difference between previous and\n //current x position is the horizontal mouse speed\n var speed = abs(winMouseX - pwinMouseX);\n //change the size of the circle\n //according to the horizontal speed\n ellipse(50, 50, 10 + speed * 5, 10 + speed * 5);\n //move the canvas to the mouse position\n myCanvas.position(winMouseX + 1, winMouseY + 1);\n}\n</code>\n</div>" 8891 ], 8892 "alt": "fuschia ellipse moves with mouse x and y. Grows and shrinks with mouse speed", 8893 "class": "p5", 8894 "module": "Events", 8895 "submodule": "Mouse" 8896 }, 8897 { 8898 "file": "src/events/mouse.js", 8899 "line": 249, 8900 "description": "<p>The system variable pwinMouseY always contains the vertical position of\nthe mouse in the frame previous to the current frame, relative to (0, 0)\nof the window.</p>\n", 8901 "itemtype": "property", 8902 "name": "pwinMouseY", 8903 "type": "Number", 8904 "readonly": "", 8905 "example": [ 8906 "\n<div>\n<code>\nvar myCanvas;\n\nfunction setup() {\n //use a variable to store a pointer to the canvas\n myCanvas = createCanvas(100, 100);\n noStroke();\n fill(237, 34, 93);\n}\n\nfunction draw() {\n clear();\n //the difference between previous and\n //current y position is the vertical mouse speed\n var speed = abs(winMouseY - pwinMouseY);\n //change the size of the circle\n //according to the vertical speed\n ellipse(50, 50, 10 + speed * 5, 10 + speed * 5);\n //move the canvas to the mouse position\n myCanvas.position(winMouseX + 1, winMouseY + 1);\n}\n</code>\n</div>" 8907 ], 8908 "alt": "fuschia ellipse moves with mouse x and y. Grows and shrinks with mouse speed", 8909 "class": "p5", 8910 "module": "Events", 8911 "submodule": "Mouse" 8912 }, 8913 { 8914 "file": "src/events/mouse.js", 8915 "line": 290, 8916 "description": "<p>Processing automatically tracks if the mouse button is pressed and which\nbutton is pressed. The value of the system variable mouseButton is either\nLEFT, RIGHT, or CENTER depending on which button was pressed last.\nWarning: different browsers may track mouseButton differently.</p>\n", 8917 "itemtype": "property", 8918 "name": "mouseButton", 8919 "type": "Constant", 8920 "readonly": "", 8921 "example": [ 8922 "\n<div>\n<code>\nfunction draw() {\n background(237, 34, 93);\n fill(0);\n\n if (mouseIsPressed) {\n if (mouseButton === LEFT) {\n ellipse(50, 50, 50, 50);\n }\n if (mouseButton === RIGHT) {\n rect(25, 25, 50, 50);\n }\n if (mouseButton === CENTER) {\n triangle(23, 75, 50, 20, 78, 75);\n }\n }\n\n print(mouseButton);\n}\n</code>\n</div>" 8923 ], 8924 "alt": "50x50 black ellipse appears on center of fuschia canvas on mouse click/press.", 8925 "class": "p5", 8926 "module": "Events", 8927 "submodule": "Mouse" 8928 }, 8929 { 8930 "file": "src/events/mouse.js", 8931 "line": 329, 8932 "description": "<p>The boolean system variable mouseIsPressed is true if the mouse is pressed\nand false if not.</p>\n", 8933 "itemtype": "property", 8934 "name": "mouseIsPressed", 8935 "type": "Boolean", 8936 "readonly": "", 8937 "example": [ 8938 "\n<div>\n<code>\nfunction draw() {\n background(237, 34, 93);\n fill(0);\n\n if (mouseIsPressed) {\n ellipse(50, 50, 50, 50);\n } else {\n rect(25, 25, 50, 50);\n }\n\n print(mouseIsPressed);\n}\n</code>\n</div>" 8939 ],
8940 "alt": "black 50x50 rect becomes ellipse with mouse click/press. fuschia background.", 8941 "class": "p5", 8942 "module": "Events", 8943 "submodule": "Mouse" 8944 }, 8945 { 8946 "file": "src/events/mouse.js", 8947 "line": 418, 8948 "description": "<p>The mouseMoved() function is called every time the mouse moves and a mouse\nbutton is not pressed.<br><br>\nBrowsers may have different default\nbehaviors attached to various mouse events. To prevent any default\nbehavior for this event, add "return false" to the end of the method.</p>\n", 8949 "itemtype": "method", 8950 "name": "mouseMoved", 8951 "example": [ 8952 "\n<div>\n<code>\n// Move the mouse across the page\n// to change its value\n\nvar value = 0;\nfunction draw() {\n fill(value);\n rect(25, 25, 50, 50);\n}\nfunction mouseMoved() {\n value = value + 5;\n if (value > 255) {\n value = 0;\n }\n}\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\nfunction mouseMoved() {\n ellipse(mouseX, mouseY, 5, 5);\n // prevent default\n return false;\n}\n</code>\n</div>" 8953 ], 8954 "alt": "black 50x50 rect becomes lighter with mouse movements until white then resets\nno image displayed", 8955 "class": "p5", 8956 "module": "Events", 8957 "submodule": "Mouse" 8958 }, 8959 { 8960 "file": "src/events/mouse.js", 8961 "line": 462, 8962 "description": "<p>The mouseDragged() function is called once every time the mouse moves and\na mouse button is pressed. If no mouseDragged() function is defined, the\ntouchMoved() function will be called instead if it is defined.<br><br>\nBrowsers may have different default\nbehaviors attached to various mouse events. To prevent any default\nbehavior for this event, add "return false" to the end of the method.</p>\n", 8963 "itemtype": "method", 8964 "name": "mouseDragged", 8965 "example": [ 8966 "\n<div>\n<code>\n// Drag the mouse across the page\n// to change its value\n\nvar value = 0;\nfunction draw() {\n fill(value);\n rect(25, 25, 50, 50);\n}\nfunction mouseDragged() {\n value = value + 5;\n if (value > 255) {\n value = 0;\n }\n}\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\nfunction mouseDragged() {\n ellipse(mouseX, mouseY, 5, 5);\n // prevent default\n return false;\n}\n</code>\n</div>" 8967 ], 8968 "alt": "black 50x50 rect turns lighter with mouse click and drag until white, resets\nno image displayed", 8969 "class": "p5", 8970 "module": "Events", 8971 "submodule": "Mouse" 8972 }, 8973 { 8974 "file": "src/events/mouse.js", 8975 "line": 532, 8976 "description": "<p>The mousePressed() function is called once after every time a mouse button\nis pressed. The mouseButton variable (see the related reference entry)\ncan be used to determine which button has been pressed. If no\nmousePressed() function is defined, the touchStarted() function will be\ncalled instead if it is defined.<br><br>\nBrowsers may have different default\nbehaviors attached to various mouse events. To prevent any default\nbehavior for this event, add "return false" to the end of the method.</p>\n", 8977 "itemtype": "method", 8978 "name": "mousePressed", 8979 "example": [ 8980 "\n<div>\n<code>\n// Click within the image to change\n// the value of the rectangle\n\nvar value = 0;\nfunction draw() {\n fill(value);\n rect(25, 25, 50, 50);\n}\nfunction mousePressed() {\n if (value === 0) {\n value = 255;\n } else {\n value = 0;\n }\n}\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\nfunction mousePressed() {\n ellipse(mouseX, mouseY, 5, 5);\n // prevent default\n return false;\n}\n</code>\n</div>" 8981 ], 8982 "alt": "black 50x50 rect turns white with mouse click/press.\nno image displayed", 8983 "class": "p5", 8984 "module": "Events", 8985 "submodule": "Mouse" 8986 }, 8987 { 8988 "file": "src/events/mouse.js", 8989 "line": 598, 8990 "description": "<p>The mouseReleased() function is called every time a mouse button is\nreleased. If no mouseReleased() function is defined, the touchEnded()\nfunction will be called instead if it is defined.<br><br>\nBrowsers may have different default\nbehaviors attached to various mouse events. To prevent any default\nbehavior for this event, add "return false" to the end of the method.</p>\n", 8991 "itemtype": "method", 8992 "name": "mouseReleased", 8993 "example": [ 8994 "\n<div>\n<code>\n// Click within the image to change\n// the value of the rectangle\n/
8994/ after the mouse has been clicked\n\nvar value = 0;\nfunction draw() {\n fill(value);\n rect(25, 25, 50, 50);\n}\nfunction mouseReleased() {\n if (value === 0) {\n value = 255;\n } else {\n value = 0;\n }\n}\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\nfunction mouseReleased() {\n ellipse(mouseX, mouseY, 5, 5);\n // prevent default\n return false;\n}\n</code>\n</div>" 8995 ], 8996 "alt": "black 50x50 rect turns white with mouse click/press.\nno image displayed", 8997 "class": "p5", 8998 "module": "Events", 8999 "submodule": "Mouse" 9000 }, 9001 { 9002 "file": "src/events/mouse.js", 9003 "line": 665, 9004 "description": "<p>The mouseClicked() function is called once after a mouse button has been\npressed and then released.<br><br>\nBrowsers handle clicks differently, so this function is only guaranteed to be\nrun when the left mouse button is clicked. To handle other mouse buttons\nbeing pressed or released, see mousePressed() or mouseReleased().<br><br>\nBrowsers may have different default\nbehaviors attached to various mouse events. To prevent any default\nbehavior for this event, add "return false" to the end of the method.</p>\n", 9005 "itemtype": "method", 9006 "name": "mouseClicked", 9007 "example": [ 9008 "\n<div>\n<code>\n// Click within the image to change\n// the value of the rectangle\n// after the mouse has been clicked\n\nvar value = 0;\nfunction draw() {\n fill(value);\n rect(25, 25, 50, 50);\n}\n\nfunction mouseClicked() {\n if (value === 0) {\n value = 255;\n } else {\n value = 0;\n }\n}\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\nfunction mouseClicked() {\n ellipse(mouseX, mouseY, 5, 5);\n // prevent default\n return false;\n}\n</code>\n</div>" 9009 ], 9010 "alt": "black 50x50 rect turns white with mouse click/press.\nno image displayed", 9011 "class": "p5", 9012 "module": "Events", 9013 "submodule": "Mouse" 9014 }, 9015 { 9016 "file": "src/events/mouse.js", 9017 "line": 724, 9018 "description": "<p>The doubleClicked() function is executed every time a event\nlistener has detected a dblclick event which is a part of the\nDOM L3 specification. The doubleClicked event is fired when a\npointing device button (usually a mouse's primary button)\nis clicked twice on a single element. For more info on the\ndblclick event refer to mozilla's documentation here:\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/Events/dblclick\">https://developer.mozilla.org/en-US/docs/Web/Events/dblclick</a></p>\n", 9019 "itemtype": "method", 9020 "name": "doubleClicked", 9021 "example": [ 9022 "\n<div>\n<code>\n// Click within the image to change\n// the value of the rectangle\n// after the mouse has been double clicked\n\nvar value = 0;\nfunction draw() {\n fill(value);\n rect(25, 25, 50, 50);\n}\n\nfunction doubleClicked() {\n if (value === 0) {\n value = 255;\n } else {\n value = 0;\n }\n}\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\nfunction doubleClicked() {\n ellipse(mouseX, mouseY, 5, 5);\n // prevent default\n return false;\n}\n</code>\n</div>" 9023 ], 9024 "alt": "black 50x50 rect turns white with mouse doubleClick/press.\nno image displayed", 9025 "class": "p5", 9026 "module": "Events", 9027 "submodule": "Mouse" 9028 }, 9029 { 9030 "file": "src/events/mouse.js", 9031 "line": 782, 9032 "description": "<p>The function mouseWheel() is executed every time a vertical mouse wheel\nevent is detected either triggered by an actual mouse wheel or by a\ntouchpad.<br><br>\nThe event.delta property returns the amount the mouse wheel\nhave scrolled. The values can be positive or negative depending on the\nscroll direction (on OS X with "natural" scrolling enabled, the signs\nare inverted).<br><br>\nBrowsers may have different default behaviors attached to various\nmouse events. To prevent any default behavior for this event, add\n"return false" to the end of the method.<br><br>\nDue to the current support of the "wheel" event on Safari, the function\nmay only work as expected if "return false" is included while using Safari.</p>\n", 9033 "itemtype": "method", 9034 "name": "mouseWheel", 9035 "example": [ 9036 "\n<div>\n<code>\nvar pos = 25;\n\nfunction draw() {\n background(237, 34, 93);\n fill(0);\n rect(25, pos, 50, 50);\n}\n\nfunction mouseWheel(event) {\n print(event.delta);\n //move the square according to the vertical scroll amount\n pos += event.delta;\n //uncomment to block page scrolling\n //return false;\n}\n</code>\n</div>" 9037 ],
9038 "alt": "black 50x50 rect moves up and down with vertical scroll. fuschia background", 9039 "class": "p5", 9040 "module": "Events", 9041 "submodule": "Mouse" 9042 }, 9043 { 9044 "file": "src/events/touch.js", 9045 "line": 12, 9046 "description": "<p>The system variable touches[] contains an array of the positions of all\ncurrent touch points, relative to (0, 0) of the canvas, and IDs identifying a\nunique touch as it moves. Each element in the array is an object with x, y,\nand id properties.</p>\n<p>The touches[] array is not supported on Safari and IE on touch-based\ndesktops (laptops).</p>\n", 9047 "itemtype": "property", 9048 "name": "touches", 9049 "type": "Object[]", 9050 "readonly": "", 9051 "class": "p5", 9052 "module": "Events", 9053 "submodule": "Touch" 9054 }, 9055 { 9056 "file": "src/events/touch.js", 9057 "line": 57, 9058 "description": "<p>The touchStarted() function is called once after every time a touch is\nregistered. If no touchStarted() function is defined, the mousePressed()\nfunction will be called instead if it is defined.<br><br>\nBrowsers may have different default behaviors attached to various touch\nevents. To prevent any default behavior for this event, add "return false"\nto the end of the method.</p>\n", 9059 "itemtype": "method", 9060 "name": "touchStarted", 9061 "example": [ 9062 "\n<div>\n<code>\n// Touch within the image to change\n// the value of the rectangle\n\nvar value = 0;\nfunction draw() {\n fill(value);\n rect(25, 25, 50, 50);\n}\nfunction touchStarted() {\n if (value === 0) {\n value = 255;\n } else {\n value = 0;\n }\n}\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\nfunction touchStarted() {\n ellipse(mouseX, mouseY, 5, 5);\n // prevent default\n return false;\n}\n</code>\n</div>" 9063 ], 9064 "alt": "50x50 black rect turns white with touch event.\nno image displayed", 9065 "class": "p5", 9066 "module": "Events", 9067 "submodule": "Touch" 9068 }, 9069 { 9070 "file": "src/events/touch.js", 9071 "line": 120, 9072 "description": "<p>The touchMoved() function is called every time a touch move is registered.\nIf no touchMoved() function is defined, the mouseDragged() function will\nbe called instead if it is defined.<br><br>\nBrowsers may have different default behaviors attached to various touch\nevents. To prevent any default behavior for this event, add "return false"\nto the end of the method.</p>\n", 9073 "itemtype": "method", 9074 "name": "touchMoved", 9075 "example": [ 9076 "\n<div>\n<code>\n// Move your finger across the page\n// to change its value\n\nvar value = 0;\nfunction draw() {\n fill(value);\n rect(25, 25, 50, 50);\n}\nfunction touchMoved() {\n value = value + 5;\n if (value > 255) {\n value = 0;\n }\n}\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\nfunction touchMoved() {\n ellipse(mouseX, mouseY, 5, 5);\n // prevent default\n return false;\n}\n</code>\n</div>" 9077 ], 9078 "alt": "50x50 black rect turns lighter with touch until white. resets\nno image displayed", 9079 "class": "p5", 9080 "module": "Events", 9081 "submodule": "Touch" 9082 }, 9083 { 9084 "file": "src/events/touch.js", 9085 "line": 182, 9086 "description": "<p>The touchEnded() function is called every time a touch ends. If no\ntouchEnded() function is defined, the mouseReleased() function will be\ncalled instead if it is defined.<br><br>\nBrowsers may have different default behaviors attached to various touch\nevents. To prevent any default behavior for this event, add "return false"\nto the end of the method.</p>\n", 9087 "itemtype": "method", 9088 "name": "touchEnded", 9089 "example": [ 9090 "\n<div>\n<code>\n// Release touch within the image to\n// change the value of the rectangle\n\nvar value = 0;\nfunction draw() {\n fill(value);\n rect(25, 25, 50, 50);\n}\nfunction touchEnded() {\n if (value === 0) {\n value = 255;\n } else {\n value = 0;\n }\n}\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\nfunction touchEnded() {\n ellipse(mouseX, mouseY, 5, 5);\n // prevent default\n return false;\n}\n</code>\n</div>" 9091 ], 9092 "alt": "50x50 black rect turns white with touch.\nno image displayed", 9093 "class": "p5", 9094 "module": "Events", 9095 "submodule": "Touch" 9096 }, 9097 { 9098 "file": "src/image/filters.js", 9099 "line": 3, 9100 "description": "<p>This module defines the filters for use with image buffers.</p>\n<p>This module is basically a collection of functions stored in an object\nas opposed to modules. The functions are destructive, modifying\nthe passed in canvas rather than creating a copy.</p>\n<p>Generally speaking users of this module will use the Filters.apply method\non a canvas to create an effect.</p>\n<p>A number of functions are borrowed/adapted from\n<a href=\"http://www.html5rocks.com/en/tutorials/canvas/imagefilters/\">http://www.html5rocks.com/en/tutorials/canvas/imagefilters/</a>\nor the java processing implementation.</p>\n", 9101 "class": "p5", 9102 "module": "Events" 9103 }, 9104 { 9105 "file": "src/image/image.js", 9106 "line": 8, 9107 "description": "<p>This module defines the p5 methods for the p5.Image class\nfor drawing images to the main display canvas.</p>\n", 9108 "class": "p5", 9109 "module": "Image", 9110 "submodule": "Image" 9111 }, 9112 { 9113 "file": "src/image/image.js", 9114 "line": 18, 9115 "description": "<p>Creates a new p5.Image (the datatype for storing images). This provides a\nfresh buffer of pixels to play with. Set the size of the buffer with the\nwidth and height parameters.\n<br><br>\n.pixels gives access to an array containing the values for all the pixels\nin the display window.\nThese values are numbers. This array is the size (including an appropriate\nfactor for the pixelDensity) of the display window x4,\nrepresenting the R, G, B, A values in order for each pixel, mov
9115ing from\nleft to right across each row, then down each column. See .pixels for\nmore info. It may also be simpler to use set() or get().\n<br><br>\nBefore accessing the pixels of an image, the data must loaded with the\nloadPixels() function. After the array data has been modified, the\nupdatePixels() function must be run to update the changes.</p>\n", 9116 "itemtype": "method", 9117 "name": "createImage", 9118 "params": [ 9119 { 9120 "name": "width", 9121 "description": "<p>width in pixels</p>\n", 9122 "type": "Integer" 9123 }, 9124 { 9125 "name": "height", 9126 "description": "<p>height in pixels</p>\n", 9127 "type": "Integer" 9128 } 9129 ], 9130 "return": { 9131 "description": "the p5.Image object", 9132 "type": "p5.Image" 9133 }, 9134 "example": [ 9135 "\n<div>\n<code>\nvar img = createImage(66, 66);\nimg.loadPixels();\nfor (var i = 0; i < img.width; i++) {\n for (var j = 0; j < img.height; j++) {\n img.set(i, j, color(0, 90, 102));\n }\n}\nimg.updatePixels();\nimage(img, 17, 17);\n</code>\n</div>\n\n<div>\n<code>\nvar img = createImage(66, 66);\nimg.loadPixels();\nfor (var i = 0; i < img.width; i++) {\n for (var j = 0; j < img.height; j++) {\n img.set(i, j, color(0, 90, 102, (i % img.width) * 2));\n }\n}\nimg.updatePixels();\nimage(img, 17, 17);\nimage(img, 34, 34);\n</code>\n</div>\n\n<div>\n<code>\nvar pink = color(255, 102, 204);\nvar img = createImage(66, 66);\nimg.loadPixels();\nvar d = pixelDensity();\nvar halfImage = 4 * (width * d) * (height / 2 * d);\nfor (var i = 0; i < halfImage; i += 4) {\n img.pixels[i] = red(pink);\n img.pixels[i + 1] = green(pink);\n img.pixels[i + 2] = blue(pink);\n img.pixels[i + 3] = alpha(pink);\n}\nimg.updatePixels();\nimage(img, 17, 17);\n</code>\n</div>" 9136 ], 9137 "alt": "66x66 dark turquoise rect in center of canvas.\n2 gradated dark turquoise rects fade left. 1 center 1 bottom right of canvas\nno image displayed", 9138 "class": "p5", 9139 "module": "Image", 9140 "submodule": "Image" 9141 }, 9142 { 9143 "file": "src/image/image.js", 9144 "line": 98, 9145 "description": "<p>Save the current canvas as an image. In Safari, this will open the\nimage in the window and the user must provide their own\nfilename on save-as. Other browsers will either save the\nfile immediately, or prompt the user with a dialogue window.</p>\n", 9146 "itemtype": "method", 9147 "name": "saveCanvas", 9148 "example": [ 9149 "\n <div class='norender notest'><code>\n function setup() {\n var c = createCanvas(100, 100);\n background(255, 0, 0);\n saveCanvas(c, 'myCanvas', 'jpg');\n }\n </code></div>\n <div class='norender notest'><code>\n // note that this example has the same result as above\n // if no canvas is specified, defaults to main canvas\n function setup() {\n var c = createCanvas(100, 100);\n background(255, 0, 0);\n saveCanvas('myCanvas', 'jpg');\n\n // all of the following are valid\n saveCanvas(c, 'myCanvas', 'jpg');\n saveCanvas(c, 'myCanvas.jpg');\n saveCanvas(c, 'myCanvas');\n saveCanvas(c);\n saveCanvas('myCanvas', 'png');\n saveCanvas('myCanvas');\n saveCanvas();\n }\n </code></div>" 9150 ], 9151 "alt": "no image displayed\n no image displayed\n no image displayed", 9152 "class": "p5", 9153 "module": "Image", 9154 "submodule": "Image", 9155 "overloads": [ 9156 { 9157 "line": 98, 9158 "params": [ 9159 { 9160 "name": "selectedCanvas", 9161 "description": "<p>a variable\n representing a specific html5 canvas (optional)</p>\n", 9162 "type": "p5.Element|HTMLCanvasElement" 9163 }, 9164 { 9165 "name": "filename", 9166 "description": "", 9167 "type": "String", 9168 "optional": true 9169 }, 9170 { 9171 "name": "extension", 9172 "description": "<p>'jpg' or 'png'</p>\n", 9173 "type": "String", 9174 "optional": true 9175 } 9176 ] 9177 }, 9178 { 9179 "line": 142, 9180 "params": [ 9181 { 9182 "name": "filename", 9183 "description": "", 9184 "type": "String", 9185 "optional": true 9186 }, 9187 { 9188 "name": "extension", 9189 "description": "", 9190 "type": "String", 9191 "optional": true 9192 } 9193 ] 9194 } 9195 ] 9196 }, 9197 { 9198 "file": "src/image/image.js", 9199 "line": 193, 9200 "description": "<p>Capture a sequence of frames that can be used to create a movie.\nAccepts a callback. For example, you may wish to
9200send the frames\nto a server where they can be stored or converted into a movie.\nIf no callback is provided, the browser will pop up save dialogues in an\nattempt to download all of the images that have just been created. With the\ncallback provided the image data isn't saved by default but instead passed\nas an argument to the callback function as an array of objects, with the\nsize of array equal to the total number of frames.</p>\n<p>Note that saveFrames() will only save the first 15 frames of an animation.\nTo export longer animations, you might look into a library like\n<a href=\"https://github.com/spite/ccapture.js/\">ccapture.js</a>.</p>\n", 9201 "itemtype": "method", 9202 "name": "saveFrames", 9203 "params": [ 9204 { 9205 "name": "filename", 9206 "description": "", 9207 "type": "String" 9208 }, 9209 { 9210 "name": "extension", 9211 "description": "<p>'jpg' or 'png'</p>\n", 9212 "type": "String" 9213 }, 9214 { 9215 "name": "duration", 9216 "description": "<p>Duration in seconds to save the frames for.</p>\n", 9217 "type": "Number" 9218 }, 9219 { 9220 "name": "framerate", 9221 "description": "<p>Framerate to save the frames in.</p>\n", 9222 "type": "Number" 9223 }, 9224 { 9225 "name": "callback", 9226 "description": "<p>A callback function that will be executed\n to handle the image data. This function\n should accept an array as argument. The\n array will contain the specified number of\n frames of objects. Each object has three\n properties: imageData - an\n image/octet-stream, filename and extension.</p>\n", 9227 "type": "Function(Array)", 9228 "optional": true 9229 } 9230 ], 9231 "example": [ 9232 "\n<div><code>\n function draw() {\n background(mouseX);\n }\n\n function mousePressed() {\n saveFrames('out', 'png', 1, 25, function(data) {\n print(data);\n });\n }\n</code></div>" 9233 ], 9234 "alt": "canvas background goes from light to dark with mouse x.", 9235 "class": "p5", 9236 "module": "Image", 9237 "submodule": "Image" 9238 }, 9239 { 9240 "file": "src/image/loading_displaying.js", 9241 "line": 17, 9242 "description": "<p>Loads an image from a path and creates a p5.Image from it.\n<br><br>\nThe image may not be immediately available for rendering\nIf you want to ensure that the image is ready before doing\nanything with it, place the loadImage() call in preload().\nYou may also supply a callback function to handle the image when it's ready.\n<br><br>\nThe path to the image should be relative to the HTML file\nthat links in your sketch. Loading an image from a URL or other\nremote location may be blocked due to your browser's built-in\nsecurity.</p>\n", 9243 "itemtype": "method", 9244 "name": "loadImage", 9245 "params": [ 9246 { 9247 "name": "path", 9248 "description": "<p>Path of the image to be loaded</p>\n", 9249 "type": "String" 9250 }, 9251 { 9252 "name": "successCallback", 9253 "description": "<p>Function to be called once\n the image is loaded. Will be passed the\n p5.Image.</p>\n", 9254 "type": "function(p5.Image)", 9255 "optional": true 9256 }, 9257 { 9258 "name": "failureCallback", 9259 "description": "<p>called with event error if\n the image fails to load.</p>\n", 9260 "type": "Function(Event)", 9261 "optional": true 9262 } 9263 ], 9264 "return": { 9265 "description": "the p5.Image object", 9266 "type": "p5.Image" 9267 }, 9268 "example": [ 9269 "\n<div>\n<code>\nvar img;\nfunction preload() {\n img = loadImage('assets/laDefense.jpg');\n}\nfunction setup() {\n image(img, 0, 0);\n}\n</code>\n</div>\n<div>\n<code>\nfunction setup() {\n // here we use a callback to display the image after loading\n loadImage('assets/laDefense.jpg', function(img) {\n image(img, 0, 0);\n });\n}\n</code>\n</div>" 9270 ], 9271 "alt": "image of the underside of a white umbrella and grided ceililng above\nimage of the underside of a white umbrella and grided ceililng above", 9272 "class": "p5", 9273 "module": "Image", 9274 "submodule": "Loading & Displaying" 9275 }, 9276 { 9277 "file": "src/image/loading_displaying.js", 9278 "line": 125, 9279 "description": "<p>Draw an image to the p5.js canvas.</p>\n<p>This function can be used with different numbers of parameters. The\nsimplest use requires only three parameters: img, x, and
9279yâwhere (x, y) is\nthe position of the image. Two more parameters can optionally be added to\nspecify the width and height of the image.</p>\n<p>This function can also be used with all eight Number parameters. To\ndifferentiate between all these parameters, p5.js uses the language of\n"destination rectangle" (which corresponds to "dx", "dy", etc.) and "source\nimage" (which corresponds to "sx", "sy", etc.) below. Specifying the\n"source image" dimensions can be useful when you want to display a\nsubsection of the source image instead of the whole thing. Here's a diagram\nto explain further:\n<img src=\"assets/drawImage.png\"></img></p>\n", 9280 "itemtype": "method", 9281 "name": "image", 9282 "example": [ 9283 "\n<div>\n<code>\nvar img;\nfunction preload() {\n img = loadImage('assets/laDefense.jpg');\n}\nfunction setup() {\n // Top-left corner of the img is at (0, 0)\n // Width and height are the img's original width and height\n image(img, 0, 0);\n}\n</code>\n</div>\n<div>\n<code>\nvar img;\nfunction preload() {\n img = loadImage('assets/laDefense.jpg');\n}\nfunction setup() {\n background(50);\n // Top-left corner of the img is at (10, 10)\n // Width and height are 50 x 50\n image(img, 10, 10, 50, 50);\n}\n</code>\n</div>\n<div>\n<code>\nfunction setup() {\n // Here, we use a callback to display the image after loading\n loadImage('assets/laDefense.jpg', function(img) {\n image(img, 0, 0);\n });\n}\n</code>\n</div>\n<div>\n<code>\nvar img;\nfunction preload() {\n img = loadImage('assets/gradient.png');\n}\nfunction setup() {\n // 1. Background image\n // Top-left corner of the img is at (0, 0)\n // Width and height are the img's original width and height, 100 x 100\n image(img, 0, 0);\n // 2. Top right image\n // Top-left corner of destination rectangle is at (50, 0)\n // Destination rectangle width and height are 40 x 20\n // The next parameters are relative to the source image:\n // - Starting at position (50, 50) on the source image, capture a 50 x 50\n // subsection\n // - Draw this subsection to fill the dimensions of the destination rectangle\n image(img, 50, 0, 40, 20, 50, 50, 50, 50);\n}\n</code>\n</div>" 9284 ], 9285 "alt": "image of the underside of a white umbrella and gridded ceiling above\nimage of the underside of a white umbrella and gridded ceiling above", 9286 "class": "p5", 9287 "module": "Image", 9288 "submodule": "Loading & Displaying", 9289 "overloads": [ 9290 { 9291 "line": 125, 9292 "params": [ 9293 { 9294 "name": "img", 9295 "description": "<p>the image to display</p>\n", 9296 "type": "p5.Image|p5.Element" 9297 }, 9298 { 9299 "name": "x", 9300 "description": "<p>the x-coordinate of the top-left corner of the image</p>\n", 9301 "type": "Number" 9302 }, 9303 { 9304 "name": "y", 9305 "description": "<p>the y-coordinate of the top-left corner of the image</p>\n", 9306 "type": "Number" 9307 }, 9308 { 9309 "name": "width", 9310 "description": "<p>the width to draw the image</p>\n", 9311 "type": "Number", 9312 "optional": true 9313 }, 9314 { 9315 "name": "height", 9316 "description": "<p>the height to draw the image</p>\n", 9317 "type": "Number", 9318 "optional": true 9319 } 9320 ] 9321 }, 9322 { 9323 "line": 213, 9324 "params": [ 9325 { 9326 "name": "img", 9327 "description": "", 9328 "type": "p5.Image|p5.Element" 9329 }, 9330 { 9331 "name": "dx", 9332 "description": "<p>the x-coordinate of the destination\n rectangle in which to draw the source image</p>\n", 9333 "type": "Number" 9334 }, 9335 { 9336 "name": "dy", 9337 "description": "<p>the y-coordinate of the destination\n rectangle in which to draw the source image</p>\n", 9338 "type": "Number" 9339 }, 9340 { 9341 "name": "dWidth", 9342 "description": "<p>the width of the destination rectangle</p>\n", 9343 "type": "Number" 9344 }, 9345 { 9346 "name": "dHeight", 9347 "description": "<p>the height of the destination rectangle</p>\n", 9348 "type": "Number" 9349 }, 9350 { 9351 "name": "sx", 9352 "description": "<p>the x-coordinate of the subsection of the source\nimage to draw into the destination rectangle</p>\n", 9353 "type": "Number" 9354 }, 9355 { 9356 "name": "sy", 9357 "description": "<p>the y-coordinate of the subsection of the source\nimage to draw into the destination rectangle</p>\n", 9358 "type": "Number" 9359 }, 9360 { 9361 "name": "sWidth", 9362 "description": "<p>the width of the subsection of the\n source image to draw into the destination\n rectangle</p>\n", 9363 "type": "Number", 9364 "optional": true 9365 }, 9366 { 9367 "name": "sHeight", 9368 "description": "<p>the height of the subsection of the\n source image to draw into the destination rectangle</p>\n", 9369 "type": "Number", 9370 "optional": true 9371 } 9372 ] 9373 } 9374 ] 9375 }, 9376 { 9377 "file": "src/image/loading_displaying.js", 9378 "line": 296, 9379 "description": "<p>Sets the fill value for displaying images. Images can be tinted to\nspecified colors or made transparent by including an alpha value.\n<br><br>\nTo apply transparency to an image without affecting its color, use\nwhite as the tint color and specify an alpha value. For instance,\ntint(255, 128) will make an image 50% transparent (assuming the default\nalpha range of 0-255, which can be changed with colorMode()).\n<br><br>\nThe value for the gray parameter must be less than or equal to the current\nmaximum value as specified by colorMode(). The default maximum value is\n255.</p>\n", 9380 "itemtype": "method", 9381 "name": "tint", 9382 "example": [ 9383 "\n<div>\n<code>\nvar img;\nfunction preload() {\n img = loadImage('assets/laDefense.jpg');\n}\nfunction setup() {\n image(img, 0, 0);\n tint(0, 153, 204); // Tint blue\n image(img, 50, 0);\n}\n</code>\n</div>\n\n<div>\n<code>\nvar img;\nfunction preload() {\n img = loadImage('assets/laDefense.jpg');\n}\nfunction setup() {\n image(img, 0, 0);\n tint(0, 153, 204, 126); // Tint blue and set transparency\n image(img, 50, 0);\n}\n</code>\n</div>\n\n<div>\n<code>\nvar img;\nfunction preload() {\n img = loadImage('assets/laDefense.jpg');\n}\nfunction setup() {\n image(img, 0, 0);\n tint(255, 126); // Apply transparency without changing color\n image(img, 50, 0);\n}\n</code>\n</div>" 9384 ], 9385 "alt": "2 side by side images of umbrella and ceiling, one image with blue tint\nImages of umbrella and ceiling, one half of image with blue tint\n2 side by side images of umbrella and ceiling, one image translucent", 9386 "class": "p5", 9387 "module": "Image", 9388 "submodule": "Loading & Displaying", 9389 "overloads": [ 9390 { 9391 "line": 296, 9392 "params": [ 9393 { 9394 "name": "v1", 9395 "description": "<p>red or hue value relative to\n the current color range</p>\n", 9396 "type": "Number" 9397 }, 9398 { 9399 "name": "v2", 9400 "description": "<p>
9400green or saturation value\n relative to the current color range</p>\n", 9401 "type": "Number" 9402 }, 9403 { 9404 "name": "v3", 9405 "description": "<p>blue or brightness value\n relative to the current color range</p>\n", 9406 "type": "Number" 9407 }, 9408 { 9409 "name": "alpha", 9410 "description": "", 9411 "type": "Number", 9412 "optional": true 9413 } 9414 ] 9415 }, 9416 { 9417 "line": 369, 9418 "params": [ 9419 { 9420 "name": "value", 9421 "description": "<p>a color string</p>\n", 9422 "type": "String" 9423 } 9424 ] 9425 }, 9426 { 9427 "line": 374, 9428 "params": [ 9429 { 9430 "name": "gray", 9431 "description": "<p>a gray value</p>\n", 9432 "type": "Number" 9433 }, 9434 { 9435 "name": "alpha", 9436 "description": "", 9437 "type": "Number", 9438 "optional": true 9439 } 9440 ] 9441 }, 9442 { 9443 "line": 380, 9444 "params": [ 9445 { 9446 "name": "values", 9447 "description": "<p>an array containing the red,green,blue &\n and alpha components of the color</p>\n", 9448 "type": "Number[]" 9449 } 9450 ] 9451 }, 9452 { 9453 "line": 386, 9454 "params": [ 9455 { 9456 "name": "color", 9457 "description": "<p>the tint color</p>\n", 9458 "type": "p5.Color" 9459 } 9460 ] 9461 } 9462 ] 9463 }, 9464 { 9465 "file": "src/image/loading_displaying.js", 9466 "line": 396, 9467 "description": "<p>Removes the current fill value for displaying images and reverts to\ndisplaying images with their original hues.</p>\n", 9468 "itemtype": "method", 9469 "name": "noTint", 9470 "example": [ 9471 "\n<div>\n<code>\nvar img;\nfunction preload() {\n img = loadImage('assets/bricks.jpg');\n}\nfunction setup() {\n tint(0, 153, 204); // Tint blue\n image(img, 0, 0);\n noTint(); // Disable tint\n image(img, 50, 0);\n}\n</code>\n</div>" 9472 ], 9473 "alt": "2 side by side images of bricks, left image with blue tint", 9474 "class": "p5", 9475 "module": "Image", 9476 "submodule": "Loading & Displaying" 9477 }, 9478 { 9479 "file": "src/image/loading_displaying.js", 9480 "line": 462, 9481 "description": "<p>Set image mode. Modifies the location from which images are drawn by\nchanging the way in which parameters given to image() are interpreted.\nThe default mode is imageMode(CORNER), which interprets the second and\nthird parameters of image() as the upper-left corner of the image. If\ntwo additional parameters are specified, they are used to set the image's\nwidth and height.\n<br><br>\nimageMode(CORNERS) interprets the second and third parameters of image()\nas the location of one corner, and the fourth and fifth parameters as the\nopposite corner.\n<br><br>\nimageMode(CENTER) interprets the second and third parameters of image()\nas the image's center point. If two additional parameters are specified,\nthey are used to set the image's width and height.</p>\n", 9482 "itemtype": "method", 9483 "name": "imageMode", 9484 "params": [ 9485 { 9486 "name": "mode", 9487 "description": "<p>either CORNER, CORNERS, or CENTER</p>\n", 9488 "type": "Constant" 9489 } 9490 ], 9491 "example": [ 9492 "\n\n<div>\n<code>\nvar img;\nfunction preload() {\n img = loadImage('assets/bricks.jpg');\n}\nfunction setup() {\n imageMode(CORNER);
9492\n image(img, 10, 10, 50, 50);\n}\n</code>\n</div>\n\n<div>\n<code>\nvar img;\nfunction preload() {\n img = loadImage('assets/bricks.jpg');\n}\nfunction setup() {\n imageMode(CORNERS);\n image(img, 10, 10, 90, 40);\n}\n</code>\n</div>\n\n<div>\n<code>\nvar img;\nfunction preload() {\n img = loadImage('assets/bricks.jpg');\n}\nfunction setup() {\n imageMode(CENTER);\n image(img, 50, 50, 80, 80);\n}\n</code>\n</div>" 9493 ], 9494 "alt": "small square image of bricks\nhorizontal rectangle image of bricks\nlarge square image of bricks", 9495 "class": "p5", 9496 "module": "Image", 9497 "submodule": "Loading & Displaying" 9498 }, 9499 { 9500 "file": "src/image/p5.Image.js", 9501 "line": 9, 9502 "description": "<p>This module defines the p5.Image class and P5 methods for\ndrawing images to the main display canvas.</p>\n", 9503 "class": "p5.Image", 9504 "module": "Image", 9505 "submodule": "Image" 9506 }, 9507 { 9508 "file": "src/image/p5.Image.js", 9509 "line": 90, 9510 "description": "<p>Image width.</p>\n", 9511 "itemtype": "property", 9512 "name": "width", 9513 "type": "Number", 9514 "readonly": "", 9515 "example": [ 9516 "\n<div><code>\nvar img;\nfunction preload() {\n img = loadImage('assets/rockies.jpg');\n}\n\nfunction setup() {\n createCanvas(100, 100);\n image(img, 0, 0);\n for (var i = 0; i < img.width; i++) {\n var c = img.get(i, img.height / 2);\n stroke(c);\n line(i, height / 2, i, height);\n }\n}\n</code></div>" 9517 ], 9518 "alt": "rocky mountains in top and horizontal lines in corresponding colors in bottom.", 9519 "class": "p5.Image", 9520 "module": "Image", 9521 "submodule": "Image" 9522 }, 9523 { 9524 "file": "src/image/p5.Image.js", 9525 "line": 117, 9526 "description": "<p>Image height.</p>\n", 9527 "itemtype": "property", 9528 "name": "height", 9529 "type": "Number", 9530 "readonly": "", 9531 "example": [ 9532 "\n<div><code>\nvar img;\nfunction preload() {\n img = loadImage('assets/rockies.jpg');\n}\n\nfunction setup() {\n createCanvas(100, 100);\n image(img, 0, 0);\n for (var i = 0; i < img.height; i++) {\n var c = img.get(img.width / 2, i);\n stroke(c);\n line(0, i, width / 2, i);\n }\n}\n</code></div>" 9533 ], 9534 "alt": "rocky mountains on right and vertical lines in corresponding colors on left.", 9535 "class": "p5.Image", 9536 "module": "Image", 9537 "submodule": "Image" 9538 }, 9539 { 9540 "file": "src/image/p5.Image.js", 9541 "line": 151, 9542 "description": "<p>Array containing the values for all the pixels in the display window.\nThese values are numbers. This array is the size (include an appropriate\nfactor for pixelDensity) of the display window x4,\nrepresenting the R, G, B, A values in order for each pixel, moving from\nleft to right across each row, then down each column. Retina and other\nhigh denisty displays may have more pixels[] (by a factor of\npixelDensity^2).\nFor example, if the image is 100x100 pixels, there will be 40,000. With\npixelDensity = 2, there will be 160,000. The first four values\n(indices 0-3) in the array will be the R, G, B, A values of the pixel at\n(0, 0). The second four values (indices 4-7) will contain the R, G, B, A\nvalues of the pixel at (1, 0). More generally, to set values for a pixel\nat (x, y):</p>\n<pre><code class=\"lang-javascript\">var d = pixelDensity();\nfor (var i = 0; i < d; i++) {\n for (var j = 0; j < d; j++) {\n // loop over\n idx = 4 * ((y * d + j) * width * d + (x * d + i
9542));\n pixels[idx] = r;\n pixels[idx+1] = g;\n pixels[idx+2] = b;\n pixels[idx+3] = a;\n }\n}\n</code></pre>\n<p><br><br>\nBefore accessing this array, the data must loaded with the loadPixels()\nfunction. After the array data has been modified, the updatePixels()\nfunction must be run to update the changes.</p>\n", 9543 "itemtype": "property", 9544 "name": "pixels", 9545 "type": "Number[]", 9546 "example": [ 9547 "\n<div>\n<code>\nvar img = createImage(66, 66);\nimg.loadPixels();\nfor (var i = 0; i < img.width; i++) {\n for (var j = 0; j < img.height; j++) {\n img.set(i, j, color(0, 90, 102));\n }\n}\nimg.updatePixels();\nimage(img, 17, 17);\n</code>\n</div>\n<div>\n<code>\nvar pink = color(255, 102, 204);\nvar img = createImage(66, 66);\nimg.loadPixels();\nfor (var i = 0; i < 4 * (width * height / 2); i += 4) {\n img.pixels[i] = red(pink);\n img.pixels[i + 1] = green(pink);\n img.pixels[i + 2] = blue(pink);\n img.pixels[i + 3] = alpha(pink);\n}\nimg.updatePixels();\nimage(img, 17, 17);\n</code>\n</div>" 9548 ], 9549 "alt": "66x66 turquoise rect in center of canvas\n66x66 pink rect in center of canvas", 9550 "class": "p5.Image", 9551 "module": "Image", 9552 "submodule": "Image" 9553 }, 9554 { 9555 "file": "src/image/p5.Image.js", 9556 "line": 221, 9557 "description": "<p>Helper fxn for sharing pixel methods</p>\n", 9558 "class": "p5.Image", 9559 "module": "Image", 9560 "submodule": "Image" 9561 }, 9562 { 9563 "file": "src/image/p5.Image.js", 9564 "line": 230, 9565 "description": "<p>Loads the pixels data for this image into the [pixels] attribute.</p>\n", 9566 "itemtype": "method", 9567 "name": "loadPixels", 9568 "example": [ 9569 "\n<div><code>\nvar myImage;\nvar halfImage;\n\nfunction preload() {\n myImage = loadImage('assets/rockies.jpg');\n}\n\nfunction setup() {\n myImage.loadPixels();\n halfImage = 4 * width * height / 2;\n for (var i = 0; i < halfImage; i++) {\n myImage.pixels[i + halfImage] = myImage.pixels[i];\n }\n myImage.updatePixels();\n}\n\nfunction draw() {\n image(myImage, 0, 0);\n}\n</code></div>" 9570 ], 9571 "alt": "2 images of rocky mountains vertically stacked", 9572 "class": "p5.Image", 9573 "module": "Image", 9574 "submodule": "Image" 9575 }, 9576 { 9577 "file": "src/image/p5.Image.js", 9578 "line": 266, 9579 "description": "<p>Updates the backing canvas for this image with the contents of\nthe [pixels] array.</p>\n", 9580 "itemtype": "method", 9581 "name": "updatePixels", 9582 "example": [ 9583 "\n<div><code>\nvar myImage;\nvar halfImage;\n\nfunction preload() {\n myImage = loadImage('assets/rockies.jpg');\n}\n\nfunction setup() {\n myImage.loadPixels();\n halfImage = 4 * width * height / 2;\n for (var i = 0; i < halfImage; i++) {\n myImage.pixels[i + halfImage] = myImage.pixels[i];\n }\n myImage.updatePixels();\n}\n\nfunction draw() {\n image(myImage, 0, 0);\n}\n</code></div>" 9584 ], 9585 "alt": "2 images of rocky mountains vertically stacked", 9586 "class": "p5.Image", 9587 "module": "Image", 9588 "submodule": "Image", 9589 "overloads": [ 9590 { 9591 "line": 266, 9592 "params": [ 9593 { 9594 "name": "x", 9595 "description": "<p>x-offset of the target update area for the\n underlying canvas</p>\n", 9596 "type": "Integer" 9597 }, 9598 { 9599 "name": "y", 9600 "description": "<p>y-offset of the target update area for the\n underlying canvas</p>\n", 9601 "type": "Integer" 9602 }, 9603 { 9604 "name": "w", 9605 "description": "<p>height of the target update area for the\n underlying canvas</p>\n", 9606 "type": "Integer" 9607 }, 9608 { 9609 "name": "h", 9610 "description": "<p>height of the target update area for the\n underlying canvas</p>\n", 9611 "type": "Integer" 9612 } 9613 ] 9614 }, 9615 { 9616 "line": 306, 9617 "params": [] 9618 } 9619 ] 9620 }, 9621 { 9622 "file": "src/image/p5.Image.js", 9623 "line": 314, 9624 "description": "<p>Get a region of pixels from an image.</p>\n<p>If no params are passed, those whole image is returned,\nif x and y are the only params passed a single pixel is extracted\nif all params are passed a rectangle region is extracted and a p5.Image\nis returned.</p>\n<p>Returns undefined if the region is outside the bounds of the image</p>\n", 9625 "itemtype": "method", 9626 "name": "get", 9627 "params": [ 9628 { 9629 "name": "x", 9630 "description": "<p>x-coordinate of the pixel</p>\n", 9631 "type": "Number", 9632 "optional": true 9633 }, 9634 { 9635 "name": "y", 9636 "description": "<p>y-coordinate of the pixel</p>\n", 9637 "type": "Number", 9638 "optional": true 9639 }, 9640 { 9641 "name": "w", 9642 "description": "<p>width</p>\n", 9643 "type": "Number", 9644 "optional": true 9645 }, 9646 { 9647 "name": "h", 9648 "description": "<p>height</p>\n", 9649 "type": "Number", 9650 "optional": true 9651 } 9652 ], 9653 "return": { 9654 "description": "color of pixel at x,y in array format\n [R, G, B, A] or p5.Image", 9655 "type": "Number[]|Color|p5.Image" 9656 }, 9657 "example": [ 9658 "\n<div><code>\nvar myImage;\nvar c;\n\nfunction preload() {\n myImage = loadImage('assets/rockies.jpg');\n}\n\nfunction setup() {\n background(myImage);\n noStroke();\n c = myImage.get(60, 90);\n fill(c);\n rect(25, 25, 50, 50);\n}\n\n//get() returns color here\n</code></div>" 9659 ], 9660 "alt": "image of rocky mountains with 50x50 green rect in front", 9661 "class": "p5.Image", 9662 "module": "Image", 9663 "submodule": "Image" 9664 }, 9665 { 9666 "file": "src/image/p5.Image.js", 9667 "line": 359, 9668 "description": "<p>Set the color of a single pixel or write an image into\nthis p5.Image.</p>\n<p>Note that for a large number of pixels this will\nbe slower than directly manipulating the pixels array\nand then calling updatePixels().</p>\n", 9669 "itemtype": "method", 9670 "name": "set", 9671 "params": [ 9672 { 9673 "name": "x", 9674 "description": "<p>x-coordinate of the pixel</p>\n", 9675 "type": "Number" 9676 }, 9677 { 9678 "name": "y", 9679 "description": "<p>y-coordinate of the pixel</p>\n", 9680 "type": "Number" 9681 }, 9682 { 9683 "name": "a", 9684 "description": "<p>grayscale value | pixel array |\n a p5.Color | image to copy</p>\n", 9685 "type": "Number|Number[]|Object" 9686 } 9687 ], 9688 "example": [ 9689 "\n<div>\n<code>\nvar img = createImage(66, 66);\nimg.loadPixels();\nfor (var i = 0; i < img.width;
9689 i++) {\n for (var j = 0; j < img.height; j++) {\n img.set(i, j, color(0, 90, 102, (i % img.width) * 2));\n }\n}\nimg.updatePixels();\nimage(img, 17, 17);\nimage(img, 34, 34);\n</code>\n</div>" 9690 ], 9691 "alt": "2 gradated dark turquoise rects fade left. 1 center 1 bottom right of canvas", 9692 "class": "p5.Image", 9693 "module": "Image", 9694 "submodule": "Image" 9695 }, 9696 { 9697 "file": "src/image/p5.Image.js", 9698 "line": 397, 9699 "description": "<p>Resize the image to a new width and height. To make the image scale\nproportionally, use 0 as the value for the wide or high parameter.\nFor instance, to make the width of an image 150 pixels, and change\nthe height using the same proportion, use resize(150, 0).</p>\n", 9700 "itemtype": "method", 9701 "name": "resize", 9702 "params": [ 9703 { 9704 "name": "width", 9705 "description": "<p>the resized image width</p>\n", 9706 "type": "Number" 9707 }, 9708 { 9709 "name": "height", 9710 "description": "<p>the resized image height</p>\n", 9711 "type": "Number" 9712 } 9713 ], 9714 "example": [ 9715 "\n<div><code>\nvar img;\n\nfunction preload() {\n img = loadImage('assets/rockies.jpg');\n}\n\nfunction draw() {\n image(img, 0, 0);\n}\n\nfunction mousePressed() {\n img.resize(50, 100);\n}\n</code></div>" 9716 ], 9717 "alt": "image of rocky mountains. zoomed in", 9718 "class": "p5.Image", 9719 "module": "Image", 9720 "submodule": "Image" 9721 }, 9722 { 9723 "file": "src/image/p5.Image.js", 9724 "line": 481, 9725 "description": "<p>Copies a region of pixels from one image to another. If no\nsrcImage is specified this is used as the source. If the source\nand destination regions aren't the same size, it will\nautomatically resize source pixels to fit the specified\ntarget region.</p>\n", 9726 "itemtype": "method", 9727 "name": "copy", 9728 "example": [ 9729 "\n<div><code>\nvar photo;\nvar bricks;\nvar x;\nvar y;\n\nfunction preload() {\n photo = loadImage('assets/rockies.jpg');\n bricks = loadImage('assets/bricks.jpg');\n}\n\nfunction setup() {\n x = bricks.width / 2;\n y = bricks.height / 2;\n photo.copy(bricks, 0, 0, x, y, 0, 0, x, y);\n image(photo, 0, 0);\n}\n</code></div>" 9730 ], 9731 "alt": "image of rocky mountains and smaller image on top of bricks at top left", 9732 "class": "p5.Image", 9733 "module": "Image", 9734 "submodule": "Image", 9735 "overloads": [ 9736 { 9737 "line": 481, 9738 "params": [ 9739 { 9740 "name": "srcImage", 9741 "description": "<p>source image</p>\n", 9742 "type": "p5.Image|p5.Element" 9743 }, 9744 { 9745 "name": "sx", 9746 "description": "<p>X coordinate of the source's upper left corner</p>\n", 9747 "type": "Integer" 9748 }, 9749 { 9750 "name": "sy", 9751 "description": "<p>Y coordinate of the source's upper left corner</p>\n", 9752 "type": "Integer" 9753 }, 9754 { 9755 "name": "sw", 9756 "description": "<p>source image width</p>\n", 9757 "type": "Integer" 9758 }, 9759 { 9760 "name": "sh", 9761 "description": "<p>source image height</p>\n", 9762 "type": "Integer" 9763 }, 9764 { 9765 "name": "dx", 9766 "description": "<p>X coordinate of the destination's upper left corner</p>\n", 9767 "type": "Integer" 9768 }, 9769 { 9770 "name": "dy", 9771 "description": "<p>Y coordinate of the destination's upper left corner</p>\n", 9772 "type": "Integer" 9773 }, 9774 { 9775 "name": "dw", 9776 "description": "<p>destination image width</p>\n", 9777 "type": "Integer" 9778 }, 9779 { 9780 "name": "dh", 9781 "description": "<p>destination image height</p>\n", 9782 "type": "Integer" 9783 } 9784 ] 9785 }, 9786 { 9787 "line": 522, 9788 "params": [ 9789 { 9790 "name": "sx", 9791 "description": "", 9792 "type": "Integer" 9793 }, 9794 { 9795 "name": "sy", 9796 "description": "", 9797 "type": "Integer" 9798 }, 9799 { 9800 "name": "sw", 9801 "description": "", 9802 "type": "Integer" 9803 }, 9804 { 9805 "name": "sh", 9806 "description": "", 9807 "type": "Integer" 9808 }, 9809 { 9810 "name": "dx", 9811 "description": "", 9812 "type": "Integer" 9813 }, 9814 { 9815 "name": "dy", 9816 "description": "", 9817 "type": "Integer" 9818 }, 9819 { 9820 "name": "dw", 9821 "description": "", 9822 "type": "Integer" 9823 }, 9824 { 9825 "name": "dh", 9826 "description": "", 9827 "type": "Integer" 9828 } 9829 ] 9830 } 9831 ] 9832 }, 9833 { 9834 "file": "src/image/p5.Image.js", 9835 "line": 561, 9836 "description": "<p>Masks part of an image from displaying by loading another\nimage and using it's alpha channel as an alpha channel for\nthis image.</p>\n", 9837 "itemtype": "method", 9838 "name": "mask", 9839 "params": [ 9840 { 9841 "name": "srcImage", 9842 "description": "<p>source image</p>\n", 9843 "type": "p5.Image" 9844 } 9845 ], 9846 "example": [ 9847 "\n<div><code>\nvar photo, maskImage;\nfunction preload() {\n photo = loadImage('assets/rockies.jpg');\n maskImage = loadImage('assets/mask2.png');\n}\n\nfunction setup() {\n createCanvas(100, 100);\n photo.mask(maskImage);\n image(photo, 0, 0);\n}\n</code></div>" 9848 ], 9849 "alt": "image of rocky mountains with white at right\n\n\nhttp://blogs.adobe.com/webplatform/2013/01/28/blending-features-in-canvas/", 9850 "class": "p5.Image", 9851 "module": "Image", 9852 "submodule": "Image" 9853 }, 9854 { 9855 "file": "src/image/p5.Image.js", 9856 "line": 624, 9857 "description": "<p>Applies an image filter to a p5.Image</p>\n", 9858 "itemtype": "method", 9859 "name": "filter", 9860 "params": [ 9861 { 9862 "name": "filterType", 9863 "description": "<p>either THRESHOLD, GRAY, OPAQUE, INVERT,\n POSTERIZE, BLUR, ERODE, DILATE or BLUR.\
9863n See Filters.js for docs on\n each available filter</p>\n", 9864 "type": "Constant" 9865 }, 9866 { 9867 "name": "filterParam", 9868 "description": "<p>an optional parameter unique\n to each filter, see above</p>\n", 9869 "type": "Number", 9870 "optional": true 9871 } 9872 ], 9873 "example": [ 9874 "\n<div><code>\nvar photo1;\nvar photo2;\n\nfunction preload() {\n photo1 = loadImage('assets/rockies.jpg');\n photo2 = loadImage('assets/rockies.jpg');\n}\n\nfunction setup() {\n photo2.filter('gray');\n image(photo1, 0, 0);\n image(photo2, width / 2, 0);\n}\n</code></div>" 9875 ], 9876 "alt": "2 images of rocky mountains left one in color, right in black and white", 9877 "class": "p5.Image", 9878 "module": "Image", 9879 "submodule": "Image" 9880 }, 9881 { 9882 "file": "src/image/p5.Image.js", 9883 "line": 660, 9884 "description": "<p>Copies a region of pixels from one image to another, using a specified\nblend mode to do the operation.</p>\n", 9885 "itemtype": "method", 9886 "name": "blend", 9887 "example": [ 9888 "\n<div><code>\nvar mountains;\nvar bricks;\n\nfunction preload() {\n mountains = loadImage('assets/rockies.jpg');\n bricks = loadImage('assets/bricks_third.jpg');\n}\n\nfunction setup() {\n mountains.blend(bricks, 0, 0, 33, 100, 67, 0, 33, 100, ADD);\n image(mountains, 0, 0);\n image(bricks, 0, 0);\n}\n</code></div>\n<div><code>\nvar mountains;\nvar bricks;\n\nfunction preload() {\n mountains = loadImage('assets/rockies.jpg');\n bricks = loadImage('assets/bricks_third.jpg');\n}\n\nfunction setup() {\n mountains.blend(bricks, 0, 0, 33, 100, 67, 0, 33, 100, DARKEST);\n image(mountains, 0, 0);\n image(bricks, 0, 0);\n}\n</code></div>\n<div><code>\nvar mountains;\nvar bricks;\n\nfunction preload() {\n mountains = loadImage('assets/rockies.jpg');\n bricks = loadImage('assets/bricks_third.jpg');\n}\n\nfunction setup() {\n mountains.blend(bricks, 0, 0, 33, 100, 67, 0, 33, 100, LIGHTEST);\n image(mountains, 0, 0);\n image(bricks, 0, 0);\n}\n</code></div>" 9889 ], 9890 "alt": "image of rocky mountains. Brick images on left and right. Right overexposed\nimage of rockies. Brickwall images on left and right. Right mortar transparent\nimage of rockies. Brickwall images on left and right. Right translucent", 9891 "class": "p5.Image", 9892 "module": "Image", 9893 "submodule": "Image", 9894 "overloads": [ 9895 { 9896 "line": 660, 9897 "params": [ 9898 { 9899 "name": "srcImage", 9900 "description": "<p>source image</p>\n", 9901 "type": "p5.Image" 9902 }, 9903 { 9904 "name": "sx", 9905 "description": "<p>X coordinate of the source's upper left corner</p>\n", 9906 "type": "Integer" 9907 }, 9908 { 9909 "name": "sy", 9910 "description": "<p>Y coordinate of the source's upper left corner</p>\n", 9911 "type": "Integer" 9912 }, 9913 { 9914 "name": "sw", 9915 "description": "<p>source image width</p>\n", 9916 "type": "Integer" 9917 }, 9918 { 9919 "name": "sh", 9920 "description": "<p>source image height</p>\n", 9921 "type": "Integer" 9922 }, 9923 { 9924 "name": "dx", 9925 "description": "<p>X coordinate of the destination's upper left corner</p>\n", 9926 "type": "Integer" 9927 }, 9928 { 9929 "name": "dy", 9930 "description": "<p>Y coordinate of the destination's upper left corner</p>\n", 9931 "type": "Integer" 9932 }, 9933 { 9934 "name": "dw", 9935 "description": "<p>destination image width</p>\n", 9936 "type": "Integer" 9937 }, 9938 { 9939 "name": "dh", 9940 "description": "<p>destination image height</p>\n", 9941 "type": "Integer" 9942 }, 9943 { 9944 "name": "blendMode", 9945 "description": "<p>the blend mode. either\n BLEND, DARKEST, LIGHTEST, DIFFERENCE,\n MULTIPLY, EXCLUSION, SCREEN, REPLACE, OVERLAY, HARD_LIGHT,\n SOFT_LIGHT, DODGE, BURN, ADD or NORMAL.</p>\n<p>Available blend modes are: normal | multiply | screen | overlay |\n darken | lighten | color-dodge | color-burn | hard-light |\n soft-light | difference | exclusion | hue | saturation |\n color | luminosity</p>\n<p><a href=\"http://blogs.adobe.com/webplatform/2013/01/28/blending-features-in-canvas/\">http://blogs.adobe.com/webplatform/2013/01/28/blending-features-in-canvas/</a></p>\n", 9946 "type": "Constant" 9947 } 9948 ] 9949 }, 9950 { 9951 "line": 739, 9952 "params": [ 9953 { 9954 "name": "sx", 9955 "description": "", 9956 "type": "Integer" 9957 }, 9958 { 9959 "name": "sy", 9960 "description": "", 9961 "type": "Integer" 9962 }, 9963 { 9964 "name": "sw", 9965 "description": "", 9966 "type": "Integer" 9967 }, 9968 { 9969 "name": "sh", 9970 "description": "", 9971 "type": "Integer" 9972 }, 9973 { 9974 "name": "dx", 9975 "description": "", 9976 "type": "Integer" 9977 }, 9978 { 9979 "name": "dy", 9980 "description": "", 9981 "type": "Integer" 9982 }, 9983 { 9984 "name": "dw", 9985 "description": "", 9986 "type": "Integer" 9987 }, 9988 { 9989 "name": "dh", 9990 "description": "", 9991 "type": "Integer" 9992 }, 9993 { 9994 "name": "blendMode", 9995 "description": "", 9996 "type": "Constant" 9997 } 9998 ] 9999 } 10000 ] 10001 }, 10002 { 10003 "file": "src/image/p5.Image.js", 10004 "line": 782, 10005 "description": "<p>Saves the image to a file and force the browser to download it.\nAccepts two strings for filename and file extension\nSupports png (default) and jpg.</p>\n", 10006 "itemtype": "method", 10007 "name": "save", 10008 "params": [ 10009 { 10010 "name": "filename", 10011 "description": "<p>give your file a name</p>\n", 10012 "type": "String" 10013 }, 10014 { 10015 "name": "extension", 10016 "description": "<p>'png' or 'jpg'</p>\n", 10017 "type": "String" 10018 } 10019 ], 10020 "example": [ 10021 "\n<div><code>\nvar photo;\n\nfunction preload() {\n photo = loadImage('assets/rockies.jpg');\n}\n\nfunction draw() {\n image(photo, 0, 0);\n}\n\nfunction keyTyped() {\n if (key === 's') {\n photo.save('photo', 'png');\n }\n}\n</code></div>" 10022 ], 10023 "alt": "image of rocky mountains.", 10024 "class": "p5.Image", 10025 "module": "Image", 10026 "submodule": "Image" 10027 }, 10028 { 10029 "file": "src/image/pixels.js", 10030 "line": 14, 10031 "description": "<p><a href='https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference\n/Global_Objects/Uint8ClampedArray' target='_blank'>Uint8ClampedArray</a>\ncontaining the values for all the pixels in the display window.\nThese values are numbers. This array is the size (include an appropriate\nfactor for pixelDensity) of the display window x4,\nrepresenting the R, G, B, A values in order for each pixel, mov
10031ing from\nleft to right across each row, then down each column. Retina and other\nhigh density displays will have more pixels[] (by a factor of\npixelDensity^2).\nFor example, if the image is 100x100 pixels, there will be 40,000. On a\nretina display, there will be 160,000.\n<br><br>\nThe first four values (indices 0-3) in the array will be the R, G, B, A\nvalues of the pixel at (0, 0). The second four values (indices 4-7) will\ncontain the R, G, B, A values of the pixel at (1, 0). More generally, to\nset values for a pixel at (x, y):</p>\n<pre><code class=\"lang-javascript\">var d = pixelDensity();\nfor (var i = 0; i < d; i++) {\n for (var j = 0; j < d; j++) {\n // loop over\n idx = 4 * ((y * d + j) * width * d + (x * d + i));\n pixels[idx] = r;\n pixels[idx+1] = g;\n pixels[idx+2] = b;\n pixels[idx+3] = a;\n }\n}\n</code></pre>\n<p>While the above method is complex, it is flexible enough to work with\nany pixelDensity. Note that set() will automatically take care of\nsetting all the appropriate values in pixels[] for a given (x, y) at\nany pixelDensity, but the performance may not be as fast when lots of\nmodifications are made to the pixel array.\n<br><br>\nBefore accessing this array, the data must loaded with the loadPixels()\nfunction. After the array data has been modified, the updatePixels()\nfunction must be run to update the changes.\n<br><br>\nNote that this is not a standard javascript array. This means that\nstandard javascript functions such as <code>slice()</code> or\n<code>arrayCopy()</code> do not\nwork.</p>", 10032 "itemtype": "property", 10033 "name": "pixels", 10034 "type": "Number[]", 10035 "example": [ 10036 "\n<div>\n<code>\nvar pink = color(255, 102, 204);\nloadPixels();\nvar d = pixelDensity();\nvar halfImage = 4 * (width * d) * (height / 2 * d);\nfor (var i = 0; i < halfImage; i += 4) {\n pixels[i] = red(pink);\n pixels[i + 1] = green(pink);\n pixels[i + 2] = blue(pink);\n pixels[i + 3] = alpha(pink);\n}\nupdatePixels();\n</code>\n</div>" 10037 ], 10038 "alt": "top half of canvas pink, bottom grey", 10039 "class": "p5", 10040 "module": "Image", 10041 "submodule": "Pixels" 10042 }, 10043 { 10044 "file": "src/image/pixels.js", 10045 "line": 83, 10046 "description": "<p>Copies a region of pixels from one image to another, using a specified\nblend mode to do the operation.</p>\n", 10047 "itemtype": "method", 10048 "name": "blend", 10049 "example": [ 10050 "\n<div><code>\nvar img0;\nvar img1;\n\nfunction preload() {\n img0 = loadImage('assets/rockies.jpg');\n img1 = loadImage('assets/bricks_third.jpg');\n}\n\nfunction setup() {\n background(img0);\n image(img1, 0, 0);\n blend(img1, 0, 0, 33, 100, 67, 0, 33, 100, LIGHTEST);\n}\n</code></div>\n<div><code>\nvar img0;\nvar img1;\n\nfunction preload() {\n img0 = loadImage('assets/rockies.jpg');\n img1 = loadImage('assets/bricks_third.jpg');\n}\n\nfunction setup() {\n background(img0);\n image(img1, 0, 0);\n blend(img1, 0, 0, 33, 100, 67, 0, 33, 100, DARKEST);\n}\n</code></div>\n<div><code>\nvar img0;\nvar img1;\n\nfunction preload() {\n img0 = loadImage('assets/rockies.jpg');\n img1 = loadImage('assets/bricks_third.jpg');\n}\n\nfunction setup() {\n background(img0);\n image(img1, 0, 0);\n blend(img1, 0, 0, 33, 100, 67, 0, 33, 100, ADD);\n}\n</code></div>" 10051 ], 10052 "alt": "image of rocky mountains. Brick images on left and right. Right overexposed\nimage of rockies. Brickwall images on left and right. Right mortar transparent\nimage of rockies. Brickwall images on left and right. Right translucent", 10053 "class": "p5", 10054 "module": "Image", 10055 "submodule": "Pixels", 10056 "overloads": [ 10057 { 10058 "line": 83, 10059 "params": [ 10060 { 10061 "name": "srcImage", 10062 "description": "<p>source image</p>\n", 10063 "type": "p5.Image" 10064 }, 10065 { 10066 "name": "sx", 10067 "description": "<p>X coordinate of the source's upper left corner</p>\n", 10068 "type": "Integer" 10069 }, 10070 { 10071 "name": "sy", 10072 "description": "<p>Y coordinate of the source's upper left corner</p>\n", 10073 "type": "Integer" 10074 }, 10075 { 10076 "name": "sw", 10077 "description": "<p>source image width</p>\n", 10078 "type": "Integer" 10079 }, 10080 { 10081 "name": "sh", 10082 "description": "<p>source image height</p>\n", 10083 "type": "Integer" 10084 }, 10085 { 10086 "name": "dx", 10087 "description": "<p>X coordinate of the destination's upper left corner</p>\n", 10088 "type": "Integer" 10089 }, 10090 { 10091 "name": "dy", 10092 "description": "<p>Y coordinate of the destination's upper left corner</p>\n", 10093 "type": "Integer" 10094 }, 10095 { 10096 "name": "dw", 10097 "description": "<p>destination image width</p>\n", 10098 "type": "Integer" 10099 }, 10100 { 10101 "name": "dh", 10102 "description": "<p>destination image height</p>\n", 10103 "type": "Integer" 10104 }, 10105 { 10106 "name": "blendMode", 10107 "description": "<p>the blend mode. either\n BLEND, DARKEST, LIGHTEST, DIFFERENCE,\n MULTIPLY, EXCLUSION, SCREEN, REPLACE, OVERLAY, HARD_LIGHT,\n SOFT_LIGHT, DODGE, BURN, ADD or NORMAL.</p>\n", 10108 "type": "Constant" 10109 } 10110 ] 10111 }, 10112 { 10113 "line": 156, 10114 "params": [ 10115 { 10116 "name": "sx", 10117 "description": "", 10118 "type": "Integer" 10119 }, 10120 { 10121 "name": "sy", 10122 "description": "", 10123 "type": "Integer" 10124 }, 10125 { 10126 "name": "sw", 10127 "description": "", 10128 "type": "Integer" 10129 }, 10130 { 10131 "name": "sh", 10132 "description": "", 10133 "type": "Integer" 10134 }, 10135 { 10136 "name": "dx", 10137 "description": "", 10138 "type": "Integer" 10139 }, 10140 { 10141 "name": "dy", 10142 "description": "", 10143 "type": "Integer" 10144 }, 10145 { 10146 "name": "dw", 10147 "description": "", 10148 "type": "Integer" 10149 }, 10150 { 10151 "name": "dh", 10152 "description": "", 10153 "type": "Integer" 10154 }, 10155 { 10156 "name": "blendMode", 10157 "description": "", 10158 "type": "Constant" 10159 } 10160 ] 10161 } 10162 ] 10163 }, 10164 { 10165 "file": "src/image/pixels.js", 10166 "line": 177, 10167 "description": "<p>Copies a region of the canvas to another region of the canvas\nand copies a region of pixels from an image used as the srcImg parameter\ninto the canvas srcImage is specified this is used as the source. If\nthe source and destination regions aren't the same size, it will\nautomatically resize source pixels to fit the specified\ntarget region.</p>\n", 10168 "itemtype": "method", 10169 "name": "copy", 10170 "example": [ 10171 "\n<div><code>\nvar img;\n\nfunction preload() {\n img = loadImage('assets/rockies.jpg');\n}\n\nfunction setup() {\n background(img);\n copy(img, 7, 22, 10, 10, 35, 25, 50, 50);
10171\n stroke(255);\n noFill();\n // Rectangle shows area being copied\n rect(7, 22, 10, 10);\n}\n</code></div>" 10172 ], 10173 "alt": "image of rocky mountains. Brick images on left and right. Right overexposed\nimage of rockies. Brickwall images on left and right. Right mortar transparent\nimage of rockies. Brickwall images on left and right. Right translucent", 10174 "class": "p5", 10175 "module": "Image", 10176 "submodule": "Pixels", 10177 "overloads": [ 10178 { 10179 "line": 177, 10180 "params": [ 10181 { 10182 "name": "srcImage", 10183 "description": "<p>source image</p>\n", 10184 "type": "p5.Image|p5.Element" 10185 }, 10186 { 10187 "name": "sx", 10188 "description": "<p>X coordinate of the source's upper left corner</p>\n", 10189 "type": "Integer" 10190 }, 10191 { 10192 "name": "sy", 10193 "description": "<p>Y coordinate of the source's upper left corner</p>\n", 10194 "type": "Integer" 10195 }, 10196 { 10197 "name": "sw", 10198 "description": "<p>source image width</p>\n", 10199 "type": "Integer" 10200 }, 10201 { 10202 "name": "sh", 10203 "description": "<p>source image height</p>\n", 10204 "type": "Integer" 10205 }, 10206 { 10207 "name": "dx", 10208 "description": "<p>X coordinate of the destination's upper left corner</p>\n", 10209 "type": "Integer" 10210 }, 10211 { 10212 "name": "dy", 10213 "description": "<p>Y coordinate of the destination's upper left corner</p>\n", 10214 "type": "Integer" 10215 }, 10216 { 10217 "name": "dw", 10218 "description": "<p>destination image width</p>\n", 10219 "type": "Integer" 10220 }, 10221 { 10222 "name": "dh", 10223 "description": "<p>destination image height</p>\n", 10224 "type": "Integer" 10225 } 10226 ] 10227 }, 10228 { 10229 "line": 220, 10230 "params": [ 10231 { 10232 "name": "sx", 10233 "description": "", 10234 "type": "Integer" 10235 }, 10236 { 10237 "name": "sy", 10238 "description": "", 10239 "type": "Integer" 10240 }, 10241 { 10242 "name": "sw", 10243 "description": "", 10244 "type": "Integer" 10245 }, 10246 { 10247 "name": "sh", 10248 "description": "", 10249 "type": "Integer" 10250 }, 10251 { 10252 "name": "dx", 10253 "description": "", 10254 "type": "Integer" 10255 }, 10256 { 10257 "name": "dy", 10258 "description": "", 10259 "type": "Integer" 10260 }, 10261 { 10262 "name": "dw", 10263 "description": "", 10264 "type": "Integer" 10265 }, 10266 { 10267 "name": "dh", 10268 "description": "", 10269 "type": "Integer" 10270 } 10271 ] 10272 } 10273 ] 10274 }, 10275 { 10276 "file": "src/image/pixels.js", 10277 "line": 236, 10278 "description": "<p>Applies a filter to the canvas.\n<br><br></p>\n<p>The presets options are:\n<br><br></p>\n<p>THRESHOLD\nConverts the image to black and white pixels depending if they are above or\nbelow the threshold defined by the level parameter. The parameter must be\nbetween 0.0 (black) and 1.0 (white). If no level is specified, 0.5 is used.\n<br><br></p>\n<p>GRAY\nConverts any colors in the image to grayscale equivalents. No parameter\nis used.\n<br><br></p>\n<p>OPAQUE\nSets the alpha channel to entirely opaque. No parameter is used.\n<br><br></p>\n<p>INVERT\nSets each pixel to its inverse value. No parameter is used.\n<br><br></p>\n<p>POSTERIZE\nLimits each channel of the image to the number of colors specified as the\nparameter. The parameter can be set to values between 2 and 255, but\nresults are most noticeable in the lower ranges.\n<br><br></p>\n<p>BLUR\nExecutes a Gaussian blur with the level parameter specifying the extent\nof the blurring. If no parameter is used, the blur is equivalent to\nGaussian blur of radius 1. Larger values increase the blur.\n<br><br></p>\n<p>ERODE\nReduces the light areas. No parameter is used.\n<br><br></p>\n<p>DILATE\nIncreases the light areas. No parameter is used.</p>\n", 10279 "itemtype": "method", 10280 "name": "filter", 10281 "params": [ 10282 { 10283 "name": "filterType", 10284 "description": "<p>either THRESHOLD, GRAY, OPAQUE, INVERT,\n POSTERIZE, BLUR, ERODE, DILATE or BLUR.\
10284n See Filters.js for docs on\n each available filter</p>\n", 10285 "type": "Constant" 10286 }, 10287 { 10288 "name": "filterParam", 10289 "description": "<p>an optional parameter unique\n to each filter, see above</p>\n", 10290 "type": "Number", 10291 "optional": true 10292 } 10293 ], 10294 "example": [ 10295 "\n<div>\n<code>\nvar img;\nfunction preload() {\n img = loadImage('assets/bricks.jpg');\n}\nfunction setup() {\n image(img, 0, 0);\n filter(THRESHOLD);\n}\n</code>\n</div>\n\n<div>\n<code>\nvar img;\nfunction preload() {\n img = loadImage('assets/bricks.jpg');\n}\nfunction setup() {\n image(img, 0, 0);\n filter(GRAY);\n}\n</code>\n</div>\n\n<div>\n<code>\nvar img;\nfunction preload() {\n img = loadImage('assets/bricks.jpg');\n}\nfunction setup() {\n image(img, 0, 0);\n filter(OPAQUE);\n}\n</code>\n</div>\n\n<div>\n<code>\nvar img;\nfunction preload() {\n img = loadImage('assets/bricks.jpg');\n}\nfunction setup() {\n image(img, 0, 0);\n filter(INVERT);\n}\n</code>\n</div>\n\n<div>\n<code>\nvar img;\nfunction preload() {\n img = loadImage('assets/bricks.jpg');\n}\nfunction setup() {\n image(img, 0, 0);\n filter(POSTERIZE, 3);\n}\n</code>\n</div>\n\n<div>\n<code>\nvar img;\nfunction preload() {\n img = loadImage('assets/bricks.jpg');\n}\nfunction setup() {\n image(img, 0, 0);\n filter(DILATE);\n}\n</code>\n</div>\n\n<div>\n<code>\nvar img;\nfunction preload() {\n img = loadImage('assets/bricks.jpg');\n}\nfunction setup() {\n image(img, 0, 0);
10295\n filter(BLUR, 3);\n}\n</code>\n</div>\n\n<div>\n<code>\nvar img;\nfunction preload() {\n img = loadImage('assets/bricks.jpg');\n}\nfunction setup() {\n image(img, 0, 0);\n filter(ERODE);\n}\n</code>\n</div>" 10296 ], 10297 "alt": "black and white image of a brick wall.\ngreyscale image of a brickwall\nimage of a brickwall\njade colored image of a brickwall\nred and pink image of a brickwall\nimage of a brickwall\nblurry image of a brickwall\nimage of a brickwall\nimage of a brickwall with less detail", 10298 "class": "p5", 10299 "module": "Image", 10300 "submodule": "Pixels" 10301 }, 10302 { 10303 "file": "src/image/pixels.js", 10304 "line": 415, 10305 "description": "<p>Returns an array of [R,G,B,A] values for any pixel or grabs a section of\nan image. If no parameters are specified, the entire image is returned.\nUse the x and y parameters to get the value of one pixel. Get a section of\nthe display window by specifying additional w and h parameters. When\ngetting an image, the x and y parameters define the coordinates for the\nupper-left corner of the image, regardless of the current imageMode().\n<br><br>\nIf the pixel requested is outside of the image window, [0,0,0,255] is\nreturned. To get the numbers scaled according to the current color ranges\nand taking into account colorMode, use getColor instead of get.\n<br><br>\nGetting the color of a single pixel with get(x, y) is easy, but not as fast\nas grabbing the data directly from pixels[]. The equivalent statement to\nget(x, y) using pixels[] with pixel density d is\n<code>\nvar x, y, d; // set these to the coordinates\nvar off = (y <em> width + x) </em> d * 4;\nvar components = [\n pixels[off],\n pixels[off + 1],\n pixels[off + 2],\n pixels[off + 3]\n];\nprint(components);\n</code>\n<br><br>\nSee the reference for pixels[] for more information.</p>\n", 10306 "itemtype": "method", 10307 "name": "get", 10308 "params": [ 10309 { 10310 "name": "x", 10311 "description": "<p>x-coordinate of the pixel</p>\n", 10312 "type": "Number", 10313 "optional": true 10314 }, 10315 { 10316 "name": "y", 10317 "description": "<p>y-coordinate of the pixel</p>\n", 10318 "type": "Number", 10319 "optional": true 10320 }, 10321 { 10322 "name": "w", 10323 "description": "<p>width</p>\n", 10324 "type": "Number", 10325 "optional": true 10326 }, 10327 { 10328 "name": "h", 10329 "description": "<p>height</p>\n", 10330 "type": "Number", 10331 "optional": true 10332 } 10333 ], 10334 "return": { 10335 "description": "values of pixel at x,y in array format\n [R, G, B, A] or p5.Image", 10336 "type": "Number[]|p5.Image" 10337 }, 10338 "example": [ 10339 "\n<div>\n<code>\nvar img;\nfunction preload() {\n img = loadImage('assets/rockies.jpg');\n}\nfunction setup() {\n image(img, 0, 0);\n var c = get();\n image(c, width / 2, 0);\n}\n</code>\n</div>\n\n<div>\n<code>\nvar img;\nfunction preload() {\n img = loadImage('assets/rockies.jpg');\n}\nfunction setup() {\n image(img, 0, 0);\n var c = get(50, 90);\n fill(c);\n noStroke();\n rect(25, 25, 50, 50);\n}\n</code>\n</div>" 10340 ], 10341 "alt": "2 images of the rocky mountains, side-by-side\nImage of the rocky mountains with 50x50 green rect in center of canvas", 10342 "class": "p5", 10343 "module": "Image", 10344 "submodule": "Pixels" 10345 }, 10346 { 10347 "file": "src/image/pixels.js", 10348 "line": 491, 10349 "description": "<p>Loads the pixel data for the display window into the pixels[] array. This\nfunction must always be called before reading from or writing to pixels[].\nNote that only changes made with set() or direct manipulation of pixels[]\nwill occur.</p>\n", 10350 "itemtype": "method", 10351 "name": "loadPixels", 10352 "example": [ 10353 "\n<div>\n<code>\nvar img;\nfunction preload() {\n img = loadImage('assets/rockies.jpg');\n}\n\nfunction setup() {\n image(img, 0, 0);\n var d = pixelDensity();\n var halfImage = 4 * (img.width * d) * (img.height * d / 2);\n loadPixels();\n for (var i = 0; i < halfImage;
10353 i++) {\n pixels[i + halfImage] = pixels[i];\n }\n updatePixels();\n}\n</code>\n</div>" 10354 ], 10355 "alt": "two images of the rocky mountains. one on top, one on bottom of canvas.", 10356 "class": "p5", 10357 "module": "Image", 10358 "submodule": "Pixels" 10359 }, 10360 { 10361 "file": "src/image/pixels.js", 10362 "line": 528, 10363 "description": "<p>Changes the color of any pixel, or writes an image directly to the\ndisplay window.</p>\n<p>The x and y parameters specify the pixel to change and the c parameter\nspecifies the color value. This can be a p5.Color object, or [R, G, B, A]\npixel array. It can also be a single grayscale value.\nWhen setting an image, the x and y parameters define the coordinates for\nthe upper-left corner of the image, regardless of the current imageMode().\n</p>\n<p>\nAfter using set(), you must call updatePixels() for your changes to appear.\nThis should be called once all pixels have been set, and must be called before\ncalling .get() or drawing the image.\n</p>\n<p>Setting the color of a single pixel with set(x, y) is easy, but not as\nfast as putting the data directly into pixels[]. Setting the pixels[]\nvalues directly may be complicated when working with a retina display,\nbut will perform better when lots of pixels need to be set directly on\nevery loop.</p>\n<p>See the reference for pixels[] for more information.</p>", 10364 "itemtype": "method", 10365 "name": "set", 10366 "params": [ 10367 { 10368 "name": "x", 10369 "description": "<p>x-coordinate of the pixel</p>\n", 10370 "type": "Number" 10371 }, 10372 { 10373 "name": "y", 10374 "description": "<p>y-coordinate of the pixel</p>\n", 10375 "type": "Number" 10376 }, 10377 { 10378 "name": "c", 10379 "description": "<p>insert a grayscale value | a pixel array |\n a p5.Color object | a p5.Image to copy</p>\n", 10380 "type": "Number|Number[]|Object" 10381 } 10382 ], 10383 "example": [ 10384 "\n<div>\n<code>\nvar black = color(0);\nset(30, 20, black);\nset(85, 20, black);\nset(85, 75, black);\nset(30, 75, black);\nupdatePixels();\n</code>\n</div>\n\n<div>\n<code>\nfor (var i = 30; i < width - 15; i++) {\n for (var j = 20; j < height - 25; j++) {\n var c = color(204 - j, 153 - i, 0);\n set(i, j, c);\n }\n}\nupdatePixels();\n</code>\n</div>\n\n<div>\n<code>\nvar img;\nfunction preload() {\n img = loadImage('assets/rockies.jpg');\n}\n\nfunction setup() {\n set(0, 0, img);\n updatePixels();\n line(0, 0, width, height);\n line(0, height, width, 0);\n}\n</code>\n</div>" 10385 ], 10386 "alt": "4 black points in the shape of a square middle-right of canvas.\nsquare with orangey-brown gradient lightening at bottom right.\nimage of the rocky mountains. with lines like an 'x' through the center.", 10387 "class": "p5", 10388 "module": "Image", 10389 "submodule": "Pixels" 10390 }, 10391 { 10392 "file": "src/image/pixels.js", 10393 "line": 602, 10394 "description": "<p>Updates the display window with the data in the pixels[] array.\nUse in conjunction with loadPixels(). If you're only reading pixels from\nthe array, there's no need to call updatePixels() â updating is only\nnecessary to apply changes. updatePixels() should be called anytime the\npixels array is manipulated or set() is called, and only changes made with\nset() or direct changes to pixels[] will occur.</p>\n", 10395 "itemtype": "method", 10396 "name": "updatePixels", 10397 "params": [ 10398 { 10399 "name": "x", 10400 "description": "<p>x-coordinate of the upper-left corner of region\n to update</p>\n", 10401 "type": "Number", 10402 "optional": true 10403 }, 10404 { 10405 "name": "y", 10406 "description": "<p>y-coordinate of the upper-left corner of region\n to update</p>\n", 10407 "type": "Number", 10408 "optional": true 10409 }, 10410 { 10411 "name": "w", 10412 "description": "<p>width of region to update</p>\n", 10413 "type": "Number", 10414 "optional": true 10415 }, 10416 { 10417 "name": "h", 10418 "description": "<p>height of region to update</p>\n", 10419 "type": "Number", 10420 "optional": true 10421 } 10422 ], 10423 "example": [ 10424 "\n<div>\n<code>\nvar img;\nfunction preload() {\n img = loadImage('assets/rockies.jpg');\n}\n\nfunction setup() {\n image(img, 0, 0);\n var d = pixelDensity();\n var halfImage = 4 * (img.width * d) * (img.height * d / 2);\n loadPixels();\n for (var i = 0; i < halfImage;
10424 i++) {\n pixels[i + halfImage] = pixels[i];\n }\n updatePixels();\n}\n</code>\n</div>" 10425 ], 10426 "alt": "two images of the rocky mountains. one on top, one on bottom of canvas.", 10427 "class": "p5", 10428 "module": "Image", 10429 "submodule": "Pixels" 10430 }, 10431 { 10432 "file": "src/io/files.js", 10433 "line": 19, 10434 "description": "<p>Loads a JSON file from a file or a URL, and returns an Object.\nNote that even if the JSON file contains an Array, an Object will be\nreturned with index numbers as keys.</p>\n<p>This method is asynchronous, meaning it may not finish before the next\nline in your sketch is executed. JSONP is supported via a polyfill and you\ncan pass in as the second argument an object with definitions of the json\ncallback following the syntax specified <a href=\"https://github.com/camsong/\nfetch-jsonp\">here</a>.</p>\n", 10435 "itemtype": "method", 10436 "name": "loadJSON", 10437 "return": { 10438 "description": "JSON data", 10439 "type": "Object|Array" 10440 }, 10441 "example": [ 10442 "\n\n<p>Calling loadJSON() inside preload() guarantees to complete the\noperation before setup() and draw() are called.</p>\n\n<div><code>\n// Examples use USGS Earthquake API:\n// https://earthquake.usgs.gov/fdsnws/event/1/#methods\nvar earthquakes;\nfunction preload() {\n // Get the most recent earthquake in the database\n var url =\n 'https://earthquake.usgs.gov/earthquakes/feed/v1.0/' +\n 'summary/all_day.geojson';\n earthquakes = loadJSON(url);\n}\n\nfunction setup() {\n noLoop();\n}\n\nfunction draw() {\n background(200);\n // Get the magnitude and name of the earthquake out of the loaded JSON\n var earthquakeMag = earthquakes.features[0].properties.mag;\n var earthquakeName = earthquakes.features[0].properties.place;\n ellipse(width / 2, height / 2, earthquakeMag * 10, earthquakeMag * 10);\n textAlign(CENTER);\n text(earthquakeName, 0, height - 30, width, 30);\n}\n</code></div>\n\n\n<p>Outside of preload(), you may supply a callback function to handle the\nobject:</p>\n<div><code>\nfunction setup() {\n noLoop();\n var url =\n 'https://earthquake.usgs.gov/earthquakes/feed/v1.0/' +\n 'summary/all_day.geojson';\n loadJSON(url, drawEarthquake);\n}\n\nfunction draw() {\n background(200);\n}\n\nfunction drawEarthquake(earthquakes) {\n // Get the magnitude and name of the earthquake out of the loaded JSON\n var earthquakeMag = earthquakes.features[0].properties.mag;\n var earthquakeName = earthquakes.features[0].properties.place;\n ellipse(width / 2, height / 2, earthquakeMag * 10, earthquakeMag * 10);\n textAlign(CENTER);\n text(earthquakeName, 0, height - 30, width, 30);\n}\n</code></div>" 10443 ], 10444 "alt": "50x50 ellipse that changes from black to white depending on the current humidity\n50x50 ellipse that changes from black to white depending on the current humidity", 10445 "class": "p5", 10446 "module": "IO", 10447 "submodule": "Input", 10448 "overloads": [ 10449 { 10450 "line": 19, 10451 "params": [ 10452 { 10453 "name": "path", 10454 "description": "<p>name of the file or url to load</p>\n", 10455 "type": "String" 10456 }, 10457 { 10458 "name": "jsonpOptions", 10459 "description": "<p>options object for jsonp related settings</p>\n", 10460 "type": "Object", 10461 "optional": true 10462 }, 10463 { 10464 "name": "datatype", 10465 "description": "<p>"json" or "jsonp"</p>\n", 10466 "type": "String", 10467 "optional": true 10468 }, 10469 { 10470 "name": "callback", 10471 "description": "<p>function to be executed after\n loadJSON() completes, data is passed\n in as first argument</p>\n", 10472 "type": "Function", 10473 "optional": true 10474 }, 10475 { 10476 "name": "errorCallback", 10477 "description": "<p>function to be executed if\n there is an error, response is passed\n in as first argument</p>\n", 10478 "type": "Function", 10479 "optional": true 10480 } 10481 ], 10482 "return": { 10483 "description": "JSON data", 10484 "type": "Object|Array" 10485 } 10486 }, 10487 { 10488 "line": 104, 10489 "params": [ 10490 { 10491 "name": "path", 10492 "description": "", 10493 "type": "String" 10494 }, 10495 { 10496 "name": "datatype", 10497 "description": "", 10498 "type": "String" 10499 }, 10500 { 10501 "name": "callback", 10502 "description": "", 10503 "type": "Function", 10504 "optional": true 10505 }, 10506 { 10507 "name": "errorCallback", 10508 "description": "", 10509 "type": "Function", 10510 "optional": true 10511 } 10512 ], 10513 "return": { 10514 "description": "", 10515 "type": "Object|Array" 10516 } 10517 }, 10518 { 10519 "line": 112, 10520 "params": [ 10521 { 10522 "name": "path", 10523 "description": "", 10524 "type": "String" 10525 }, 10526 { 10527 "name": "callback", 10528 "description": "", 10529 "type": "Function" 10530 }, 10531 { 10532 "name": "errorCallback", 10533 "description": "", 10534 "type": "Function", 10535 "optional": true 10536 } 10537 ], 10538 "return": { 10539 "description": "", 10540 "type": "Object|Array" 10541 } 10542 } 10543 ] 10544 }, 10545 { 10546 "file": "src/io/files.js", 10547 "line": 170, 10548 "description": "<p>Reads the contents of a file and creates a String array of its individual\nlines. If the name of the file is used as the parameter, as in the above\nexample, the file must be located in the sketch directory/folder.\n<br><br>\nAlternatively, the file maybe be loaded from anywhere on the local\ncomputer using an absolute path (something that starts with / on Unix and\nLinux, or a drive letter on Windows), or the filename parameter can be a\nURL for a file found on a network.\n<br><br>\nThis method is asynchronous, meaning it may not finish before the next\nline in your sketch is executed.</p>\n", 10549 "itemtype": "method", 10550 "name": "loadStrings", 10551 "params": [ 10552 { 10553 "name": "filename", 10554 "description": "<p>name of the file or url to load</p>\n", 10555 "type": "String" 10556 }, 10557 { 10558 "name": "callback", 10559 "description": "<p>function to be executed after loadStrings()\n completes, Array is passed in as first\n argument</p>\n", 10560 "type": "Function", 10561 "optional": true 10562 }, 10563 { 10564 "name": "errorCallback", 10565 "description": "<p>function to be executed if\n there is an error, response is passed\n in as first argument</p>\n", 10566 "type": "Function", 10567 "optional": true 10568 } 10569 ], 10570 "return": { 10571 "description": "Array of Strings", 10572 "type": "String[]" 10573 }, 10574 "example": [ 10575 "\n\n<p>Calling loadStrings() inside preload() guarantees to complete the\noperation before setup() and draw() are called.</p>\n\n<div><code>\nvar result;\nfunction preload() {\n result = loadStrings('assets/test.txt');\n}\n\nfunction setup() {\n background(200);\n var ind = floor(random(result.length));\n text(result[ind], 10, 10, 80, 80);\n}\n</code></div>\n\n<p>Outside of preload(), you may supply a callback function to handle the\nobject:</p>\n\n<div><code>\nfunction setup() {\n loadStrings('assets/test.txt', pickString);\n}\n\nfunction pickString(result) {\n background(200);\n var ind = floor(random(result.length));\n text(result[ind], 10, 10, 80, 80);\n}\n</code></div>" 10576 ], 10577 "alt": "randomly generated text from a file, for example \"i smell like butter\"\nrandomly generated text from a file, for example \"i have three feet\"", 10578 "class": "p5", 10579 "module": "IO", 10580 "submodule": "Input" 10581 }, 10582 { 10583 "file": "src/io/files.js", 10584 "line": 271, 10585 "description": "<p>Reads the contents of a file or URL and creates a p5.Table object with\nits values. If a file is specified, it must be located in the sketch's\n"data" folder. The filename parameter can also be a URL to a file found\nonline. By default, the file is assumed to be comma-separated (in CSV\nformat). Table only looks for a header row if the 'header' option is\nincluded.</p>\n\n<p>Possible options include:\n<ul>\n<li>csv - parse the table as comma-separated values</li>\n<li>tsv - parse the table as tab-separated values</li>\n<li>header - this table has a header (title) row</li>\n</ul>\n</p>\n\n<p>When passing in multiple options, pass them in as separate parameters,\nseperated by commas. For example:\n<br><br>\n<code>\nloadTable('my_csv_file.csv', 'csv', 'header');\n</code>\n</p>\n\n<p> All files loaded and saved use UTF-8 encoding.</p>\n\n<p>This method is asynchronous, meaning it may not finish before the next\nline in your sketch is executed. Calling loadTable() inside preload()\nguarantees to complete the operation before setup() and draw() are called.\n<p>Outside of preload(), you may supply a callback function to handle the\nobject:</p>\n</p>", 10586 "itemtype": "method", 10587 "name": "loadTable", 10588 "return": {
10589 "description": "Table object containing data", 10590 "type": "Object" 10591 }, 10592 "example": [ 10593 "\n<div class=\"norender\">\n<code>\n// Given the following CSV file called \"mammals.csv\"\n// located in the project's \"assets\" folder:\n//\n// id,species,name\n// 0,Capra hircus,Goat\n// 1,Panthera pardus,Leopard\n// 2,Equus zebra,Zebra\n\nvar table;\n\nfunction preload() {\n //my table is comma separated value \"csv\"\n //and has a header specifying the columns labels\n table = loadTable('assets/mammals.csv', 'csv', 'header');\n //the file can be remote\n //table = loadTable(\"http://p5js.org/reference/assets/mammals.csv\",\n // \"csv\", \"header\");\n}\n\nfunction setup() {\n //count the columns\n print(table.getRowCount() + ' total rows in table');\n print(table.getColumnCount() + ' total columns in table');\n\n print(table.getColumn('name'));\n //[\"Goat\", \"Leopard\", \"Zebra\"]\n\n //cycle through the table\n for (var r = 0; r < table.getRowCount(); r++)\n for (var c = 0; c < table.getColumnCount(); c++) {\n print(table.getString(r, c));\n }\n}\n</code>\n</div>" 10594 ], 10595 "alt": "randomly generated text from a file, for example \"i smell like butter\"\nrandomly generated text from a file, for example \"i have three feet\"", 10596 "class": "p5", 10597 "module": "IO", 10598 "submodule": "Input", 10599 "overloads": [ 10600 { 10601 "line": 271, 10602 "params": [ 10603 { 10604 "name": "filename", 10605 "description": "<p>name of the file or URL to load</p>\n", 10606 "type": "String" 10607 }, 10608 { 10609 "name": "options", 10610 "description": "<p>"header" "csv" "tsv"</p>\n", 10611 "type": "String" 10612 }, 10613 { 10614 "name": "callback", 10615 "description": "<p>function to be executed after\n loadTable() completes. On success, the\n Table object is passed in as the\n first argument.</p>\n", 10616 "type": "Function", 10617 "optional": true 10618 }, 10619 { 10620 "name": "errorCallback", 10621 "description": "<p>function to be executed if\n there is an error, response is passed\n in as first argument</p>\n", 10622 "type": "Function", 10623 "optional": true 10624 } 10625 ], 10626 "return": { 10627 "description": "Table object containing data", 10628 "type": "Object" 10629 } 10630 }, 10631 { 10632 "line": 360, 10633 "params": [ 10634 { 10635 "name": "filename", 10636 "description": "", 10637 "type": "String" 10638 }, 10639 { 10640 "name": "callback", 10641 "description": "", 10642 "type": "Function", 10643 "optional": true 10644 }, 10645 { 10646 "name": "errorCallback", 10647 "description": "", 10648 "type": "Function", 10649 "optional": true 10650 } 10651 ], 10652 "return": { 10653 "description": "", 10654 "type": "Object" 10655 } 10656 } 10657 ] 10658 }, 10659 { 10660 "file": "src/io/files.js", 10661 "line": 603, 10662 "description": "<p>
10662Reads the contents of a file and creates an XML object with its values.\nIf the name of the file is used as the parameter, as in the above example,\nthe file must be located in the sketch directory/folder.</p>\n<p>Alternatively, the file maybe be loaded from anywhere on the local\ncomputer using an absolute path (something that starts with / on Unix and\nLinux, or a drive letter on Windows), or the filename parameter can be a\nURL for a file found on a network.</p>\n<p>This method is asynchronous, meaning it may not finish before the next\nline in your sketch is executed. Calling loadXML() inside preload()\nguarantees to complete the operation before setup() and draw() are called.</p>\n<p>Outside of preload(), you may supply a callback function to handle the\nobject.</p>\n", 10663 "itemtype": "method", 10664 "name": "loadXML", 10665 "params": [ 10666 { 10667 "name": "filename", 10668 "description": "<p>name of the file or URL to load</p>\n", 10669 "type": "String" 10670 }, 10671 { 10672 "name": "callback", 10673 "description": "<p>function to be executed after loadXML()\n completes, XML object is passed in as\n first argument</p>\n", 10674 "type": "Function", 10675 "optional": true 10676 }, 10677 { 10678 "name": "errorCallback", 10679 "description": "<p>function to be executed if\n there is an error, response is passed\n in as first argument</p>\n", 10680 "type": "Function", 10681 "optional": true 10682 } 10683 ], 10684 "return": { 10685 "description": "XML object containing data", 10686 "type": "Object" 10687 }, 10688 "example": [ 10689 "\n<div class='norender'><code>\n// The following short XML file called \"mammals.xml\" is parsed\n// in the code below.\n//\n// <?xml version=\"1.0\"?>\n// <mammals>\n// <animal id=\"0\" species=\"Capra hircus\">Goat</animal>\n// <animal id=\"1\" species=\"Panthera pardus\">Leopard</animal>\n// <animal id=\"2\" species=\"Equus zebra\">Zebra</animal>\n// </mammals>\n\nvar xml;\n\nfunction preload() {\n xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n var children = xml.getChildren('animal');\n\n for (var i = 0; i < children.length; i++) {\n var id = children[i].getNum('id');\n var coloring = children[i].getString('species');\n var name = children[i].getContent();\n print(id + ', ' + coloring + ', ' + name);\n }\n}\n\n// Sketch prints:\n// 0, Capra hircus, Goat\n// 1, Panthera pardus, Leopard\n// 2, Equus zebra, Zebra\n</code></div>" 10690 ], 10691 "alt": "no image displayed", 10692 "class": "p5", 10693 "module": "IO", 10694 "submodule": "Input" 10695 }, 10696 { 10697 "file": "src/io/files.js", 10698 "line": 704, 10699 "itemtype": "method", 10700 "name": "loadBytes", 10701 "params": [ 10702 { 10703 "name": "file", 10704 "description": "<p>name of the file or URL to load</p>\n", 10705 "type": "String" 10706 }, 10707 { 10708 "name": "callback", 10709 "description": "<p>function to be executed after loadBytes()\n completes</p>\n", 10710 "type": "Function", 10711 "optional": true 10712 }, 10713 { 10714 "name": "errorCallback", 10715 "description": "<p>function to be executed if there\n is an error</p>\n", 10716 "type": "Function", 10717 "optional": true 10718 } 10719 ], 10720 "return": { 10721 "description": "an object whose 'bytes' property will be the loaded buffer", 10722 "type": "Object" 10723 }, 10724 "example": [ 10725 "\n<div class='norender'><code>\nvar data;\n\nfunction preload() {\n data = loadBytes('assets/mammals.xml');\n}\n\nfunction setup() {\n for (var i = 0; i < 5;
10725 i++) {\n console.log(data.bytes[i].toString(16));\n }\n}\n</code></div>" 10726 ], 10727 "alt": "no image displayed", 10728 "class": "p5", 10729 "module": "IO", 10730 "submodule": "Input" 10731 }, 10732 { 10733 "file": "src/io/files.js", 10734 "line": 754, 10735 "description": "<p>Method for executing an HTTP GET request. If data type is not specified,\np5 will try to guess based on the URL, defaulting to text. This is equivalent to\ncalling <code>httpDo(path, 'GET')</code>. The 'binary' datatype will return\na Blob object, and the 'arrayBuffer' datatype will return an ArrayBuffer\nwhich can be used to initialize typed arrays (such as Uint8Array).</p>\n", 10736 "itemtype": "method", 10737 "name": "httpGet", 10738 "example": [ 10739 "\n<div class='norender'><code>\n// Examples use USGS Earthquake API:\n// https://earthquake.usgs.gov/fdsnws/event/1/#methods\nvar earthquakes;\nfunction preload() {\n // Get the most recent earthquake in the database\n var url =\n 'https://earthquake.usgs.gov/fdsnws/event/1/query?' +\n 'format=geojson&limit=1&orderby=time';\n httpGet(url, 'jsonp', false, function(response) {\n // when the HTTP request completes, populate the variable that holds the\n // earthquake data used in the visualization.\n earthquakes = response;\n });\n}\n\nfunction draw() {\n if (!earthquakes) {\n // Wait until the earthquake data has loaded before drawing.\n return;\n }\n background(200);\n // Get the magnitude and name of the earthquake out of the loaded JSON\n var earthquakeMag = earthquakes.features[0].properties.mag;\n var earthquakeName = earthquakes.features[0].properties.place;\n ellipse(width / 2, height / 2, earthquakeMag * 10, earthquakeMag * 10);\n textAlign(CENTER);\n text(earthquakeName, 0, height - 30, width, 30);\n noLoop();\n}\n</code></div>" 10740 ], 10741 "class": "p5", 10742 "module": "IO", 10743 "submodule": "Input", 10744 "overloads": [ 10745 { 10746 "line": 754, 10747 "params": [ 10748 { 10749 "name": "path", 10750 "description": "<p>name of the file or url to load</p>\n", 10751 "type": "String" 10752 }, 10753 { 10754 "name": "datatype", 10755 "description": "<p>"json", "jsonp", "binary", "arrayBuffer",\n "xml", or "text"</p>\n", 10756 "type": "String", 10757 "optional": true 10758 }, 10759 { 10760 "name": "data", 10761 "description": "<p>param data passed sent with request</p>\n", 10762 "type": "Object|Boolean", 10763 "optional": true 10764 }, 10765 { 10766 "name": "callback", 10767 "description": "<p>function to be executed after\n httpGet() completes, data is passed in\n as first argument</p>\n", 10768 "type": "Function", 10769 "optional": true 10770 }, 10771 { 10772 "name": "errorCallback", 10773 "description": "<p>function to be executed if\n there is an error, response is passed\n in as first argument</p>\n", 10774 "type": "Function", 10775 "optional": true 10776 } 10777 ] 10778 }, 10779 { 10780 "line": 805, 10781 "params": [ 10782 { 10783 "name": "path", 10784 "description": "", 10785 "type": "String" 10786 }, 10787 { 10788 "name": "data", 10789 "description": "", 10790 "type": "Object|Boolean" 10791 }, 10792 { 10793 "name": "callback", 10794 "description": "", 10795 "type": "Function", 10796 "optional": true 10797 }, 10798 { 10799 "name": "errorCallback", 10800 "description": "", 10801 "type": "Function", 10802 "optional": true 10803 } 10804 ] 10805 }, 10806 { 10807 "line": 812, 10808 "params": [ 10809 { 10810 "name": "path", 10811 "description": "", 10812 "type": "String" 10813 }, 10814 { 10815 "name": "callback", 10816 "description": "", 10817 "type": "Function" 10818 }, 10819 { 10820 "name": "errorCallback", 10821 "description": "", 10822 "type": "Function", 10823 "optional": true 10824 } 10825 ] 10826 } 10827 ] 10828 }, 10829 { 10830 "file": "src/io/files.js", 10831 "line": 826, 10832 "description": "<p>Method for executing an HTTP POST request. If data type is not specified,\np5 will try to guess based on the URL, defaulting to text. This is equivalent to\ncalling <code>httpDo(path, 'POST')</code>.</p>\n", 10833 "itemtype": "method", 10834 "name": "httpPost", 10835 "example": [ 10836 "\n<div>\n<code>\n// Examples use jsonplaceholder.typicode.com for a Mock Data API\n\nvar url = 'https://jsonplaceholder.typicode.com/posts';\nvar postData = { userId: 1, title: 'p5 Clicked!', body: 'p5.js is way cool.' };\n\nfunction setup() {\n createCanvas(800, 800);\n}\n\nfunction mousePressed() {\n // Pick new random color values\n var r = random(255);\n var g = random(255);\n var b = random(255);\n\n httpPost(url, 'json', postData, function(result) {\n strokeWeight(2);\n stroke(r, g, b);\n fill(r, g, b, 127);\n ellipse(mouseX, mouseY, 200, 200);\n text(result.body, mouseX, mouseY);\n });\n}\n</code>\n</div>\n\n\n<div><code>\nvar url = 'https://invalidURL'; // A bad URL that will cause errors\nvar postData = { title: 'p5 Clicked!', body: 'p5.js is way cool.' };\n\nfunction setup() {\n createCanvas(800, 800);\n}\n\nfunction mousePressed() {\n // Pick new random color values\n var r = random(255);\n var g = random(255);\n var b = random(255);\n\n httpPost(\n url,\n 'json',\n postData,\n function(result) {\n // ... won't be called\n },\n function(error) {\n strokeWeight(2);\n stroke(r, g, b);\n fill(r, g, b, 127);\n text(error.toString(), mouseX, mouseY);\n }\n );\n}\n</code></div>\n" 10837 ], 10838 "class": "p5", 10839 "module": "IO", 10840 "submodule": "Input", 10841 "overloads": [ 10842 { 10843 "line": 826, 10844 "params": [ 10845 { 10846 "name": "path", 10847 "description": "<p>name of the file or url to load</p>\n", 10848 "type": "String" 10849 }, 10850 { 10851 "name": "datatype", 10852 "description": "<p>"json", "jsonp", "xml", or "text".\n If omitted, httpPost() will guess.</p>\n", 10853 "type": "String", 10854 "optional": true 10855 }, 10856 { 10857 "name": "data", 10858 "description": "<p>param data passed sent with request</p>\n", 10859 "type": "Object|Boolean", 10860 "optional": true 10861 }, 10862 { 10863 "name": "callback", 10864 "description": "<p>function to be executed after\n httpPost() completes, data is passed in\n as first argument</p>\n", 10865 "type": "Function", 10866 "optional": true 10867 }, 10868 { 10869 "name": "errorCallback", 10870 "description": "<p>function to be executed if\n there is an error, response is passed\n in as first argument</p>\n", 10871 "type": "Function", 10872 "optional": true 10873 } 10874 ] 10875 }, 10876 { 10877 "line": 905, 10878 "params": [ 10879 { 10880 "name": "path", 10881 "description": "", 10882 "type": "String" 10883 }, 10884 { 10885 "name": "data", 10886 "description": "", 10887 "type": "Object|Boolean" 10888 }, 10889 { 10890 "name": "callback", 10891 "description": "", 10892 "type": "Function", 10893 "optional": true 10894 }, 10895 { 10896 "name": "errorCallback", 10897 "description": "", 10898 "type": "Function", 10899 "optional": true 10900 } 10901 ] 10902 }, 10903 { 10904 "line": 912, 10905 "params": [ 10906 { 10907 "name": "path", 10908 "description": "", 10909 "type": "String" 10910 }, 10911 { 10912 "name": "callback", 10913 "description": "", 10914 "type": "Function" 10915 }, 10916 { 10917 "name": "errorCallback", 10918 "description": "", 10919 "type": "Function", 10920 "optional": true 10921 } 10922 ] 10923 } 10924 ] 10925 }, 10926 { 10927 "file": "src/io/files.js", 10928 "line": 926, 10929 "description": "<p>Method for executing an HTTP request. If data type is not specified,\np5 will try to guess based on the URL, defaulting to text.<br><br>\nFor more advanced use, you may also pass in the path as the first argument\nand a object as the second argument, the signature follows the one specified\nin the Fetch API specification.</p>\n", 10930 "itemtype": "method", 10931 "name": "httpDo", 10932 "example": [ 10933 "\n<div>\n<code>\n// Examples use USGS Earthquake API:\n// https://earthquake.usgs.gov/fdsnws/event/1/#methods\n\n// dis
10933plays an animation of all USGS earthquakes\nvar earthquakes;\nvar eqFeatureIndex = 0;\n\nfunction preload() {\n var url = 'https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson';\n httpDo(\n url,\n {\n method: 'GET',\n // Other Request options, like special headers for apis\n headers: { authorization: 'Bearer secretKey' }\n },\n function(res) {\n earthquakes = res;\n }\n );\n}\n\nfunction draw() {\n // wait until the data is loaded\n if (!earthquakes || !earthquakes.features[eqFeatureIndex]) {\n return;\n }\n clear();\n\n var feature = earthquakes.features[eqFeatureIndex];\n var mag = feature.properties.mag;\n var rad = mag / 11 * ((width + height) / 2);\n fill(255, 0, 0, 100);\n ellipse(width / 2 + random(-2, 2), height / 2 + random(-2, 2), rad, rad);\n\n if (eqFeatureIndex >= earthquakes.features.length) {\n eqFeatureIndex = 0;\n } else {\n eqFeatureIndex += 1;\n }\n}\n</code>\n</div>" 10934 ], 10935 "class": "p5", 10936 "module": "IO", 10937 "submodule": "Input", 10938 "overloads": [ 10939 { 10940 "line": 926, 10941 "params": [ 10942 { 10943 "name": "path", 10944 "description": "<p>name of the file or url to load</p>\n", 10945 "type": "String" 10946 }, 10947 { 10948 "name": "method", 10949 "description": "<p>either "GET", "POST", or "PUT",\n defaults to "GET"</p>\n", 10950 "type": "String", 10951 "optional": true 10952 }, 10953 { 10954 "name": "datatype", 10955 "description": "<p>"json", "jsonp", "xml", or "text"</p>\n", 10956 "type": "String", 10957 "optional": true 10958 }, 10959 { 10960 "name": "data", 10961 "description": "<p>param data passed sent with request</p>\n", 10962 "type": "Object", 10963 "optional": true 10964 }, 10965 { 10966 "name": "callback", 10967 "description": "<p>function to be executed after\n httpGet() completes, data is passed in\n as first argument</p>\n", 10968 "type": "Function", 10969 "optional": true 10970 }, 10971 { 10972 "name": "errorCallback", 10973 "description": "<p>function to be executed if\n there is an error, response is passed\n in as first argument</p>\n", 10974 "type": "Function", 10975 "optional": true 10976 } 10977 ] 10978 }, 10979 { 10980 "line": 994, 10981 "params": [ 10982 { 10983 "name": "path", 10984 "description": "", 10985 "type": "String" 10986 }, 10987 { 10988 "name": "options", 10989 "description": "<p>Request object options as documented in the\n "fetch" API\n<a href=\"https://developer.mozilla.org/en/docs/Web/API/Fetch_API\">reference</a></p>\n", 10990 "type": "Object" 10991 }, 10992 { 10993 "name": "callback", 10994 "description": "", 10995 "type": "Function", 10996 "optional": true 10997 }, 10998 { 10999 "name": "errorCallback", 11000 "description": "", 11001 "type": "Function", 11002 "optional": true 11003 } 11004 ] 11005 } 11006 ] 11007 }, 11008 { 11009 "file": "src/io/files.js", 11010 "line": 1130, 11011 "itemtype": "method", 11012 "name": "createWriter", 11013 "params": [ 11014 { 11015 "name": "name", 11016 "description": "<p>name of the file to be created</p>\n", 11017 "type": "String" 11018 }, 11019 { 11020 "name": "extension", 11021 "description": "", 11022 "type": "String", 11023 "optional": true 11024 } 11025 ], 11026 "return": { 11027 "description": "", 11028 "type": "p5.PrintWriter" 11029 }, 11030 "example": [ 11031 "\n<div>\n<code>\ncreateButton('save')\n .position(10, 10)\n .mousePressed(function() {\
11031n var writer = createWriter('squares.txt');\n for (var i = 0; i < 10; i++) {\n writer.print(i * i);\n }\n writer.close();\n writer.clear();\n });\n</code>\n</div>" 11032 ], 11033 "class": "p5", 11034 "module": "IO", 11035 "submodule": "Output" 11036 }, 11037 { 11038 "file": "src/io/files.js", 11039 "line": 1179, 11040 "description": "<p>Writes data to the PrintWriter stream</p>\n", 11041 "itemtype": "method", 11042 "name": "write", 11043 "params": [ 11044 { 11045 "name": "data", 11046 "description": "<p>all data to be written by the PrintWriter</p>\n", 11047 "type": "Array" 11048 } 11049 ], 11050 "example": [ 11051 "\n<div class=\"norender notest\">\n<code>\n// creates a file called 'newFile.txt'\nvar writer = createWriter('newFile.txt');\n// write 'Hello world!'' to the file\nwriter.write(['Hello world!']);\n// close the PrintWriter and save the file\nwriter.close();\n</code>\n</div>\n<div class='norender notest'>\n<code>\n// creates a file called 'newFile2.txt'\nvar writer = createWriter('newFile2.txt');\n// write 'apples,bananas,123' to the file\nwriter.write(['apples', 'bananas', 123]);\n// close the PrintWriter and save the file\nwriter.close();\n</code>\n</div>\n<div class='norender notest'>\n<code>\n// creates a file called 'newFile3.txt'\nvar writer = createWriter('newFile3.txt');\n// write 'My name is: Teddy' to the file\nwriter.write('My name is:');\nwriter.write(' Teddy');\n// close the PrintWriter and save the file\nwriter.close();\n</code>\n</div>" 11052 ], 11053 "class": "p5.PrintWriter", 11054 "module": "IO", 11055 "submodule": "Output" 11056 }, 11057 { 11058 "file": "src/io/files.js", 11059 "line": 1219, 11060 "description": "<p>Writes data to the PrintWriter stream, and adds a new line at the end</p>\n", 11061 "itemtype": "method", 11062 "name": "print", 11063 "params": [ 11064 { 11065 "name": "data", 11066 "description": "<p>all data to be printed by the PrintWriter</p>\n", 11067 "type": "Array" 11068 } 11069 ], 11070 "example": [ 11071 "\n<div class='norender notest'>\n<code>\n// creates a file called 'newFile.txt'\nvar writer = createWriter('newFile.txt');\n// creates a file containing\n// My name is:\n// Teddy\nwriter.print('My name is:');\nwriter.print('Teddy');\n// close the PrintWriter and save the file\nwriter.close();\n</code>\n</div>\n<div class='norender notest'>\n<code>\nvar writer;\n\nfunction setup() {\n createCanvas(400, 400);\n // create a PrintWriter\n writer = createWriter('newFile.txt');\n}\n\nfunction draw() {\n // print all mouseX and mouseY coordinates to the stream\n writer.print([mouseX, mouseY]);\n}\n\nfunction mouseClicked() {\n // close the PrintWriter and save the file\n writer.close();\n}\n</code>\n</div>" 11072 ], 11073 "class": "p5.PrintWriter", 11074 "module": "IO", 11075 "submodule": "Output" 11076 }, 11077 { 11078 "file": "src/io/files.js", 11079 "line": 1262, 11080 "description": "<p>Clears the data already written to the PrintWriter object</p>\n", 11081 "itemtype": "method", 11082 "name": "clear", 11083 "example": [ 11084 "\n<div class =\"norender notest\"><code>\n// create writer object\nvar writer = createWriter('newFile.txt');\nwriter.write(['clear me']);\n// clear writer object here\nwriter.clear();\n// close writer\nwriter.close();\n</code></div>\n" 11085 ], 11086 "class": "p5.PrintWriter", 11087 "module": "IO", 11088 "submodule": "Output" 11089 }, 11090 { 11091 "file": "src/io/files.js", 11092 "line": 1280, 11093 "description": "<p>Closes the PrintWriter</p>\n", 11094 "itemtype": "method", 11095 "name": "close", 11096 "example": [ 11097 "\n<div class=\"norender notest\">\n<code>\n// create a file called 'newFile.txt'\nvar writer = createWriter('newFile.txt');\n// close the PrintWriter and save the file\nwriter.close();\n</code>\n</div>\n<div class='norender notest'>\n<code>\n// create a file called 'newFile2.txt'\nvar writer = createWriter('newFile2.txt');\n// write some data to the file\nwriter.write([100, 101, 102]);\n// close the PrintWriter and save the file\nwriter.close();\n</code>\n</div>" 11098 ], 11099 "class": "p5.PrintWriter", 11100 "module": "IO", 11101 "submodule": "Output" 11102 }, 11103 { 11104 "file": "src/io/files.js", 11105 "line": 1329, 11106 "description": "<p>Save an image, text, json, csv, wav, or html. Prompts download to\nthe client's computer. <b>Note that it is not recommended to call save()\nwithin draw if it's looping, as the save() function will open a new save\ndialog every frame.</b></p>\n<p>The default behavior is to save the canvas as an image. You can\noptionally specify a filename.\nFor example:</p>\n <pre class='language-javascript'><code>\n save();
11106\n save('myCanvas.jpg'); // save a specific canvas with a filename\n </code></pre>\n\n<p>Alternately, the first parameter can be a pointer to a canvas\np5.Element, an Array of Strings,\nan Array of JSON, a JSON object, a p5.Table, a p5.Image, or a\np5.SoundFile (requires p5.sound). The second parameter is a filename\n(including extension). The third parameter is for options specific\nto this type of object. This method will save a file that fits the\ngiven paramaters. For example:</p>\n\n <pre class='language-javascript'><code>\n // Saves canvas as an image\n save('myCanvas.jpg');\n\n // Saves pImage as a png image\n var img = createImage(10, 10);\n save(img, 'my.png');\n\n // Saves canvas as an image\n var cnv = createCanvas(100, 100);\n save(cnv, 'myCanvas.jpg');\n\n // Saves p5.Renderer object as an image\n var gb = createGraphics(100, 100);\n save(gb, 'myGraphics.jpg');\n\n var myTable = new p5.Table();\n\n // Saves table as html file\n save(myTable, 'myTable.html');\n\n // Comma Separated Values\n save(myTable, 'myTable.csv');\n\n // Tab Separated Values\n save(myTable, 'myTable.tsv');\n\n var myJSON = { a: 1, b: true };\n\n // Saves pretty JSON\n save(myJSON, 'my.json');\n\n // Optimizes JSON filesize\n save(myJSON, 'my.json', true);\n\n // Saves array of strings to a text file with line breaks after each item\n var arrayOfStrings = ['a', 'b'];\n save(arrayOfStrings, 'my.txt');\n </code></pre>", 11107 "itemtype": "method", 11108 "name": "save", 11109 "params": [ 11110 { 11111 "name": "objectOrFilename", 11112 "description": "<p>If filename is provided, will\n save canvas as an image with\n either png or jpg extension\n depending on the filename.\n If object is provided, will\n save depending on the object\n and filename (see examples\n above).</p>\n", 11113 "type": "Object|String", 11114 "optional": true 11115 }, 11116 { 11117 "name": "filename", 11118 "description": "<p>If an object is provided as the first\n parameter, then the second parameter\n indicates the filename,\n and should include an appropriate\n file extension (see examples above).</p>\n", 11119 "type": "String", 11120 "optional": true 11121 }, 11122 { 11123 "name": "options", 11124 "description": "<p>Additional options depend on\n filetype. For example, when saving JSON,\n <code>true</code> indicates that the\n output will be optimized for filesize,\n rather than readability.</p>\n", 11125 "type": "Boolean|String", 11126 "optional": true 11127 } 11128 ], 11129 "class": "p5", 11130 "module": "IO", 11131 "submodule": "Output" 11132 }, 11133 { 11134 "file": "src/io/files.js", 11135 "line": 1457, 11136 "description": "<p>Writes the contents of an Array or a JSON object to a .json file.\nThe file saving process and location of the saved file will\nvary between web browsers.</p>\n", 11137 "itemtype": "method", 11138 "name": "saveJSON", 11139 "params": [ 11140 { 11141 "name": "json", 11142 "description": "", 11143 "type": "Array|Object" 11144 }, 11145 { 11146 "name": "filename", 11147 "description": "", 11148 "type": "String" 11149 }, 11150 { 11151 "name": "optimize", 11152 "description": "<p>If true, removes line breaks\n and spaces from the output\n file to optimize filesize\n (but not readability).</p>\n", 11153 "type": "Boolean", 11154 "optional": true 11155 } 11156 ], 11157 "example": [ 11158 "\n <div><code>\n var json = {}; // new JSON Object\n\n json.id = 0;\n json.species = 'Panthera leo';\n json.name = 'Lion';\n\n createButton('save')\n .position(10, 10)\n .mousePressed(function() {\
11158n saveJSON(json, 'lion.json');\n });\n\n // saves the following to a file called \"lion.json\":\n // {\n // \"id\": 0,\n // \"species\": \"Panthera leo\",\n // \"name\": \"Lion\"\n // }\n </code></div>" 11159 ], 11160 "alt": "no image displayed", 11161 "class": "p5", 11162 "module": "IO", 11163 "submodule": "Output" 11164 }, 11165 { 11166 "file": "src/io/files.js", 11167 "line": 1509, 11168 "description": "<p>Writes an array of Strings to a text file, one line per String.\nThe file saving process and location of the saved file will\nvary between web browsers.</p>\n", 11169 "itemtype": "method", 11170 "name": "saveStrings", 11171 "params": [ 11172 { 11173 "name": "list", 11174 "description": "<p>string array to be written</p>\n", 11175 "type": "String[]" 11176 }, 11177 { 11178 "name": "filename", 11179 "description": "<p>filename for output</p>\n", 11180 "type": "String" 11181 }, 11182 { 11183 "name": "extension", 11184 "description": "<p>the filename's extension</p>\n", 11185 "type": "String", 11186 "optional": true 11187 } 11188 ], 11189 "example": [ 11190 "\n <div><code>\n var words = 'apple bear cat dog';\n\n // .split() outputs an Array\n var list = split(words, ' ');\n\n createButton('save')\n .position(10, 10)\n .mousePressed(function() {\n saveStrings(list, 'nouns.txt');\n });\n\n // Saves the following to a file called 'nouns.txt':\n //\n // apple\n // bear\n // cat\n // dog\n </code></div>" 11191 ], 11192 "alt": "no image displayed", 11193 "class": "p5", 11194 "module": "IO", 11195 "submodule": "Output" 11196 }, 11197 { 11198 "file": "src/io/files.js", 11199 "line": 1571, 11200 "description": "<p>Writes the contents of a Table object to a file. Defaults to a\ntext file with comma-separated-values ('csv') but can also\nuse tab separation ('tsv'), or generate an HTML table ('html').\nThe file saving process and location of the saved file will\nvary between web browsers.</p>\n", 11201 "itemtype": "method", 11202 "name": "saveTable", 11203 "params": [ 11204 { 11205 "name": "Table", 11206 "description": "<p>the Table object to save to a file</p>\n", 11207 "type": "p5.Table" 11208 }, 11209 { 11210 "name": "filename", 11211 "description": "<p>the filename to which the Table should be saved</p>\n", 11212 "type": "String" 11213 }, 11214 { 11215 "name": "options", 11216 "description": "<p>can be one of "tsv", "csv", or "html"</p>\n", 11217 "type": "String", 11218 "optional": true 11219 } 11220 ], 11221 "example": [ 11222 "\n<div><code>\n var table;\n\n function setup() {\n table = new p5.Table();\n\n table.addColumn('id');\n table.addColumn('species');\n table.addColumn('name');\n\n var newRow = table.addRow();\n newRow.setNum('id', table.getRowCount() - 1);\n newRow.setString('species', 'Panthera leo');\n newRow.setString('name', 'Lion');\n\n // To save, un-comment next line then click 'run'\n // saveTable(table, 'new.csv');\n }\n\n // Saves the following to a file called 'new.csv':\n // id,species,name\n // 0,Panthera leo,Lion\n </code></div>" 11223 ], 11224 "alt": "no image displayed", 11225 "class": "p5", 11226 "module": "IO", 11227 "submodule": "Output" 11228 }, 11229 { 11230 "file": "src/io/p5.Table.js", 11231 "line": 11, 11232 "description": "<p>Table Options</p>\n<p>Generic class for handling tabular data, typically from a\nCSV, TSV, or other sort of spreadsheet file.</p>\n<p>CSV files are\n<a href=\"http://en.wikipedia.org/wiki/Comma-separated_values\">\ncomma separated values</a>, often with the data in quotes. TSV\nfiles use tabs as separators, and usually don't bother with the\nquotes.</p>\n<p>File names should end with .csv if they're comma separated.</p>\n<p>A rough "spec" for CSV can be found\n<a href=\"http://tools.ietf.org/html/rfc4180\">here</a>.</p>\n<p>To load files, use the loadTable method.</p>\n<p>To save tables to your computer, use the save method\n or the saveTable method.</p>\n\n<p>Possible options include:</p>\n<ul>\n<li>csv - parse the table as comma-separated values\n<li>tsv - parse the table as tab-separated values\n<li>header - this table has a header (title) row\n</ul>", 11233 "class": "p5.Table", 11234 "module": "IO", 11235 "submodule": "Table" 11236 }, 11237 { 11238 "file": "src/io/p5.Table.js", 11239 "line": 45, 11240 "itemtype": "property", 11241 "name": "columns", 11242 "type": "String[]", 11243 "class": "p5.Table", 11244 "module": "IO", 11245 "submodule": "Table" 11246 }, 11247 { 11248 "file": "src/io/p5.Table.js", 11249 "line": 50, 11250 "itemtype": "property", 11251 "name": "rows", 11252 "type": "p5.TableRow[]", 11253 "class": "p5.Table", 11254 "module": "IO", 11255 "submodule": "Table" 11256 }, 11257 { 11258 "file": "src/io/p5.Table.js", 11259 "line": 56, 11260 "description": "<p>Use addRow() to add a new row of data to a p5.Table object. By default,\nan empty row is created. Typically, you would store a reference to\nthe new row in a TableRow object (see newRow in the example above),\nand then set individual values using set().</p>\n<p>If a p5.TableRow object is included as a parameter, then that row is\nduplicated and added to the table.</p>\n", 11261 "itemtype": "method", 11262 "name": "addRow", 11263 "params": [ 11264 { 11265 "name": "row", 11266 "description": "<p>row to be added to the table</p>\n", 11267 "type": "p5.TableRow", 11268 "optional": true 11269 } 11270 ], 11271 "example": [ 11272 "\n <div class=\"norender\">\n <code>\n // Given the CSV file \"mammals.csv\"\n // in the project's \"assets\" folder:\n //\n // id,species,name\n // 0,Capra hircus,Goat\n // 1,Panthera pardus,Leopard\n // 2,Equus zebra,Zebra\n\n var table;\n\n function preload() {\n //my table is comma separated value \"csv\"\n //and has a header specifying the columns labels\n table = loadTable('assets/mammals.csv', 'csv', 'header');\n }\n\n function setup() {\n //add a row\n var newRow = table.addRow();\n newRow.setString('id', table.getRowCount() - 1);\n newRow.setString('species', 'Canis Lupus');\n newRow.setString('name', 'Wolf');\n\n //print the results\n for (var r = 0; r < table.getRowCount(); r++)\n for (var c = 0; c < table.getColumnCount(); c++)\n print(table.getString(r, c));\n }\n </code>\n </div>" 11273 ], 11274 "alt": "no image displayed", 11275 "class": "p5.Table", 11276 "module": "IO", 11277 "submodule": "Table" 11278 }, 11279 { 11280 "file": "src/io/p5.Table.js", 11281 "line": 119, 11282 "description": "<p>Removes a row from the table object.</p>\n", 11283 "itemtype": "method", 11284 "name": "removeRow", 11285 "params": [ 11286 { 11287 "name": "id", 11288 "description": "<p>ID number of the row to remove</p>\n", 11289 "type": "Integer" 11290 } 11291 ], 11292 "example": [ 11293 "\n<div class=\"norender\">\n<code>\n// Given the CSV file \"mammals.csv\"\n// in the project's \"assets\" folder:\n//\n// id,species,name\n// 0,Capra hircus,Goat\n// 1,Panthera pardus,Leopard\n// 2,Equus zebra,Zebra\n\nvar table;\n\nfunction preload() {\n //my table is comma separated value \"csv\"\n //and has a header specifying the columns labels\n table = loadTable('assets/mammals.csv', 'csv', 'header');\n}\n\nfunction setup() {\n //remove the first row\n table.removeRow(0);\n\n //print the results\n for (var r = 0; r < table.getRowCount(); r++)\n for (var c = 0; c < table.getColumnCount(); c++)\n print(table.getString(r, c));\n}\n</code>\n</div>" 11294 ], 11295 "alt": "no image displayed", 11296 "class": "p5.Table", 11297 "module": "IO", 11298 "submodule": "Table" 11299 }, 11300 { 11301 "file": "src/io/p5.Table.js", 11302 "line": 167, 11303 "description": "<p>Returns a reference to the specified p5.TableRow. The reference\ncan then be used to get and set values of the selected row.</p>\n", 11304 "itemtype": "method", 11305 "name": "getRow", 11306 "params": [ 11307 { 11308 "name": "rowID", 11309 "description": "<p>ID number of the row to get</p>\n", 11310 "type": "Integer" 11311 } 11312 ], 11313 "return": { 11314 "description": "p5.TableRow object", 11315 "type": "p5.TableRow" 11316 }, 11317 "example": [ 11318 "\n<div class=\"norender\">\n<code>\n// Given the CSV file \"mammals.csv\"\n// in the project's \"assets\" folder:\n//\n// id,species,name\n// 0,Capra hircus,Goat\n// 1,Panthera pardus,Leopard\n// 2,Equus zebra,Zebra\n\nvar table;\n\nfunction preload() {\n //my table is comma separated value \"csv\"\n //and has a header specifying the columns labels\n table = loadTable('assets/mammals.csv', 'csv', 'header');\n}\n\nfunction setup() {\n var row = table.getRow(1);\n //print it column by column\n //note: a row is an object, not an array\n for (var c = 0; c < table.getColumnCount(); c++) {\n print(row.getString(c));\n }\n}\n</code>\n</div>" 11319 ], 11320 "alt": "no image displayed", 11321 "class": "p5.Table", 11322 "module": "IO", 11323 "submodule": "Table" 11324 }, 11325 { 11326 "file": "src/io/p5.Table.js", 11327 "line": 213, 11328 "description": "<p>Gets all rows from the table. Returns an array of p5.TableRows.</p>\n", 11329 "itemtype": "method", 11330 "name": "getRows", 11331 "return": { 11332 "description": "Array of p5.TableRows", 11333 "type": "p5.TableRow[]" 11334 }, 11335 "example": [ 11336 "\n <div class=\"norender\">\n <code>\n // Given the CSV file \"mammals.csv\"\n // in the project's \"assets\" folder:\n //\n // id,species,name\n // 0,Capra hircus,Goat\n // 1,Panthera pardus,Leopard\n // 2,Equus zebra,Zebra\n\n var table;\n\n function preload() {\n //my table is comma separated value \"csv\"\n //and has a header specifying the columns labels\n table = loadTable('assets/mammals.csv', 'csv', 'header');\n }\n\n function setup() {\n var rows = table.getRows();\n\n //warning: rows is an array of objects\n for (var r = 0; r < rows.length; r++) {\n rows[r].set('name', 'Unicorn');\n }\n\n //print the results\n for (r = 0; r < table.getRowCount(); r++)\n for (var c = 0; c < table.getColumnCount(); c++)\n print(table.getString(r, c));\n }\n </code>\n </div>" 11337 ], 11338 "alt": "no image displayed", 11339 "class": "p5.Table", 11340 "module": "IO", 11341 "submodule": "Table" 11342 }, 11343 { 11344 "file": "src/io/p5.Table.js", 11345 "line": 262, 11346 "description": "<p>Finds the first row in the Table that contains the value\nprovided, and returns a reference to that row. Even if\nmultiple rows are possible matches, only the first matching\nrow is returned. The column to search may be specified by\neither its ID or title.</p>\n", 11347 "itemtype": "method", 11348 "name": "findRow", 11349 "params": [ 11350 { 11351 "name": "value", 11352 "description": "<p>The value to match</p>\n", 11353 "type": "String" 11354 }, 11355 { 11356 "name": "column", 11357 "description": "<p>ID number or title of the\n column to search</p>\n", 11358 "type": "Integer|String" 11359 } 11360 ], 11361 "return": { 11362 "description": "", 11363 "type": "p5.TableRow" 11364 }, 11365 "example": [ 11366 "\n <div class=\"norender\">\n <code>\n // Given the CSV file \"mammals.csv\"\n // in the project's \"assets\" folder:\n //\n // id,species,name\n // 0,Capra hircus,Goat\n // 1,Panthera pardus,Leopard\n // 2,Equus zebra,Zebra\n\n var table;\n\n function preload() {\n //my table is comma separated value \"csv\"\n //and has a header specifying the columns labels\n table = loadTable('assets/mammals.csv', 'csv', 'header');\n }\n\n function setup() {\n //find the animal named zebra\n var row = table.findRow('Zebra', 'name');\n //find the corresponding species\n print(row.getString('species'));\n }\n </code>\n </div>" 11367 ], 11368 "alt": "no image displayed", 11369 "class": "p5.Table", 11370 "module": "IO", 11371 "submodule": "Table" 11372 }, 11373 { 11374 "file": "src/io/p5.Table.js", 11375 "line": 327, 11376 "description": "<p>Finds the rows in the Table that contain the value\nprovided, and returns references to those rows. Returns an\nArray, so for must be used to iterate through all the rows,\nas shown in the example above. The column to search may be\nspecified by either its ID or title.</p>\n", 11377 "itemtype": "method", 11378 "name": "findRows", 11379 "params": [ 11380 { 11381 "name": "value", 11382 "description": "<p>The value to match</p>\n", 11383 "type": "String" 11384 }, 11385 { 11386 "name": "column", 11387 "description": "<p>ID number or title of the\n column to search</p>\n", 11388 "type": "Integer|String" 11389 } 11390 ], 11391 "return": { 11392 "description": "An Array of TableRow objects", 11393 "type": "p5.TableRow[]" 11394 }, 11395 "example": [ 11396 "\n <div class=\"norender\">\n <code>\n // Given the CSV file \"mammals.csv\"\n // in the project's \"assets\" folder:\n //\n // id,species,name\n // 0,Capra hircus,Goat\n // 1,Panthera pardus,Leopard\n // 2,Equus zebra,Zebra\n\n var table;\n\n function preload() {\n //my table is comma separated value \"csv\"\n //and has a header specifying the columns labels\n table = loadTable('assets/mammals.csv', 'csv', 'header');\n }\n\n function setup() {\n //add another goat\n var newRow = table.addRow();\n newRow.setString('id', table.getRowCount() - 1);\n newRow.setString('species', 'Scape Goat');\n newRow.setString('name', 'Goat');\n\n //find the rows containing animals named Goat\n var rows = table.findRows('Goat', 'name');\n print(rows.length + ' Goats found');\n }\n </code>\n </div>" 11397 ], 11398 "alt": "no image displayed", 11399 "class": "p5.Table", 11400 "module": "IO", 11401 "submodule": "Table" 11402 }, 11403 { 11404 "file": "src/io/p5.Table.js", 11405 "line": 396, 11406 "description": "<p>Finds the first row in the Table that matches the regular\nexpression provided, and returns a reference to that row.\nEven if multiple rows are possible matches, only the first\nmatching row is returned. The column to search may be\nspecified by either its ID or title.</p>\n", 11407 "itemtype": "method", 11408 "name": "matchRow", 11409 "params": [ 11410 { 11411 "name": "regexp", 11412 "description": "<p>The regular expression to match</p>\n", 11413 "type": "String|RegExp" 11414 }, 11415 { 11416 "name": "column", 11417 "description": "<p>The column ID (number) or\n title (string)</p>\n", 11418 "type": "String|Integer" 11419 } 11420 ], 11421 "return": { 11422 "description": "TableRow object", 11423
11423 "type": "p5.TableRow" 11424 }, 11425 "example": [ 11426 "\n<div class=\"norender\">\n<code>\n// Given the CSV file \"mammals.csv\"\n// in the project's \"assets\" folder:\n//\n// id,species,name\n// 0,Capra hircus,Goat\n// 1,Panthera pardus,Leopard\n// 2,Equus zebra,Zebra\n\nvar table;\n\nfunction preload() {\n //my table is comma separated value \"csv\"\n //and has a header specifying the columns labels\n table = loadTable('assets/mammals.csv', 'csv', 'header');\n}\n\nfunction setup() {\n //Search using specified regex on a given column, return TableRow object\n var mammal = table.matchRow(new RegExp('ant'), 1);\n print(mammal.getString(1));\n //Output \"Panthera pardus\"\n}\n</code>\n</div>\n" 11427 ], 11428 "class": "p5.Table", 11429 "module": "IO", 11430 "submodule": "Table" 11431 }, 11432 { 11433 "file": "src/io/p5.Table.js", 11434 "line": 455, 11435 "description": "<p>Finds the rows in the Table that match the regular expression provided,\nand returns references to those rows. Returns an array, so for must be\nused to iterate through all the rows, as shown in the example. The\ncolumn to search may be specified by either its ID or title.</p>\n", 11436 "itemtype": "method", 11437 "name": "matchRows", 11438 "params": [ 11439 { 11440 "name": "regexp", 11441 "description": "<p>The regular expression to match</p>\n", 11442 "type": "String" 11443 }, 11444 { 11445 "name": "column", 11446 "description": "<p>The column ID (number) or\n title (string)</p>\n", 11447 "type": "String|Integer", 11448 "optional": true 11449 } 11450 ], 11451 "return": { 11452 "description": "An Array of TableRow objects", 11453 "type": "p5.TableRow[]" 11454 }, 11455 "example": [ 11456 "\n<div class=\"norender\">\n<code>\nvar table;\n\nfunction setup() {\n table = new p5.Table();\n\n table.addColumn('name');\n table.addColumn('type');\n\n var newRow = table.addRow();\n newRow.setString('name', 'Lion');\n newRow.setString('type', 'Mammal');\n\n newRow = table.addRow();\n newRow.setString('name', 'Snake');\n newRow.setString('type', 'Reptile');\n\n newRow = table.addRow();\n newRow.setString('name', 'Mosquito');\n newRow.setString('type', 'Insect');\n\n newRow = table.addRow();\n newRow.setString('name', 'Lizard');\n newRow.setString('type', 'Reptile');\n\n var rows = table.matchRows('R.*', 'type');\n for (var i = 0; i < rows.length; i++) {\n print(rows[i].getString('name') + ': ' + rows[i].getString('type'));\n }\n}\n// Sketch prints:\n// Snake: Reptile\n// Lizard: Reptile\n</code>\n</div>" 11457 ], 11458 "class": "p5.Table", 11459 "module": "IO", 11460 "submodule": "Table" 11461 }, 11462 { 11463 "file": "src/io/p5.Table.js", 11464 "line": 522, 11465 "description": "<p>Retrieves all values in the specified column, and returns them\nas an array. The column may be specified by either its ID or title.</p>\n", 11466 "itemtype": "method", 11467 "name": "getColumn", 11468 "params": [ 11469 { 11470 "name": "column", 11471 "description": "<p>String or Number of the column to return</p>\n", 11472 "type": "String|Number" 11473 } 11474 ], 11475 "return": { 11476 "description": "Array of column values", 11477 "type": "Array" 11478 }, 11479 "example": [ 11480 "\n <div class=\"norender\">\n <code>\n // Given the CSV file \"mammals.csv\"\n // in the project's \"assets\" folder:\n //\n // id,species,name\n // 0,Capra hircus,Goat\n // 1,Panthera pardus,Leopard\n // 2,Equus zebra,Zebra\n\n var table;\n\n function preload() {\n //my table is comma separated value \"csv\"\n //and has a header specifying the columns labels\n table = loadTable('assets/mammals.csv', 'csv', 'header');\n }\n\n function setup() {\n //getColumn returns an array that can be printed directly\n print(table.getColumn('species'));\n //outputs [\"Capra hircus\", \"Panthera pardus\", \"Equus zebra\"]\n }\n </code>\n </div>" 11481 ], 11482 "alt": "no image displayed", 11483 "class": "p5.Table", 11484 "module": "IO", 11485 "submodule": "Table" 11486 }, 11487 { 11488 "file": "src/io/p5.Table.js", 11489 "line": 575, 11490 "description": "<p>Removes all rows from a Table. While all rows are removed,\ncolumns and column titles are maintained.</p>\n", 11491 "itemtype": "method", 11492 "name": "clearRows", 11493 "example": [ 11494 "\n <div class=\"norender\">\n <code>\n // Given the CSV file \"mammals.csv\"\n // in the project's \"assets\" folder:\n //\n // id,species,name\n // 0,Capra hircus,Goat\n // 1,Panthera pardus,Leopard\n // 2,Equus zebra,Zebra\n\n var table;\n\n function preload() {\n //my table is comma separated value \"csv\"\n //and has a header specifying the columns labels\n table = loadTable('assets/mammals.csv', 'csv', 'header');\n }\n\n function setup() {\n table.clearRows();\n print(table.getRowCount() + ' total rows in table');\n print(table.getColumnCount() + ' total columns in table');\n }\n </code>\n </div>" 11495 ], 11496 "alt": "no image displayed", 11497 "class": "p5.Table", 11498 "module": "IO", 11499 "submodule": "Table" 11500 }, 11501 { 11502 "file": "src/io/p5.Table.js", 11503 "line": 617, 11504 "description": "<p>Use addColumn() to add a new column to a Table object.\nTypically, you will want to specify a title, so the column\nmay be easily referenced later by name. (If no title is\nspecified, the new column's title will be null.)</p>\n", 11505 "itemtype": "method", 11506 "name": "addColumn", 11507 "params": [ 11508 { 11509 "name": "title", 11510 "description": "<p>title of the given column</p>\n", 11511 "type": "String", 11512 "optional": true 11513 } 11514 ], 11515 "example": [ 11516 "\n <div class=\"norender\">\n <code>\n // Given the CSV file \"mammals.csv\"\n // in the project's \"assets\" folder:\n //\n // id,species,name\n // 0,Capra hircus,Goat\n // 1,Panthera pardus,Leopard\n // 2,Equus zebra,Zebra\n\n var table;\n\n function preload() {\n //my table is comma separated value \"csv\"\n //and has a header specifying the columns labels\n table = loadTable('assets/mammals.csv', 'csv', 'header');\n }\n\n function setup() {\n table.addColumn('carnivore');\n table.set(0, 'carnivore', 'no');\n table.set(1, 'carnivore', 'yes');\n table.set(2, 'carnivore', 'no');\n\n //print the results\n for (var r = 0; r < table.getRowCount(); r++)\n for (var c = 0; c < table.getColumnCount(); c++)\n print(table.getString(r, c));\n }\n </code>\n </div>" 11517 ], 11518 "alt": "no image displayed", 11519 "class": "p5.Table", 11520 "module": "IO", 11521 "submodule": "Table" 11522 }, 11523 { 11524 "file": "src/io/p5.Table.js", 11525 "line": 668, 11526 "description": "<p>Returns the total number of columns in a Table.</p>\n", 11527 "itemtype": "method", 11528 "name": "getColumnCount", 11529 "return": { 11530 "description": "Number of columns in this table", 11531 "type": "Integer" 11532 }, 11533 "example": [ 11534 "\n <div>\n <code>\n // given the cvs file \"blobs.csv\" in /assets directory\n // ID, Name, Flavor, Shape, Color\n // Blob1, Blobby, Sweet, Blob, Pink\n // Blob2, Saddy, Savory, Blob, Blue\n\n var table;\n\n function preload() {\n table = loadTable('assets/blobs.csv');\n }\n\n function setup() {\n createCanvas(200, 100);\n textAlign(CENTER);\n background(255);\n }\n\n function draw() {\n var numOfColumn = table.getColumnCount();\n text('There are ' + numOfColumn + ' columns in the table.', 100, 50);\n }\n </code>\n </div>" 11535 ], 11536 "class": "p5.Table", 11537 "module": "IO", 11538 "submodule": "Table" 11539 }, 11540 { 11541 "file": "src/io/p5.Table.js", 11542 "line": 704, 11543 "description": "<p>Returns the total number of rows in a Table.</p>\n", 11544 "itemtype": "method", 11545 "name": "getRowCount", 11546 "return": { 11547 "description": "Number of rows in this table", 11548 "type": "Integer" 11549 }, 11550 "example": [ 11551 "\n <div>\n <code>\n // given the cvs file \"blobs.csv\" in /assets directory\n //\n // ID, Name, Flavor, Shape, Color\n // Blob1, Blobby, Sweet, Blob, Pink\n // Blob2, Saddy, Savory, Blob, Blue\n\n var table;\n\n function preload() {\n table = loadTable('assets/blobs.csv');\n }\n\n function setup() {\n createCanvas(200, 100);\n textAlign(CENTER);\n background(255);\n }\n\n function draw() {\n text('There are ' + table.getRowCount() + ' rows in the table.', 100, 50);\n }\n </code>\n </div>" 11552 ], 11553 "class": "p5.Table", 11554 "module": "IO", 11555 "submodule": "Table" 11556 }, 11557 { 11558 "file": "src/io/p5.Table.js", 11559 "line": 740, 11560 "description": "<p>Removes any of the specified characters (or "tokens").</p>\n\n<p>If no column is specified, then the values in all columns and\nrows are processed. A specific column may be referenced by\neither its ID or title.</p>", 11561 "itemtype": "method", 11562 "name": "removeTokens", 11563 "params": [ 11564 { 11565 "name": "chars", 11566 "description": "<p>String listing characters to be removed</p>\n", 11567 "type": "String" 11568 }, 11569 { 11570 "name": "column", 11571 "description": "<p>Column ID (number)\n or name (string)</p>\n", 11572 "type": "String|Integer", 11573 "optional": true 11574 } 11575 ], 11576 "example": [ 11577 "\n <div class=\"norender\"><code>\n function setup() {\n var table = new p5.Table();\n\n table.addColumn('name');\n table.addColumn('type');\n\n var newRow = table.addRow();\n newRow.setString('name', ' $Lion ,');\n newRow.setString('type', ',,,Mammal');\n\n newRow = table.addRow();\n newRow.setString('name', '$Snake ');\n newRow.setString('type', ',,,Reptile');\n\n table.removeTokens(',$ ');\n print(table.getArray());\n }\n\n // prints:\n // 0 \"Lion\" \"Mamal\"\n // 1 \"Snake\" \"Reptile\"\n </code></div>" 11578 ], 11579 "class": "p5.Table", 11580 "module": "IO", 11581 "submodule": "Table" 11582 }, 11583 { 11584 "file": "src/io/p5.Table.js", 11585 "line": 814, 11586 "description": "<p>Trims leading and trailing whitespace, such as spaces and tabs,\nfrom String table values. If no column is specified, then the\nvalues in all columns and rows are trimmed. A specific column\nmay be referenced by either its ID or title.</p>\n", 11587 "itemtype": "method", 11588 "name": "trim", 11589 "params": [ 11590 { 11591 "name": "column", 11592 "description": "<p>Column ID (number)\n or name (string)</p>\n", 11593 "type": "String|Integer", 11594 "optional": true 11595 } 11596 ], 11597 "example": [ 11598 "\n <div class=\"norender\"><code>\n function setup() {\n var table = new p5.Table();\n\n table.addColumn('name');\n table.addColumn('type');\n\n var newRow = table.addRow();\n newRow.setString('name', ' Lion ,');\n newRow.setString('type', ' Mammal ');\n\n newRow = table.addRow();\n newRow.setString('name', ' Snake ');\n newRow.setString('type', ' Reptile ');\n\n table.trim();\n print(table.getArray());\n }\n\n // prints:\n // 0 \"Lion\" \"Mamal\"\n // 1 \"Snake\" \"Reptile\"\n </code></div>" 11599 ], 11600 "class": "p5.Table", 11601 "module": "IO", 11602 "submodule": "Table" 11603 }, 11604 { 11605 "file": "src/io/p5.Table.js", 11606 "line": 878, 11607 "description": "<p>Use removeColumn() to remove an existing column from a Table\nobject. The column to be removed may be identified by either\nits title (a String) or its index value (an int).\nremoveC
11607olumn(0) would remove the first column, removeColumn(1)\nwould remove the second column, and so on.</p>\n", 11608 "itemtype": "method", 11609 "name": "removeColumn", 11610 "params": [ 11611 { 11612 "name": "column", 11613 "description": "<p>columnName (string) or ID (number)</p>\n", 11614 "type": "String|Integer" 11615 } 11616 ], 11617 "example": [ 11618 "\n <div class=\"norender\">\n <code>\n // Given the CSV file \"mammals.csv\"\n // in the project's \"assets\" folder:\n //\n // id,species,name\n // 0,Capra hircus,Goat\n // 1,Panthera pardus,Leopard\n // 2,Equus zebra,Zebra\n\n var table;\n\n function preload() {\n //my table is comma separated value \"csv\"\n //and has a header specifying the columns labels\n table = loadTable('assets/mammals.csv', 'csv', 'header');\n }\n\n function setup() {\n table.removeColumn('id');\n print(table.getColumnCount());\n }\n </code>\n </div>" 11619 ], 11620 "alt": "no image displayed", 11621 "class": "p5.Table", 11622 "module": "IO", 11623 "submodule": "Table" 11624 }, 11625 { 11626 "file": "src/io/p5.Table.js", 11627 "line": 944, 11628 "description": "<p>Stores a value in the Table's specified row and column.\nThe row is specified by its ID, while the column may be specified\nby either its ID or title.</p>\n", 11629 "itemtype": "method", 11630 "name": "set", 11631 "params": [ 11632 { 11633 "name": "row", 11634 "description": "<p>row ID</p>\n", 11635 "type": "Integer" 11636 }, 11637 { 11638 "name": "column", 11639 "description": "<p>column ID (Number)\n or title (String)</p>\n", 11640 "type": "String|Integer" 11641 }, 11642 { 11643 "name": "value", 11644 "description": "<p>value to assign</p>\n", 11645 "type": "String|Number" 11646 } 11647 ], 11648 "example": [ 11649 "\n<div class=\"norender\">\n<code>\n// Given the CSV file \"mammals.csv\"\n// in the project's \"assets\" folder:\n//\n// id,species,name\n// 0,Capra hircus,Goat\n// 1,Panthera pardus,Leopard\n// 2,Equus zebra,Zebra\n\nvar table;\n\nfunction preload() {\n //my table is comma separated value \"csv\"\n //and has a header specifying the columns labels\n table = loadTable('assets/mammals.csv', 'csv', 'header');\n}\n\nfunction setup() {\n table.set(0, 'species', 'Canis Lupus');\n table.set(0, 'name', 'Wolf');\n\n //print the results\n for (var r = 0; r < table.getRowCount(); r++)\n for (var c = 0; c < table.getColumnCount(); c++)\n print(table.getString(r, c));\n}\n</code>\n</div>" 11650 ], 11651 "alt": "no image displayed", 11652 "class": "p5.Table", 11653 "module": "IO", 11654 "submodule": "Table" 11655 }, 11656 { 11657 "file": "src/io/p5.Table.js", 11658 "line": 994, 11659 "description": "<p>Stores a Float value in the Table's specified row and column.\nThe row is specified by its ID, while the column may be specified\nby either its ID or title.</p>\n", 11660 "itemtype": "method", 11661 "name": "setNum", 11662 "params": [ 11663 { 11664 "name": "row", 11665 "description": "<p>row ID</p>\n", 11666 "type": "Integer" 11667 }, 11668 { 11669 "name": "column", 11670 "description": "<p>column ID (Number)\n or title (String)</p>\n", 11671 "type": "String|Integer" 11672 }, 11673 { 11674 "name": "value", 11675 "description": "<p>value to assign</p>\n", 11676 "type": "Number" 11677 } 11678 ], 11679 "example": [ 11680 "\n<div class=\"norender\">\n<code>\n// Given the CSV file \"mammals.csv\"\n// in the project's \"assets\" folder:\n//\n// id,species,name\n// 0,Capra hircus,Goat\n// 1,Panthera pardus,Leopard\n// 2,Equus zebra,Zebra\n\nvar table;\n\nfunction preload() {\n //my table is comma separated value \"csv\"\n //and has a header specifying the columns labels\n table = loadTable('assets/mammals.csv', 'csv', 'header');\n}\n\nfunction setup() {\n table.setNum(1, 'id', 1);\n\n print(table.getColumn(0));\n //[\"0\", 1, \"2\"]\n}\n</code>\n</div>" 11681 ], 11682 "alt": "no image displayed", 11683 "class": "p5.Table", 11684 "module": "IO", 11685 "submodule": "Table" 11686 }, 11687 { 11688 "file": "src/io/p5.Table.js", 11689 "line": 1040, 11690 "description": "<p>Stores a String value in the Table's specified row and column.\nThe row is specified by its ID, while the column may be specified\nby either its ID or title.</p>\n", 11691 "itemtype": "method", 11692 "name": "setString", 11693 "params": [ 11694 { 11695 "name": "row", 11696 "description": "<p>row ID</p>\n", 11697 "type": "Integer" 11698 }, 11699 { 11700 "name": "column", 11701 "description": "<p>column ID (Number)\n or title (String)</p>\n", 11702 "type": "String|Integer" 11703 }, 11704 { 11705 "name": "value", 11706 "description": "<p>value to assign</p>\n", 11707 "type": "String" 11708 } 11709 ], 11710 "example": [ 11711 "\n<div class=\"norender\"><code>\n// Given the CSV file \"mammals.csv\" in the project's \"assets\" folder:\n//\n// id,species,name\n// 0,Capra hircus,Goat\n// 1,Panthera pardus,Leopard\n// 2,Equus zebra,Zebra\n\nvar table;\n\nfunction preload() {\n //my table is comma separated value \"csv\"\n //and has a header specifying the columns labels\n table = loadTable('assets/mammals.csv', 'csv', 'header');\n}\n\nfunction setup() {\n //add a row\n var newRow = table.addRow();\n newRow.setString('id', table.getRowCount() - 1);\n newRow.setString('species', 'Canis Lupus');\n newRow.setString('name', 'Wolf');\n\n print(table.getArray());\n}\n</code></div>" 11712 ], 11713 "alt": "no image displayed", 11714 "class": "p5.Table", 11715 "module": "IO", 11716 "submodule": "Table" 11717 }, 11718 { 11719 "file": "src/io/p5.Table.js", 11720 "line": 1085,
11721 "description": "<p>Retrieves a value from the Table's specified row and column.\nThe row is specified by its ID, while the column may be specified by\neither its ID or title.</p>\n", 11722 "itemtype": "method", 11723 "name": "get", 11724 "params": [ 11725 { 11726 "name": "row", 11727 "description": "<p>row ID</p>\n", 11728 "type": "Integer" 11729 }, 11730 { 11731 "name": "column", 11732 "description": "<p>columnName (string) or\n ID (number)</p>\n", 11733 "type": "String|Integer" 11734 } 11735 ], 11736 "return": { 11737 "description": "", 11738 "type": "String|Number" 11739 }, 11740 "example": [ 11741 "\n<div class=\"norender\">\n<code>\n// Given the CSV file \"mammals.csv\"\n// in the project's \"assets\" folder:\n//\n// id,species,name\n// 0,Capra hircus,Goat\n// 1,Panthera pardus,Leopard\n// 2,Equus zebra,Zebra\n\nvar table;\n\nfunction preload() {\n //my table is comma separated value \"csv\"\n //and has a header specifying the columns labels\n table = loadTable('assets/mammals.csv', 'csv', 'header');\n}\n\nfunction setup() {\n print(table.get(0, 1));\n //Capra hircus\n print(table.get(0, 'species'));\n //Capra hircus\n}\n</code>\n</div>" 11742 ], 11743 "alt": "no image displayed", 11744 "class": "p5.Table", 11745 "module": "IO", 11746 "submodule": "Table" 11747 }, 11748 { 11749 "file": "src/io/p5.Table.js", 11750 "line": 1132, 11751 "description": "<p>Retrieves a Float value from the Table's specified row and column.\nThe row is specified by its ID, while the column may be specified by\neither its ID or title.</p>\n", 11752 "itemtype": "method", 11753 "name": "getNum", 11754 "params": [ 11755 { 11756 "name": "row", 11757 "description": "<p>row ID</p>\n", 11758 "type": "Integer" 11759 }, 11760 { 11761 "name": "column", 11762 "description": "<p>columnName (string) or\n ID (number)</p>\n", 11763 "type": "String|Integer" 11764 } 11765 ], 11766 "return": { 11767 "description": "", 11768 "type": "Number" 11769 }, 11770 "example": [ 11771 "\n<div class=\"norender\">\n<code>\n// Given the CSV file \"mammals.csv\"\n// in the project's \"assets\" folder:\n//\n// id,species,name\n// 0,Capra hircus,Goat\n// 1,Panthera pardus,Leopard\n// 2,Equus zebra,Zebra\n\nvar table;\n\nfunction preload() {\n //my table is comma separated value \"csv\"\n //and has a header specifying the columns labels\n table = loadTable('assets/mammals.csv', 'csv', 'header');\n}\n\nfunction setup() {\n print(table.getNum(1, 0) + 100);\n //id 1 + 100 = 101\n}\n</code>\n</div>" 11772 ], 11773 "alt": "no image displayed", 11774 "class": "p5.Table", 11775 "module": "IO", 11776 "submodule": "Table" 11777 }, 11778 { 11779 "file": "src/io/p5.Table.js", 11780 "line": 1177, 11781 "description": "<p>Retrieves a String value from the Table's specified row and column.\nThe row is specified by its ID, while the column may be specified by\neither its ID or title.</p>\n", 11782 "itemtype": "method", 11783 "name": "getString", 11784 "params": [ 11785 { 11786 "name": "row", 11787 "description": "<p>row ID</p>\n", 11788 "type": "Integer" 11789 }, 11790 { 11791 "name": "column", 11792 "description": "<p>columnName (string) or\n ID (number)</p>\n", 11793 "type": "String|Integer" 11794 } 11795 ], 11796 "return": { 11797 "description": "", 11798 "type": "String" 11799 }, 11800 "example": [ 11801 "\n<div class=\"norender\">\n<code>\n// Given the CSV file \"mammals.csv\"\n// in the project's \"assets\" folder:\n//\n// id,species,name\n// 0,Capra hircus,Goat\n// 1,Panthera pardus,Leopard\n// 2,Equus zebra,Zebra\n\nvar table;\n\nfunction preload() {\n // table is comma separated value \"CSV\"\n // and has specifiying header for column labels\n table = loadTable('assets/mammals.csv', 'csv', 'header');\n}\n\nfunction setup() {\n print(table.getString(0, 0)); // 0\n print(table.getString(0, 1)); // Capra hircus\n print(table.getString(0, 2)); // Goat\n print(table.getString(1, 0)); // 1\n print(table.getString(1, 1)); // Panthera pardus\n print(table.getString(1, 2)); // Leopard\n print(table.getString(2, 0)); // 2\n print(table.getString(2, 1)); // Equus zebra\n print(table.getString(2, 2)); // Zebra\n}\n</code>\n</div>" 11802 ], 11803 "alt": "no image displayed", 11804 "class": "p5.Table", 11805 "module": "IO", 11806 "submodule": "Table" 11807 }, 11808 { 11809 "file": "src/io/p5.Table.js", 11810 "line": 1230, 11811 "description": "<p>Retrieves all table data and returns as an object. If a column name is\npassed in, each row object will be stored with that attribute as its\ntitle.</p>\n", 11812 "itemtype": "method", 11813 "name": "getObject", 11814 "params": [ 11815 { 11816 "name": "headerColumn", 11817 "description": "<p>Name of the column which should be used to\n title each row object (optional)</p>\n", 11818 "type": "String", 11819 "optional": true 11820 } 11821 ], 11822 "return": { 11823 "description": "", 11824 "type": "Object" 11825 }, 11826 "example": [ 11827 "\n<div class=\"norender\">\n<code>\n// Given the CSV file \"mammals.csv\"\n// in the project's \"assets\" folder:\n//\n// id,species,name\n// 0,Capra hircus,Goat\n// 1,Panthera pardus,Leopard\n// 2,Equus zebra,Zebra\n\nvar table;\n\nfunction preload() {\n //my table is comma separated value \"csv\"\n //and has a header specifying the columns labels\n table = loadTable('assets/mammals.csv', 'csv', 'header');\n}\n\nfunction setup() {\n var tableObject = table.getObject();\n\n print(tableObject);\n //outputs an object\n}\n</code>\n</div>" 11828 ], 11829 "alt": "no image displayed", 11830 "class": "p5.Table", 11831 "module": "IO", 11832 "submodule": "Table" 11833 }, 11834 { 11835 "file": "src/io/p5.Table.js", 11836 "line": 1294, 11837 "description": "<p>Retrieves all table data and returns it as a multidimensional array.</p>\n", 11838 "itemtype": "method", 11839 "name": "getArray", 11840 "return": { 11841 "description": "", 11842 "type": "Array" 11843 }, 11844 "example": [ 11845 "\n<div class=\"norender\">\n<code>\n// Given the CSV file \"mammals.csv\"\n// in the project's \"assets\" folder\n//\n// id,species,name\n// 0,Capra hircus,Goat\n// 1,Panthera pardus,Leoperd\n// 2,Equus zebra,Zebra\n\nvar table;\n\nfunction preload() {\n // table is comma separated value \"CSV\"\n // and has specifiying header for column labels\n table = loadTable('assets/mammals.csv', 'csv', 'header');\n}\n\nfunction setup() {\n var tableArray = table.getArray();\n for (var i = 0; i < tableArray.length;
11845 i++) {\n print(tableArray[i]);\n }\n}\n</code>\n</div>" 11846 ], 11847 "alt": "no image displayed", 11848 "class": "p5.Table", 11849 "module": "IO", 11850 "submodule": "Table" 11851 }, 11852 { 11853 "file": "src/io/p5.TableRow.js", 11854 "line": 42, 11855 "description": "<p>Stores a value in the TableRow's specified column.\nThe column may be specified by either its ID or title.</p>\n", 11856 "itemtype": "method", 11857 "name": "set", 11858 "params": [ 11859 { 11860 "name": "column", 11861 "description": "<p>Column ID (Number)\n or Title (String)</p>\n", 11862 "type": "String|Integer" 11863 }, 11864 { 11865 "name": "value", 11866 "description": "<p>The value to be stored</p>\n", 11867 "type": "String|Number" 11868 } 11869 ], 11870 "example": [ 11871 "\n <div class=\"norender\"><code>\n // Given the CSV file \"mammals.csv\" in the project's \"assets\" folder:\n //\n // id,species,name\n // 0,Capra hircus,Goat\n // 1,Panthera pardus,Leopard\n // 2,Equus zebra,Zebra\n\n var table;\n\n function preload() {\n //my table is comma separated value \"csv\"\n //and has a header specifying the columns labels\n table = loadTable('assets/mammals.csv', 'csv', 'header');\n }\n\n function setup() {\n var rows = table.getRows();\n for (var r = 0; r < rows.length; r++) {\n rows[r].set('name', 'Unicorn');\n }\n\n //print the results\n print(table.getArray());\n }\n </code></div>" 11872 ], 11873 "alt": "no image displayed", 11874 "class": "p5.TableRow", 11875 "module": "IO", 11876 "submodule": "Table" 11877 }, 11878 { 11879 "file": "src/io/p5.TableRow.js", 11880 "line": 104, 11881 "description": "<p>Stores a Float value in the TableRow's specified column.\nThe column may be specified by either its ID or title.</p>\n", 11882 "itemtype": "method", 11883 "name": "setNum", 11884 "params": [ 11885 { 11886 "name": "column", 11887 "description": "<p>Column ID (Number)\n or Title (String)</p>\n", 11888 "type": "String|Integer" 11889 }, 11890 { 11891 "name": "value", 11892 "description": "<p>The value to be stored\n as a Float</p>\n", 11893 "type": "Number|String" 11894 } 11895 ], 11896 "example": [ 11897 "\n <div class=\"norender\"><code>\n // Given the CSV file \"mammals.csv\" in the project's \"assets\" folder:\n //\n // id,species,name\n // 0,Capra hircus,Goat\n // 1,Panthera pardus,Leopard\n // 2,Equus zebra,Zebra\n\n var table;\n\n function preload() {\n //my table is comma separated value \"csv\"\n //and has a header specifying the columns labels\n table = loadTable('assets/mammals.csv', 'csv', 'header');\n }\n\n function setup() {\n var rows = table.getRows();\n for (var r = 0; r < rows.length; r++) {\n rows[r].setNum('id', r + 10);\n }\n\n print(table.getArray());\n }\n </code></div>" 11898 ], 11899 "alt": "no image displayed", 11900 "class": "p5.TableRow", 11901 "module": "IO", 11902 "submodule": "Table" 11903 }, 11904 { 11905 "file": "src/io/p5.TableRow.js", 11906 "line": 148, 11907 "description": "<p>Stores a String value in the TableRow's specified column.\nThe column may be specified by either its ID or title.</p>\n", 11908 "itemtype": "method", 11909 "name": "setString", 11910 "params": [ 11911 { 11912 "name": "column", 11913 "description": "<p>Column ID (Number)\n or Title (String)</p>\n", 11914 "type": "String|Integer" 11915 }, 11916 { 11917 "name": "value", 11918 "description": "<p>The value to be stored\n as a String</p>\n", 11919 "type": "String|Number|Boolean|Object" 11920 } 11921 ], 11922 "example": [ 11923 "\n <div class=\"norender\"><code>\n // Given the CSV file \"mammals.csv\" in the project's \"assets\" folder:\n //\n // id,species,name\n // 0,Capra hircus,Goat\n // 1,Panthera pardus,Leopard\n // 2,Equus zebra,Zebra\n\n var table;\n\n function preload() {\n //my table is comma separated value \"csv\"\n //and has a header specifying the columns labels\n table = loadTable('assets/mammals.csv', 'csv', 'header');\n }\n\n function setup() {\n var rows = table.getRows();\n for (var r = 0; r < rows.length; r++) {\n var name = rows[r].getString('name');\n rows[r].setString('name', 'A ' + name + ' named George');\n }\n\n print(table.getArray());\n }\n </code></div>" 11924 ], 11925 "alt": "no image displayed", 11926 "class": "p5.TableRow", 11927 "module": "IO", 11928 "submodule": "Table" 11929 }, 11930 { 11931 "file": "src/io/p5.TableRow.js", 11932 "line": 193, 11933 "description": "<p>Retrieves a value from the TableRow's specified column.\nThe column may be specified by either its ID or title.</p>\n", 11934 "itemtype": "method", 11935 "name": "get", 11936 "params": [ 11937 { 11938 "name": "column", 11939 "description": "<p>columnName (string) or\n ID (number)</p>\n", 11940 "type": "String|Integer" 11941 } 11942 ], 11943 "return": { 11944 "description": "", 11945 "type": "String|Number" 11946 }, 11947 "example": [ 11948 "\n <div class=\"norender\"><code>\n // Given the CSV file \"mammals.csv\" in the project's \"assets\" folder:\n //\n // id,species,name\n // 0,Capra hircus,Goat\n // 1,Panthera pardus,Leopard\n // 2,Equus zebra,Zebra\n\n var table;\n\n function preload() {\n //my table is comma separated value \"csv\"\n //and has a header specifying the columns labels\n table = loadTable('assets/mammals.csv', 'csv', 'header');\n }\n\n function setup() {\n var names = [];\n var rows = table.getRows();\n for (var r = 0; r < rows.length; r++) {\n names.push(rows[r].get('name'));\n }\n\n print(names);\n }\n </code></div>" 11949 ], 11950 "alt": "no image displayed", 11951 "class": "p5.TableRow", 11952 "module": "IO", 11953 "submodule": "Table" 11954 }, 11955 { 11956 "file": "src/io/p5.TableRow.js", 11957 "line": 241, 11958 "description": "<p>Retrieves a Float value from the TableRow's specified\ncolumn. The column may be specified by either its ID or\ntitle.</p>\n", 11959 "itemtype": "method", 11960 "name": "getNum", 11961 "params": [ 11962 { 11963 "name": "column", 11964 "description": "<p>columnName (string) or\n ID (number)</p>\n", 11965 "type": "String|Integer" 11966 } 11967 ], 11968 "return": { 11969 "description": "Float Floating point number", 11970 "type": "Number" 11971 }, 11972 "example": [ 11973 "\n <div class=\"norender\"><code>\n // Given the CSV file \"mammals.csv\" in the project's \"assets\" folder:\n //\n // id,species,name\n // 0,Capra hircus,Goat\n // 1,Panthera pardus,Leopard\n // 2,Equus zebra,Zebra\n\n var table;\n\n function preload() {\n //my table is comma separated value \"csv\"\n //and has a header specifying the columns labels\n table = loadTable('assets/mammals.csv', 'csv', 'header');\n }\n\n function setup() {\n var rows = table.getRows();\n var minId = Infinity;\n var maxId = -Infinity;\n for (var r = 0; r < rows.length; r++) {\n var id = rows[r].getNum('id');\n minId = min(minId, id);\n maxId = min(maxId, id);\n }\n print('minimum id = ' + minId + ', maximum id = ' + maxId);\n }\n </code></div>" 11974 ], 11975 "alt": "no image displayed", 11976 "class": "p5.TableRow", 11977 "module": "IO", 11978 "submodule": "Table" 11979 }, 11980 { 11981 "file": "src/io/p5.TableRow.js", 11982 "line": 297, 11983 "description": "<p>Retrieves an String value from the TableRow's specified\ncolumn. The column may be specified by either its ID or\ntitle.</p>\n", 11984 "itemtype": "method", 11985 "name": "getString", 11986 "params": [ 11987 { 11988 "name": "column", 11989 "description": "<p>columnName (string) or\n ID (number)</p>\n", 11990 "type": "String|Integer" 11991 } 11992 ], 11993 "return": { 11994 "description": "String", 11995 "type": "String" 11996 }, 11997 "example": [ 11998 "\n <div class=\"norender\"><code>\n // Given the CSV file \"mammals.csv\" in the project's \"assets\" folder:\n //\n // id,species,name\n // 0,Capra hircus,Goat\n // 1,Panthera pardus,Leopard\n // 2,Equus zebra,Zebra\n\n var table;\n\n function preload() {\n //my table is comma separated value \"csv\"\n //and has a header specifying the columns labels\n table = loadTable('assets/mammals.csv', 'csv', 'header');\n }\n\n function setup() {\n var rows = table.getRows();\n var longest = '';\n for (var r = 0; r < rows.length; r++) {\n var species = rows[r].getString('species');\n if (longest.length < species.length) {\n longest = species;\n }\n }\n\n print('longest: ' + longest);\n }\n </code></div>" 11999 ], 12000 "alt": "no image displayed", 12001 "class": "p5.TableRow", 12002 "module": "IO", 12003 "submodule": "Table" 12004 }, 12005 { 12006 "file": "src/io/p5.XML.js", 12007 "line": 64, 12008 "description": "<p>Gets a copy of the element's parent. Returns the parent as another\np5.XML object.</p>\n", 12009 "itemtype": "method", 12010 "name": "getParent", 12011 "return": { 12012 "description": "element parent", 12013 "type": "p5.XML" 12014 }, 12015 "example": [ 12016 "\n<div class='norender'><code>\n// The following short XML file called \"mammals.xml\" is parsed\n// in the code below.\n//\n// <?xml version=\"1.0\"?>\n// <mammals>\n// <animal id=\"0\" species=\"Capra hircus\">Goat</animal>\n// <animal id=\"1\" species=\"Panthera pardus\">Leopard</animal>\n// <animal id=\"2\" species=\"Equus zebra\">Zebra</animal>\n// </mammals>\n\nvar xml;\n\nfunction preload() {\n xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n var children = xml.getChildren('animal');\n var parent = children[1].getParent();\n print(parent.getName());\n}\n\n// Sketch prints:\n// mammals\n</code></div>" 12017 ], 12018 "class": "p5.XML", 12019 "module": "IO", 12020 "submodule": "XML" 12021 }, 12022 { 12023 "file": "src/io/p5.XML.js", 12024 "line": 102, 12025 "description": "<p>Gets the element's full name, which is returned as a String.</p>\n", 12026 "itemtype": "method", 12027 "name": "getName", 12028 "return": { 12029 "description": "the name of the node", 12030 "type": "String" 12031 }, 12032 "example": [ 12033 "<animal\n <div class='norender'><code>\n // The following short XML file called \"mammals.xml\" is parsed\n // in the code below.\n //\n // <?xml version=\"1.0\"?>\n // <mammals>\n // <animal id=\"0\" species=\"Capra hircus\">Goat</animal>\n // <animal id=\"1\" species=\"Panthera pardus\">Leopard</animal>\n // <animal id=\"2\" species=\"Equus zebra\">Zebra</animal>\n // </mammals>\n\n var xml;\n\n function preload() {\n xml = loadXML('assets/mammals.xml');\n }\n\n function setup() {\n print(xml.getName());\n }\n\n // Sketch prints:\n // mammals\n </code></div>" 12034 ], 12035 "class": "p5.XML", 12036 "module": "IO", 12037 "submodule": "XML" 12038 }, 12039 { 12040 "file": "src/io/p5.XML.js", 12041 "line": 137, 12042 "description": "<p>Sets the element's name, which is specified as a String.</p>\n", 12043 "itemtype": "method", 12044 "name": "setName", 12045 "params": [ 12046 { 12047 "name": "the", 12048 "description": "<p>new name of the node</p>\n", 12049 "type": "String" 12050 } 12051 ], 12052 "example": [ 12053 "<animal\n<div class='norender'><code>\n// The following short XML file called \"mammals.xml\" is parsed\n// in the code below.\n//\n// <?xml version=\"1.0\"?>\n// <mammals>\n// <animal id=\"0\" species=\"Capra hircus\">Goat</animal>\n// <animal id=\"1\" species=\"Panthera pardus\">Leopard</animal>\n// <animal id=\"2\" species=\"Equus zebra\">Zebra</animal>\n// </mammals>\n\nvar xml;\n\nfunction preload() {\n xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n print(xml.getName());\n xml.setName('fish');\n print(xml.getName());\n}\n\n// Sketch prints:\n// mammals\n// fish\n</code></div>" 12054 ], 12055 "class": "p5.XML", 12056 "module": "IO", 12057 "submodule": "XML" 12058 }, 12059 { 12060 "file": "src/io/p5.XML.js", 12061 "line": 175, 12062 "description": "<p>Checks whether or not the element has any children, and returns the result\nas a boolean.</p>\n", 12063 "itemtype": "method", 12064 "name": "hasChildren", 12065 "return": { 12066 "description": "", 12067 "type": "Boolean" 12068 }, 12069 "example": [ 12070 "<animal\n<div class='norender'><code>\n// The following short XML file called \"mammals.xml\" is parsed\n// in the code below.\n//\n// <?xml version=\"1.0\"?>\n// <mammals>\n// <animal id=\"0\" species=\"Capra hircus\">Goat</animal>\n// <animal id=\"1\" species=\"Panthera pardus\">Leopard</animal>\n// <animal id=\"2\" species=\"Equus zebra\">Zebra</animal>\n// </mammals>\n\nvar xml;\n\nfunction preload() {\n xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n print(xml.hasChildren());\n}\n\n// Sketch prints:\n// true\n</code></div>" 12071 ], 12072 "class": "p5.XML", 12073 "module": "IO", 12074 "submodule": "XML" 12075 }, 12076 { 12077 "file": "src/io/p5.XML.js", 12078 "line": 211, 12079 "description": "<p>Get the names of all of the element's children, and returns the names as an\narray of Strings. This is the same as looping through and calling getName()\non each child element individually.</p>\n", 12080 "itemtype": "method", 12081 "name": "listChildren", 12082 "return": { 12083 "description": "names of the children of the element", 12084 "type": "String[]" 12085 }, 12086 "example": [ 12087 "<animal\n<div class='norender'><code>\n// The following short XML file called \"mammals.xml\" is parsed\n// in the code below.\n//\n// <?xml version=\"1.0\"?>\n// <mammals>\n// <animal id=\"0\" species=\"Capra hircus\">Goat</animal>\n// <animal id=\"1\" species=\"Panthera pardus\">Leopard</animal>\n// <animal id=\"2\" species=\"Equus zebra\">Zebra</animal>\n// </mammals>\n\nvar xml;\n\nfunction preload() {\n xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n print(xml.listChildren());\n}\n\n// Sketch prints:\n// [\"animal\", \"animal\", \"animal\"]\n</code></div>" 12088 ], 12089 "class": "p5.XML", 12090 "module": "IO", 12091 "submodule": "XML" 12092 }, 12093 { 12094 "file": "src/io/p5.XML.js", 12095 "line": 250, 12096 "description": "<p>Returns all of the element's children as an array of p5.XML objects. When\nthe name parameter is specified, then it will return all children that match\nthat name.</p>\n", 12097 "itemtype": "method", 12098 "name": "getChildren", 12099 "params": [ 12100 { 12101
12101 "name": "name", 12102 "description": "<p>element name</p>\n", 12103 "type": "String", 12104 "optional": true 12105 } 12106 ], 12107 "return": { 12108 "description": "children of the element", 12109 "type": "p5.XML[]" 12110 }, 12111 "example": [ 12112 "<animal\n<div class='norender'><code>\n// The following short XML file called \"mammals.xml\" is parsed\n// in the code below.\n//\n// <?xml version=\"1.0\"?>\n// <mammals>\n// <animal id=\"0\" species=\"Capra hircus\">Goat</animal>\n// <animal id=\"1\" species=\"Panthera pardus\">Leopard</animal>\n// <animal id=\"2\" species=\"Equus zebra\">Zebra</animal>\n// </mammals>\n\nvar xml;\n\nfunction preload() {\n xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n var animals = xml.getChildren('animal');\n\n for (var i = 0; i < animals.length; i++) {\n print(animals[i].getContent());\n }\n}\n\n// Sketch prints:\n// \"Goat\"\n// \"Leopard\"\n// \"Zebra\"\n</code></div>" 12113 ], 12114 "class": "p5.XML", 12115 "module": "IO", 12116 "submodule": "XML" 12117 }, 12118 { 12119 "file": "src/io/p5.XML.js", 12120 "line": 300, 12121 "description": "<p>Returns the first of the element's children that matches the name parameter\nor the child of the given index.It returns undefined if no matching\nchild is found.</p>\n", 12122 "itemtype": "method", 12123 "name": "getChild", 12124 "params": [ 12125 { 12126 "name": "name", 12127 "description": "<p>element name or index</p>\n", 12128 "type": "String|Integer" 12129 } 12130 ], 12131 "return": { 12132 "description": "", 12133 "type": "p5.XML" 12134 }, 12135 "example": [ 12136 "<animal\n<div class='norender'><code>\n// The following short XML file called \"mammals.xml\" is parsed\n// in the code below.\n//\n// <?xml version=\"1.0\"?>\n// <mammals>\n// <animal id=\"0\" species=\"Capra hircus\">Goat</animal>\n// <animal id=\"1\" species=\"Panthera pardus\">Leopard</animal>\n// <animal id=\"2\" species=\"Equus zebra\">Zebra</animal>\n// </mammals>\n\nvar xml;\n\nfunction preload() {\n xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n var firstChild = xml.getChild('animal');\n print(firstChild.getContent());\n}\n\n// Sketch prints:\n// \"Goat\"\n</code></div>\n<div class='norender'><code>\nvar xml;\n\nfunction preload() {\n xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n var secondChild = xml.getChild(1);\n print(secondChild.getContent());\n}\n\n// Sketch prints:\n// \"Leopard\"\n</code></div>" 12137 ], 12138 "class": "p5.XML", 12139 "module": "IO", 12140 "submodule": "XML" 12141 }, 12142 { 12143 "file": "src/io/p5.XML.js", 12144 "line": 361, 12145 "description": "<p>Appends a new child to the element. The child can be specified with\neither a String, which will be used as the new tag's name, or as a\nreference to an existing p5.XML object.\nA reference to the newly created child is returned as an p5.XML object.</p>\n", 12146 "itemtype": "method", 12147 "name": "addChild", 12148 "params": [ 12149 { 12150 "name": "node", 12151 "description": "<p>a p5.XML Object which will be the child to be added</p>\n", 12152 "type": "p5.XML" 12153 } 12154 ], 12155 "example": [ 12156 "\n<div class='norender'><code>\n// The following short XML file called \"mammals.xml\" is parsed\n// in the code below.\n//\n// <?xml version=\"1.0\"?>\n// <mammals>\n// <animal id=\"0\" species=\"Capra hircus\">Goat</animal>\n// <animal id=\"1\" species=\"Panthera pardus\">Leopard</animal>\n// <animal id=\"2\" species=\"Equus zebra\">Zebra</animal>\n// </mammals>\n\nvar xml;\n\nfunction preload() {\n xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n var child = new p5.XML();\n child.setAttribute('id', '3');
12156\n child.setAttribute('species', 'Ornithorhynchus anatinus');\n child.setContent('Platypus');\n xml.addChild(child);\n\n var animals = xml.getChildren('animal');\n print(animals[animals.length - 1].getContent());\n}\n\n// Sketch prints:\n// \"Goat\"\n// \"Leopard\"\n// \"Zebra\"\n</code></div>" 12157 ], 12158 "class": "p5.XML", 12159 "module": "IO", 12160 "submodule": "XML" 12161 }, 12162 { 12163 "file": "src/io/p5.XML.js", 12164 "line": 412, 12165 "description": "<p>Removes the element specified by name or index.</p>\n", 12166 "itemtype": "method", 12167 "name": "removeChild", 12168 "params": [ 12169 { 12170 "name": "name", 12171 "description": "<p>element name or index</p>\n", 12172 "type": "String|Integer" 12173 } 12174 ], 12175 "example": [ 12176 "\n<div class='norender'><code>\n// The following short XML file called \"mammals.xml\" is parsed\n// in the code below.\n//\n// <?xml version=\"1.0\"?>\n// <mammals>\n// <animal id=\"0\" species=\"Capra hircus\">Goat</animal>\n// <animal id=\"1\" species=\"Panthera pardus\">Leopard</animal>\n// <animal id=\"2\" species=\"Equus zebra\">Zebra</animal>\n// </mammals>\n\nvar xml;\n\nfunction preload() {\n xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n xml.removeChild('animal');\n var children = xml.getChildren();\n for (var i = 0; i < children.length; i++) {\n print(children[i].getContent());\n }\n}\n\n// Sketch prints:\n// \"Leopard\"\n// \"Zebra\"\n</code></div>\n<div class='norender'><code>\nvar xml;\n\nfunction preload() {\n xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n xml.removeChild(1);\n var children = xml.getChildren();\n for (var i = 0; i < children.length; i++) {\n print(children[i].getContent());\n }\n}\n\n// Sketch prints:\n// \"Goat\"\n// \"Zebra\"\n</code></div>" 12177 ], 12178 "class": "p5.XML", 12179 "module": "IO", 12180 "submodule": "XML" 12181 }, 12182 { 12183 "file": "src/io/p5.XML.js", 12184 "line": 484, 12185 "description": "<p>Counts the specified element's number of attributes, returned as an Number.</p>\n", 12186 "itemtype": "method", 12187 "name": "getAttributeCount", 12188 "return": { 12189 "description": "", 12190 "type": "Integer" 12191 }, 12192 "example": [ 12193 "\n<div class='norender'><code>\n// The following short XML file called \"mammals.xml\" is parsed\n// in the code below.\n//\n// <?xml version=\"1.0\"?>\n// <mammals>\n// <animal id=\"0\" species=\"Capra hircus\">Goat</animal>\n// <animal id=\"1\" species=\"Panthera pardus\">Leopard</animal>\n// <animal id=\"2\" species=\"Equus zebra\">Zebra</animal>\n// </mammals>\n\nvar xml;\n\nfunction preload() {\n xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n var firstChild = xml.getChild('animal');\n print(firstChild.getAttributeCount());\n}\n\n// Sketch prints:\n// 2\n</code></div>" 12194 ], 12195 "class": "p5.XML", 12196 "module": "IO", 12197 "submodule": "XML" 12198 }, 12199 { 12200 "file": "src/io/p5.XML.js", 12201 "line": 520, 12202 "description": "<p>Gets all of the specified element's attributes, and returns them as an\narray of Strings.</p>\n", 12203 "itemtype": "method", 12204 "name": "listAttributes", 12205 "return": { 12206 "description": "an array of strings containing the names of attributes", 12207 "type": "String[]" 12208 }, 12209 "example": [ 12210 "\n<div class='norender'><code>\n// The following short XML file called \"mammals.xml\" is parsed\n// in the code below.\n//\n// <?xml version=\"1.0\"?>\n// <mammals>\n// <animal id=\"0\" species=\"Capra hircus\">Goat</animal>\n// <animal id=\"1\" species=\"Panthera pardus\">Leopard</animal>\n// <animal id=\"2\" species=\"Equus zebra\">Zebra</animal>\n// </mammals>\n\nvar xml;\n\nfunction preload() {\n xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n var firstChild = xml.getChild('animal');\n print(firstChild.listAttributes());\n}\n\n// Sketch prints:\n// [\"id\", \"species\"]\n</code></div>" 12211 ], 12212 "class": "p5.XML", 12213 "module": "IO", 12214 "submodule": "XML" 12215 }, 12216 { 12217 "file": "src/io/p5.XML.js", 12218 "line": 557, 12219 "description": "<p>Checks whether or not an element has the specified attribute.</p>\n", 12220 "itemtype": "method", 12221 "name": "hasAttribute", 12222 "params": [ 12223 { 12224 "name": "the", 12225 "description": "<p>attribute to be checked</p>\n", 12226 "type": "String" 12227 } 12228 ], 12229 "return": { 12230 "description": "true if attribute found else false", 12231 "type": "Boolean" 12232 }, 12233 "example": [ 12234 "\n <div class='norender'><code>\n // The following short XML file called \"mammals.xml\" is parsed\n // in the code below.\n //\n // <?xml version=\"1.0\"?>\n // <mammals>\n // <animal id=\"0\" species=\"Capra hircus\">Goat</animal>\n // <animal id=\"1\" species=\"Panthera pardus\">Leopard</animal>\n // <animal id=\"2\" species=\"Equus zebra\">Zebra</animal>\n // </mammals>\n\n var xml;\n\n function preload() {\n xml = loadXML('assets/mammals.xml');\n }\n\n function setup() {\n var firstChild = xml.getChild('animal');\n print(firstChild.hasAttribute('species'));\n print(firstChild.hasAttribute('color'));\n }\n\n // Sketch prints:\n // true\n // false\n </code></div>" 12235 ], 12236 "class": "p5.XML", 12237 "module": "IO", 12238 "submodule": "XML" 12239 }, 12240 { 12241 "file": "src/io/p5.XML.js", 12242 "line": 596, 12243 "description": "<p>Returns an attribute value of the element as an Number. If the defaultValue\nparameter is specified and the attribute doesn't exist, then defaultValue\nis returned. If no defaultValue is specified and the attribute doesn't\nexist, the value 0 is returned.</p>\n", 12244 "itemtype": "method", 12245 "name": "getNum", 12246 "params": [ 12247 { 12248 "name": "name", 12249 "description": "<p>the non-null full name of the attribute</p>\n", 12250 "type": "String" 12251 }, 12252 { 12253 "name": "defaultValue", 12254 "description": "<p>the default value of the attribute</p>\n", 12255 "type": "Number", 12256 "optional": true 12257 } 12258 ], 12259 "return": { 12260 "description": "", 12261 "type": "Number" 12262 }, 12263 "example": [ 12264 "\n<div class='norender'><code>\n// The following short XML file called \"mammals.xml\" is parsed\n// in the code below.\n//\n// <?xml version=\"1.0\"?>\n// <mammals>\n// <animal id=\"0\" species=\"Capra hircus\">Goat</animal>\n// <animal id=\"1\" species=\"Panthera pardus\">Leopard</animal>\n// <animal id=\"2\" species=\"Equus zebra\">Zebra</animal>\n// </mammals>\n\nvar xml;\n\nfunction preload() {\n xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n var firstChild = xml.getChild('animal');\n print(firstChild.getNum('id'));\n}\n\n// Sketch prints:\n// 0\n</code></div>" 12265 ], 12266 "class": "p5.XML", 12267 "module": "IO", 12268 "submodule": "XML" 12269 }, 12270 { 12271 "file": "src/io/p5.XML.js", 12272 "line": 637, 12273 "description": "<p>Returns an attribute value of the element as an String. If the defaultValue\nparameter is specified and the attribute doesn't exist, then defaultValue\nis returned. If no defaultValue is specified and the attribute doesn't\nexist, null is returned.</p>\n", 12274 "itemtype": "method", 12275 "name": "getString", 12276 "params": [ 12277 { 12278 "name": "name", 12279 "description": "<p>the non-null full name of the attribute</p>\n", 12280 "type": "String" 12281 }, 12282 { 12283 "name": "defaultValue", 12284 "description": "<p>the default value of the attribute</p>\n", 12285 "type": "Number", 12286 "optional": true 12287 } 12288 ], 12289 "return": { 12290 "description": "", 12291 "type": "String" 12292 }, 12293 "example": [ 12294 "\n<div class='norender'><code>\n// The following short XML file called \"mammals.xml\" is parsed\n// in the code below.\n//\n// <?xml version=\"1.0\"?>\n// <mammals>\n// <animal id=\"0\" species=\"Capra hircus\">Goat</animal>\n// <animal id=\"1\" species=\"Panthera pardus\">Leopard</animal>\n// <animal id=\"2\" species=\"Equus zebra\">Zebra</animal>\n// </mammals>\n\nvar xml;\n\nfunction preload() {\n xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n var firstChild = xml.getChild('animal');
12294\n print(firstChild.getString('species'));\n}\n\n// Sketch prints:\n// \"Capra hircus\"\n</code></div>" 12295 ], 12296 "class": "p5.XML", 12297 "module": "IO", 12298 "submodule": "XML" 12299 }, 12300 { 12301 "file": "src/io/p5.XML.js", 12302 "line": 678, 12303 "description": "<p>Sets the content of an element's attribute. The first parameter specifies\nthe attribute name, while the second specifies the new content.</p>\n", 12304 "itemtype": "method", 12305 "name": "setAttribute", 12306 "params": [ 12307 { 12308 "name": "name", 12309 "description": "<p>the full name of the attribute</p>\n", 12310 "type": "String" 12311 }, 12312 { 12313 "name": "value", 12314 "description": "<p>the value of the attribute</p>\n", 12315 "type": "Number|String|Boolean" 12316 } 12317 ], 12318 "example": [ 12319 "\n<div class='norender'><code>\n// The following short XML file called \"mammals.xml\" is parsed\n// in the code below.\n//\n// <?xml version=\"1.0\"?>\n// <mammals>\n// <animal id=\"0\" species=\"Capra hircus\">Goat</animal>\n// <animal id=\"1\" species=\"Panthera pardus\">Leopard</animal>\n// <animal id=\"2\" species=\"Equus zebra\">Zebra</animal>\n// </mammals>\n\nvar xml;\n\nfunction preload() {\n xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n var firstChild = xml.getChild('animal');\n print(firstChild.getString('species'));\n firstChild.setAttribute('species', 'Jamides zebra');\n print(firstChild.getString('species'));\n}\n\n// Sketch prints:\n// \"Capra hircus\"\n// \"Jamides zebra\"\n</code></div>" 12320 ], 12321 "class": "p5.XML", 12322 "module": "IO", 12323 "submodule": "XML" 12324 }, 12325 { 12326 "file": "src/io/p5.XML.js", 12327 "line": 721, 12328 "description": "<p>Returns the content of an element. If there is no such content,\ndefaultValue is returned if specified, otherwise null is returned.</p>\n", 12329 "itemtype": "method", 12330 "name": "getContent", 12331 "params": [ 12332 { 12333 "name": "defaultValue", 12334 "description": "<p>value returned if no content is found</p>\n", 12335 "type": "String", 12336 "optional": true 12337 } 12338 ], 12339 "return": { 12340 "description": "", 12341 "type": "String" 12342 }, 12343 "example": [ 12344 "\n<div class='norender'><code>\n// The following short XML file called \"mammals.xml\" is parsed\n// in the code below.\n//\n// <?xml version=\"1.0\"?>\n// <mammals>\n// <animal id=\"0\" species=\"Capra hircus\">Goat</animal>\n// <animal id=\"1\" species=\"Panthera pardus\">Leopard</animal>\n// <animal id=\"2\" species=\"Equus zebra\">Zebra</animal>\n// </mammals>\n\nvar xml;\n\nfunction preload() {\n xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n var firstChild = xml.getChild('animal');\n print(firstChild.getContent());\n}\n\n// Sketch prints:\n// \"Goat\"\n</code></div>" 12345 ], 12346 "class": "p5.XML", 12347 "module": "IO", 12348 "submodule": "XML" 12349 }, 12350 { 12351 "file": "src/io/p5.XML.js", 12352 "line": 759, 12353 "description": "<p>Sets the element's content.</p>\n", 12354 "itemtype": "method", 12355 "name": "setContent", 12356 "params": [ 12357 { 12358 "name": "text", 12359 "description": "<p>the new content</p>\n", 12360 "type": "String" 12361 } 12362 ], 12363 "example": [ 12364 "\n<div class='norender'><code>\n// The following short XML file called \"mammals.xml\" is parsed\n// in the code below.\n//\n// <?xml version=\"1.0\"?>\n// <mammals>\n// <animal id=\"0\" species=\"Capra hircus\">Goat</animal>\n// <animal id=\"1\" species=\"Panthera pardus\">Leopard</animal>\n// <animal id=\"2\" species=\"Equus zebra\">Zebra</animal>\n// </mammals>\n\nvar xml;\n\nfunction preload() {\n xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n var firstChild = xml.getChild('animal');\n print(firstChild.getContent());\n firstChild.setContent('Mountain Goat');\n print(firstChild.getContent());\n}\n\n// Sketch prints:\n// \"Goat\"\n// \"Mountain Goat\"\n</code></div>" 12365 ], 12366 "class": "p5.XML", 12367 "module": "IO", 12368 "submodule": "XML" 12369 }, 12370 { 12371 "file": "src/io/p5.XML.js", 12372 "line": 801, 12373 "description": "<p>This method is called while the parsing of XML (when loadXML() is\ncalled). The difference between this method and the setContent()\nmethod defined later is that this one is used to set the content\nwhen the node in question has more nodes under it and so on and\nnot directly text content. While in the other one is used when\nthe node in question directly has text inside it.</p>\n", 12374 "class": "p5.XML", 12375 "module": "IO", 12376 "submodule": "XML" 12377 }, 12378 { 12379 "file": "src/io/p5.XML.js", 12380 "line": 818, 12381 "description": "<p>This method is called while the parsing of XML (when loadXML() is\ncalled). The XML node is passed and its attributes are stored in the\np5.XML's attribute Object.</p>\n", 12382 "class": "p5.XML", 12383 "module": "IO", 12384 "submodule": "XML" 12385 }, 12386 { 12387 "file": "src/math/calculation.js", 12388 "line": 12, 12389 "description": "<p>Calculates the absolute value (magnitude) of a number. Maps to Math.abs().\nThe absolute value of a number is always positive.</p>\n", 12390 "itemtype": "method", 12391 "name": "abs", 12392 "params": [ 12393 { 12394 "name": "n", 12395 "description": "<p>number to compute</p>\n", 12396 "type": "Number" 12397 } 12398 ], 12399 "return": { 12400 "description": "absolute value of given number", 12401 "type": "Number" 12402 }, 12403 "example": [ 12404 "\n<div class = \"norender\"><code>\nfunction setup() {\n var x = -3;\n var y = abs(x);\n\n print(x); // -3\n print(y); // 3\n}\n</code></div>" 12405 ], 12406 "alt": "no image displayed", 12407 "class": "p5", 12408 "module": "Math", 12409 "submodule": "Calculation" 12410 }, 12411 { 12412 "file": "src/math/calculation.js", 12413 "line": 36, 12414 "description": "<p>Calculates the closest int value that is greater than or equal to the\nvalue of the parameter. Maps to Math.ceil(). For example, ceil(9.03)\nreturns the value 10.</p>\n", 12415 "itemtype": "method", 12416 "name": "ceil", 12417 "params": [ 12418 { 12419 "name": "n", 12420 "description": "<p>number to round up</p>\n", 12421 "type": "Number" 12422 } 12423 ], 12424 "return": { 12425 "description": "rounded up number", 12426 "type": "Integer" 12427 }, 12428 "example": [ 12429 "\n<div><code>\nfunction draw() {\n background(200);\n // map, mouseX between 0 and 5.\n var ax = map(mouseX, 0, 100, 0, 5);\n var ay = 66;\n\n //Get the ceiling of the mapped number.\n var bx = ceil(map(mouseX, 0, 100, 0, 5));\n var by = 33;\n\n // Multiply the mapped numbers by 20 to more easily\n // see the changes.\n stroke(0);\n fill(0);\n line(0, ay, ax * 20, ay);\n line(0, by, bx * 20, by);\n\n // Reformat the float returned by map and draw it.\n noStroke();\n text(nfc(ax, 2), ax, ay - 5);\n text(nfc(bx, 1), bx, by - 5);\n}\n</code></div>" 12430 ], 12431 "alt": "2 horizontal lines & number sets. increase with mouse x. bottom to 2 decimals", 12432 "class": "p5", 12433 "module": "Math", 12434 "submodule": "Calculation" 12435 }, 12436 { 12437 "file": "src/math/calculation.js", 12438 "line": 76, 12439 "description": "<p>Constrains a value between a minimum and maximum value.</p>\n", 12440 "itemtype": "method", 12441 "name": "constrain", 12442 "params": [ 12443 { 12444 "name": "n", 12445 "description": "<p>number to constrain</p>\n", 12446 "type": "Number" 12447 }, 12448 { 12449 "name": "low", 12450 "description": "<p>minimum limit</p>\n", 12451 "type": "Number" 12452 }, 12453 { 12454 "name": "high", 12455 "description": "<p>maximum limit</p>\n", 12456 "type": "Number" 12457 } 12458 ], 12459 "return": { 12460 "description": "constrained number", 12461 "type": "Number" 12462 }, 12463 "example": [ 12464 "\n<div><code>\nfunction draw() {\n background(200);\n\n var leftWall = 25;\n var rightWall = 75;\n\n // xm is just the mouseX, while\n // xc is the mouseX, but constrained\n // between the leftWall and rightWall!\n var xm = mouseX;\n var xc = constrain(mouseX, leftWall, rightWall);\n\n // Draw the walls.\n stroke(150);\n line(leftWall, 0, leftWall, height);\n line(rightWall, 0, rightWall, height);\n\n // Draw xm and xc as circles.\n noStroke();\n fill(150);\n ellipse(xm, 33, 9, 9); // Not Constrained\n fill(0);\n ellipse(xc, 66, 9, 9); // Constrained\n}\n</code></div>" 12465 ], 12466 "alt": "2 vertical lines. 2 ellipses move with mouse X 1 does not move passed lines", 12467 "class": "p5", 12468 "module": "Math", 12469 "submodule": "Calculation" 12470 }, 12471 { 12472 "file": "src/math/calculation.js", 12473 "line": 121, 12474 "description": "<p>Calculates the distance between two points.</p>\n", 12475 "itemtype": "method", 12476 "name": "dist", 12477 "return": { 12478 "description": "distance between the two points", 12479 "type": "Number" 12480 }, 12481 "example": [ 12482 "\n<div><code>\n// Move your mouse inside the canvas to see the\n// change in distance between two points!\nfunction draw() {\n background(200);\n fill(0);\n\n var x1 = 10;\n var y1 = 90;\n var x2 = mouseX;\n var y2 = mouseY;\n\n line(x1, y1, x2, y2);\n ellipse(x1, y1, 7, 7);\n ellipse(x2, y2, 7, 7);\n\n // d is the length of the line\n // the distance from point 1 to point 2.\n var d = int(dist(x1, y1, x2, y2));\n\n // Let's write d along the line we are drawing!\n push();\n translate((x1 + x2) / 2, (y1 + y2) / 2);\n rotate(atan2(y2 - y1, x2 - x1));
12482\n text(nfc(d, 1), 0, -5);\n pop();\n // Fancy!\n}\n</code></div>" 12483 ], 12484 "alt": "2 ellipses joined by line. 1 ellipse moves with mouse X&Y. Distance displayed.", 12485 "class": "p5", 12486 "module": "Math", 12487 "submodule": "Calculation", 12488 "overloads": [ 12489 { 12490 "line": 121, 12491 "params": [ 12492 { 12493 "name": "x1", 12494 "description": "<p>x-coordinate of the first point</p>\n", 12495 "type": "Number" 12496 }, 12497 { 12498 "name": "y1", 12499 "description": "<p>y-coordinate of the first point</p>\n", 12500 "type": "Number" 12501 }, 12502 { 12503 "name": "x2", 12504 "description": "<p>x-coordinate of the second point</p>\n", 12505 "type": "Number" 12506 }, 12507 { 12508 "name": "y2", 12509 "description": "<p>y-coordinate of the second point</p>\n", 12510 "type": "Number" 12511 } 12512 ], 12513 "return": { 12514 "description": "distance between the two points", 12515 "type": "Number" 12516 } 12517 }, 12518 { 12519 "line": 165, 12520 "params": [ 12521 { 12522 "name": "x1", 12523 "description": "", 12524 "type": "Number" 12525 }, 12526 { 12527 "name": "y1", 12528 "description": "", 12529 "type": "Number" 12530 }, 12531 { 12532 "name": "z1", 12533 "description": "<p>z-coordinate of the first point</p>\n", 12534 "type": "Number" 12535 }, 12536 { 12537 "name": "x2", 12538 "description": "", 12539 "type": "Number" 12540 }, 12541 { 12542 "name": "y2", 12543 "description": "", 12544 "type": "Number" 12545 }, 12546 { 12547 "name": "z2", 12548 "description": "<p>z-coordinate of the second point</p>\n", 12549 "type": "Number" 12550 } 12551 ], 12552 "return": { 12553 "description": "distance between the two points", 12554 "type": "Number" 12555 } 12556 } 12557 ] 12558 }, 12559 { 12560 "file": "src/math/calculation.js", 12561 "line": 190, 12562 "description": "<p>Returns Euler's number e (2.71828...) raised to the power of the n\nparameter. Maps to Math.exp().</p>\n", 12563 "itemtype": "method", 12564 "name": "exp", 12565 "params": [ 12566 { 12567 "name": "n", 12568 "description": "<p>exponent to raise</p>\n", 12569 "type": "Number" 12570 } 12571 ], 12572 "return": { 12573 "description": "e^n", 12574 "type": "Number" 12575 }, 12576 "example": [ 12577 "\n<div><code>\nfunction draw() {\n background(200);\n\n // Compute the exp() function with a value between 0 and 2\n var xValue = map(mouseX, 0, width, 0, 2);\n var yValue = exp(xValue);\n\n var y = map(yValue, 0, 8, height, 0);\n\n var legend = 'exp (' + nfc(xValue, 3) + ')\\n= ' + nf(yValue, 1, 4);\n stroke(150);\n line(mouseX, y, mouseX, height);\n fill(0);\n text(legend, 5, 15);\n noStroke();\n ellipse(mouseX, y, 7, 7);\n\n // Draw the exp(x) curve,\n // over the domain of x from 0 to 2\n noFill();\n stroke(0);\n beginShape();\n for (var x = 0; x < width; x++) {\n xValue = map(x, 0, width, 0, 2);\n yValue = exp(xValue);\n y = map(yValue, 0, 8, height, 0);\n vertex(x, y);\n }\n\n endShape();\n line(0, 0, 0, height);\n line(0, height - 1, width, height - 1);\n}\n</code></div>" 12578 ], 12579 "alt": "ellipse moves along a curve with mouse x. e^n displayed.", 12580 "class": "p5", 12581 "module": "Math", 12582 "submodule": "Calculation" 12583 }, 12584 { 12585 "file": "src/math/calculation.js", 12586 "line": 240, 12587 "description": "<p>Calculates the closest int value that is less than or equal to the\nvalue of the parameter. Maps to Math.floor().</p>\n", 12588 "itemtype": "method", 12589 "name": "floor", 12590 "params": [ 12591 { 12592 "name": "n", 12593 "description": "<p>number to round down</p>\n", 12594 "type": "Number" 12595 } 12596 ], 12597 "return": { 12598 "description": "rounded down number", 12599 "type": "Integer" 12600 }, 12601 "example": [ 12602 "\n<div><code>\nfunction draw() {\n background(200);\n //map, mouseX between 0 and 5.\n var ax = map(mouseX, 0, 100, 0, 5);\n var ay = 66;\n\n //Get the floor of the mapped number.\n var bx = floor(map(mouseX, 0, 100, 0, 5));\n var by = 33;\n\n // Multiply the mapped numbers by 20 to more easily\n // see the changes.\n stroke(0);\n fill(0);\n line(0, ay, ax * 20, ay);\n line(0, by, bx * 20, by);\n\n // Reformat the float returned by map and draw it.\n noStroke();\n text(nfc(ax, 2), ax, ay - 5);\n text(nfc(bx, 1), bx, by - 5);\n}\n</code></div>" 12603 ], 12604 "alt": "2 horizontal lines & number sets. increase with mouse x. bottom to 2 decimals", 12605 "class": "p5", 12606 "module": "Math", 12607 "submodule": "Calculation" 12608 }, 12609 { 12610 "file": "src/math/calculation.js", 12611 "line": 279, 12612 "description": "<p>Calculates a number between two numbers at a specific increment. The amt\nparameter is the amount to interpolate between the two values where 0.0\nequal to the first point, 0.1 is very near the first point, 0.5 is\nhalf-way in between, etc. The lerp function is convenient for creating\
12612nmotion along a straight path and for drawing dotted lines.</p>\n", 12613 "itemtype": "method", 12614 "name": "lerp", 12615 "params": [ 12616 { 12617 "name": "start", 12618 "description": "<p>first value</p>\n", 12619 "type": "Number" 12620 }, 12621 { 12622 "name": "stop", 12623 "description": "<p>second value</p>\n", 12624 "type": "Number" 12625 }, 12626 { 12627 "name": "amt", 12628 "description": "<p>number between 0.0 and 1.0</p>\n", 12629 "type": "Number" 12630 } 12631 ], 12632 "return": { 12633 "description": "lerped value", 12634 "type": "Number" 12635 }, 12636 "example": [ 12637 "\n<div><code>\nfunction setup() {\n background(200);\n var a = 20;\n var b = 80;\n var c = lerp(a, b, 0.2);\n var d = lerp(a, b, 0.5);\n var e = lerp(a, b, 0.8);\n\n var y = 50;\n\n strokeWeight(5);\n stroke(0); // Draw the original points in black\n point(a, y);\n point(b, y);\n\n stroke(100); // Draw the lerp points in gray\n point(c, y);\n point(d, y);\n point(e, y);\n}\n</code></div>" 12638 ], 12639 "alt": "5 points horizontally staggered mid-canvas. mid 3 are grey, outer black", 12640 "class": "p5", 12641 "module": "Math", 12642 "submodule": "Calculation" 12643 }, 12644 { 12645 "file": "src/math/calculation.js", 12646 "line": 324, 12647 "description": "<p>Calculates the natural logarithm (the base-e logarithm) of a number. This\nfunction expects the n parameter to be a value greater than 0.0. Maps to\nMath.log().</p>\n", 12648 "itemtype": "method", 12649 "name": "log", 12650 "params": [ 12651 { 12652 "name": "n", 12653 "description": "<p>number greater than 0</p>\n", 12654 "type": "Number" 12655 } 12656 ], 12657 "return": { 12658 "description": "natural logarithm of n", 12659 "type": "Number" 12660 }, 12661 "example": [ 12662 "\n<div><code>\nfunction draw() {\n background(200);\n var maxX = 2.8;\n var maxY = 1.5;\n\n // Compute the natural log of a value between 0 and maxX\n var xValue = map(mouseX, 0, width, 0, maxX);\n if (xValue > 0) {\n // Cannot take the log of a negative number.\n var yValue = log(xValue);\n var y = map(yValue, -maxY, maxY, height, 0);\n\n // Display the calculation occurring.\n var legend = 'log(' + nf(xValue, 1, 2) + ')\\n= ' + nf(yValue, 1, 3);\n stroke(150);\n line(mouseX, y, mouseX, height);\n fill(0);\n text(legend, 5, 15);\n noStroke();\n ellipse(mouseX, y, 7, 7);\n }\n\n // Draw the log(x) curve,\n // over the domain of x from 0 to maxX\n noFill();\n stroke(0);\n beginShape();\n for (var x = 0; x < width; x++) {\n xValue = map(x, 0, width, 0, maxX);\n yValue = log(xValue);\n y = map(yValue, -maxY, maxY, height, 0);\n vertex(x, y);\n }\n endShape();\n line(0, 0, 0, height);\n line(0, height / 2, width, height / 2);\n}\n</code></div>" 12663 ], 12664 "alt": "ellipse moves along a curve with mouse x. natural logarithm of n displayed.", 12665 "class": "p5", 12666 "module": "Math", 12667 "submodule": "Calculation" 12668 }, 12669 { 12670 "file": "src/math/calculation.js", 12671 "line": 379, 12672 "description": "<p>Calculates the magnitude (or length) of a vector. A vector is a direction\nin space commonly used in computer graphics and linear algebra. Because it\nhas no "start" position, the magnitude of a vector can be thought of as\nthe distance from the coordinate 0,0 to its x,y value. Therefore, mag() is\na shortcut for writing dist(0, 0, x, y).</p>\n", 12673 "itemtype": "method", 12674 "name": "mag", 12675 "params": [ 12676 { 12677 "name": "a", 12678 "description": "<p>first value</p>\n", 12679 "type": "Number" 12680 }, 12681 { 12682 "name": "b", 12683 "description": "<p>second value</p>\n", 12684 "type": "Number" 12685 } 12686 ], 12687 "return": { 12688 "description": "magnitude of vector from (0,0) to (a,b)", 12689 "type": "Number" 12690 }, 12691 "example": [ 12692 "\n<div><code>\nfunction setup() {\n var x1 = 20;\n var x2 = 80;\n var y1 = 30;\n var y2 = 70;\n\n line(0, 0, x1, y1);\n print(mag(x1, y1)); // Prints \"36.05551275463989\"\n line(0, 0, x2, y1);\n print(mag(x2, y1)); // Prints \"85.44003745317531\"\n line(0, 0, x1, y2);\n print(mag(x1, y2)); // Prints \"72.80109889280519\"\n line(0, 0, x2, y2);\n print(mag(x2, y2)); // Prints \"106.3014581273465\"\n}\n</code></div>" 12693 ], 12694 "alt": "4 lines of different length radiate from top left of canvas.", 12695 "class": "p5", 12696 "module": "Math", 12697 "submodule": "Calculation" 12698 }, 12699 { 12700 "file": "src/math/calculation.js", 12701 "line": 418, 12702 "description": "<p>Re-maps a number from one range to another.\n<br><br>\nIn the first example above, the number 25 is converted from a value in the\nrange of 0 to 100 into a value that ranges from the left edge of the\nwindow (0) to the right edge (width).</p>\n", 12703 "itemtype": "method", 12704 "name": "map", 12705 "params": [ 12706 { 12707 "name": "value", 12708 "description": "<p>the incoming value to be converted</p>\n", 12709 "type": "Number" 12710 }, 12711 { 12712 "name": "start1", 12713 "description": "<p>lower bound of the value's current range</p>\n", 12714 "type": "Number" 12715 }, 12716 { 12717 "name": "stop1", 12718 "description": "<p>upper bound of the value's current range</p>\n", 12719 "type": "Number" 12720 }, 12721 { 12722 "name": "start2", 12723 "description": "<p>lower bound of the value's target range</p>\n", 12724 "type": "Number" 12725 }, 12726 { 12727 "name": "stop2", 12728 "description": "<p>upper bound of the value's target range</p>\n", 12729 "type": "Number" 12730 }, 12731 { 12732 "name": "withinBounds", 12733 "description": "<p>constrain the value to the newly mapped range</p>\n", 12734 "type": "Boolean", 12735 "optional": true 12736 } 12737 ], 12738 "return": { 12739 "description": "remapped number", 12740 "type": "Number" 12741 }, 12742 "example": [ 12743 "\n <div><code>\nvar value = 25;\nvar m = map(value, 0, 100, 0, width);\nellipse(m, 50, 10, 10);\n</code></div>\n\n <div><code>\nfunction setup() {\n noStroke();\n}\n\nfunction draw() {\n background(204);\n var x1 = map(mouseX, 0, width, 25, 75);\n ellipse(x1, 25, 25, 25);\n //This ellipse is constrained to the 0-100 range\n //after setting withinBounds to true\n var x2 = map(mouseX, 0, width, 0, 100, true);\n ellipse(x2, 75, 25, 25);\n}\n</code></div>" 12744 ], 12745 "alt": "10 by 10 white ellipse with in mid left canvas\n2 25 by 25 white ellipses move with mouse x. Bottom has more range from X", 12746 "class": "p5", 12747 "module": "Math", 12748 "submodule": "Calculation" 12749 }, 12750 { 12751 "file": "src/math/calculation.js", 12752 "line": 474, 12753 "description": "<p>Determines the largest value in a sequence of numbers, and then returns\nthat value. max() accepts any number of Number parameters, or an Array\nof any length.</p>\n", 12754 "itemtype": "method", 12755 "name": "max", 12756 "return": { 12757 "description": "maximum Number", 12758 "type": "Number" 12759 }, 12760 "example": [ 12761 "\n<div><code>\nfunction setup() {\n // Change the elements in the array and run the sketch\n // to show how max() works!\n var numArray = [2, 1, 5, 4, 8, 9];\n fill(0);\n noStroke();\n text('Array Elements', 0, 10);\n // Draw all numbers in the array\n var spacing = 15;\n var elemsY = 25;\n for (var i = 0; i < numArray.length;
12761 i++) {\n text(numArray[i], i * spacing, elemsY);\n }\n var maxX = 33;\n var maxY = 80;\n // Draw the Maximum value in the array.\n textSize(32);\n text(max(numArray), maxX, maxY);\n}\n</code></div>" 12762 ], 12763 "alt": "Small text at top reads: Array Elements 2 1 5 4 8 9. Large text at center: 9", 12764 "class": "p5", 12765 "module": "Math", 12766 "submodule": "Calculation", 12767 "overloads": [ 12768 { 12769 "line": 474, 12770 "params": [ 12771 { 12772 "name": "n0", 12773 "description": "<p>Number to compare</p>\n", 12774 "type": "Number" 12775 }, 12776 { 12777 "name": "n1", 12778 "description": "<p>Number to compare</p>\n", 12779 "type": "Number" 12780 } 12781 ], 12782 "return": { 12783 "description": "maximum Number", 12784 "type": "Number" 12785 } 12786 }, 12787 { 12788 "line": 510, 12789 "params": [ 12790 { 12791 "name": "nums", 12792 "description": "<p>Numbers to compare</p>\n", 12793 "type": "Number[]" 12794 } 12795 ], 12796 "return": { 12797 "description": "", 12798 "type": "Number" 12799 } 12800 } 12801 ] 12802 }, 12803 { 12804 "file": "src/math/calculation.js", 12805 "line": 524, 12806 "description": "<p>Determines the smallest value in a sequence of numbers, and then returns\nthat value. min() accepts any number of Number parameters, or an Array\nof any length.</p>\n", 12807 "itemtype": "method", 12808 "name": "min", 12809 "return": { 12810 "description": "minimum Number", 12811 "type": "Number" 12812 }, 12813 "example": [ 12814 "\n<div><code>\nfunction setup() {\n // Change the elements in the array and run the sketch\n // to show how min() works!\n var numArray = [2, 1, 5, 4, 8, 9];\n fill(0);\n noStroke();\n text('Array Elements', 0, 10);\n // Draw all numbers in the array\n var spacing = 15;\n var elemsY = 25;\n for (var i = 0; i < numArray.length; i++) {\n text(numArray[i], i * spacing, elemsY);\n }\n var maxX = 33;\n var maxY = 80;\n // Draw the Minimum value in the array.\n textSize(32);\n text(min(numArray), maxX, maxY);\n}\n</code></div>" 12815 ], 12816 "alt": "Small text at top reads: Array Elements 2 1 5 4 8 9. Large text at center: 1", 12817 "class": "p5", 12818 "module": "Math", 12819 "submodule": "Calculation", 12820 "overloads": [ 12821 { 12822 "line": 524, 12823 "params": [ 12824 { 12825 "name": "n0", 12826 "description": "<p>Number to compare</p>\n", 12827 "type": "Number" 12828 }, 12829 { 12830 "name": "n1", 12831 "description": "<p>Number to compare</p>\n", 12832 "type": "Number" 12833 } 12834 ], 12835 "return": { 12836 "description": "minimum Number", 12837 "type": "Number" 12838 } 12839 }, 12840 { 12841 "line": 560, 12842 "params": [ 12843 { 12844 "name": "nums", 12845 "description": "<p>Numbers to compare</p>\n", 12846 "type": "Number[]" 12847 } 12848 ], 12849 "return": { 12850 "description": "", 12851 "type": "Number" 12852 } 12853 } 12854 ] 12855 }, 12856 { 12857 "file": "src/math/calculation.js", 12858 "line": 574, 12859 "description": "<p>Normalizes a number from another range into a value between 0 and 1.\nIdentical to map(value, low, high, 0, 1).\nNumbers outside of the range are not clamped to 0 and 1, because\nout-of-range values are often intentional and useful. (See the second\nexample above.)</p>\n", 12860 "itemtype": "method", 12861 "name": "norm", 12862 "params": [ 12863 { 12864 "name": "value", 12865 "description": "<p>incoming value to be normalized</p>\n", 12866 "type": "Number" 12867 }, 12868 { 12869 "name": "start", 12870 "description": "<p>lower bound of the value's current range</p>\n", 12871 "type": "Number" 12872 }, 12873 { 12874 "name": "stop", 12875 "description": "<p>upper bound of the value's current range</p>\n", 12876 "type": "Number" 12877 } 12878 ], 12879 "return": { 12880 "description": "normalized number", 12881 "type": "Number" 12882 }, 12883 "example": [ 12884 "\n<div><code>\nfunction draw() {\n background(200);\n var currentNum = mouseX;\n var lowerBound = 0;\n var upperBound = width; //100;\n var normalized = norm(currentNum, lowerBound, upperBound);\n var lineY = 70;\n line(0, lineY, width, lineY);\n //Draw an ellipse mapped to the non-normalized value.\n noStroke();\n fill(50);\n var s = 7; // ellipse size\n ellipse(currentNum, lineY, s, s);\n\n // Draw the guide\n var guideY = lineY + 15;\n text('0', 0, guideY);\n textAlign(RIGHT);\n text('100', width, guideY);
12884\n\n // Draw the normalized value\n textAlign(LEFT);\n fill(0);\n textSize(32);\n var normalY = 40;\n var normalX = 20;\n text(normalized, normalX, normalY);\n}\n</code></div>" 12885 ], 12886 "alt": "ellipse moves with mouse. 0 shown left & 100 right and updating values center", 12887 "class": "p5", 12888 "module": "Math", 12889 "submodule": "Calculation" 12890 }, 12891 { 12892 "file": "src/math/calculation.js", 12893 "line": 627, 12894 "description": "<p>Facilitates exponential expressions. The pow() function is an efficient\nway of multiplying numbers by themselves (or their reciprocals) in large\nquantities. For example, pow(3, 5) is equivalent to the expression\n3<em>3</em>3<em>3</em>3 and pow(3, -5) is equivalent to 1 / 3<em>3</em>3<em>3</em>3. Maps to\nMath.pow().</p>\n", 12895 "itemtype": "method", 12896 "name": "pow", 12897 "params": [ 12898 { 12899 "name": "n", 12900 "description": "<p>base of the exponential expression</p>\n", 12901 "type": "Number" 12902 }, 12903 { 12904 "name": "e", 12905 "description": "<p>power by which to raise the base</p>\n", 12906 "type": "Number" 12907 } 12908 ], 12909 "return": { 12910 "description": "n^e", 12911 "type": "Number" 12912 }, 12913 "example": [ 12914 "\n<div><code>\nfunction setup() {\n //Exponentially increase the size of an ellipse.\n var eSize = 3; // Original Size\n var eLoc = 10; // Original Location\n\n ellipse(eLoc, eLoc, eSize, eSize);\n\n ellipse(eLoc * 2, eLoc * 2, pow(eSize, 2), pow(eSize, 2));\n\n ellipse(eLoc * 4, eLoc * 4, pow(eSize, 3), pow(eSize, 3));\n\n ellipse(eLoc * 8, eLoc * 8, pow(eSize, 4), pow(eSize, 4));\n}\n</code></div>" 12915 ], 12916 "alt": "small to large ellipses radiating from top left of canvas", 12917 "class": "p5", 12918 "module": "Math", 12919 "submodule": "Calculation" 12920 }, 12921 { 12922 "file": "src/math/calculation.js", 12923 "line": 661, 12924 "description": "<p>Calculates the integer closest to the n parameter. For example,\nround(133.8) returns the value 134. Maps to Math.round().</p>\n", 12925 "itemtype": "method", 12926 "name": "round", 12927 "params": [ 12928 { 12929 "name": "n", 12930 "description": "<p>number to round</p>\n", 12931 "type": "Number" 12932 } 12933 ], 12934 "return": { 12935 "description": "rounded number", 12936 "type": "Integer" 12937 }, 12938 "example": [ 12939 "\n<div><code>\nfunction draw() {\n background(200);\n //map, mouseX between 0 and 5.\n var ax = map(mouseX, 0, 100, 0, 5);\n var ay = 66;\n\n // Round the mapped number.\n var bx = round(map(mouseX, 0, 100, 0, 5));\n var by = 33;\n\n // Multiply the mapped numbers by 20 to more easily\n // see the changes.\n stroke(0);\n fill(0);\n line(0, ay, ax * 20, ay);\n line(0, by, bx * 20, by);\n\n // Reformat the float returned by map and draw it.\n noStroke();\n text(nfc(ax, 2), ax, ay - 5);\n text(nfc(bx, 1), bx, by - 5);\n}\n</code></div>" 12940 ], 12941 "alt": "horizontal center line squared values displayed on top and regular on bottom.", 12942 "class": "p5", 12943 "module": "Math", 12944 "submodule": "Calculation" 12945 }, 12946 { 12947 "file": "src/math/calculation.js", 12948 "line": 700, 12949 "description": "<p>Squares a number (multiplies a number by itself). The result is always a\npositive number, as multiplying two negative numbers always yields a\npositive result. For example, -1 * -1 = 1.</p>\n", 12950 "itemtype": "method", 12951 "name": "sq", 12952 "params": [ 12953 { 12954 "name": "n", 12955 "description": "<p>number to square</p>\n", 12956 "type": "Number" 12957 } 12958 ], 12959 "return": { 12960 "description": "squared number", 12961 "type": "Number" 12962 }, 12963 "example": [ 12964 "\n<div><code>\nfunction draw() {\n background(200);\n var eSize = 7;\n var x1 = map(mouseX, 0, width, 0, 10);\n var y1 = 80;\n var x2 = sq(x1);\n var y2 = 20;\n\n // Draw the non-squared.\n line(0, y1, width, y1);\n ellipse(x1, y1, eSize, eSize);\n\n // Draw the squared.\n line(0, y2, width, y2);\n ellipse(x2, y2, eSize, eSize);\n\n // Draw dividing line.\n stroke(100);\n line(0, height / 2, width, height / 2);\n\n // Draw text.\n var spacing = 15;\n noStroke();\n fill(0);\n text('x = ' + x1, 0, y1 + spacing);\n text('sq(x) = ' + x2, 0, y2 + spacing);\n}\n</code></div>" 12965 ], 12966 "alt": "horizontal center line squared values displayed on top and regular on bottom.", 12967 "class": "p5", 12968 "module": "Math", 12969 "submodule": "Calculation" 12970 }, 12971 { 12972 "file": "src/math/calculation.js", 12973 "line": 747, 12974 "description": "<p>Calculates the square root of a number. The square root of a number is\nalways positive, even though there may be a valid negative root. The\nsquare root s of number a is such that s*s = a. It is the opposite of\nsquaring. Maps to Math.sqrt().</p>\n", 12975 "itemtype": "method", 12976 "name": "sqrt", 12977 "params": [ 12978 { 12979 "name": "n", 12980 "description": "<p>non-negative number to square root</p>\n", 12981 "type": "Number" 12982 } 12983 ], 12984 "return": { 12985 "description": "square root of number", 12986 "type": "Number" 12987 }, 12988 "example": [ 12989 "\n<div><code>\nfunction draw() {\n background(200);\n var eSize = 7;\n var x1 = mouseX;\n var y1 = 80;\n var x2 = sqrt(x1);\n var y2 = 20;\n\n // Draw the non-squared.\n line(0, y1, width, y1);\n ellipse(x1, y1, eSize, eSize);\n\n // Draw the squared.\n line(0, y2, width, y2);\n ellipse(x2, y2, eSize, eSize);\n\n // Draw dividing line.\n stroke(100);\n line(0, height / 2, width, height / 2);\n\n // Draw text.\n noStroke();\n fill(0);\n var spacing = 15;\n text('x = ' + x1, 0, y1 + spacing);\n text('sqrt(x) = ' + x2, 0, y2 + spacing);\n}\n</code></div>" 12990 ], 12991 "alt": "horizontal center line squareroot values displayed on top and regular on bottom.", 12992 "class": "p5", 12993 "module": "Math", 12994 "submodule": "Calculation" 12995 }, 12996 { 12997 "file": "src/math/math.js", 12998 "line": 12, 12999 "description": "<p>Creates a new p5.Vector (the datatype for storing vectors). This provides a\ntwo or three dimensional vector, specifically a Euclidean (also known as\ngeometric) vector. A vector is an entity that has both magnitude and\ndirection.</p>\n", 13000 "itemtype": "method", 13001 "name": "createVector", 13002 "params": [ 13003 { 13004 "name": "x", 13005 "description": "<p>x component of the vector</p>\n", 13006 "type": "Number", 13007 "optional": true 13008 }, 13009 { 13010 "name": "y", 13011 "description": "<p>y component of the vector</p>\n", 13012 "type": "Number", 13013 "optional": true 13014 }, 13015 { 13016 "name": "z", 13017 "description": "<p>z component of the vector</p>\n", 13018 "type": "Number", 13019 "optional": true 13020 } 13021 ], 13022 "return": { 13023 "description": "", 13024 "type": "p5.Vector" 13025 }, 13026 "example": [ 13027 "\n<div modernizr='webgl'><code>\nfunction setup() {\n createCanvas(100, 100, WEBGL);\n noStroke();\n fill(255, 102, 204);\n}\n\nfunction draw() {\n background(255);\n pointLight(color(255), createVector(sin(millis() / 1000) * 20, -40, -10));\n scale(0.75);\n sphere();\n}\n</code></div>" 13028 ], 13029 "alt": "a purple sphere lit by a point light oscillating horizontally", 13030 "class": "p5", 13031 "module": "Math", 13032 "submodule": "Math" 13033 }, 13034 { 13035 "file": "src/math/noise.js", 13036 "line": 40, 13037 "description": "<p>Returns the Perlin noise value at specified coordinates. Perlin noise is\na random sequence generator producing a more natural ordered, harmonic\nsuccession of numbers compared to the standard <b>random()</b>
13037 function.\nIt was invented by Ken Perlin in the 1980s and been used since in\ngraphical applications to produce procedural textures, natural motion,\nshapes, terrains etc.<br /><br /> The main difference to the\n<b>random()</b> function is that Perlin noise is defined in an infinite\nn-dimensional space where each pair of coordinates corresponds to a\nfixed semi-random value (fixed only for the lifespan of the program; see\nthe noiseSeed() function). p5.js can compute 1D, 2D and 3D noise,\ndepending on the number of coordinates given. The resulting value will\nalways be between 0.0 and 1.0. The noise value can be animated by moving\nthrough the noise space as demonstrated in the example above. The 2nd\nand 3rd dimension can also be interpreted as time.<br /><br />The actual\nnoise is structured similar to an audio signal, in respect to the\nfunction's use of frequencies. Similar to the concept of harmonics in\nphysics, perlin noise is computed over several octaves which are added\ntogether for the final result. <br /><br />Another way to adjust the\ncharacter of the resulting sequence is the scale of the input\ncoordinates. As the function works within an infinite space the value of\nthe coordinates doesn't matter as such, only the distance between\nsuccessive coordinates does (eg. when using <b>noise()</b> within a\nloop). As a general rule the smaller the difference between coordinates,\nthe smoother the resulting noise sequence will be. Steps of 0.005-0.03\nwork best for most applications, but this will differ depending on use.</p>\n", 13038 "itemtype": "method", 13039 "name": "noise", 13040 "params": [ 13041 { 13042 "name": "x", 13043 "description": "<p>x-coordinate in noise space</p>\n", 13044 "type": "Number" 13045 }, 13046 { 13047 "name": "y", 13048 "description": "<p>y-coordinate in noise space</p>\n", 13049 "type": "Number", 13050 "optional": true 13051 }, 13052 { 13053 "name": "z", 13054 "description": "<p>z-coordinate in noise space</p>\n", 13055 "type": "Number", 13056 "optional": true 13057 } 13058 ], 13059 "return": { 13060 "description": "Perlin noise value (between 0 and 1) at specified\n coordinates", 13061 "type": "Number" 13062 }, 13063 "example": [ 13064 "\n<div>\n<code>\nvar xoff = 0.0;\n\nfunction draw() {\n background(204);\n xoff = xoff + 0.01;\n var n = noise(xoff) * width;\n line(n, 0, n, height);\n}\n</code>\n</div>\n<div>\n<code>var noiseScale=0.02;\n\nfunction draw() {\n background(0);\n for (var x=0; x < width; x++) {\n var noiseVal = noise((mouseX+x)*noiseScale, mouseY*noiseScale);\n stroke(noiseVal*255);\n line(x, mouseY+noiseVal*80, x, height);\n }\n}\n</code>\n</div>" 13065 ], 13066 "alt": "vertical line moves left to right with updating noise values.\nhorizontal wave pattern effected by mouse x-position & updating noise values.", 13067 "class": "p5", 13068 "module": "Math", 13069 "submodule": "Noise" 13070 }, 13071 { 13072 "file": "src/math/noise.js", 13073 "line": 187, 13074 "description": "<p>Adjusts the character and level of detail produced by the Perlin noise\n function. Similar to harmonics in physics, noise is computed over\n several octaves. Lower octaves contribute more to the output signal and\n as such define the overall intensity of the noise, whereas higher octaves\n create finer grained details in the noise sequence.\n <br><br>\n By default, noise is computed over 4 octaves with each octave contributing\n exactly half than its predecessor, starting at 50% strength for the 1st\n octave. This falloff amount can be changed by adding an additional function\n parameter. Eg. a falloff factor of 0.75 means each octave will now have\n 75% impact (25% less) of the previous lower octave. Any value between\n 0.0 and 1.0 is valid, however note that values greater than 0.5 might\n result in greater than 1.0 values returned by <b>noise()</b>.\n <br><br>\n By changing these parameters, the signal created by the <b>noise()</b>\n function can be adapted to fit very specific needs and characteristics.</p>\n", 13075 "itemtype": "method", 13076 "name": "noiseDetail", 13077 "params": [ 13078 { 13079 "name": "lod", 13080 "description": "<p>number of octaves to be used by the noise</p>\n", 13081 "type": "Number" 13082 }, 13083 { 13084 "name": "falloff", 13085 "description": "<p>falloff factor for each octave</p>\n", 13086 "type": "Number" 13087 } 13088 ], 13089 "example": [ 13090 "\n <div>\n <code>\n var noiseVal;\n var noiseScale = 0.02;\nfunction setup() {\n createCanvas(100, 100);\n }\nfunction draw() {\n background(0);\n for (var y = 0; y < height;
13090 y++) {\n for (var x = 0; x < width / 2; x++) {\n noiseDetail(2, 0.2);\n noiseVal = noise((mouseX + x) * noiseScale, (mouseY + y) * noiseScale);\n stroke(noiseVal * 255);\n point(x, y);\n noiseDetail(8, 0.65);\n noiseVal = noise(\n (mouseX + x + width / 2) * noiseScale,\n (mouseY + y) * noiseScale\n );\n stroke(noiseVal * 255);\n point(x + width / 2, y);\n }\n }\n }\n </code>\n </div>" 13091 ], 13092 "alt": "2 vertical grey smokey patterns affected my mouse x-position and noise.", 13093 "class": "p5", 13094 "module": "Math", 13095 "submodule": "Noise" 13096 }, 13097 { 13098 "file": "src/math/noise.js", 13099 "line": 253, 13100 "description": "<p>Sets the seed value for <b>noise()</b>. By default, <b>noise()</b>\nproduces different results each time the program is run. Set the\n<b>value</b> parameter to a constant to return the same pseudo-random\nnumbers each time the software is run.</p>\n", 13101 "itemtype": "method", 13102 "name": "noiseSeed", 13103 "params": [ 13104 { 13105 "name": "seed", 13106 "description": "<p>the seed value</p>\n", 13107 "type": "Number" 13108 } 13109 ], 13110 "example": [ 13111 "\n<div>\n<code>var xoff = 0.0;\n\nfunction setup() {\n noiseSeed(99);\n stroke(0, 10);\n}\n\nfunction draw() {\n xoff = xoff + .01;\n var n = noise(xoff) * width;\n line(n, 0, n, height);\n}\n</code>\n</div>" 13112 ], 13113 "alt": "vertical grey lines drawing in pattern affected by noise.", 13114 "class": "p5", 13115 "module": "Math", 13116 "submodule": "Noise" 13117 }, 13118 { 13119 "file": "src/math/p5.Vector.js", 13120 "line": 67, 13121 "description": "<p>The x component of the vector</p>\n", 13122 "itemtype": "property", 13123 "name": "x", 13124 "type": "Number", 13125 "class": "p5.Vector", 13126 "module": "Math", 13127 "submodule": "Math" 13128 }, 13129 { 13130 "file": "src/math/p5.Vector.js", 13131 "line": 72, 13132 "description": "<p>The y component of the vector</p>\n", 13133 "itemtype": "property", 13134 "name": "y", 13135 "type": "Number", 13136 "class": "p5.Vector", 13137 "module": "Math", 13138 "submodule": "Math" 13139 }, 13140 { 13141 "file": "src/math/p5.Vector.js", 13142 "line": 77, 13143 "description": "<p>The z component of the vector</p>\n", 13144 "itemtype": "property", 13145 "name": "z", 13146 "type": "Number", 13147 "class": "p5.Vector", 13148 "module": "Math", 13149 "submodule": "Math" 13150 }, 13151 { 13152 "file": "src/math/p5.Vector.js", 13153 "line": 84, 13154 "description": "<p>Returns a string representation of a vector v by calling String(v)\nor v.toString(). This method is useful for logging vectors in the\nconsole.</p>\n", 13155 "itemtype": "method", 13156 "name": "toString", 13157 "return": { 13158 "description": "", 13159 "type": "String" 13160 }, 13161 "example": [ 13162 "\n<div class = \"norender\">\n<code>\nfunction setup() {\n var v = createVector(20, 30);\n print(String(v)); // prints \"p5.Vector Object : [20, 30, 0]\"\n}\n</code>\n</div>\n\n<div>\n<code>\nfunction draw() {\n background(240);\n\n var v0 = createVector(0, 0);\n var v1 = createVector(mouseX, mouseY);\n drawArrow(v0, v1, 'black');\n\n noStroke();\n text(v1.toString(), 10, 25, 90, 75);\n}\n\n// draw an arrow for a vector at a given base position\nfunction drawArrow(base, vec, myColor) {\n push();\n stroke(myColor);\n strokeWeight(3);\n fill(myColor);\n translate(base.x, base.y);\n line(0, 0, vec.x, vec.y);\n rotate(vec.heading());\n var arrowSize = 7;\n translate(vec.mag() - arrowSize, 0);\n triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);\n pop();\n}\n</code>\n</div>" 13163 ], 13164 "class": "p5.Vector", 13165 "module": "Math", 13166 "submodule": "Math" 13167 }, 13168 { 13169 "file": "src/math/p5.Vector.js", 13170 "line": 134, 13171 "description": "<p>Sets the x, y, and z component of the vector using two or three separate\nvariables, the data from a p5.Vector, or the values from a float array.</p>\n", 13172 "itemtype": "method", 13173 "name": "set", 13174 "chainable": 1, 13175 "example": [ 13176 "\n<div class=\"norender\">\n<code>\nfunction setup() {\n var v = createVector(1, 2, 3);
13176\n v.set(4, 5, 6); // Sets vector to [4, 5, 6]\n\n var v1 = createVector(0, 0, 0);\n var arr = [1, 2, 3];\n v1.set(arr); // Sets vector to [1, 2, 3]\n}\n</code>\n</div>\n\n<div>\n<code>\nvar v0, v1;\nfunction setup() {\n createCanvas(100, 100);\n\n v0 = createVector(0, 0);\n v1 = createVector(50, 50);\n}\n\nfunction draw() {\n background(240);\n\n drawArrow(v0, v1, 'black');\n v1.set(v1.x + random(-1, 1), v1.y + random(-1, 1));\n\n noStroke();\n text('x: ' + round(v1.x) + ' y: ' + round(v1.y), 20, 90);\n}\n\n// draw an arrow for a vector at a given base position\nfunction drawArrow(base, vec, myColor) {\n push();\n stroke(myColor);\n strokeWeight(3);\n fill(myColor);\n translate(base.x, base.y);\n line(0, 0, vec.x, vec.y);\n rotate(vec.heading());\n var arrowSize = 7;\n translate(vec.mag() - arrowSize, 0);\n triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);\n pop();\n}\n</code>\n</div>" 13177 ], 13178 "class": "p5.Vector", 13179 "module": "Math", 13180 "submodule": "Math", 13181 "overloads": [ 13182 { 13183 "line": 134, 13184 "params": [ 13185 { 13186 "name": "x", 13187 "description": "<p>the x component of the vector</p>\n", 13188 "type": "Number", 13189 "optional": true 13190 }, 13191 { 13192 "name": "y", 13193 "description": "<p>the y component of the vector</p>\n", 13194 "type": "Number", 13195 "optional": true 13196 }, 13197 { 13198 "name": "z", 13199 "description": "<p>the z component of the vector</p>\n", 13200 "type": "Number", 13201 "optional": true 13202 } 13203 ], 13204 "chainable": 1 13205 }, 13206 { 13207 "line": 193, 13208 "params": [ 13209 { 13210 "name": "value", 13211 "description": "<p>the vector to set</p>\n", 13212 "type": "p5.Vector|Number[]" 13213 } 13214 ], 13215 "chainable": 1 13216 } 13217 ] 13218 }, 13219 { 13220 "file": "src/math/p5.Vector.js", 13221 "line": 217, 13222 "description": "<p>Gets a copy of the vector, returns a p5.Vector object.</p>\n", 13223 "itemtype": "method", 13224 "name": "copy", 13225 "return": { 13226 "description": "the copy of the p5.Vector object", 13227 "type": "p5.Vector" 13228 }, 13229 "example": [ 13230 "\n<div class=\"norender\">\n<code>\nvar v1 = createVector(1, 2, 3);\nvar v2 = v1.copy();\nprint(v1.x === v2.x && v1.y === v2.y && v1.z === v2.z);\n// Prints \"true\"\n</code>\n</div>" 13231 ], 13232 "class": "p5.Vector", 13233 "module": "Math", 13234 "submodule": "Math" 13235 }, 13236 { 13237 "file": "src/math/p5.Vector.js", 13238 "line": 240, 13239 "description": "<p>Adds x, y, and z components to a vector, adds one vector to another, or\nadds two independent vectors together. The version of the method that adds\ntwo vectors together is a static method and returns a p5.Vector, the others\nacts directly on the vector. See the examples for more context.</p>\n", 13240 "itemtype": "method", 13241 "name": "add", 13242 "chainable": 1, 13243 "example": [ 13244 "\n<div class=\"norender\">\n<code>\nvar v = createVector(1, 2, 3);\nv.add(4, 5, 6);\n// v's components are set to [5, 7, 9]\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\n// Static method\nvar v1 = createVector(1, 2, 3);\nvar v2 = createVector(2, 3, 4);\n\nvar v3 = p5.Vector.add(v1, v2);\n// v3 has components [3, 5, 7]\nprint(v3);\n</code>\n</div>\n\n<div>\n<code>\n// red vector + blue vector = purple vector\nfunction draw() {\n background(240);\n\n var v0 = createVector(0, 0);\n var v1 = createVector(mouseX, mouseY);\n drawArrow(v0, v1, 'red');\n\n var v2 = createVector(-30, 20);\n drawArrow(v1, v2, 'blue');\n\n var v3 = p5.Vector.add(v1, v2);\n drawArrow(v0, v3, 'purple');\n}\n\n// draw an arrow for a vector at a given base position\nfunction drawArrow(base, vec, myColor) {\n push();\n stroke(myColor);\n strokeWeight(3);\n fill(myColor);\n translate(base.x, base.y);\n line(0, 0, vec.x, vec.y);\n rotate(vec.heading());\n var arrowSize = 7;\n translate(vec.mag() - arrowSize, 0);\n triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);\n pop();\n}\n</code>\n</div>" 13245 ], 13246 "class": "p5.Vector", 13247 "module": "Math", 13248 "submodule": "Math", 13249 "overloads": [ 13250 { 13251 "line": 240, 13252 "params": [ 13253 { 13254 "name": "x", 13255 "description": "<p>the x component of the vector to be added</p>\n", 13256 "type": "Number" 13257 }, 13258 { 13259 "name": "y", 13260 "description": "<p>the y component of the vector to be added</p>\n", 13261 "type": "Number", 13262 "optional": true 13263 }, 13264 { 13265 "name": "z", 13266 "description": "<p>the z component of the vector to be added</p>\n", 13267 "type": "Number", 13268 "optional": true 13269 } 13270 ], 13271 "chainable": 1 13272 }, 13273 { 13274 "line": 306, 13275 "params": [ 13276 { 13277 "name": "value", 13278 "description": "<p>the vector to add</p>\n", 13279 "type": "p5.Vector|Number[]" 13280 } 13281 ], 13282 "chainable": 1 13283 }, 13284 { 13285 "line": 1556, 13286 "params": [ 13287 { 13288 "name": "v1", 13289 "description": "<p>a p5.Vector to add</p>\n", 13290 "type": "p5.Vector" 13291 }, 13292 { 13293 "name": "v2", 13294 "description": "<p>a p5.Vector to add</p>\n", 13295 "type": "p5.Vector" 13296 }, 13297 { 13298 "name": "target", 13299 "description": "<p>the vector to receive the result</p>\n", 13300 "type": "p5.Vector" 13301 } 13302 ], 13303 "static": 1 13304 }, 13305 { 13306 "line": 1563, 13307 "params": [ 13308 { 13309 "name": "v1", 13310 "description": "", 13311 "type": "p5.Vector" 13312 }, 13313 { 13314 "name": "v2", 13315 "description": "", 13316 "type": "p5.Vector" 13317 } 13318 ], 13319 "static": 1, 13320 "return": { 13321 "description": "the resulting p5.Vector", 13322 "type": "p5.Vector" 13323 } 13324 } 13325 ] 13326 }, 13327 { 13328 "file": "src/math/p5.Vector.js", 13329 "line": 330, 13330 "description": "<p>Subtracts x, y, and z components from a vector, subtracts one vector from\nanother, or subtracts two independent vectors. The version of the method\nthat subtracts two vectors is a static method and returns a p5.Vector, the\nother acts directly on the vector. See the examples for more context.</p>\n", 13331 "itemtype": "method", 13332 "name": "sub", 13333 "chainable": 1, 13334 "example": [ 13335 "\n<div class=\"norender\">\n<code>
13335\nvar v = createVector(4, 5, 6);\nv.sub(1, 1, 1);\n// v's components are set to [3, 4, 5]\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\n// Static method\nvar v1 = createVector(2, 3, 4);\nvar v2 = createVector(1, 2, 3);\n\nvar v3 = p5.Vector.sub(v1, v2);\n// v3 has components [1, 1, 1]\nprint(v3);\n</code>\n</div>\n\n<div>\n<code>\n// red vector - blue vector = purple vector\nfunction draw() {\n background(240);\n\n var v0 = createVector(0, 0);\n var v1 = createVector(70, 50);\n drawArrow(v0, v1, 'red');\n\n var v2 = createVector(mouseX, mouseY);\n drawArrow(v0, v2, 'blue');\n\n var v3 = p5.Vector.sub(v1, v2);\n drawArrow(v2, v3, 'purple');\n}\n\n// draw an arrow for a vector at a given base position\nfunction drawArrow(base, vec, myColor) {\n push();\n stroke(myColor);\n strokeWeight(3);\n fill(myColor);\n translate(base.x, base.y);\n line(0, 0, vec.x, vec.y);\n rotate(vec.heading());\n var arrowSize = 7;\n translate(vec.mag() - arrowSize, 0);\n triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);\n pop();\n}\n</code>\n</div>" 13336 ], 13337 "class": "p5.Vector", 13338 "module": "Math", 13339 "submodule": "Math", 13340 "overloads": [ 13341 { 13342 "line": 330, 13343 "params": [ 13344 { 13345 "name": "x", 13346 "description": "<p>the x component of the vector to subtract</p>\n", 13347 "type": "Number" 13348 }, 13349 { 13350 "name": "y", 13351 "description": "<p>the y component of the vector to subtract</p>\n", 13352 "type": "Number", 13353 "optional": true 13354 }, 13355 { 13356 "name": "z", 13357 "description": "<p>the z component of the vector to subtract</p>\n", 13358 "type": "Number", 13359 "optional": true 13360 } 13361 ], 13362 "chainable": 1 13363 }, 13364 { 13365 "line": 396, 13366 "params": [ 13367 { 13368 "name": "value", 13369 "description": "<p>the vector to subtract</p>\n", 13370 "type": "p5.Vector|Number[]" 13371 } 13372 ], 13373 "chainable": 1 13374 }, 13375 { 13376 "line": 1586, 13377 "params": [ 13378 { 13379 "name": "v1", 13380 "description": "<p>a p5.Vector to subtract from</p>\n", 13381 "type": "p5.Vector" 13382 }, 13383 { 13384 "name": "v2", 13385 "description": "<p>a p5.Vector to subtract</p>\n", 13386 "type": "p5.Vector" 13387 }, 13388 { 13389 "name": "target", 13390 "description": "<p>if undefined a new vector will be created</p>\n", 13391 "type": "p5.Vector" 13392 } 13393 ], 13394 "static": 1 13395 }, 13396 { 13397 "line": 1593, 13398 "params": [ 13399 { 13400 "name": "v1", 13401 "description": "", 13402 "type": "p5.Vector" 13403 }, 13404 { 13405 "name": "v2", 13406 "description": "", 13407 "type": "p5.Vector" 13408 } 13409 ], 13410 "static": 1, 13411 "return": { 13412 "description": "the resulting p5.Vector", 13413 "type": "p5.Vector" 13414 } 13415 } 13416 ] 13417 }, 13418 { 13419 "file": "src/math/p5.Vector.js", 13420 "line": 420, 13421 "description": "<p>Multiply the vector by a scalar. The static version of this method\ncreates a new p5.Vector while the non static version acts on the vector\ndirectly. See the examples for more context.</p>\n", 13422 "itemtype": "method", 13423 "name": "mult", 13424 "chainable": 1, 13425 "example": [ 13426 "\n<div class=\"norender\">\n<code>\nvar v = createVector(1, 2, 3);\nv.mult(2);\n// v's components are set to [2, 4, 6]\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\n// Static method\nvar v1 = createVector(1, 2, 3);\nvar v2 = p5.Vector.mult(v1, 2);\n// v2 has components [2, 4, 6]\nprint(v2);\n</code>\n</div>\n\n<div>\n<code>\nfunction draw() {\n background(240);\n\n var v0 = createVector(50, 50);\n var v1 = createVector(25, -25);\n drawArrow(v0, v1, 'red');\n\n var num = map(mouseX, 0, width, -2, 2, true);\n var v2 = p5.Vector.mult(v1, num);\n drawArrow(v0, v2, 'blue');\n\n noStroke();\n text('multiplied by ' + num.toFixed(2), 5, 90);\n}\n\n// draw an arrow for a vector at a given base position\nfunction drawArrow(base, vec, myColor) {\n push();\n stroke(myColor);\n strokeWeight(3);\n fill(myColor);\n translate(base.x, base.y);\n line(0, 0, vec.x, vec.y);\n rotate(vec.heading());\n var arrowSize = 7;\n translate(vec.mag() - arrowSize, 0);\n triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);\n pop();\n}\n</code>\n</div>" 13427 ], 13428 "class": "p5.Vector", 13429 "module": "Math", 13430 "submodule": "Math", 13431 "overloads": [ 13432 { 13433 "line": 420, 13434 "params": [ 13435 { 13436 "name": "n", 13437 "description": "<p>the number to multiply with the vector</p>\n", 13438 "type": "Number" 13439 } 13440 ], 13441 "chainable": 1 13442 }, 13443 { 13444 "line": 1614, 13445 "params": [ 13446 { 13447 "name": "v", 13448 "description": "<p>the vector to multiply</p>\n", 13449 "type": "p5.Vector" 13450 }, 13451 { 13452 "name": "n", 13453 "description": "", 13454 "type": "Number" 13455 }, 13456 { 13457 "name": "target", 13458 "description": "<p>if undefined a new vector will be created</p>\n", 13459 "type": "p5.Vector" 13460 } 13461 ], 13462 "static": 1 13463 }, 13464 { 13465 "line": 1621, 13466 "params": [ 13467 { 13468 "name": "v", 13469 "description": "", 13470 "type": "p5.Vector" 13471 }, 13472 { 13473 "name": "n", 13474 "description": "", 13475 "type": "Number" 13476 } 13477 ], 13478 "static": 1, 13479 "return": { 13480 "description": "the resulting new p5.Vector", 13481 "type": "p5.Vector" 13482 } 13483 } 13484 ] 13485 }, 13486 { 13487 "file": "src/math/p5.Vector.js", 13488 "line": 495, 13489 "description": "<p>Divide the vector by a scalar. The static version of this method creates a\nnew p5.Vector while the non static version acts on the vector directly.\nSee the examples for more context.</p>\n", 13490 "itemtype": "method", 13491 "name": "div", 13492 "chainable": 1, 13493 "example": [ 13494 "\n<div class=\"norender\">\n<code>\nvar v = createVector(6, 4, 2);\nv.div(2); //v's components are set to [3, 2, 1]\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\n// Static method\nvar v1 = createVector(6, 4, 2);\nvar v2 = p5.Vector.div(v1, 2);\n// v2 has components [3, 2, 1]\nprint(v2);\n</code>\n</div>\n\n<div>\n<code>\nfunction draw() {\n background(240);\n\n var v0 = createVector(0, 100);\n var v1 = createVector(50, -50);\n drawArrow(v0, v1, 'red');\n\n var num = map(mouseX, 0, width, 10, 0.5, true);\n var v2 = p5.Vector.div(v1, num);\n drawArrow(v0, v2, 'blue');\n\n noStroke();\n text('divided by ' + num.toFixed(2), 10, 90);\n}\n\n// draw an arrow for a vector at a given base position\nfunction drawArrow(base, vec, myColor) {\n push();\n stroke(myColor);\n strokeWeight(3);\n fill(myColor);\n translate(base.x, base.y);\n line(0, 0, vec.x, vec.y);\n rotate(vec.heading());\n var arrowSize = 7;\n translate(vec.mag() - arrowSize, 0);\n triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);\n pop();\n}\n</code>\n</div>" 13495 ], 13496 "class": "p5.Vector", 13497 "module": "Math", 13498 "submodule": "Math", 13499 "overloads": [ 13500 { 13501 "line": 495, 13502 "params": [ 13503 { 13504 "name": "n", 13505 "description": "<p>the number to divide the vector by</p>\n", 13506 "type": "Number" 13507 } 13508 ], 13509 "chainable": 1 13510 }, 13511 { 13512 "line": 1641, 13513 "params": [ 13514 { 13515 "name": "v", 13516 "description": "<p>the vector to divide</p>\n", 13517 "type": "p5.Vector" 13518 }, 13519 { 13520 "name": "n", 13521 "description": "", 13522 "type": "Number" 13523 }, 13524 { 13525 "name": "target", 13526 "description": "<p>if undefined a new vector will be created</p>\n", 13527 "type": "p5.Vector" 13528 } 13529 ], 13530 "static": 1 13531 }, 13532 { 13533 "line": 1648, 13534 "params": [ 13535 { 13536 "name": "v", 13537 "description": "", 13538 "type": "p5.Vector" 13539 }, 13540 { 13541 "name": "n", 13542 "description": "", 13543 "type": "Number" 13544 } 13545 ], 13546 "static": 1, 13547 "return": { 13548 "description": "the resulting new p5.Vector", 13549 "type": "p5.Vector" 13550 } 13551 } 13552 ] 13553 }, 13554 { 13555 "file": "src/math/p5.Vector.js", 13556 "line": 573, 13557 "description": "<p>Calculates the magnitude (length) of the vector and returns the result as\na float (this is simply the equation sqrt(x<em>x + y</em>y + z*z).)</p>\n", 13558 "itemtype": "method", 13559 "name": "mag", 13560 "return": { 13561 "description": "magnitude of the vector", 13562 "type": "Number" 13563 }, 13564 "example": [ 13565 "\n<div>\n<code>\nfunction draw() {\n background(240);\n\n var v0 = createVector(0, 0);\n var v1 = createVector(mouseX, mouseY);\n drawArrow(v0, v1, 'black');\n\n noStroke();
13565\n text('vector length: ' + v1.mag().toFixed(2), 10, 70, 90, 30);\n}\n\n// draw an arrow for a vector at a given base position\nfunction drawArrow(base, vec, myColor) {\n push();\n stroke(myColor);\n strokeWeight(3);\n fill(myColor);\n translate(base.x, base.y);\n line(0, 0, vec.x, vec.y);\n rotate(vec.heading());\n var arrowSize = 7;\n translate(vec.mag() - arrowSize, 0);\n triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);\n pop();\n}\n</code>\n</div>\n<div class=\"norender\">\n<code>\nvar v = createVector(20.0, 30.0, 40.0);\nvar m = v.mag();\nprint(m); // Prints \"53.85164807134504\"\n</code>\n</div>" 13566 ], 13567 "class": "p5.Vector", 13568 "module": "Math", 13569 "submodule": "Math", 13570 "overloads": [ 13571 { 13572 "line": 573, 13573 "params": [], 13574 "return": { 13575 "description": "magnitude of the vector", 13576 "type": "Number" 13577 } 13578 }, 13579 { 13580 "line": 1738, 13581 "params": [ 13582 { 13583 "name": "vecT", 13584 "description": "<p>the vector to return the magnitude of</p>\n", 13585 "type": "p5.Vector" 13586 } 13587 ], 13588 "static": 1, 13589 "return": { 13590 "description": "the magnitude of vecT", 13591 "type": "Number" 13592 } 13593 } 13594 ] 13595 }, 13596 { 13597 "file": "src/math/p5.Vector.js", 13598 "line": 621, 13599 "description": "<p>Calculates the squared magnitude of the vector and returns the result\nas a float (this is simply the equation <em>(x<em>x + y</em>y + z*z)</em>.)\nFaster if the real length is not required in the\ncase of comparing vectors, etc.</p>\n", 13600 "itemtype": "method", 13601 "name": "magSq", 13602 "return": { 13603 "description": "squared magnitude of the vector", 13604 "type": "Number" 13605 }, 13606 "example": [ 13607 "\n<div class=\"norender\">\n<code>\n// Static method\nvar v1 = createVector(6, 4, 2);\nprint(v1.magSq()); // Prints \"56\"\n</code>\n</div>\n\n<div>\n<code>\nfunction draw() {\n background(240);\n\n var v0 = createVector(0, 0);\n var v1 = createVector(mouseX, mouseY);\n drawArrow(v0, v1, 'black');\n\n noStroke();\n text('vector length squared: ' + v1.magSq().toFixed(2), 10, 45, 90, 55);\n}\n\n// draw an arrow for a vector at a given base position\nfunction drawArrow(base, vec, myColor) {\n push();\n stroke(myColor);\n strokeWeight(3);\n fill(myColor);\n translate(base.x, base.y);\n line(0, 0, vec.x, vec.y);\n rotate(vec.heading());\n var arrowSize = 7;\n translate(vec.mag() - arrowSize, 0);\n triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);\n pop();\n}\n</code>\n</div>" 13608 ], 13609 "class": "p5.Vector", 13610 "module": "Math", 13611 "submodule": "Math" 13612 }, 13613 { 13614 "file": "src/math/p5.Vector.js", 13615 "line": 675, 13616 "description": "<p>Calculates the dot product of two vectors. The version of the method\nthat computes the dot product of two independent vectors is a static\nmethod. See the examples for more context.</p>\n", 13617 "itemtype": "method", 13618 "name": "dot", 13619 "return": { 13620 "description": "the dot product", 13621 "type": "Number" 13622 }, 13623 "example": [ 13624 "\n<div class=\"norender\">\n<code>\nvar v1 = createVector(1, 2, 3);\nvar v2 = createVector(2, 3, 4);\n\nprint(v1.dot(v2)); // Prints \"20\"\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\n//Static method\nvar v1 = createVector(1, 2, 3);\nvar v2 = createVector(3, 2, 1);\nprint(p5.Vector.dot(v1, v2)); // Prints \"10\"\n</code>\n</div>" 13625 ], 13626 "class": "p5.Vector", 13627 "module": "Math", 13628 "submodule": "Math", 13629 "overloads": [ 13630 { 13631 "line": 675, 13632 "params": [ 13633 { 13634 "name": "x", 13635 "description": "<p>x component of the vector</p>\n", 13636 "type": "Number" 13637 }, 13638 { 13639 "name": "y", 13640 "description": "<p>y component of the vector</p>\n", 13641 "type": "Number", 13642 "optional": true 13643 }, 13644 { 13645 "name": "z", 13646 "description": "<p>z component of the vector</p>\n", 13647 "type": "Number", 13648 "optional": true 13649 } 13650 ], 13651 "return": { 13652 "description": "the dot product", 13653 "type": "Number" 13654 } 13655 }, 13656 { 13657 "line": 706, 13658 "params": [ 13659 { 13660 "name": "value", 13661 "description": "<p>value component of the vector or a p5.Vector</p>\n", 13662 "type": "p5.Vector" 13663 } 13664 ], 13665 "return": { 13666 "description": "", 13667 "type": "Number" 13668 } 13669 }, 13670 { 13671 "line": 1668, 13672 "params": [ 13673 { 13674 "name": "v1", 13675 "description": "<p>the first p5.Vector</p>\n", 13676 "type": "p5.Vector" 13677 }, 13678 { 13679 "name": "v2", 13680 "description": "<p>the second p5.Vector</p>\n", 13681 "type": "p5.Vector" 13682 } 13683 ], 13684 "static": 1, 13685 "return": { 13686 "description": "the dot product", 13687 "type": "Number" 13688 } 13689 } 13690 ] 13691 }, 13692 { 13693 "file": "src/math/p5.Vector.js", 13694 "line": 718, 13695 "description": "<p>Calculates and returns a vector composed of the cross product between\ntwo vectors. Both the static and non static methods return a new p5.Vector.\nSee the examples for more context.</p>\n", 13696 "itemtype": "method", 13697 "name": "cross", 13698 "return": { 13699 "description": "p5.Vector composed of cross product", 13700 "type": "p5.Vector" 13701 }, 13702 "example": [ 13703 "\n<div class=\"norender\">\n<code>\nvar v1 = createVector(1, 2, 3);\nvar v2 = createVector(1, 2, 3);\n\nv1.cross(v2); // v's components are [0, 0, 0]\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\n// Static method\nvar v1 = createVector(1, 0, 0);\nvar v2 = createVector(0, 1, 0);
13703\n\nvar crossProduct = p5.Vector.cross(v1, v2);\n// crossProduct has components [0, 0, 1]\nprint(crossProduct);\n</code>\n</div>" 13704 ], 13705 "class": "p5.Vector", 13706 "module": "Math", 13707 "submodule": "Math", 13708 "overloads": [ 13709 { 13710 "line": 718, 13711 "params": [ 13712 { 13713 "name": "v", 13714 "description": "<p>p5.Vector to be crossed</p>\n", 13715 "type": "p5.Vector" 13716 } 13717 ], 13718 "return": { 13719 "description": "p5.Vector composed of cross product", 13720 "type": "p5.Vector" 13721 } 13722 }, 13723 { 13724 "line": 1682, 13725 "params": [ 13726 { 13727 "name": "v1", 13728 "description": "<p>the first p5.Vector</p>\n", 13729 "type": "p5.Vector" 13730 }, 13731 { 13732 "name": "v2", 13733 "description": "<p>the second p5.Vector</p>\n", 13734 "type": "p5.Vector" 13735 } 13736 ], 13737 "static": 1, 13738 "return": { 13739 "description": "the cross product", 13740 "type": "Number" 13741 } 13742 } 13743 ] 13744 }, 13745 { 13746 "file": "src/math/p5.Vector.js", 13747 "line": 759, 13748 "description": "<p>Calculates the Euclidean distance between two points (considering a\npoint as a vector object).</p>\n", 13749 "itemtype": "method", 13750 "name": "dist", 13751 "return": { 13752 "description": "the distance", 13753 "type": "Number" 13754 }, 13755 "example": [ 13756 "\n<div class=\"norender\">\n<code>\nvar v1 = createVector(1, 0, 0);\nvar v2 = createVector(0, 1, 0);\n\nvar distance = v1.dist(v2); // distance is 1.4142...\nprint(distance);\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\n// Static method\nvar v1 = createVector(1, 0, 0);\nvar v2 = createVector(0, 1, 0);\n\nvar distance = p5.Vector.dist(v1, v2);\n// distance is 1.4142...\nprint(distance);\n</code>\n</div>\n\n<div>\n<code>\nfunction draw() {\n background(240);\n\n var v0 = createVector(0, 0);\n\n var v1 = createVector(70, 50);\n drawArrow(v0, v1, 'red');\n\n var v2 = createVector(mouseX, mouseY);\n drawArrow(v0, v2, 'blue');\n\n noStroke();\n text('distance between vectors: ' + v2.dist(v1).toFixed(2), 5, 50, 95, 50);\n}\n\n// draw an arrow for a vector at a given base position\nfunction drawArrow(base, vec, myColor) {\n push();\n stroke(myColor);\n strokeWeight(3);\n fill(myColor);\n translate(base.x, base.y);\n line(0, 0, vec.x, vec.y);\n rotate(vec.heading());\n var arrowSize = 7;\n translate(vec.mag() - arrowSize, 0);\n triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);\n pop();\n}\n</code>\n</div>" 13757 ], 13758 "class": "p5.Vector", 13759 "module": "Math", 13760 "submodule": "Math", 13761 "overloads": [ 13762 { 13763 "line": 759, 13764 "params": [ 13765 { 13766 "name": "v", 13767 "description": "<p>the x, y, and z coordinates of a p5.Vector</p>\n", 13768 "type": "p5.Vector" 13769 } 13770 ], 13771 "return": { 13772 "description": "the distance", 13773 "type": "Number" 13774 } 13775 }, 13776 { 13777 "line": 1697, 13778 "params": [ 13779 { 13780 "name": "v1", 13781 "description": "<p>the first p5.Vector</p>\n", 13782 "type": "p5.Vector" 13783 }, 13784 { 13785 "name": "v2", 13786 "description": "<p>the second p5.Vector</p>\n", 13787 "type": "p5.Vector" 13788 } 13789 ], 13790 "static": 1, 13791 "return": { 13792 "description": "the distance", 13793 "type": "Number" 13794 } 13795 } 13796 ] 13797 }, 13798 { 13799 "file": "src/math/p5.Vector.js", 13800 "line": 830, 13801 "description": "<p>Normalize the vector to length 1 (make it a unit vector).</p>\n", 13802 "itemtype": "method", 13803 "name": "normalize", 13804 "return": { 13805 "description": "normalized p5.Vector", 13806 "type": "p5.Vector" 13807 }, 13808 "example": [ 13809 "\n<div class=\"norender\">\n<code>\nvar v = createVector(10, 20, 2);\n// v has components [10.0, 20.0, 2.0]\nv.normalize();\n// v's components are set to\n// [0.4454354, 0.8908708, 0.089087084]\n</code>\n</div>\n<div>\n<code>\nfunction draw() {\n background(240);\n\n var v0 = createVector(50, 50);\n var v1 = createVector(mouseX - 50, mouseY - 50);\n\n drawArrow(v0, v1, 'red');\n v1.normalize();\n drawArrow(v0, v1.mult(35), 'blue');\n\n noFill();\n ellipse(50, 50, 35 * 2);\n}\n\n// draw an arrow for a vector at a given base position\nfunction drawArrow(base, vec, myColor) {\n push();\n stroke(myColor);\n strokeWeight(3);\n fill(myColor);\n translate(base.x, base.y);\n line(0, 0, vec.x, vec.y);\n rotate(vec.heading());\n var arrowSize = 7;\n translate(vec.mag() - arrowSize, 0);\n triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);\n pop();\n}\n</code>\n</div>" 13810 ], 13811 "class": "p5.Vector", 13812 "module": "Math", 13813 "submodule": "Math" 13814 }, 13815 { 13816 "file": "src/math/p5.Vector.js", 13817 "line": 886, 13818 "description": "<p>Limit the magnitude of this vector to the value used for the <b>max</b>\nparameter.</p>\n", 13819 "itemtype": "method", 13820 "name": "limit", 13821 "params": [ 13822 { 13823 "name": "max", 13824 "description": "<p>the maximum magnitude for the vector</p>\n", 13825 "type": "Number" 13826 } 13827 ], 13828 "chainable": 1, 13829 "example": [ 13830 "\n<div class=\"norender\">\n<code>\nvar v = createVector(10, 20, 2);\n// v has components [10.0, 20.0, 2.0]\nv.limit(5);\n// v's components are set to\n// [2.2271771, 4.4543543, 0.4454354]\n</code>\n</div>\n<div>\n<code>\nfunction draw() {\n background(240);\n\n var v0 = createVector(50, 50);\n var v1 = createVector(mouseX - 50, mouseY - 50);\n\n drawArrow(v0, v1, 'red');\n drawArrow(v0, v1.limit(35), 'blue');\n\n noFill();\n ellipse(50, 50, 35 * 2);\n}\n\n// draw an arrow for a vector at a given base position\nfunction drawArrow(base, vec, myColor) {\n push();\n stroke(myColor);\n strokeWeight(3);\n fill(myColor);\n translate(base.x, base.y);\n line(0, 0, vec.x, vec.y);\n rotate(vec.heading());\n var arrowSize = 7;\n translate(vec.mag() - arrowSize, 0);\n triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);\n pop();\n}\n</code>\n</div>" 13831 ], 13832 "class": "p5.Vector", 13833 "module": "Math", 13834 "submodule": "Math" 13835 }, 13836 { 13837 "file": "src/math/p5.Vector.js", 13838 "line": 944, 13839 "description": "<p>Set the magnitude of this vector to the value used for the <b>len</b>\nparameter.</p>\n", 13840 "itemtype": "method", 13841 "name": "setMag", 13842 "params": [ 13843 { 13844 "name": "len", 13845 "description": "<p>the new length for this vector</p>\n", 13846 "type": "Number" 13847 } 13848 ], 13849 "chainable": 1, 13850 "example": [ 13851 "\n<div class=\"norender\">\n<code>\nvar v = createVector(10, 20, 2);\n// v has components [10.0, 20.0, 2.0]\nv.setMag(10);\n// v's components are set to [6.0, 8.0, 0.0]\n</code>\n</div>\n\n<div>\n<code>\nfunction draw() {\n background(240);\n\n var v0 = createVector(0, 0);\n var v1 = createVector(50, 50);\n\n drawArrow(v0, v1, 'red');\n\n var length = map(mouseX, 0, width, 0, 141, true);\n v1.setMag(length);\n drawArrow(v0, v1, 'blue');\n\n noStroke();\n text('magnitude set to: ' + length.toFixed(2), 10, 70, 90, 30);\n}\n\n// draw an arrow for a vector at a given base position\nfunction drawArrow(base, vec, myColor) {\n push();\n stroke(myColor);\n strokeWeight(3);\n fill(myColor);\n translate(base.x, base.y);\n line(0, 0, vec.x, vec.y);\n rotate(vec.heading());\n var arrowSize = 7;\n translate(vec.mag() - arrowSize, 0);\n triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);\n pop();\n}\n</code>\n</div>" 13852 ], 13853 "class": "p5.Vector", 13854 "module": "Math", 13855 "submodule": "Math" 13856 }, 13857 { 13858 "file": "src/math/p5.Vector.js", 13859 "line": 1000, 13860 "description": "<p>Calculate the angle of rotation for this vector (only 2D vectors)</p>\n", 13861 "itemtype": "method", 13862 "name": "heading", 13863 "return": { 13864 "description": "the angle of rotation", 13865 "type": "Number" 13866 }, 13867 "example": [ 13868 "\n<div class = \"norender\">\n<code>\nfunction setup() {\n var v1 = createVector(30, 50);\n print(v1.heading()); // 1.0303768265243125\n\n v1 = createVector(40, 50);\n print(v1.heading());
13868 // 0.8960553845713439\n\n v1 = createVector(30, 70);\n print(v1.heading()); // 1.1659045405098132\n}\n</code>\n</div>\n\n<div>\n<code>\nfunction draw() {\n background(240);\n\n var v0 = createVector(50, 50);\n var v1 = createVector(mouseX - 50, mouseY - 50);\n\n drawArrow(v0, v1, 'black');\n\n var myHeading = v1.heading();\n noStroke();\n text(\n 'vector heading: ' +\n myHeading.toFixed(2) +\n ' radians or ' +\n degrees(myHeading).toFixed(2) +\n ' degrees',\n 10,\n 50,\n 90,\n 50\n );\n}\n\n// draw an arrow for a vector at a given base position\nfunction drawArrow(base, vec, myColor) {\n push();\n stroke(myColor);\n strokeWeight(3);\n fill(myColor);\n translate(base.x, base.y);\n line(0, 0, vec.x, vec.y);\n rotate(vec.heading());\n var arrowSize = 7;\n translate(vec.mag() - arrowSize, 0);\n triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);\n pop();\n}\n</code>\n</div>" 13869 ], 13870 "class": "p5.Vector", 13871 "module": "Math", 13872 "submodule": "Math" 13873 }, 13874 { 13875 "file": "src/math/p5.Vector.js", 13876 "line": 1069, 13877 "description": "<p>Rotate the vector by an angle (only 2D vectors), magnitude remains the\nsame</p>\n", 13878 "itemtype": "method", 13879 "name": "rotate", 13880 "params": [ 13881 { 13882 "name": "angle", 13883 "description": "<p>the angle of rotation</p>\n", 13884 "type": "Number" 13885 } 13886 ], 13887 "chainable": 1, 13888 "example": [ 13889 "\n<div class=\"norender\">\n<code>\nvar v = createVector(10.0, 20.0);\n// v has components [10.0, 20.0, 0.0]\nv.rotate(HALF_PI);\n// v's components are set to [-20.0, 9.999999, 0.0]\n</code>\n</div>\n\n<div>\n<code>\nvar angle = 0;\nfunction draw() {\n background(240);\n\n var v0 = createVector(50, 50);\n var v1 = createVector(50, 0);\n\n drawArrow(v0, v1.rotate(angle), 'black');\n angle += 0.01;\n}\n\n// draw an arrow for a vector at a given base position\nfunction drawArrow(base, vec, myColor) {\n push();\n stroke(myColor);\n strokeWeight(3);\n fill(myColor);\n translate(base.x, base.y);\n line(0, 0, vec.x, vec.y);\n rotate(vec.heading());\n var arrowSize = 7;\n translate(vec.mag() - arrowSize, 0);\n triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);\n pop();\n}\n</code>\n</div>" 13890 ], 13891 "class": "p5.Vector", 13892 "module": "Math", 13893 "submodule": "Math" 13894 }, 13895 { 13896 "file": "src/math/p5.Vector.js", 13897 "line": 1125, 13898 "description": "<p>Calculates and returns the angle (in radians) between two vectors.</p>\n", 13899 "itemtype": "method", 13900 "name": "angleBetween", 13901 "params": [ 13902 { 13903 "name": "the", 13904 "description": "<p>x, y, and z components of a p5.Vector</p>\n", 13905 "type": "p5.Vector" 13906 } 13907 ], 13908 "return": { 13909 "description": "the angle between (in radians)", 13910 "type": "Number" 13911 }, 13912 "example": [ 13913 "\n<div class=\"norender\">\n<code>\nvar v1 = createVector(1, 0, 0);\nvar v2 = createVector(0, 1, 0);\n\nvar angle = v1.angleBetween(v2);\n// angle is PI/2\nprint(angle);\n</code>\n</div>\n\n<div>\n<code>\nfunction draw() {\n background(240);\n var v0 = createVector(50, 50);\n\n var v1 = createVector(50, 0);\n drawArrow(v0, v1, 'red');\n\n var v2 = createVector(mouseX - 50, mouseY - 50);\n drawArrow(v0, v2, 'blue');\n\n var angleBetween = v1.angleBetween(v2);\n noStroke();\n text(\n 'angle between: ' +\n angleBetween.toFixed(2) +\n ' radians or ' +\n degrees(angleBetween).toFixed(2) +\n ' degrees',\n 10,\n 50,\n 90,\n 50\n );\n}\n\n// draw an arrow for a vector at a given base position\nfunction drawArrow(base, vec, myColor) {\n push();\n stroke(myColor);\n strokeWeight(3);\n fill(myColor);\n translate(base.x, base.y);\n line(0, 0, vec.x, vec.y);\n rotate(vec.heading());\n var arrowSize = 7;\n translate(vec.mag() - arrowSize, 0);\n triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);\n pop();\n}\n</code>\n</div>" 13914 ], 13915 "class": "p5.Vector", 13916 "module": "Math", 13917 "submodule": "Math" 13918 }, 13919 { 13920 "file": "src/math/p5.Vector.js", 13921 "line": 1198, 13922 "description": "<p>Linear interpolate the vector to another vector</p>\n", 13923 "itemtype": "method", 13924 "name": "lerp", 13925 "chainable": 1, 13926 "example": [ 13927 "\n<div class=\"norender\">\n<code>\nvar v = createVector(1, 1, 0);\n\nv.lerp(3, 3, 0, 0.5); // v now has components [2,2,0]\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\nvar v1 = createVector(0, 0, 0);\nvar v2 = createVector(100, 100, 0);\n\nvar v3 = p5.Vector.lerp(v1, v2, 0.5);\n// v3 has components [50,50,0]\nprint(v3);\n</code>\n</div>\n\n<div>\n<code>\nvar step = 0.01;\nvar amount = 0;\n\nfunction draw() {\n background(240);\n var v0 = createVector(0, 0);\n\n var v1 = createVector(mouseX, mouseY);\n drawArrow(v0, v1, 'red');\n\n var v2 = createVector(90, 90);\n drawArrow(v0, v2, 'blue');\n\n if (amount > 1 || amount < 0) {\n step *= -1;\n }\n amount += step;\n var v3 = p5.Vector.lerp(v1, v2, amount);\n\n drawArrow(v0, v3, 'purple');\n}\n\n// draw an arrow for a vector at a given base position\nfunction drawArrow(base, vec, myColor) {\n push();\n stroke(myColor);\n strokeWeight(3);\n fill(myColor);\n translate(base.x, base.y);\n line(0, 0, vec.x, vec.y);\n rotate(vec.heading());\n var arrowSize = 7;\n translate(vec.mag() - arrowSize, 0);\n triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);\n pop();\n}\n</code>\n</div>" 13928 ], 13929 "class": "p5.Vector", 13930 "module": "Math", 13931 "submodule": "Math", 13932 "overloads": [ 13933 { 13934 "line": 1198, 13935 "params": [ 13936 { 13937 "name": "x", 13938 "description": "<p>the x component</p>\n", 13939 "type": "Number" 13940 }, 13941 { 13942 "name": "y", 13943 "description": "<p>the y component</p>\n", 13944 "type": "Number" 13945 }, 13946 { 13947 "name": "z", 13948 "description": "<p>the z component</p>\n", 13949 "type": "Number" 13950 }, 13951 { 13952 "name": "amt", 13953 "description": "<p>the amount of interpolation; some value between 0.0\n (old vector) and 1.0 (new vector). 0.9 is very near\n the new vector. 0.5 is halfway in between.</p>\n", 13954 "type": "Number" 13955 } 13956 ], 13957 "chainable": 1 13958 }, 13959 { 13960 "line": 1271, 13961 "params": [ 13962 { 13963 "name": "v", 13964 "description": "<p>the p5.Vector to lerp to</p>\n", 13965 "type": "p5.Vector" 13966 }, 13967 { 13968 "name": "amt", 13969 "description": "", 13970 "type": "Number" 13971 } 13972 ], 13973 "chainable": 1 13974 }, 13975 { 13976 "line": 1712, 13977 "params": [ 13978 { 13979 "name": "v1", 13980 "description": "", 13981 "type": "p5.Vector" 13982 }, 13983 { 13984 "name": "v2", 13985 "description": "", 13986 "type": "p5.Vector" 13987 }, 13988 { 13989 "name": "amt", 13990 "description": "", 13991 "type": "Number" 13992 }, 13993 { 13994 "name": "target", 13995 "description": "<p>if undefined a new vector will be created</p>\n", 13996 "type": "p5.Vector" 13997 } 13998 ], 13999 "static": 1 14000 }, 14001 { 14002 "line": 1720, 14003 "params": [ 14004 { 14005 "name": "v1", 14006 "description": "", 14007 "type": "p5.Vector" 14008 }, 14009 { 14010 "name": "v2", 14011 "description": "", 14012 "type": "p5.Vector" 14013 }, 14014 { 14015 "name": "amt", 14016 "description": "", 14017 "type": "Number" 14018 } 14019 ], 14020 "static": 1, 14021 "return": { 14022 "description": "the lerped value", 14023 "type": "Number" 14024 } 14025 } 14026 ] 14027 }, 14028 { 14029 "file": "src/math/p5.Vector.js", 14030 "line": 1287, 14031 "description": "<p>Return a representation of this vector as a float array. This is only\nfor temporary use. If used in any other fashion, the contents should be\ncopied by using the <b>p5.Vector.copy()</b>
14031 method to copy into your own\narray.</p>\n", 14032 "itemtype": "method", 14033 "name": "array", 14034 "return": { 14035 "description": "an Array with the 3 values", 14036 "type": "Number[]" 14037 }, 14038 "example": [ 14039 "\n<div class = \"norender\">\n<code>\nfunction setup() {\n var v = createVector(20, 30);\n print(v.array()); // Prints : Array [20, 30, 0]\n}\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\nvar v = createVector(10.0, 20.0, 30.0);\nvar f = v.array();\nprint(f[0]); // Prints \"10.0\"\nprint(f[1]); // Prints \"20.0\"\nprint(f[2]); // Prints \"30.0\"\n</code>\n</div>" 14040 ], 14041 "class": "p5.Vector", 14042 "module": "Math", 14043 "submodule": "Math" 14044 }, 14045 { 14046 "file": "src/math/p5.Vector.js", 14047 "line": 1319, 14048 "description": "<p>Equality check against a p5.Vector</p>\n", 14049 "itemtype": "method", 14050 "name": "equals", 14051 "return": { 14052 "description": "whether the vectors are equals", 14053 "type": "Boolean" 14054 }, 14055 "example": [ 14056 "\n<div class = \"norender\">\n<code>\nvar v1 = createVector(5, 10, 20);\nvar v2 = createVector(5, 10, 20);\nvar v3 = createVector(13, 10, 19);\n\nprint(v1.equals(v2.x, v2.y, v2.z)); // true\nprint(v1.equals(v3.x, v3.y, v3.z)); // false\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\nvar v1 = createVector(10.0, 20.0, 30.0);\nvar v2 = createVector(10.0, 20.0, 30.0);\nvar v3 = createVector(0.0, 0.0, 0.0);\nprint(v1.equals(v2)); // true\nprint(v1.equals(v3)); // false\n</code>\n</div>" 14057 ], 14058 "class": "p5.Vector", 14059 "module": "Math", 14060 "submodule": "Math", 14061 "overloads": [ 14062 { 14063 "line": 1319, 14064 "params": [ 14065 { 14066 "name": "x", 14067 "description": "<p>the x component of the vector</p>\n", 14068 "type": "Number", 14069 "optional": true 14070 }, 14071 { 14072 "name": "y", 14073 "description": "<p>the y component of the vector</p>\n", 14074 "type": "Number", 14075 "optional": true 14076 }, 14077 { 14078 "name": "z", 14079 "description": "<p>the z component of the vector</p>\n", 14080 "type": "Number", 14081 "optional": true 14082 } 14083 ], 14084 "return": { 14085 "description": "whether the vectors are equals", 14086 "type": "Boolean" 14087 } 14088 }, 14089 { 14090 "line": 1349, 14091 "params": [ 14092 { 14093 "name": "value", 14094 "description": "<p>the vector to compare</p>\n", 14095 "type": "p5.Vector|Array" 14096 } 14097 ], 14098 "return": { 14099 "description": "", 14100 "type": "Boolean" 14101 } 14102 } 14103 ] 14104 }, 14105 { 14106 "file": "src/math/p5.Vector.js", 14107 "line": 1374, 14108 "description": "<p>Make a new 2D vector from an angle</p>\n", 14109 "itemtype": "method", 14110 "name": "fromAngle", 14111 "static": 1, 14112 "params": [ 14113 { 14114 "name": "angle", 14115 "description": "<p>the desired angle, in radians</p>\n", 14116 "type": "Number" 14117 }, 14118 { 14119 "name": "length", 14120 "description": "<p>the length of the new vector (defaults to 1)</p>\n", 14121 "type": "Number", 14122 "optional": true 14123 } 14124 ], 14125 "return": { 14126 "description": "the new p5.Vector object", 14127 "type": "p5.Vector" 14128 }, 14129 "example": [ 14130 "\n<div>\n<code>\nfunction draw() {\n background(200);\n\n // Create a variable, proportional to the mouseX,\n // varying from 0-360, to represent an angle in degrees.\n angleMode(DEGREES);\n var myDegrees = map(mouseX, 0, width, 0, 360);\n\n // Display that variable in an onscreen text.\n // (Note the nfc() function to truncate additional decimal places,\n // and the \"\\xB0\" character for the degree symbol.)\n var readout = 'angle = ' + nfc(myDegrees, 1) + '\\xB0';\n noStroke();\n fill(0);\n text(readout, 5, 15);\n\n // Create a p5.Vector using the fromAngle function,\n // and extract its x and y components.\n var v = p5.Vector.fromAngle(radians(myDegrees), 30);\n var vx = v.x;\n var vy = v.y;\n\n push();\n translate(width / 2, height / 2);\n noFill();\n stroke(150);\n line(0, 0, 30, 0);\n stroke(0);\n line(0, 0, vx, vy);\n pop();\n}\n</code>\n</div>" 14131 ], 14132 "class": "p5.Vector", 14133 "module": "Math", 14134 "submodule": "Math" 14135 }, 14136 { 14137 "file": "src/math/p5.Vector.js", 14138 "line": 1426, 14139 "description": "<p>Make a new 3D vector from a pair of ISO spherical angles</p>\n", 14140 "itemtype": "method", 14141 "name": "fromAngles", 14142 "static": 1, 14143 "params": [ 14144 { 14145 "name": "theta", 14146 "description": "<p>the polar angle, in radians (zero is up)</p>\n", 14147 "type": "Number" 14148 }, 14149 { 14150 "name": "phi", 14151 "description": "<p>the azimuthal angle, in radians\n (zero is out of the screen)</p>\n", 14152 "type": "Number" 14153 }, 14154 { 14155 "name": "length", 14156 "description": "<p>the length of the new vector (defaults to 1)</p>\n", 14157 "type": "Number", 14158 "optional": true 14159 } 14160 ], 14161 "return": { 14162 "description": "the new p5.Vector object", 14163 "type": "p5.Vector" 14164 }, 14165 "example": [ 14166 "\n<div modernizr='webgl'>\n<code>\nfunction setup() {\n createCanvas(100, 100, WEBGL);\n fill(255);\n noStroke();\n}\nfunction draw() {\n background(255);\n\n var t = millis() / 1000;\n\n // add three point lights\n pointLight(color('#f00'), p5.Vector.fromAngles(t * 1.0, t * 1.3, 100));\n pointLight(color('#0f0'), p5.Vector.fromAngles(t * 1.1, t * 1.2, 100));\n pointLight(color('#00f'), p5.Vector.fromAngles(t * 1.2, t * 1.1, 100));\n\n sphere(35);\n}\n</code>\n</div>" 14167 ], 14168 "class": "p5.Vector", 14169 "module": "Math", 14170 "submodule": "Math" 14171 }, 14172 { 14173 "file": "src/math/p5.Vector.js", 14174 "line": 1475, 14175 "description": "<p>Make a new 2D unit vector from a random angle</p>\n", 14176 "itemtype": "method", 14177 "name": "random2D", 14178 "static": 1, 14179 "return": { 14180 "description": "the new p5.Vector object", 14181 "type": "p5.Vector" 14182 }, 14183 "example": [ 14184 "\n<div class=\"norender\">\n<code>\nvar v = p5.Vector.random2D();\n// May make v's attributes something like:\n// [0.61554617, -0.51195765, 0.0] or\n// [-0.4695841, -0.
1418414366731, 0.0] or\n// [0.6091097, -0.22805278, 0.0]\nprint(v);\n</code>\n</div>\n\n<div>\n<code>\nfunction setup() {\n frameRate(1);\n}\n\nfunction draw() {\n background(240);\n\n var v0 = createVector(50, 50);\n var v1 = p5.Vector.random2D();\n drawArrow(v0, v1.mult(50), 'black');\n}\n\n// draw an arrow for a vector at a given base position\nfunction drawArrow(base, vec, myColor) {\n push();\n stroke(myColor);\n strokeWeight(3);\n fill(myColor);\n translate(base.x, base.y);\n line(0, 0, vec.x, vec.y);\n rotate(vec.heading());\n var arrowSize = 7;\n translate(vec.mag() - arrowSize, 0);\n triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);\n pop();\n}\n</code>\n</div>" 14185 ], 14186 "class": "p5.Vector", 14187 "module": "Math", 14188 "submodule": "Math" 14189 }, 14190 { 14191 "file": "src/math/p5.Vector.js", 14192 "line": 1528, 14193 "description": "<p>Make a new random 3D unit vector.</p>\n", 14194 "itemtype": "method", 14195 "name": "random3D", 14196 "static": 1, 14197 "return": { 14198 "description": "the new p5.Vector object", 14199 "type": "p5.Vector" 14200 }, 14201 "example": [ 14202 "\n<div class=\"norender\">\n<code>\nvar v = p5.Vector.random3D();\n// May make v's attributes something like:\n// [0.61554617, -0.51195765, 0.599168] or\n// [-0.4695841, -0.14366731, -0.8711202] or\n// [0.6091097, -0.22805278, -0.7595902]\nprint(v);\n</code>\n</div>" 14203 ], 14204 "class": "p5.Vector", 14205 "module": "Math", 14206 "submodule": "Math" 14207 }, 14208 { 14209 "file": "src/math/p5.Vector.js", 14210 "line": 1611, 14211 "description": "<p>Multiplies a vector by a scalar and returns a new vector.</p>\n", 14212 "class": "p5.Vector", 14213 "module": "Math", 14214 "submodule": "Math" 14215 }, 14216 { 14217 "file": "src/math/p5.Vector.js", 14218 "line": 1638, 14219 "description": "<p>Divides a vector by a scalar and returns a new vector.</p>\n", 14220 "class": "p5.Vector", 14221 "module": "Math", 14222 "submodule": "Math" 14223 }, 14224 { 14225 "file": "src/math/p5.Vector.js", 14226 "line": 1665, 14227 "description": "<p>Calculates the dot product of two vectors.</p>\n", 14228 "class": "p5.Vector", 14229 "module": "Math", 14230 "submodule": "Math" 14231 }, 14232 { 14233 "file": "src/math/p5.Vector.js", 14234 "line": 1679, 14235 "description": "<p>Calculates the cross product of two vectors.</p>\n", 14236 "class": "p5.Vector", 14237 "module": "Math", 14238 "submodule": "Math" 14239 }, 14240 { 14241 "file": "src/math/p5.Vector.js", 14242 "line": 1693, 14243 "description": "<p>Calculates the Euclidean distance between two points (considering a\npoint as a vector object).</p>\n", 14244 "class": "p5.Vector", 14245 "module": "Math", 14246 "submodule": "Math" 14247 }, 14248 { 14249 "file": "src/math/p5.Vector.js", 14250 "line": 1708, 14251 "description": "<p>Linear interpolate a vector to another vector and return the result as a\nnew vector.</p>\n", 14252 "class": "p5.Vector", 14253 "module": "Math", 14254 "submodule": "Math" 14255 }, 14256 { 14257 "file": "src/math/random.js", 14258 "line": 48, 14259 "description": "<p>Sets the seed value for random().</p>\n<p>By default, random() produces different results each time the program\nis run. Set the seed parameter to a constant to return the same\npseudo-random numbers each time the software is run.</p>\n", 14260 "itemtype": "method", 14261 "name": "randomSeed", 14262 "params": [ 14263 { 14264 "name": "seed", 14265 "description": "<p>the seed value</p>\n", 14266 "type": "Number" 14267 } 14268 ], 14269 "example": [ 14270 "\n<div>\n<code>\nrandomSeed(99);\nfor (var i = 0; i < 100;
14270 i++) {\n var r = random(0, 255);\n stroke(r);\n line(i, 0, i, 100);\n}\n</code>\n</div>" 14271 ], 14272 "alt": "many vertical lines drawn in white, black or grey.", 14273 "class": "p5", 14274 "module": "Math", 14275 "submodule": "Random" 14276 }, 14277 { 14278 "file": "src/math/random.js", 14279 "line": 79, 14280 "description": "<p>Return a random floating-point number.</p>\n<p>Takes either 0, 1 or 2 arguments.</p>\n<p>If no argument is given, returns a random number from 0\nup to (but not including) 1.</p>\n<p>If one argument is given and it is a number, returns a random number from 0\nup to (but not including) the number.</p>\n<p>If one argument is given and it is an array, returns a random element from\nthat array.</p>\n<p>If two arguments are given, returns a random number from the\nfirst argument up to (but not including) the second argument.</p>\n", 14281 "itemtype": "method", 14282 "name": "random", 14283 "return": { 14284 "description": "the random number", 14285 "type": "Number" 14286 }, 14287 "example": [ 14288 "\n<div>\n<code>\nfor (var i = 0; i < 100; i++) {\n var r = random(50);\n stroke(r * 5);\n line(50, i, 50 + r, i);\n}\n</code>\n</div>\n<div>\n<code>\nfor (var i = 0; i < 100; i++) {\n var r = random(-50, 50);\n line(50, i, 50 + r, i);\n}\n</code>\n</div>\n<div>\n<code>\n// Get a random element from an array using the random(Array) syntax\nvar words = ['apple', 'bear', 'cat', 'dog'];\nvar word = random(words); // select random word\ntext(word, 10, 50); // draw the word\n</code>\n</div>" 14289 ], 14290 "alt": "100 horizontal lines from center canvas to right. size+fill change each time\n100 horizontal lines from center of canvas. height & side change each render\nword displayed at random. Either apple, bear, cat, or dog", 14291 "class": "p5", 14292 "module": "Math", 14293 "submodule": "Random", 14294 "overloads": [ 14295 { 14296 "line": 79, 14297 "params": [ 14298 { 14299 "name": "min", 14300 "description": "<p>the lower bound (inclusive)</p>\n", 14301 "type": "Number", 14302 "optional": true 14303 }, 14304 { 14305 "name": "max", 14306 "description": "<p>the upper bound (exclusive)</p>\n", 14307 "type": "Number", 14308 "optional": true 14309 } 14310 ], 14311 "return": { 14312 "description": "the random number", 14313 "type": "Number" 14314 } 14315 }, 14316 { 14317 "line": 133, 14318 "params": [ 14319 { 14320 "name": "choices", 14321 "description": "<p>the array to choose from</p>\n", 14322 "type": "Array" 14323 } 14324 ], 14325 "return": { 14326 "description": "the random element from the array", 14327 "type": "*" 14328 } 14329 } 14330 ] 14331 }, 14332 { 14333 "file": "src/math/random.js", 14334 "line": 166, 14335 "description": "<p>Returns a random number fitting a Gaussian, or\n normal, distribution. There is theoretically no minimum or maximum\n value that randomGaussian() might return. Rather, there is\n just a very low probability that values far from the mean will be\n returned; and a higher probability that numbers near the mean will\n be returned.\n <br><br>\n Takes either 0, 1 or 2 arguments.<br>\n If no args, returns a mean of 0 and standard deviation of 1.<br>\n If one arg, that arg is the mean (standard deviation is 1).<br>\n If two args, first is mean, second is standard deviation.</p>\n", 14336 "itemtype": "method", 14337 "name": "randomGaussian", 14338 "params": [ 14339 { 14340 "name": "mean", 14341 "description": "<p>the mean</p>\n", 14342 "type": "Number" 14343 }, 14344 { 14345 "name": "sd", 14346 "description": "<p>the standard deviation</p>\n", 14347 "type": "Number" 14348 } 14349 ], 14350 "return": { 14351 "description": "the random number", 14352 "type": "Number" 14353 }, 14354 "example": [ 14355 "\n <div>\n <code>\n for (var y = 0; y < 100;
14355 y++) {\n var x = randomGaussian(50, 15);\n line(50, y, x, y);\n }\n </code>\n </div>\n <div>\n <code>\n var distribution = new Array(360);\nfunction setup() {\n createCanvas(100, 100);\n for (var i = 0; i < distribution.length; i++) {\n distribution[i] = floor(randomGaussian(0, 15));\n }\n }\nfunction draw() {\n background(204);\n translate(width / 2, width / 2);\n for (var i = 0; i < distribution.length; i++) {\n rotate(TWO_PI / distribution.length);\n stroke(0);\n var dist = abs(distribution[i]);\n line(0, 0, dist, 0);\n }\n }\n </code>\n </div>" 14356 ], 14357 "alt": "100 horizontal lines from center of canvas. height & side change each render\n black lines radiate from center of canvas. size determined each render", 14358 "class": "p5", 14359 "module": "Math", 14360 "submodule": "Random" 14361 }, 14362 { 14363 "file": "src/math/trigonometry.js", 14364 "line": 20, 14365 "description": "<p>The inverse of cos(), returns the arc cosine of a value. This function\nexpects the values in the range of -1 to 1 and values are returned in\nthe range 0 to PI (3.1415927).</p>\n", 14366 "itemtype": "method", 14367 "name": "acos", 14368 "params": [ 14369 { 14370 "name": "value", 14371 "description": "<p>the value whose arc cosine is to be returned</p>\n", 14372 "type": "Number" 14373 } 14374 ], 14375 "return": { 14376 "description": "the arc cosine of the given value", 14377 "type": "Number" 14378 }, 14379 "example": [ 14380 "\n<div class= ânorender\">\n<code>\nvar a = PI;\nvar c = cos(a);\nvar ac = acos(c);\n// Prints: \"3.1415927 : -1.0 : 3.1415927\"\nprint(a + ' : ' + c + ' : ' + ac);\n</code>\n</div>\n\n<div class= ânorender\">\n<code>\nvar a = PI + PI / 4.0;\nvar c = cos(a);\nvar ac = acos(c);\n// Prints: \"3.926991 : -0.70710665 : 2.3561943\"\nprint(a + ' : ' + c + ' : ' + ac);\n</code>\n</div>" 14381 ], 14382 "class": "p5", 14383 "module": "Math", 14384 "submodule": "Trigonometry" 14385 }, 14386 { 14387 "file": "src/math/trigonometry.js", 14388 "line": 54, 14389 "description": "<p>The inverse of sin(), returns the arc sine of a value. This function\nexpects the values in the range of -1 to 1 and values are returned\nin the range -PI/2 to PI/2.</p>\n", 14390 "itemtype": "method", 14391 "name": "asin", 14392 "params": [ 14393 { 14394 "name": "value", 14395 "description": "<p>the value whose arc sine is to be returned</p>\n", 14396 "type": "Number" 14397 } 14398 ], 14399 "return": { 14400 "description": "the arc sine of the given value", 14401 "type": "Number" 14402 }, 14403 "example": [ 14404 "\n<div class= ânorender\">\n<code>\nvar a = PI + PI / 3;\nvar s = sin(a);\nvar as = asin(s);\n// Prints: \"1.0471976 : 0.86602545 : 1.0471976\"\nprint(a + ' : ' + s + ' : ' + as);\n</code>\n</div>\n\n<div class= ânorender\">\n<code>\nvar a = PI + PI / 3.0;\nvar s = sin(a);\nvar as = asin(s);\n// Prints: \"4.1887903 : -0.86602545 : -1.0471976\"\nprint(a + ' : ' + s + ' : ' + as);\n</code>\n</div>\n" 14405 ], 14406 "class": "p5", 14407 "module": "Math", 14408 "submodule": "Trigonometry" 14409 }, 14410 { 14411 "file": "src/math/trigonometry.js", 14412 "line": 89, 14413 "description": "<p>The inverse of tan(), returns the arc tangent of a value. This function\nexpects the values in the range of -Infinity to Infinity (exclusive) and\nvalues are returned in the range -PI/2 to PI/2.</p>\n", 14414 "itemtype": "method", 14415 "name": "atan", 14416 "params": [ 14417 { 14418 "name": "value", 14419 "description": "<p>the value whose arc tangent is to be returned</p>\n", 14420 "type": "Number" 14421 } 14422 ], 14423 "return": { 14424 "description": "the arc tangent of the given value", 14425 "type": "Number" 14426 }, 14427 "example": [ 14428 "\n<div class= ânorender\">\n<code>\nvar a = PI + PI / 3;\nvar t = tan(a);\nvar at = atan(t);\n// Prints: \"1.0471976 : 1.7320509 : 1.0471976\"\nprint(a + ' : ' + t + ' : ' + at);\n</code>\n</div>\n\n<div class= ânorender\">\n<code>\nvar a = PI + PI / 3.0;\nvar t = tan(a);\nvar at = atan(t);\n// Prints: \"4.1887903 : 1.7320513 : 1.0471977\"\nprint(a + ' : ' + t + ' : ' + at);\n</code>\n</div>\n" 14429 ], 14430 "class": "p5", 14431 "module": "Math", 14432 "submodule": "Trigonometry" 14433 }, 14434 { 14435 "file": "src/math/trigonometry.js", 14436 "line": 124, 14437 "description": "<p>Calculates the angle (in radians) from a specified point to the coordinate\norigin as measured from the positive x-axis. Values are returned as a\nfloat in the range from PI to -PI. The atan2() function is most often used\nfor orienting geometry to the position of the cursor.\n<br><br>\nNote: The y-coordinate of the point is the first parameter, and the\nx-coordinate is the second parameter, due the the structure of calculating\nthe tangent.</p>\n", 14438 "itemtype": "method", 14439 "name": "atan2", 14440 "params": [ 14441 { 14442 "name": "y", 14443 "description": "<p>y-coordinate of the point</p>\n", 14444 "type": "Number" 14445 }, 14446 { 14447 "name": "x", 14448 "description": "<p>x-coordinate of the point</p>\n", 14449 "type": "Number" 14450 } 14451 ], 14452 "return": { 14453 "description": "the arc tangent of the given point", 14454 "type": "Number" 14455 }, 14456 "example": [ 14457 "\n<div>\n<code>\nfunction draw() {\n background(204);\n translate(width / 2, height / 2);
14457\n var a = atan2(mouseY - height / 2, mouseX - width / 2);\n rotate(a);\n rect(-30, -5, 60, 10);\n}\n</code>\n</div>" 14458 ], 14459 "alt": "60 by 10 rect at center of canvas rotates with mouse movements", 14460 "class": "p5", 14461 "module": "Math", 14462 "submodule": "Trigonometry" 14463 }, 14464 { 14465 "file": "src/math/trigonometry.js", 14466 "line": 160, 14467 "description": "<p>Calculates the cosine of an angle. This function takes into account the\ncurrent angleMode. Values are returned in the range -1 to 1.</p>\n", 14468 "itemtype": "method", 14469 "name": "cos", 14470 "params": [ 14471 { 14472 "name": "angle", 14473 "description": "<p>the angle</p>\n", 14474 "type": "Number" 14475 } 14476 ], 14477 "return": { 14478 "description": "the cosine of the angle", 14479 "type": "Number" 14480 }, 14481 "example": [ 14482 "\n<div>\n<code>\nvar a = 0.0;\nvar inc = TWO_PI / 25.0;\nfor (var i = 0; i < 25; i++) {\n line(i * 4, 50, i * 4, 50 + cos(a) * 40.0);\n a = a + inc;\n}\n</code>\n</div>" 14483 ], 14484 "alt": "vertical black lines form wave patterns, extend-down on left and right side", 14485 "class": "p5", 14486 "module": "Math", 14487 "submodule": "Trigonometry" 14488 }, 14489 { 14490 "file": "src/math/trigonometry.js", 14491 "line": 188, 14492 "description": "<p>Calculates the sine of an angle. This function takes into account the\ncurrent angleMode. Values are returned in the range -1 to 1.</p>\n", 14493 "itemtype": "method", 14494 "name": "sin", 14495 "params": [ 14496 { 14497 "name": "angle", 14498 "description": "<p>the angle</p>\n", 14499 "type": "Number" 14500 } 14501 ], 14502 "return": { 14503 "description": "the sine of the angle", 14504 "type": "Number" 14505 }, 14506 "example": [ 14507 "\n<div>\n<code>\nvar a = 0.0;\nvar inc = TWO_PI / 25.0;\nfor (var i = 0; i < 25; i++) {\n line(i * 4, 50, i * 4, 50 + sin(a) * 40.0);\n a = a + inc;\n}\n</code>\n</div>" 14508 ], 14509 "alt": "vertical black lines extend down and up from center to form wave pattern", 14510 "class": "p5", 14511 "module": "Math", 14512 "submodule": "Trigonometry" 14513 }, 14514 { 14515 "file": "src/math/trigonometry.js", 14516 "line": 216, 14517 "description": "<p>Calculates the tangent of an angle. This function takes into account\nthe current angleMode. Values are returned in the range -1 to 1.</p>\n", 14518 "itemtype": "method", 14519 "name": "tan", 14520 "params": [ 14521 { 14522 "name": "angle", 14523 "description": "<p>the angle</p>\n", 14524 "type": "Number" 14525 } 14526 ], 14527 "return": { 14528 "description": "the tangent of the angle", 14529 "type": "Number" 14530 }, 14531 "example": [ 14532 "\n<div>\n<code>\nvar a = 0.0;\nvar inc = TWO_PI / 50.0;\nfor (var i = 0; i < 100; i = i + 2) {\n line(i, 50, i, 50 + tan(a) * 2.0);\n a = a + inc;\n}\n</code>" 14533 ], 14534 "alt": "vertical black lines end down and up from center to form spike pattern", 14535 "class": "p5", 14536 "module": "Math", 14537 "submodule": "Trigonometry" 14538 }, 14539 { 14540 "file": "src/math/trigonometry.js", 14541 "line": 244, 14542 "description": "<p>Converts a radian measurement to its corresponding value in degrees.\nRadians and degrees are two ways of measuring the same thing. There are\n360 degrees in a circle and 2*PI radians in a circle. For example,\n90° = PI/2 = 1.5707964. This function does not take into account the\ncurrent angleMode.</p>\n", 14543 "itemtype": "method", 14544 "name": "degrees", 14545 "params": [ 14546 { 14547 "name": "radians", 14548 "description": "<p>the radians value to convert to degrees</p>\n", 14549 "type": "Number" 14550 } 14551 ], 14552 "return": { 14553 "description": "the converted angle", 14554 "type": "Number" 14555 }, 14556 "example": [ 14557 "\n<div class= ânorender\">\n<code>\nvar rad = PI / 4;\nvar deg = degrees(rad);\nprint(rad + ' radians is ' + deg + ' degrees');\n// Prints: 0.7853981633974483 radians is 45 degrees\n</code>\n</div>\n" 14558 ], 14559 "class": "p5", 14560 "module": "Math", 14561 "submodule": "Trigonometry" 14562 }, 14563 { 14564 "file": "src/math/trigonometry.js", 14565 "line": 271, 14566 "description": "<p>Converts a degree measurement to its corresponding value in radians.\nRadians and degrees are two ways of measuring the same thing. There are\n360 degrees in a circle and 2*PI radians in a circle. For example,\n90° = PI/2 = 1.5707964. This function does not take into account the\ncurrent angleMode.</p>\n", 14567 "itemtype": "method", 14568 "name": "radians", 14569 "params": [ 14570 { 14571 "name": "degrees", 14572 "description": "<p>the degree value to convert to radians</p>\n", 14573 "type": "Number" 14574 } 14575 ], 14576 "return": { 14577 "description": "the converted angle", 14578 "type": "Number" 14579 }, 14580 "example": [ 14581 "\n<div class= ânorender\">\n<code>\nvar deg = 45.0;\nvar rad = radians(deg);\nprint(deg + ' degrees is ' + rad + ' radians');\n// Prints: 45 degrees is 0.7853981633974483 radians\n</code>\n</div>" 14582 ], 14583 "class": "p5", 14584 "module": "Math", 14585 "submodule": "Trigonometry" 14586 }, 14587 { 14588 "file": "src/math/trigonometry.js", 14589 "line": 296, 14590 "description": "<p>Sets the current mode of p5 to given mode. Default mode is RADIANS.</p>\n", 14591 "itemtype": "method", 14592 "name": "angleMode", 14593 "params": [ 14594 { 14595 "name": "mode", 14596 "description": "<p>either RADIANS or DEGREES</p>\n", 14597 "type": "Constant" 14598 } 14599 ], 14600 "example": [ 14601 "\n<div>\n<code>\nfunction draw() {\n background(204);\n angleMode(DEGREES);
14601 // Change the mode to DEGREES\n var a = atan2(mouseY - height / 2, mouseX - width / 2);\n translate(width / 2, height / 2);\n push();\n rotate(a);\n rect(-20, -5, 40, 10); // Larger rectangle is rotating in degrees\n pop();\n angleMode(RADIANS); // Change the mode to RADIANS\n rotate(a); // var a stays the same\n rect(-40, -5, 20, 10); // Smaller rectangle is rotating in radians\n}\n</code>\n</div>" 14602 ], 14603 "alt": "40 by 10 rect in center rotates with mouse moves. 20 by 10 rect moves faster.", 14604 "class": "p5", 14605 "module": "Math", 14606 "submodule": "Trigonometry" 14607 }, 14608 { 14609 "file": "src/typography/attributes.js", 14610 "line": 13, 14611 "description": "<p>Sets the current alignment for drawing text. Accepts two\narguments: horizAlign (LEFT, CENTER, or RIGHT) and\nvertAlign (TOP, BOTTOM, CENTER, or BASELINE).</p>\n<p>The horizAlign parameter is in reference to the x value\nof the text() function, while the vertAlign parameter is\nin reference to the y value.</p>\n<p>So if you write textAlign(LEFT), you are aligning the left\nedge of your text to the x value you give in text(). If you\nwrite textAlign(RIGHT, TOP), you are aligning the right edge\nof your text to the x value and the top of edge of the text\nto the y value.</p>\n", 14612 "itemtype": "method", 14613 "name": "textAlign", 14614 "chainable": 1, 14615 "example": [ 14616 "\n<div>\n<code>\ntextSize(16);\ntextAlign(RIGHT);\ntext('ABCD', 50, 30);\ntextAlign(CENTER);\ntext('EFGH', 50, 50);\ntextAlign(LEFT);\ntext('IJKL', 50, 70);\n</code>\n</div>" 14617 ], 14618 "alt": "Letters ABCD displayed at top right, EFGH at center and IJKL at bottom left.", 14619 "class": "p5", 14620 "module": "Typography", 14621 "submodule": "Attributes", 14622 "overloads": [ 14623 { 14624 "line": 13, 14625 "params": [ 14626 { 14627 "name": "horizAlign", 14628 "description": "<p>horizontal alignment, either LEFT,\n CENTER, or RIGHT</p>\n", 14629 "type": "Constant" 14630 }, 14631 { 14632 "name": "vertAlign", 14633 "description": "<p>vertical alignment, either TOP,\n BOTTOM, CENTER, or BASELINE</p>\n", 14634 "type": "Constant", 14635 "optional": true 14636 } 14637 ], 14638 "chainable": 1 14639 }, 14640 { 14641 "line": 51, 14642 "params": [], 14643 "return": { 14644 "description": "", 14645 "type": "Object" 14646 } 14647 } 14648 ] 14649 }, 14650 { 14651 "file": "src/typography/attributes.js", 14652 "line": 60, 14653 "description": "<p>Sets/gets the spacing, in pixels, between lines of text. This\nsetting will be used in all subsequent calls to the text() function.</p>\n", 14654 "itemtype": "method", 14655 "name": "textLeading", 14656 "chainable": 1, 14657 "example": [ 14658 "\n<div>\n<code>\n// Text to display. The \"\\n\" is a \"new line\" character\nvar lines = 'L1\\nL2\\nL3';\ntextSize(12);\n\ntextLeading(10); // Set leading to 10\ntext(lines, 10, 25);\n\ntextLeading(20); // Set leading to 20\ntext(lines, 40, 25);\n\ntextLeading(30); // Set leading to 30\ntext(lines, 70, 25);\n</code>\n</div>" 14659 ], 14660 "alt": "set L1 L2 & L3 displayed vertically 3 times. spacing increases for each set", 14661 "class": "p5", 14662 "module": "Typography", 14663 "submodule": "Attributes", 14664 "overloads": [ 14665 { 14666 "line": 60, 14667 "params": [ 14668 { 14669 "name": "leading", 14670 "description": "<p>the size in pixels for spacing between lines</p>\n", 14671 "type": "Number" 14672 } 14673 ], 14674 "chainable": 1 14675 }, 14676 { 14677 "line": 89, 14678 "params": [], 14679 "return": { 14680 "description": "", 14681 "type": "Number" 14682 } 14683 } 14684 ] 14685 }, 14686 { 14687 "file": "src/typography/attributes.js", 14688 "line": 98, 14689 "description": "<p>Sets/gets the current font size. This size will be used in all subsequent\ncalls to the text() function. Font size is measured in pixels.</p>\n", 14690 "itemtype": "method", 14691 "name": "textSize", 14692 "chainable": 1, 14693 "example": [ 14694 "\n<div>\n<code>\ntextSize(12);\ntext('Font Size 12', 10, 30);\ntextSize(14);\ntext('Font Size 14', 10, 60);\ntextSize(16);\ntext('Font Size 16', 10, 90);\n</code>\n</div>" 14695 ], 14696 "alt": "Font Size 12 displayed small, Font Size 14 medium & Font Size 16 large", 14697 "class": "p5", 14698 "module": "Typography", 14699 "submodule": "Attributes", 14700 "overloads": [ 14701 { 14702 "line": 98, 14703 "params": [ 14704 { 14705 "name": "theSize", 14706 "description": "<p>the size of the letters in units of pixels</p>\n", 14707 "type": "Number" 14708 } 14709 ], 14710 "chainable": 1 14711 }, 14712 { 14713 "line": 121, 14714 "params": [], 14715 "return": { 14716 "description": "", 14717 "type": "Number" 14718 } 14719 } 14720 ] 14721 }, 14722 { 14723 "file": "src/typography/attributes.js", 14724 "line": 130, 14725 "description": "<p>Sets/gets the style of the text for system fonts to NORMAL, ITALIC, or BOLD.\nNote: this may be is overridden by CSS styling. For non-system fonts\n(opentype, truetype, etc.) please load styled fonts instead.</p>\n", 14726 "itemtype": "method", 14727 "name": "textStyle", 14728 "chainable": 1, 14729 "example": [ 14730 "\n<div>\n<code>\nstrokeWeight(0);\ntextSize(12);\ntextStyle(NORMAL);\ntext('Font Style Normal', 10, 30);\ntextStyle(ITALIC);\ntext('Font Style Italic', 10, 60);\ntextStyle(BOLD);\ntext('Font Style Bold', 10, 90);\n</code>\n</div>" 14731 ], 14732 "alt": "words Font Style Normal displayed normally, Italic in italic and bold in bold", 14733 "class": "p5", 14734 "module": "Typography", 14735 "submodule": "Attributes", 14736 "overloads": [ 14737 { 14738 "line": 130, 14739 "params": [ 14740 { 14741 "name": "theStyle", 14742 "description": "<p>styling for text, either NORMAL,\n ITALIC, or BOLD</p>\n", 14743 "type": "Constant" 14744 } 14745 ], 14746 "chainable": 1 14747 }, 14748 { 14749 "line": 156, 14750 "params": [], 14751 "return": { 14752 "description": "", 14753 "type": "String" 14754 } 14755 } 14756 ] 14757 }, 14758 { 14759 "file": "src/typography/attributes.js", 14760 "line": 165, 14761 "description": "<p>
14761Calculates and returns the width of any character or text string.</p>\n", 14762 "itemtype": "method", 14763 "name": "textWidth", 14764 "params": [ 14765 { 14766 "name": "theText", 14767 "description": "<p>the String of characters to measure</p>\n", 14768 "type": "String" 14769 } 14770 ], 14771 "return": { 14772 "description": "", 14773 "type": "Number" 14774 }, 14775 "example": [ 14776 "\n<div>\n<code>\ntextSize(28);\n\nvar aChar = 'P';\nvar cWidth = textWidth(aChar);\ntext(aChar, 0, 40);\nline(cWidth, 0, cWidth, 50);\n\nvar aString = 'p5.js';\nvar sWidth = textWidth(aString);\ntext(aString, 0, 85);\nline(sWidth, 50, sWidth, 100);\n</code>\n</div>" 14777 ], 14778 "alt": "Letter P and p5.js are displayed with vertical lines at end. P is wide", 14779 "class": "p5", 14780 "module": "Typography", 14781 "submodule": "Attributes" 14782 }, 14783 { 14784 "file": "src/typography/attributes.js", 14785 "line": 200, 14786 "description": "<p>Returns the ascent of the current font at its current size. The ascent\nrepresents the distance, in pixels, of the tallest character above\nthe baseline.</p>\n", 14787 "itemtype": "method", 14788 "name": "textAscent", 14789 "return": { 14790 "description": "", 14791 "type": "Number" 14792 }, 14793 "example": [ 14794 "\n<div>\n<code>\nvar base = height * 0.75;\nvar scalar = 0.8; // Different for each font\n\ntextSize(32); // Set initial text size\nvar asc = textAscent() * scalar; // Calc ascent\nline(0, base - asc, width, base - asc);\ntext('dp', 0, base); // Draw text on baseline\n\ntextSize(64); // Increase text size\nasc = textAscent() * scalar; // Recalc ascent\nline(40, base - asc, width, base - asc);\ntext('dp', 40, base); // Draw text on baseline\n</code>\n</div>" 14795 ], 14796 "class": "p5", 14797 "module": "Typography", 14798 "submodule": "Attributes"
14799 }, 14800 { 14801 "file": "src/typography/attributes.js", 14802 "line": 229, 14803 "description": "<p>Returns the descent of the current font at its current size. The descent\nrepresents the distance, in pixels, of the character with the longest\ndescender below the baseline.</p>\n", 14804 "itemtype": "method", 14805 "name": "textDescent", 14806 "return": { 14807 "description": "", 14808 "type": "Number" 14809 }, 14810 "example": [ 14811 "\n<div>\n<code>\nvar base = height * 0.75;\nvar scalar = 0.8; // Different for each font\n\ntextSize(32); // Set initial text size\nvar desc = textDescent() * scalar; // Calc ascent\nline(0, base + desc, width, base + desc);\ntext('dp', 0, base); // Draw text on baseline\n\ntextSize(64); // Increase text size\ndesc = textDescent() * scalar; // Recalc ascent\nline(40, base + desc, width, base + desc);\ntext('dp', 40, base); // Draw text on baseline\n</code>\n</div>" 14812 ], 14813 "class": "p5", 14814 "module": "Typography", 14815 "submodule": "Attributes"
14816 }, 14817 { 14818 "file": "src/typography/attributes.js", 14819 "line": 258, 14820 "description": "<p>Helper function to measure ascent and descent.</p>\n", 14821 "class": "p5", 14822 "module": "Typography", 14823 "submodule": "Attributes" 14824 }, 14825 { 14826 "file": "src/typography/loading_displaying.js", 14827 "line": 16, 14828 "description": "<p>Loads an opentype font file (.otf, .ttf) from a file or a URL,\nand returns a PFont Object. This method is asynchronous,\nmeaning it may not finish before the next line in your sketch\nis executed.\n<br><br>\nThe path to the font should be relative to the HTML file\nthat links in your sketch. Loading an from a URL or other\nremote location may be blocked due to your browser's built-in\nsecurity.</p>\n", 14829 "itemtype": "method", 14830 "name": "loadFont", 14831 "params": [ 14832 { 14833 "name": "path", 14834 "description": "<p>name of the file or url to load</p>\n", 14835 "type": "String" 14836 }, 14837 { 14838 "name": "callback", 14839 "description": "<p>function to be executed after\n loadFont() completes</p>\n", 14840 "type": "Function", 14841 "optional": true 14842 }, 14843 { 14844 "name": "onError", 14845 "description": "<p>function to be executed if\n an error occurs</p>\n", 14846 "type": "Function", 14847 "optional": true 14848 } 14849 ], 14850 "return": { 14851 "description": "p5.Font object", 14852 "type": "p5.Font" 14853 }, 14854 "example": [ 14855 "\n\n<p>Calling loadFont() inside preload() guarantees that the load\noperation will have completed before setup() and draw() are called.</p>\n\n<div><code>\nvar myFont;\nfunction preload() {\n myFont = loadFont('assets/AvenirNextLTPro-Demi.otf');\n}\n\nfunction setup() {\n fill('#ED225D');\n textFont(myFont);\n textSize(36);\n text('p5*js', 10, 50);\n}\n</code></div>\n\nOutside of preload(), you may supply a callback function to handle the\nobject:\n\n<div><code>\nfunction setup() {\n loadFont('assets/AvenirNextLTPro-Demi.otf', drawText);\n}\n\nfunction drawText(font) {\n fill('#ED225D');\n textFont(font, 36);\n text('p5*js', 10, 50);\n}\n</code></div>\n\n<p>You can also use the string name of the font to style other HTML\nelements.</p>\n\n<div><code>\nfunction preload() {\n loadFont('assets/Avenir.otf');\n}\n\nfunction setup() {\n var myDiv = createDiv('hello there');\n myDiv.style('font-family', 'Avenir');\n}\n</code></div>" 14856 ], 14857 "alt": "p5*js in p5's theme dark pink\np5*js in p5's theme dark pink", 14858 "class": "p5", 14859 "module": "Typography", 14860 "submodule": "Loading & Displaying" 14861 }, 14862 { 14863 "file": "src/typography/loading_displaying.js", 14864 "line": 143, 14865 "description": "<p>Draws text to the screen. Displays the information specified in the first\nparameter on the screen in the position specified by the additional\nparameters. A default font will be used unless a font is set with the\ntextFont() function and a default size will be used unless a font is set\nwith textSize(). Change the color of the text with the fill() function.\nChange the outline of the text with the stroke() and strokeWeight(
14865)\nfunctions.\n<br><br>\nThe text displays in relation to the textAlign() function, which gives the\noption to draw to the left, right, and center of the coordinates.\n<br><br>\nThe x2 and y2 parameters define a rectangular area to display within and\nmay only be used with string data. When these parameters are specified,\nthey are interpreted based on the current rectMode() setting. Text that\ndoes not fit completely within the rectangle specified will not be drawn\nto the screen.</p>\n", 14866 "itemtype": "method", 14867 "name": "text", 14868 "params": [ 14869 { 14870 "name": "str", 14871 "description": "<p>the alphanumeric\n symbols to be displayed</p>\n", 14872 "type": "String|Object|Array|Number|Boolean" 14873 }, 14874 { 14875 "name": "x", 14876 "description": "<p>x-coordinate of text</p>\n", 14877 "type": "Number" 14878 }, 14879 { 14880 "name": "y", 14881 "description": "<p>y-coordinate of text</p>\n", 14882 "type": "Number" 14883 }, 14884 { 14885 "name": "x2", 14886 "description": "<p>by default, the width of the text box,\n see rectMode() for more info</p>\n", 14887 "type": "Number", 14888 "optional": true 14889 }, 14890 { 14891 "name": "y2", 14892 "description": "<p>by default, the height of the text box,\n see rectMode() for more info</p>\n", 14893 "type": "Number", 14894 "optional": true 14895 } 14896 ], 14897 "chainable": 1, 14898 "example": [ 14899 "\n<div>\n<code>\ntextSize(32);\ntext('word', 10, 30);\nfill(0, 102, 153);\ntext('word', 10, 60);\nfill(0, 102, 153, 51);\ntext('word', 10, 90);\n</code>\n</div>\n<div>\n<code>\nvar s = 'The quick brown fox jumped over the lazy dog.';\nfill(50);\ntext(s, 10, 10, 70, 80); // Text wraps within text box\n</code>\n</div>" 14900 ], 14901 "alt": "'word' displayed 3 times going from black, blue to translucent blue\nThe quick brown fox jumped over the lazy dog.", 14902 "class": "p5", 14903 "module": "Typography", 14904 "submodule": "Loading & Displaying" 14905 }, 14906 { 14907 "file": "src/typography/loading_displaying.js", 14908 "line": 202, 14909 "description": "<p>Sets the current font that will be drawn with the text() function.</p>\n", 14910 "itemtype": "method", 14911 "name": "textFont", 14912 "return": { 14913 "description": "the current font", 14914 "type": "Object" 14915 }, 14916 "example": [ 14917 "\n<div>\n<code>\nfill(0);\ntextSize(12);\ntextFont('Georgia');\ntext('Georgia', 12, 30);\ntextFont('Helvetica');\ntext('Helvetica', 12, 60);\n</code>\n</div>\n<div>\n<code>\nvar fontRegular, fontItalic, fontBold;\nfunction preload() {\n fontRegular = loadFont('assets/Regular.otf');\n fontItalic = loadFont('assets/Italic.ttf');\n fontBold = loadFont('assets/Bold.ttf');\n}\nfunction setup() {\n background(210);\n fill(0)\n .strokeWeight(0)\n .textSize(10);\n textFont(fontRegular);\n text('Font Style Normal', 10, 30);\n textFont(fontItalic);\n text('Font Style Italic', 10, 50);\n textFont(fontBold);\n text('Font Style Bold', 10, 70);\n}\n</code>\n</div>" 14918 ], 14919 "alt": "words Font Style Normal displayed normally, Italic in italic and bold in bold", 14920 "class": "p5", 14921 "module": "Typography", 14922 "submodule": "Loading & Displaying", 14923 "overloads": [ 14924 { 14925 "line": 202, 14926 "params": [], 14927 "return": { 14928 "description": "the current font", 14929 "type": "Object" 14930 } 14931 }, 14932 { 14933 "line": 245, 14934 "params": [ 14935 { 14936 "name": "font", 14937 "description": "<p>a font loaded via loadFont(), or a String\nrepresenting a <a href=\"https://mzl.la/2dOw8WD\">web safe font</a> (a font\nthat is generally available across all systems)</p>\n", 14938 "type": "Object|String" 14939 }, 14940 { 14941 "name": "size", 14942 "description": "<p>the font size to use</p>\n", 14943 "type": "Number", 14944 "optional": true 14945 } 14946 ], 14947 "chainable": 1 14948 } 14949 ] 14950 }, 14951 { 14952 "file": "src/typography/p5.Font.js", 14953 "line": 31, 14954 "description": "<p>Underlying opentype font implementation</p>\n", 14955 "itemtype": "property", 14956 "name": "font", 14957 "class": "p5.Font", 14958 "module": "Typography", 14959 "submodule": "Font" 14960 }, 14961 { 14962 "file": "src/typography/p5.Font.js", 14963 "line": 43, 14964 "description": "<p>
14964Returns a tight bounding box for the given text string using this\nfont (currently only supports single lines)</p>\n", 14965 "itemtype": "method", 14966 "name": "textBounds", 14967 "params": [ 14968 { 14969 "name": "line", 14970 "description": "<p>a line of text</p>\n", 14971 "type": "String" 14972 }, 14973 { 14974 "name": "x", 14975 "description": "<p>x-position</p>\n", 14976 "type": "Number" 14977 }, 14978 { 14979 "name": "y", 14980 "description": "<p>y-position</p>\n", 14981 "type": "Number" 14982 }, 14983 { 14984 "name": "fontSize", 14985 "description": "<p>font size to use (optional)</p>\n", 14986 "type": "Number", 14987 "optional": true 14988 }, 14989 { 14990 "name": "options", 14991 "description": "<p>opentype options (optional)</p>\n", 14992 "type": "Object", 14993 "optional": true 14994 } 14995 ], 14996 "return": { 14997 "description": "a rectangle object with properties: x, y, w, h", 14998 "type": "Object" 14999 }, 15000 "example": [ 15001 "\n<div>\n<code>\nvar font;\nvar textString = 'Lorem ipsum dolor sit amet.';\nfunction preload() {\n font = loadFont('./assets/Regular.otf');\n}\nfunction setup() {\n background(210);\n\n var bbox = font.textBounds(textString, 10, 30, 12);\n fill(255);\n stroke(0);\n rect(bbox.x, bbox.y, bbox.w, bbox.h);\n fill(0);\n noStroke();\n\n textFont(font);\n textSize(12);\n text(textString, 10, 30);\n}\n</code>\n</div>" 15002 ], 15003 "alt": "words Lorem ipsum dol go off canvas and contained by white bounding box", 15004 "class": "p5.Font", 15005 "module": "Typography", 15006 "submodule": "Font" 15007 }, 15008 { 15009 "file": "src/typography/p5.Font.js", 15010 "line": 158, 15011 "description": "<p>Computes an array of points following the path for specified text</p>\n", 15012 "itemtype": "method", 15013 "name": "textToPoints", 15014 "params": [ 15015 { 15016 "name": "txt", 15017 "description": "<p>a line of text</p>\n", 15018 "type": "String" 15019 }, 15020 { 15021 "name": "x", 15022 "description": "<p>x-position</p>\n", 15023 "type": "Number" 15024 }, 15025 { 15026 "name": "y", 15027 "description": "<p>y-position</p>\n", 15028 "type": "Number" 15029 }, 15030 { 15031 "name": "fontSize", 15032 "description": "<p>font size to use (optional)</p>\n", 15033 "type": "Number" 15034 }, 15035 { 15036 "name": "options", 15037 "description": "<p>an (optional) object that can contain:</p>\n<p><br>sampleFactor - the ratio of path-length to number of samples\n(default=.25); higher values yield more points and are therefore\nmore precise</p>\n<p><br>simplifyThreshold - if set to a non-zero value, collinear points will be\nbe removed from the polygon; the value represents the threshold angle to use\nwhen determining whether two edges are collinear</p>\n", 15038 "type": "Object", 15039 "optional": true 15040 } 15041 ], 15042 "return": { 15043 "description": "an array of points, each with x, y, alpha (the path angle)", 15044 "type": "Array" 15045 }, 15046 "example": [ 15047 "\n<div>\n<code>\nvar font;\nfunction preload() {\n font = loadFont('./assets/Avenir.otf');\n}\n\nvar points;\nvar bounds;\nfunction setup() {\n createCanvas(100, 100);\n stroke(0);\n fill(255, 104, 204);\n\n points = font.textToPoints('p5', 0, 0, 10, {\n sampleFactor: 5,\n simplifyThreshold: 0\n });\n bounds = font.textBounds(' p5 ', 0, 0, 10);\n}\n\nfunction draw() {\n background(255);\n beginShape();\n translate(-bounds.x * width / bounds.w, -bounds.y * height / bounds.h);\n for (var i = 0; i < points.length;
15047 i++) {\n var p = points[i];\n vertex(\n p.x * width / bounds.w +\n sin(20 * p.y / bounds.h + millis() / 1000) * width / 30,\n p.y * height / bounds.h\n );\n }\n endShape(CLOSE);\n}\n</code>\n</div>\n" 15048 ], 15049 "class": "p5.Font", 15050 "module": "Typography", 15051 "submodule": "Font" 15052 }, 15053 { 15054 "file": "src/utilities/array_functions.js", 15055 "line": 12, 15056 "description": "<p>Adds a value to the end of an array. Extends the length of\nthe array by one. Maps to Array.push().</p>\n", 15057 "itemtype": "method", 15058 "name": "append", 15059 "deprecated": true, 15060 "deprecationMessage": "Use <a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push\">array.push(value)</a> instead.", 15061 "params": [ 15062 { 15063 "name": "array", 15064 "description": "<p>Array to append</p>\n", 15065 "type": "Array" 15066 }, 15067 { 15068 "name": "value", 15069 "description": "<p>to be added to the Array</p>\n", 15070 "type": "Any" 15071 } 15072 ], 15073 "example": [ 15074 "\n<div class='norender'><code>\nfunction setup() {\n var myArray = ['Mango', 'Apple', 'Papaya'];\n print(myArray); // ['Mango', 'Apple', 'Papaya']\n\n append(myArray, 'Peach');\n print(myArray); // ['Mango', 'Apple', 'Papaya', 'Peach']\n}\n</code></div>" 15075 ], 15076 "class": "p5", 15077 "module": "Data", 15078 "submodule": "Array Functions" 15079 }, 15080 { 15081 "file": "src/utilities/array_functions.js", 15082 "line": 36, 15083 "description": "<p>Copies an array (or part of an array) to another array. The src array is\ncopied to the dst array, beginning at the position specified by\nsrcPosition and into the position specified by dstPosition. The number of\nelements to copy is determined by length. Note that copying values\noverwrites existing values in the destination array. To append values\ninstead of overwriting them, use concat().\n<br><br>\nThe simplified version with only two arguments, arrayCopy(src, dst),\ncopies an entire array to another of the same size. It is equivalent to\narrayCopy(src, 0, dst, 0, src.length).\n<br><br>\nUsing this function is far more efficient for copying array data than\niterating through a for() loop and copying each element individually.</p>\n", 15084 "itemtype": "method", 15085 "name": "arrayCopy", 15086 "deprecated": true, 15087 "example": [ 15088 "\n<div class='norender'><code>\nvar src = ['A', 'B', 'C'];\nvar dst = [1, 2, 3];\nvar srcPosition = 1;\nvar dstPosition = 0;\nvar length = 2;\n\nprint(src); // ['A', 'B', 'C']\nprint(dst); // [ 1 , 2 , 3 ]\n\narrayCopy(src, srcPosition, dst, dstPosition, length);\nprint(dst); // ['B', 'C', 3]\n</code></div>" 15089 ], 15090 "class": "p5", 15091 "module": "Data", 15092 "submodule": "Array Functions", 15093 "overloads": [ 15094 { 15095 "line": 36, 15096 "params": [ 15097 { 15098 "name": "src", 15099 "description": "<p>the source Array</p>\n", 15100 "type": "Array" 15101 }, 15102 { 15103 "name": "srcPosition", 15104 "description": "<p>starting position in the source Array</p>\n", 15105 "type": "Integer" 15106 }, 15107 { 15108 "name": "dst", 15109 "description": "<p>the destination Array</p>\n", 15110 "type": "Array" 15111 }, 15112 { 15113 "name": "dstPosition", 15114 "description": "<p>starting position in the destination Array</p>\n", 15115 "type": "Integer" 15116 }, 15117 { 15118 "name": "length", 15119 "description": "<p>number of Array elements to be copied</p>\n", 15120 "type": "Integer" 15121 } 15122 ] 15123 }, 15124 { 15125 "line": 74, 15126 "params": [ 15127 { 15128 "name": "src", 15129 "description": "", 15130 "type": "Array" 15131 }, 15132 { 15133 "name": "dst", 15134 "description": "", 15135 "type": "Array" 15136 }, 15137 { 15138 "name": "length", 15139 "description": "", 15140 "type": "Integer", 15141 "optional": true 15142 } 15143 ] 15144 } 15145 ] 15146 }, 15147 { 15148 "file": "src/utilities/array_functions.js", 15149 "line": 113, 15150 "description": "<p>Concatenates two arrays, maps to Array.concat(). Does not modify the\ninput arrays.</p>\n", 15151 "itemtype": "method", 15152 "name": "concat", 15153 "deprecated": true, 15154 "deprecationMessage": "Use <a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat\">arr1.concat(arr2)</a> instead.", 15155 "params": [ 15156 { 15157 "name": "a", 15158 "description": "<p>first Array to concatenate</p>\n", 15159 "type": "Array" 15160 }, 15161 { 15162 "name": "b", 15163 "description": "<p>second Array to concatenate</p>\n", 15164 "type": "Array" 15165 } 15166 ], 15167 "return": { 15168 "description": "concatenated array", 15169 "type": "Array" 15170 }, 15171 "example": [ 15172 "\n<div class = 'norender'><code>\nfunction setup() {\n var arr1 = ['A', 'B', 'C'];\n var arr2 = [1, 2, 3];\n\n print(arr1); // ['A','B','C']\n print(arr2); // [1,2,3]\n\n var arr3 = concat(arr1, arr2);\n\n print(arr1); // ['A','B','C']\n print(arr2); // [1, 2, 3]\n print(arr3); // ['A','B','C', 1, 2, 3]\n}\n</code></div>" 15173 ], 15174 "class": "p5", 15175 "module": "Data", 15176 "submodule": "Array Functions" 15177 }, 15178 { 15179 "file": "src/utilities/array_functions.js", 15180 "line": 144, 15181 "description": "<p>Reverses the order of an array, maps to Array.reverse()</p>\n", 15182 "itemtype": "method", 15183 "name": "reverse", 15184 "deprecated": true, 15185 "deprecationMessage": "Use <a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse\">array.reverse()</a> instead.", 15186 "params": [ 15187 { 15188 "name": "list", 15189 "description": "<p>Array to reverse</p>\n", 15190 "type": "Array" 15191 } 15192 ], 15193 "example": [ 15194 "\n<div class='norender'><code>\nfunction setup() {\n var myArray = ['A', 'B', 'C'];\n print(myArray); // ['A','B','C']\n\n reverse(myArray);\n print(myArray); // ['C','B','A']\n}\n</code></div>" 15195 ], 15196 "class": "p5", 15197 "module": "Data", 15198 "submodule": "Array Functions" 15199 }, 15200 { 15201 "file": "src/utilities/array_functions.js", 15202 "line": 165, 15203 "description": "<p>Decreases an array by one element and returns the shortened array,\nmaps to Array.pop().</p>\n", 15204 "itemtype": "method", 15205 "name": "shorten", 15206 "deprecated": true, 15207 "deprecationMessage": "Use <a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/pop\">array.pop()</a> instead.", 15208 "params": [ 15209 { 15210 "name": "list", 15211 "description": "<p>Array to shorten</p>\n", 15212 "type": "Array" 15213 } 15214 ], 15215 "return": { 15216 "description": "shortened Array", 15217 "type": "Array" 15218 }, 15219 "example": [ 15220 "\n<div class = 'norender'><code>\nfunction setup() {\n var myArray = ['A', 'B', 'C'];\n print(myArray); // ['A', 'B', 'C']\n var newArray = shorten(myArray);\n print(myArray); // ['A','B','C']\n print(newArray); // ['A','B']\n}\n</code></div>" 15221 ], 15222 "class": "p5", 15223 "module": "Data", 15224 "submodule": "Array Functions" 15225 }, 15226 { 15227 "file": "src/utilities/array_functions.js", 15228 "line": 189, 15229 "description": "<p>Randomizes the order of the elements of an array. Implements\n<a href='http://Bost.Ocks.org/mike/shuffle/' target=_blank>
15229\nFisher-Yates Shuffle Algorithm</a>.</p>\n", 15230 "itemtype": "method", 15231 "name": "shuffle", 15232 "deprecated": true, 15233 "deprecationMessage": "See <a href=\"https://stackoverflow.com/questions/6274339/how-can-i-shuffle-an-array\">shuffling an array with JS</a> instead.", 15234 "params": [ 15235 { 15236 "name": "array", 15237 "description": "<p>Array to shuffle</p>\n", 15238 "type": "Array" 15239 }, 15240 { 15241 "name": "bool", 15242 "description": "<p>modify passed array</p>\n", 15243 "type": "Boolean", 15244 "optional": true 15245 } 15246 ], 15247 "return": { 15248 "description": "shuffled Array", 15249 "type": "Array" 15250 }, 15251 "example": [ 15252 "\n<div><code>\nfunction setup() {\n var regularArr = ['ABC', 'def', createVector(), TAU, Math.E];\n print(regularArr);\n shuffle(regularArr, true); // force modifications to passed array\n print(regularArr);\n\n // By default shuffle() returns a shuffled cloned array:\n var newArr = shuffle(regularArr);\n print(regularArr);\n print(newArr);\n}\n</code></div>" 15253 ], 15254 "class": "p5", 15255 "module": "Data", 15256 "submodule": "Array Functions" 15257 }, 15258 { 15259 "file": "src/utilities/array_functions.js", 15260 "line": 232, 15261 "description": "<p>Sorts an array of numbers from smallest to largest, or puts an array of\nwords in alphabetical order. The original array is not modified; a\nre-ordered array is returned. The count parameter states the number of\nelements to sort. For example, if there are 12 elements in an array and\ncount is set to 5, only the first 5 elements in the array will be sorted.</p>\n", 15262 "itemtype": "method", 15263 "name": "sort", 15264 "deprecated": true, 15265 "deprecationMessage": "Use <a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort\">array.sort()</a> instead.", 15266 "params": [ 15267 { 15268 "name": "list", 15269 "description": "<p>Array to sort</p>\n", 15270 "type": "Array" 15271 }, 15272 { 15273 "name": "count", 15274 "description": "<p>number of elements to sort, starting from 0</p>\n", 15275 "type": "Integer", 15276 "optional": true 15277 } 15278 ], 15279 "example": [ 15280 "\n<div class = 'norender'><code>\nfunction setup() {\n var words = ['banana', 'apple', 'pear', 'lime'];\n print(words); // ['banana', 'apple', 'pear', 'lime']\n var count = 4; // length of array\n\n words = sort(words, count);\n print(words); // ['apple', 'banana', 'lime', 'pear']\n}\n</code></div>\n<div class = 'norender'><code>\nfunction setup() {\n var numbers = [2, 6, 1, 5, 14, 9, 8, 12];\n print(numbers); // [2, 6, 1, 5, 14, 9, 8, 12]\n var count = 5; // Less than the length of the array\n\n numbers = sort(numbers, count);\n print(numbers); // [1,2,5,6,14,9,8,12]\n}\n</code></div>" 15281 ], 15282 "class": "p5", 15283 "module": "Data", 15284 "submodule": "Array Functions" 15285 }, 15286 { 15287 "file": "src/utilities/array_functions.js", 15288 "line": 279, 15289 "description": "<p>Inserts a value or an array of values into an existing array. The first\nparameter specifies the initial array to be modified, and the second\nparameter defines the data to be inserted. The third parameter is an index\nvalue which specifies the array position from which to insert data.\n(Remember that array index numbering starts at zero, so the first position\nis 0, the second position is 1, and so on.)</p>\n", 15290 "itemtype": "method", 15291 "name": "splice", 15292 "deprecated": true, 15293 "deprecationMessage": "Use <a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice\">array.splice()</a> instead.", 15294 "params": [ 15295 { 15296 "name": "list", 15297 "description": "<p>Array to splice into</p>\n", 15298 "type": "Array" 15299 }, 15300 { 15301 "name": "value", 15302 "description": "<p>value to be spliced in</p>\n", 15303 "type": "Any" 15304 }, 15305 { 15306 "name": "position", 15307 "description": "<p>in the array from which to insert data</p>\n", 15308 "type": "Integer" 15309 } 15310 ], 15311 "example": [ 15312 "\n<div class = 'norender'><code>\nfunction setup() {\n var myArray = [0, 1, 2, 3, 4];\n var insArray = ['A', 'B', 'C'];\n print(myArray); // [0, 1, 2, 3, 4]\n print(insArray); // ['A','B','C']\n\n splice(myArray, insArray, 3);\n print(myArray); // [0,1,2,'A','B','C',3,4]\n}\n</code></div>" 15313 ], 15314 "class": "p5", 15315 "module": "Data", 15316 "submodule": "Array Functions" 15317 }, 15318 { 15319 "file": "src/utilities/array_functions.js", 15320 "line": 313, 15321 "description": "<p>Extracts an array of elements from an existing array. The list parameter\ndefines the array from which the elements will be copied, and the start\nand count parameters specify which elements to extract. If no count is\ngiven, elements will be extracted from the start to the end of the array.\nWhen specifying the start, remember that the first array element is 0.\nThis function does not change the source array.</p>\n", 15322 "itemtype": "method", 15323 "name": "subset", 15324 "deprecated": true, 15325 "deprecationMessage": "Use <a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice\">array.slice()</a> instead.", 15326 "params": [ 15327 { 15328 "name": "list", 15329 "description": "<p>Array to extract from</p>\n", 15330 "type": "Array" 15331 }, 15332 { 15333 "name": "start", 15334 "description": "<p>position to begin</p>\n", 15335 "type": "Integer" 15336 }, 15337 { 15338 "name": "count", 15339 "description": "<p>number of values to extract</p>\n", 15340 "type": "Integer", 15341 "optional": true 15342 } 15343 ], 15344 "return": { 15345 "description": "Array of extracted elements", 15346 "type": "Array" 15347 }, 15348 "example": [ 15349 "\n<div class = 'norender'><code>\nfunction setup() {\n var myArray = [1, 2, 3, 4, 5];\n print(myArray); // [1, 2, 3, 4, 5]\n\n var sub1 = subset(myArray, 0, 3);\n var sub2 = subset(myArray, 2, 2);\n print(sub1); // [1,2,3]\n print(sub2); // [3,4]\n}\n</code></div>" 15350 ], 15351 "class": "p5", 15352 "module": "Data", 15353 "submodule": "Array Functions" 15354 }, 15355 { 15356 "file": "src/utilities/conversion.js", 15357 "line": 12, 15358 "description": "<p>Converts a string to its floating point representation. The contents of a\nstring must resemble a number, or NaN (not a number) will be returned.\nFor example, float("1234.56") evaluates to 1234.56, but float("giraffe")\nwill return NaN.</p>\n<p>When an array of values is passed in, then an array of floats of the same\nlength is returned.</p>\n", 15359 "itemtype": "method", 15360 "name": "float", 15361 "params": [ 15362 { 15363 "name": "str", 15364 "description": "<p>float string to parse</p>\n", 15365 "type": "String" 15366 } 15367 ], 15368 "return": { 15369 "description": "floating point representation of str
15369ing", 15370 "type": "Number" 15371 }, 15372 "example": [ 15373 "\n<div><code>\nvar str = '20';\nvar diameter = float(str);\nellipse(width / 2, height / 2, diameter, diameter);\n</code></div>" 15374 ], 15375 "alt": "20 by 20 white ellipse in the center of the canvas", 15376 "class": "p5", 15377 "module": "Data", 15378 "submodule": "Conversion" 15379 }, 15380 { 15381 "file": "src/utilities/conversion.js", 15382 "line": 42, 15383 "description": "<p>Converts a boolean, string, or float to its integer representation.\nWhen an array of values is passed in, then an int array of the same length\nis returned.</p>\n", 15384 "itemtype": "method", 15385 "name": "int", 15386 "return": { 15387 "description": "integer representation of value", 15388 "type": "Number" 15389 }, 15390 "example": [ 15391 "\n<div class='norender'><code>\nprint(int('10')); // 10\nprint(int(10.31)); // 10\nprint(int(-10)); // -10\nprint(int(true)); // 1\nprint(int(false)); // 0\nprint(int([false, true, '10.3', 9.8])); // [0, 1, 10, 9]\n</code></div>" 15392 ], 15393 "class": "p5", 15394 "module": "Data", 15395 "submodule": "Conversion", 15396 "overloads": [ 15397 { 15398 "line": 42, 15399 "params": [ 15400 { 15401 "name": "n", 15402 "description": "<p>value to parse</p>\n", 15403 "type": "String|Boolean|Number" 15404 }, 15405 { 15406 "name": "radix", 15407 "description": "<p>the radix to convert to (default: 10)</p>\n", 15408 "type": "Integer", 15409 "optional": true 15410 } 15411 ], 15412 "return": { 15413 "description": "integer representation of value", 15414 "type": "Number" 15415 } 15416 }, 15417 { 15418 "line": 62, 15419 "params": [ 15420 { 15421 "name": "ns", 15422 "description": "<p>values to parse</p>\n", 15423 "type": "Array" 15424 } 15425 ], 15426 "return": { 15427 "description": "integer representation of values", 15428 "type": "Number[]" 15429 } 15430 } 15431 ] 15432 }, 15433 { 15434 "file": "src/utilities/conversion.js", 15435 "line": 82, 15436 "description": "<p>Converts a boolean, string or number to its string representation.\nWhen an array of values is passed in, then an array of strings of the same\nlength is returned.</p>\n", 15437 "itemtype": "method", 15438 "name": "str", 15439 "params": [ 15440 { 15441 "name": "n", 15442 "description": "<p>value to parse</p>\n", 15443 "type": "String|Boolean|Number|Array" 15444 } 15445 ], 15446 "return": { 15447 "description": "string representation of value", 15448 "type": "String" 15449 }, 15450 "example": [ 15451 "\n<div class='norender'><code>\nprint(str('10')); // \"10\"\nprint(str(10.31)); // \"10.31\"\nprint(str(-10)); // \"-10\"\nprint(str(true)); // \"true\"\nprint(str(false)); // \"false\"\nprint(str([true, '10.3', 9.8])); // [ \"true\", \"10.3\", \"9.8\" ]\n</code></div>" 15452 ], 15453 "class": "p5", 15454 "module": "Data", 15455 "submodule": "Conversion" 15456 }, 15457 { 15458 "file": "src/utilities/conversion.js", 15459 "line": 108, 15460 "description": "<p>Converts a number or string to its boolean representation.\nFor a number, any non-zero value (positive or negative) evaluates to true,\nwhile zero evaluates to false. For a string, the value "true" evaluates to\ntrue, while any other value evaluates to false. When an array of number or\nstring values is passed in, then a array of booleans of the same length is\nreturned.</p>\n", 15461 "itemtype": "method", 15462 "name": "boolean", 15463 "params": [ 15464 { 15465 "name": "n", 15466 "description": "<p>value to parse</p>\n", 15467 "type": "String|Boolean|Number|Array" 15468 } 15469 ], 15470 "return": { 15471 "description": "boolean representation of value", 15472 "type": "Boolean" 15473 }, 15474 "example": [ 15475 "\n<div class='norender'><code>\nprint(boolean(0)); // false\nprint(boolean(1)); // true\nprint(boolean('true')); // true\nprint(boolean('abcd')); // false\nprint(boolean([0, 12, 'true'])); // [false, true, false]\n</code></div>" 15476 ], 15477 "class": "p5", 15478 "module": "Data", 15479 "submodule": "Conversion" 15480 }, 15481 { 15482 "file": "src/utilities/conversion.js", 15483 "line": 140, 15484 "description": "<p>Converts a number, string representation of a number, or boolean to its byte\nrepresentation. A b
15484yte can be only a whole number between -128 and 127, so\nwhen a value outside of this range is converted, it wraps around to the\ncorresponding byte representation. When an array of number, string or boolean\nvalues is passed in, then an array of bytes the same length is returned.</p>\n", 15485 "itemtype": "method", 15486 "name": "byte", 15487 "return": { 15488 "description": "byte representation of value", 15489 "type": "Number" 15490 }, 15491 "example": [ 15492 "\n<div class='norender'><code>\nprint(byte(127)); // 127\nprint(byte(128)); // -128\nprint(byte(23.4)); // 23\nprint(byte('23.4')); // 23\nprint(byte('hello')); // NaN\nprint(byte(true)); // 1\nprint(byte([0, 255, '100'])); // [0, -1, 100]\n</code></div>" 15493 ], 15494 "class": "p5", 15495 "module": "Data", 15496 "submodule": "Conversion", 15497 "overloads": [ 15498 { 15499 "line": 140, 15500 "params": [ 15501 { 15502 "name": "n", 15503 "description": "<p>value to parse</p>\n", 15504 "type": "String|Boolean|Number" 15505 } 15506 ], 15507 "return": { 15508 "description": "byte representation of value", 15509 "type": "Number" 15510 } 15511 }, 15512 { 15513 "line": 162, 15514 "params": [ 15515 { 15516 "name": "ns", 15517 "description": "<p>values to parse</p>\n", 15518 "type": "Array" 15519 } 15520 ], 15521 "return": { 15522 "description": "array of byte representation of values", 15523 "type": "Number[]" 15524 } 15525 } 15526 ] 15527 }, 15528 { 15529 "file": "src/utilities/conversion.js", 15530 "line": 176, 15531 "description": "<p>Converts a number or string to its corresponding single-character\nstring representation. If a string parameter is provided, it is first\nparsed as an integer and then translated into a single-character string.\nWhen an array of number or string values is passed in, then an array of\nsingle-character strings of the same length is returned.</p>\n", 15532 "itemtype": "method", 15533 "name": "char", 15534 "return": { 15535 "description": "string representation of value", 15536 "type": "String" 15537 }, 15538 "example": [ 15539 "\n<div class='norender'><code>\nprint(char(65)); // \"A\"\nprint(char('65')); // \"A\"\nprint(char([65, 66, 67])); // [ \"A\", \"B\", \"C\" ]\nprint(join(char([65, 66, 67]), '')); // \"ABC\"\n</code></div>" 15540 ], 15541 "class": "p5", 15542 "module": "Data", 15543 "submodule": "Conversion", 15544 "overloads": [ 15545 { 15546 "line": 176, 15547 "params": [ 15548 { 15549 "name": "n", 15550 "description": "<p>value to parse</p>\n", 15551 "type": "String|Number" 15552 } 15553 ], 15554 "return": { 15555 "description": "string representation of value", 15556 "type": "String" 15557 } 15558 }, 15559 { 15560 "line": 195, 15561 "params": [ 15562 { 15563 "name": "ns", 15564 "description": "<p>values to parse</p>\n", 15565 "type": "Array" 15566 } 15567 ], 15568 "return": { 15569 "description": "array of string representation of values", 15570 "type": "String[]" 15571 } 15572 } 15573 ] 15574 }, 15575 { 15576 "file": "src/utilities/conversion.js", 15577 "line": 210, 15578 "description": "<p>Converts a single-character string to its corresponding integer\nrepresentation. When an array of single-character string values is passed\nin, then an array of integers of the same length is returned.</p>\n", 15579 "itemtype": "method", 15580 "name": "unchar", 15581 "return": { 15582 "description": "integer representation of value", 15583 "type": "Number" 15584 }, 15585 "example": [ 15586 "\n<div class='norender'><code>\nprint(unchar('A')); // 65\nprint(unchar(['A', 'B', 'C'])); // [ 65, 66, 67 ]\nprint(unchar(split('ABC', ''))); // [ 65, 66, 67 ]\n</code></div>" 15587 ], 15588 "class": "p5", 15589 "module": "Data", 15590 "submodule": "Conversion", 15591 "overloads": [ 15592 { 15593 "line": 210, 15594 "params": [ 15595 { 15596 "name": "n", 15597 "description": "<p>value to parse</p>\n", 15598 "type": "String" 15599 } 15600 ], 15601 "return": { 15602 "description": "integer representation of value", 15603 "type": "Number" 15604 } 15605 }, 15606 { 15607 "line": 226, 15608 "params": [ 15609 { 15610 "name": "ns", 15611 "description": "<p>values to parse</p>\n", 15612 "type": "Array" 15613 } 15614 ], 15615 "return": { 15616 "description": "integer representation of values", 15617 "type": "Number[]" 15618 } 15619 } 15620 ] 15621 }, 15622 { 15623 "file": "src/utilities/conversion.js", 15624 "line": 239, 15625 "description": "<p>Converts a number to a string in its equivalent hexadecimal notation. If a\nsecond parameter is passed, it is used to set the number of characters to\ngenerate in the hexadecimal notation. When an array is passed in, an\narray of str
15625ings in hexadecimal notation of the same length is returned.</p>\n", 15626 "itemtype": "method", 15627 "name": "hex", 15628 "return": { 15629 "description": "hexadecimal string representation of value", 15630 "type": "String" 15631 }, 15632 "example": [ 15633 "\n<div class='norender'><code>\nprint(hex(255)); // \"000000FF\"\nprint(hex(255, 6)); // \"0000FF\"\nprint(hex([0, 127, 255], 6)); // [ \"000000\", \"00007F\", \"0000FF\" ]\n</code></div>" 15634 ], 15635 "class": "p5", 15636 "module": "Data", 15637 "submodule": "Conversion", 15638 "overloads": [ 15639 { 15640 "line": 239, 15641 "params": [ 15642 { 15643 "name": "n", 15644 "description": "<p>value to parse</p>\n", 15645 "type": "Number" 15646 }, 15647 { 15648 "name": "digits", 15649 "description": "", 15650 "type": "Number", 15651 "optional": true 15652 } 15653 ], 15654 "return": { 15655 "description": "hexadecimal string representation of value", 15656 "type": "String" 15657 } 15658 }, 15659 { 15660 "line": 257, 15661 "params": [ 15662 { 15663 "name": "ns", 15664 "description": "<p>array of values to parse</p>\n", 15665 "type": "Number[]" 15666 }, 15667 { 15668 "name": "digits", 15669 "description": "", 15670 "type": "Number", 15671 "optional": true 15672 } 15673 ], 15674 "return": { 15675 "description": "hexadecimal string representation of values", 15676 "type": "String[]" 15677 } 15678 } 15679 ] 15680 }, 15681 { 15682 "file": "src/utilities/conversion.js", 15683 "line": 286, 15684 "description": "<p>Converts a string representation of a hexadecimal number to its equivalent\ninteger value. When an array of strings in hexadecimal notation is passed\nin, an array of integers of the same length is returned.</p>\n", 15685 "itemtype": "method", 15686 "name": "unhex", 15687 "return": { 15688 "description": "integer representation of hexadecimal value", 15689 "type": "Number" 15690 }, 15691 "example": [ 15692 "\n<div class='norender'><code>\nprint(unhex('A')); // 10\nprint(unhex('FF')); // 255\nprint(unhex(['FF', 'AA', '00'])); // [ 255, 170, 0 ]\n</code></div>" 15693 ], 15694 "class": "p5", 15695 "module": "Data", 15696 "submodule": "Conversion", 15697 "overloads": [ 15698 { 15699 "line": 286, 15700 "params": [ 15701 { 15702 "name": "n", 15703 "description": "<p>value to parse</p>\n", 15704 "type": "String" 15705 } 15706 ], 15707 "return": { 15708 "description": "integer representation of hexadecimal value", 15709 "type": "Number" 15710 } 15711 }, 15712 { 15713 "line": 302, 15714 "params": [ 15715 { 15716 "name": "ns", 15717 "description": "<p>values to parse</p>\n", 15718 "type": "Array" 15719 } 15720 ], 15721 "return": { 15722 "description": "integer representations of hexadecimal value", 15723 "type": "Number[]" 15724 } 15725 } 15726 ] 15727 }, 15728 { 15729 "file": "src/utilities/string_functions.js", 15730 "line": 15, 15731 "description": "<p>Combines an array of Strings into one String, each separated by the\ncharacter(s) used for the separator parameter. To join arrays of ints or\nfloats, it's necessary to first convert them to Strings using nf() or\nnfs().</p>\n", 15732 "itemtype": "method", 15733 "name": "join", 15734 "params": [ 15735 { 15736 "name": "list", 15737 "description": "<p>array of Strings to be joined</p>\n", 15738 "type": "Array" 15739 }, 15740 { 15741 "name": "separator", 15742 "description": "<p>String to be placed between each item</p>\n", 15743 "type": "String" 15744 } 15745 ], 15746 "return": { 15747 "description": "joined String", 15748 "type": "String" 15749 }, 15750 "example": [ 15751 "\n<div>\n<code>\nvar array = ['Hello', 'world!'];\nvar separator = ' ';\nvar message = join(array, separator);\ntext(message, 5, 50);\n</code>\n</div>" 15752 ], 15753 "alt": "\"hello world!\" displayed middle left of canvas.", 15754 "class": "p5", 15755 "module": "Data", 15756 "submodule": "String Functions" 15757 }, 15758 { 15759 "file": "src/utilities/string_functions.js", 15760 "line": 44, 15761 "description": "<p>This function is used to apply a regular expression to a piece of text,\nand return matching groups (elements found inside parentheses) as a\nString array. If there are no matches, a null value will be returned.\nIf no groups are specified in the regular expression, but the sequence\nmatches, an array of length 1 (with the matched text as the first element\nof the array) will be returned.\n<br><br>\nTo use the function, first check to see if the result is null. If the\nresult is null, then the sequence did not match at all. If the sequence\ndid match, an array is returned.\n<br><br>\nIf there are groups (specified by sets of parentheses) in the regular\nexpression, then the contents of each will be returned in the array.\nElement [0] of a regular expression match returns the entire matching\nstring, and the match groups start at element [1] (the first group is [1],\nthe second [2], and so on).</p>\n", 15762 "itemtype": "method", 15763 "name": "match", 15764 "params": [ 15765 { 15766 "name": "str", 15767 "description": "<p>the String to be searched</p>\n", 15768 "type": "String" 15769 }, 15770 { 15771 "name": "regexp", 15772 "description": "<p>the regexp to be used for matching</p>\n", 15773 "type": "String" 15774 } 15775 ], 15776 "return": { 15777 "description": "Array of Strings found", 15778 "type": "String[]" 15779 }, 15780 "example": [ 15781 "\n<div>\n<code>\nvar string = 'Hello p5js*!';\nvar regexp = 'p5js\\\\*';\nvar m = match(string, regexp);\ntext(m, 5, 50);\n</code>\n</div>" 15782 ], 15783 "alt": "\"p5js*\" displayed middle left of canvas.", 15784 "class": "p5", 15785 "module": "Data", 15786 "submodule": "String Functions" 15787 }, 15788 { 15789 "file": "src/utilities/string_functions.js", 15790 "line": 85, 15791 "description": "<p>This function is used to apply a regular expression to a piece of text,\nand return a list of matching groups (elements found inside parentheses)\nas a two-dimensional Str
15791ing array. If there are no matches, a null value\nwill be returned. If no groups are specified in the regular expression,\nbut the sequence matches, a two dimensional array is still returned, but\nthe second dimension is only of length one.\n<br><br>\nTo use the function, first check to see if the result is null. If the\nresult is null, then the sequence did not match at all. If the sequence\ndid match, a 2D array is returned.\n<br><br>\nIf there are groups (specified by sets of parentheses) in the regular\nexpression, then the contents of each will be returned in the array.\nAssuming a loop with counter variable i, element [i][0] of a regular\nexpression match returns the entire matching string, and the match groups\nstart at element [i][1] (the first group is [i][1], the second [i][2],\nand so on).</p>\n", 15792 "itemtype": "method", 15793 "name": "matchAll", 15794 "params": [ 15795 { 15796 "name": "str", 15797 "description": "<p>the String to be searched</p>\n", 15798 "type": "String" 15799 }, 15800 { 15801 "name": "regexp", 15802 "description": "<p>the regexp to be used for matching</p>\n", 15803 "type": "String" 15804 } 15805 ], 15806 "return": { 15807 "description": "2d Array of Strings found", 15808 "type": "String[]" 15809 }, 15810 "example": [ 15811 "\n<div class=\"norender\">\n<code>\nvar string = 'Hello p5js*! Hello world!';\nvar regexp = 'Hello';\nmatchAll(string, regexp);\n</code>\n</div>" 15812 ], 15813 "class": "p5", 15814 "module": "Data", 15815 "submodule": "String Functions" 15816 }, 15817 { 15818 "file": "src/utilities/string_functions.js", 15819 "line": 132, 15820 "description": "<p>Utility function for formatting numbers into strings. There are two\nversions: one for formatting floats, and one for formatting ints.\nThe values for the digits, left, and right parameters should always\nbe positive integers.</p>\n", 15821 "itemtype": "method", 15822 "name": "nf", 15823 "return": { 15824 "description": "formatted String", 15825 "type": "String" 15826 }, 15827 "example": [ 15828 "\n<div>\n<code>\nfunction setup() {\n background(200);\n var num = 112.53106115;\n\n noStroke();\n fill(0);\n textSize(14);\n // Draw formatted numbers\n text(nf(num, 5, 2), 10, 20);\n\n text(nf(num, 4, 3), 10, 55);\n\n text(nf(num, 3, 6), 10, 85);\n\n // Draw dividing lines\n stroke(120);\n line(0, 30, width, 30);\n line(0, 65, width, 65);\n}\n</code>\n</div>" 15829 ], 15830 "alt": "\"0011253\" top left, \"0112.531\" mid left, \"112.531061\" bottom left canvas", 15831 "class": "p5", 15832 "module": "Data", 15833 "submodule": "String Functions", 15834 "overloads": [ 15835 { 15836 "line": 132, 15837 "params": [ 15838 { 15839 "name": "num", 15840 "description": "<p>the Number to format</p>\n", 15841 "type": "Number|String" 15842 }, 15843 { 15844 "name": "left", 15845 "description": "<p>number of digits to the left of the\n decimal point</p>\n", 15846 "type": "Integer|String", 15847 "optional": true 15848 }, 15849 { 15850 "name": "right", 15851 "description": "<p>number of digits to the right of the\n decimal point</p>\n", 15852 "type": "Integer|String", 15853 "optional": true 15854 } 15855 ], 15856 "return": { 15857 "description": "formatted String", 15858 "type": "String" 15859 } 15860 }, 15861 { 15862 "line": 174, 15863 "params": [ 15864 { 15865 "name": "nums", 15866 "description": "<p>the Numbers to format</p>\n", 15867 "type": "Array" 15868 }, 15869 { 15870 "name": "left", 15871 "description": "", 15872 "type": "Integer|String", 15873 "optional": true 15874 }, 15875 { 15876 "name": "right", 15877 "description": "", 15878 "type": "Integer|String", 15879 "optional": true 15880 } 15881 ], 15882 "return": { 15883 "description": "formatted Strings", 15884 "type": "String[]" 15885 } 15886 } 15887 ] 15888 }, 15889 { 15890 "file": "src/utilities/string_functions.js", 15891 "line": 237, 15892 "description": "<p>Utility function for formatting numbers into strings and placing\nappropriate commas to mark units of 1000. There are two versions: one\nfor formatting ints, and one for formatting an array of ints. The value\nfor the right parameter should always be a positive integer.</p>\n", 15893 "itemtype": "method", 15894 "name": "nfc", 15895 "return": { 15896 "description": "formatted String", 15897 "type": "String" 15898 }, 15899 "example": [ 15900 "\n<div>\n<code>\nfunction setup() {\n background(200);\n var num = 11253106.115;\n var numArr = [1, 1, 2];\n\n noStroke();\n fill(0);\n textSize(12);\n\n // Draw formatted numbers\n text(nfc(num, 4), 10, 30);\n text(nfc(numArr, 2), 10, 80);\n\n // Draw dividing line\n stroke(120);\n line(0, 50, width, 50);\n}\n</code>\n</div>" 15901 ], 15902 "alt": "\"11,253,106.115\" top middle and \"1.00,1.00,2.00\" displayed bottom mid", 15903 "class": "p5", 15904 "module": "Data", 15905 "submodule": "String Functions", 15906 "overloads": [ 15907 { 15908 "line": 237, 15909 "params": [ 15910 { 15911 "name": "num", 15912 "description": "<p>the Number to format</p>\n", 15913 "type": "Number|String" 15914 }, 15915 { 15916 "name": "right", 15917 "description": "<p>number of digits to the right of the\n decimal point</p>\n", 15918 "type": "Integer|String", 15919 "optional": true 15920 } 15921 ], 15922 "return": { 15923 "description": "formatted String", 15924 "type": "String" 15925 } 15926 }, 15927 { 15928 "line": 275, 15929 "params": [ 15930 { 15931 "name": "nums", 15932 "description": "<p>the Numbers to format</p>\n", 15933 "type": "Array" 15934 }, 15935 { 15936 "name": "right", 15937 "description": "", 15938 "type": "Integer|String", 15939 "optional": true 15940 } 15941 ], 15942 "return": { 15943 "description": "formatted Strings", 15944 "type": "String[]" 15945 } 15946 } 15947 ] 15948 }, 15949 { 15950 "file": "src/utilities/string_functions.js", 15951 "line": 313, 15952 "description": "<p>Utility function for formatting numbers into strings. Similar to nf() but\nputs a "+" in front of positive numbers and a "-" in front of negative\nnumbers. There are two versions: one for formatting floats, and one for\nformatting ints. The values for left, and right parameters\nshould always be positive integers.</p>\n", 15953 "itemtype": "method", 15954 "name": "nfp", 15955 "return": { 15956 "description": "formatted String", 15957 "type": "String" 15958 }, 15959 "example": [ 15960 "\n<div>\n<code>\nfunction setup() {\n background(200);\n var num1 = 11253106.115;\n var num2 = -11253106.115;\n\n noStroke();\n fill(0);\n textSize(12);\n\n // Draw formatted numbers\n text(nfp(num1, 4, 2), 10, 30);\n text(nfp(num2, 4, 2), 10, 80);\n\n // Draw dividing line\n stroke(120);\n line(0, 50, width, 50);\n}\n</code>\n</div>" 15961 ], 15962 "alt": "\"+11253106.11\" top middle and \"-11253106.11\" displayed bottom middle", 15963 "class": "p5", 15964 "module": "Data", 15965 "submodule": "String Functions", 15966 "overloads": [ 15967 { 15968 "line": 313, 15969 "params": [ 15970 { 15971 "name": "num", 15972 "description": "<p>the Number to format</p>\n", 15973 "type": "Number" 15974 }, 15975 { 15976 "name": "left", 15977 "description": "<p>number of digits to the left of the decimal\n point</p>\n", 15978 "type": "Integer", 15979 "optional": true 15980 }, 15981 { 15982 "name": "right", 15983 "description": "<p>number of digits to the right of the\n decimal point</p>\n", 15984 "type": "Integer", 15985 "optional": true 15986 } 15987 ], 15988 "return": { 15989 "description": "formatted String", 15990 "type": "String" 15991 } 15992 }, 15993 { 15994 "line": 354, 15995 "params": [ 15996 { 15997 "name": "nums", 15998 "description": "<p>the Numbers to format</p>\n", 15999 "type": "Number[]" 16000 }, 16001 { 16002 "name": "left", 16003 "description": "", 16004 "type": "Integer", 16005 "optional": true 16006 }, 16007 { 16008 "name": "right", 16009 "description": "", 16010 "type": "Integer", 16011 "optional": true 16012 } 16013 ], 16014 "return": { 16015 "description": "formatted Strings", 16016 "type": "String[]" 16017 } 16018 } 16019 ] 16020 }, 16021 { 16022 "file": "src/utilities/string_functions.js", 16023 "line": 375, 16024 "description": "<p>Utility function for formatting numbers into strings. Similar to nf() but\nputs a " " (space) in front of positive numbers and a "-" in front of\nnegative numbers. There are two versions: one for formatting floats, and\none for formatting ints. The values for the digits, left, and right\nparameters should always be positive integers.</p>\n", 16025 "itemtype": "method", 16026 "name": "nfs", 16027 "return": { 16028 "description": "formatted String", 16029 "type": "String" 16030 }, 16031 "example": [ 16032 "\n<div>\n<code>\nfunction setup() {\n background(200);\n var num1 = 11253106.115;\n var num2 = -11253106.115;\n\n noStroke();\n fill(0);\n textSize(12);\n // Draw formatted numbers\n text(nfs(num1, 4, 2), 10, 30);\n\n text(nfs(num2, 4, 2), 10, 80);\n\n // Draw dividing line\n stroke(120);\n line(0, 50, width, 50);\n}\n</code>\n</div>" 16033 ], 16034 "alt": "\"11253106.11\" top middle and \"-11253106.11\" displayed bottom middle", 16035 "class": "p5", 16036 "module": "Data", 16037 "submodule": "String Functions", 16038 "overloads": [ 16039 { 16040 "line": 375, 16041 "params": [ 16042 { 16043 "name": "num", 16044 "description": "<p>the Number to format</p>\n", 16045 "type": "Number" 16046 }, 16047 { 16048 "name": "left", 16049 "description": "<p>number of digits to the left of the decimal\n point</p>\n", 16050 "type": "Integer", 16051 "optional": true 16052 }, 16053 { 16054 "name": "right", 16055 "description": "<p>number of digits to the right of the\n decimal point</p>\n", 16056 "type": "Integer", 16057 "optional": true 16058 } 16059 ], 16060 "return": { 16061 "description": "formatted String", 16062 "type": "String" 16063 } 16064 }, 16065 { 16066 "line": 416, 16067 "params": [ 16068 { 16069 "name": "nums", 16070 "description": "<p>the Numbers to format</p>\n", 16071 "type": "Array" 16072 }, 16073 { 16074 "name": "left", 16075 "description": "", 16076 "type": "Integer", 16077 "optional": true 16078 }, 16079 { 16080 "name": "right", 16081 "description": "", 16082 "type": "Integer", 16083 "optional": true 16084 } 16085 ], 16086 "return": { 16087 "description": "formatted Strings", 16088 "type": "String[]" 16089 } 16090 } 16091 ] 16092 }, 16093 { 16094 "file": "src/utilities/string_functions.js", 16095 "line": 437, 16096 "description": "<p>The split() function maps to String.split(), it breaks a String into\npieces using a character or string as the delimiter. The delim parameter\nspecifies the character or characters that mark the boundaries between\neach piece. A String[] array is returned that contains each of the pieces.</p>\n<p>The splitTokens() function works in a similar fashion, except that it\nsplits using a range of characters instead of a specific character or\nsequence.</p>\n", 16097 "itemtype": "method", 16098 "name": "split", 16099 "params": [ 16100 { 16101 "name": "value", 16102 "description": "<p>the String to be split</p>\n", 16103 "type": "String" 16104 }, 16105 { 16106 "name": "delim", 16107 "description": "<p>the String used to separate the data</p>\n", 16108 "type": "String" 16109 } 16110 ], 16111 "return": { 16112 "description": "Array of Strings", 16113 "type": "String[]" 16114 }, 16115 "example": [ 16116 "\n<div>\n<code>\nvar names = 'Pat,Xio,Alex';\nvar splitString = split(names, ',');
16116\ntext(splitString[0], 5, 30);\ntext(splitString[1], 5, 50);\ntext(splitString[2], 5, 70);\n</code>\n</div>" 16117 ], 16118 "alt": "\"pat\" top left, \"Xio\" mid left and \"Alex\" displayed bottom left", 16119 "class": "p5", 16120 "module": "Data", 16121 "submodule": "String Functions" 16122 }, 16123 { 16124 "file": "src/utilities/string_functions.js", 16125 "line": 471, 16126 "description": "<p>The splitTokens() function splits a String at one or many character\ndelimiters or "tokens." The delim parameter specifies the character or\ncharacters to be used as a boundary.\n<br><br>\nIf no delim characters are specified, any whitespace character is used to\nsplit. Whitespace characters include tab (\\t), line feed (\\n), carriage\nreturn (\\r), form feed (\\f), and space.</p>\n", 16127 "itemtype": "method", 16128 "name": "splitTokens", 16129 "params": [ 16130 { 16131 "name": "value", 16132 "description": "<p>the String to be split</p>\n", 16133 "type": "String" 16134 }, 16135 { 16136 "name": "delim", 16137 "description": "<p>list of individual Strings that will be used as\n separators</p>\n", 16138 "type": "String", 16139 "optional": true 16140 } 16141 ], 16142 "return": { 16143 "description": "Array of Strings", 16144 "type": "String[]" 16145 }, 16146 "example": [ 16147 "\n<div class = \"norender\">\n<code>\nfunction setup() {\n var myStr = 'Mango, Banana, Lime';\n var myStrArr = splitTokens(myStr, ',');\n\n print(myStrArr); // prints : [\"Mango\",\" Banana\",\" Lime\"]\n}\n</code>\n</div>" 16148 ], 16149 "class": "p5", 16150 "module": "Data", 16151 "submodule": "String Functions" 16152 }, 16153 { 16154 "file": "src/utilities/string_functions.js", 16155 "line": 526, 16156 "description": "<p>Removes whitespace characters from the beginning and end of a String. In\naddition to standard whitespace characters such as space, carriage return,\nand tab, this function also removes the Unicode "nbsp" character.</p>\n", 16157 "itemtype": "method", 16158 "name": "trim", 16159 "return": { 16160 "description": "a trimmed String", 16161 "type": "String" 16162 }, 16163 "example": [ 16164 "\n<div>\n<code>\nvar string = trim(' No new lines\\n ');\ntext(string + ' here', 2, 50);\n</code>\n</div>" 16165 ], 16166 "alt": "\"No new lines here\" displayed center canvas", 16167 "class": "p5", 16168 "module": "Data", 16169 "submodule": "String Functions", 16170 "overloads": [ 16171 { 16172 "line": 526, 16173 "params": [ 16174 { 16175 "name": "str", 16176 "description": "<p>a String to be trimmed</p>\n", 16177 "type": "String" 16178 } 16179 ], 16180 "return": { 16181 "description": "a trimmed String", 16182 "type": "String" 16183 } 16184 }, 16185 { 16186 "line": 546, 16187 "params": [ 16188 { 16189 "name": "strs", 16190 "description": "<p>an Array of Strings to be trimmed</p>\n", 16191 "type": "Array" 16192 } 16193 ], 16194 "return": { 16195 "description": "an Array of trimmed Strings", 16196 "type": "String[]" 16197 } 16198 } 16199 ] 16200 }, 16201 { 16202 "file": "src/utilities/time_date.js", 16203 "line": 12, 16204 "description": "<p>p5.js communicates with the clock on your computer. The day() function\nreturns the current day as a value from 1 - 31.</p>\n", 16205 "itemtype": "method", 16206 "name": "day", 16207 "return": { 16208 "description": "the current day", 16209 "type": "Integer" 16210 }, 16211 "example": [ 16212 "\n<div>\n<code>\nvar d = day();\ntext('Current day: \\n' + d, 5, 50);\n</code>\n</div>" 16213 ], 16214 "alt": "Current day is displayed", 16215 "class": "p5", 16216 "module": "IO", 16217 "submodule": "Time & Date" 16218 }, 16219 { 16220 "file": "src/utilities/time_date.js", 16221 "line": 34, 16222 "description": "<p>p5.js communicates with the clock on your computer. The hour() function\nreturns the current hour as a value from 0 - 23.</p>\n", 16223 "itemtype": "method", 16224 "name": "hour", 16225 "return": { 16226 "description": "the current hour", 16227 "type": "Integer" 16228 }, 16229 "example": [ 16230 "\n<div>\n<code>\nvar h = hour();\ntext('Current hour:\\n' + h, 5, 50);\n</code>\n</div>" 16231 ], 16232 "alt": "Current hour is displayed", 16233 "class": "p5", 16234 "module": "IO", 16235 "submodule": "Time & Date" 16236 }, 16237 { 16238 "file": "src/utilities/time_date.js", 16239 "line": 56, 16240 "description": "<p>p5.js communicates with the clock on your computer. The minute() function\nreturns the current minute as a value from 0 - 59.</p>\n", 16241 "itemtype": "method", 16242 "name": "minute", 16243 "return": { 16244 "description": "the current minute", 16245 "type": "Integer" 16246 }, 16247 "example": [ 16248 "\n<div>\n<code>\nvar m = minute();\ntext('Current minute: \\n' + m, 5, 50);\n</code>\n</div>" 16249 ], 16250 "alt": "Current minute is displayed", 16251 "class": "p5", 16252 "module": "IO", 16253 "submodule": "Time & Date" 16254 }, 16255 { 16256 "file": "src/utilities/time_date.js", 16257 "line": 78, 16258 "description": "<p>Returns the number of milliseconds (thousandths of a second) since\nstarting the program. This information is often used for timing events and\nanimation sequences.</p>\n", 16259 "itemtype": "method", 16260 "name": "millis", 16261 "return": { 16262 "description": "the number of milliseconds since starting the program", 16263 "type": "Number" 16264 }, 16265 "example": [ 16266 "\n<div>\n<code>\nvar millisecond = millis();\ntext('Milliseconds \\nrunning: \\n' + millisecond, 5, 40);\n</code>\n</div>" 16267 ], 16268 "alt": "number of milliseconds since program has started displayed", 16269 "class": "p5", 16270 "module": "IO", 16271 "submodule": "Time & Date" 16272 }, 16273 { 16274 "file": "src/utilities/time_date.js", 16275 "line": 101, 16276 "description": "<p>p5.js communicates with the clock on your computer. The month() function\nreturns the current month as a value from 1 - 12.</p>\n", 16277 "itemtype": "method", 16278 "name": "month", 16279 "return": { 16280 "description": "the current month", 16281 "type": "Integer" 16282 }, 16283 "example": [ 16284 "\n<div>\n<code>\nvar m = month();\ntext('Current month: \\n' + m, 5, 50);\n</code>\n</div>" 16285 ], 16286 "alt": "Current month is displayed", 16287 "class": "p5", 16288 "module": "IO", 16289 "submodule": "Time & Date" 16290 }, 16291 { 16292 "file": "src/utilities/time_date.js", 16293 "line": 123, 16294 "description": "<p>p5.js communicates with the clock on your computer. The second() function\nreturns the current second as a value from 0 - 59.</p>\n", 16295 "itemtype": "method", 16296 "name": "second", 16297 "return": { 16298 "description": "the current second", 16299 "type": "Integer" 16300 }, 16301 "example": [ 16302 "\n<div>\n<code>\nvar s = second();\ntext('Current second: \\n' + s, 5, 50);\n</code>\n</div>" 16303 ], 16304 "alt": "Current second is displayed", 16305 "class": "p5", 16306 "module": "IO", 16307 "submodule": "Time & Date" 16308 }, 16309 { 16310 "file": "src/utilities/time_date.js", 16311 "line": 145, 16312 "description": "<p>p5.js communicates with the clock on your computer. The year() function\nreturns the current year as an integer (2014, 2015, 2016, etc).</p>\n", 16313 "itemtype": "method", 16314 "name": "year", 16315 "return": { 16316 "description": "the current year", 16317 "type": "Integer" 16318 }, 16319 "example": [ 16320 "\n<div>\n<code>\nvar y = year();\ntext('Current year: \\n' + y, 5, 50);\n</code>\n</div>" 16321 ], 16322 "alt": "Current year is displayed", 16323 "class": "p5", 16324 "module": "IO", 16325 "submodule": "Time & Date" 16326 }, 16327 { 16328 "file": "src/webgl/camera.js", 16329 "line": 12, 16330 "description": "<p>Sets camera position for a 3D sketch. The function behaves similarly\ngluLookAt, except that it replaces the existing modelview matrix instead\nof applying any transformations calculated here on top of the existing\nmodel view.\nWhen called with no arguments, this function\nsets a default camera equivalent to calling\ncamera(0, 0, (height/2.0) / tan(PI*30.0 / 180.0), 0, 0, 0, 0, 1, 0);</p>\n", 16331 "itemtype": "method", 16332 "name": "camera", 16333 "params": [ 16334 { 16335 "name": "x", 16336 "description": "<p>camera position value on x axis</p>\n", 16337 "type": "Number", 16338 "optional": true 16339 }, 16340 { 16341 "name": "y", 16342 "description": "<p>camera position value on y axis</p>\n", 16343 "type": "Number", 16344 "optional": true 16345 }, 16346 { 16347 "name": "z", 16348 "description": "<p>camera position value on z axis</p>\n", 16349 "type": "Number", 16350 "optional": true 16351 }, 16352 { 16353 "name": "centerX", 16354 "description": "<p>x coordinate representing center of the sketch</p>\n", 16355 "type": "Number", 16356 "optional": true 16357 }, 16358 { 16359 "name": "centerY", 16360 "description": "<p>y coordinate representing center of the sketch</p>\n", 16361 "type": "Number", 16362 "optional": true 16363 }, 16364 { 16365 "name": "centerZ", 16366 "description": "<p>z coordinate representing center of the sketch</p>\n", 16367 "type": "Number", 16368 "optional": true 16369 }, 16370 { 16371 "name": "upX", 16372 "description": "<p>x component of direction 'up' from camera</p>\n", 16373 "type": "Number", 16374 "optional": true 16375 }, 16376 { 16377 "name": "upY", 16378 "description": "<p>y component of direction 'up' from camera</p>\n", 16379 "type": "Number", 16380 "optional": true 16381 }, 16382 { 16383 "name": "upZ", 16384 "description": "<p>z component of direction 'up' from camera</p>\n", 16385 "type": "Number", 16386 "optional": true 16387 } 16388 ], 16389 "chainable": 1, 16390 "example": [ 16391 "\n<div>\n<code>\nfunction setup() {\n createCanvas(100, 100, WEBGL);\n}\nfunction draw() {\n //move the camera away from the plane by a sin wave\n camera(0, 0, sin(frameCount * 0.01) * 100, 0, 0, 0, 0, 1, 0);\n plane(120, 120);\n}\n</code>\n</div>" 16392 ], 16393 "alt": "blue square shrinks in size grows to fill canvas. disappears then loops.", 16394 "class": "p5", 16395 "module": "Lights, Camera", 16396 "submodule": "Camera" 16397 }, 16398 { 16399 "file": "src/webgl/camera.js", 16400 "line": 161, 16401 "description": "<p>Sets perspective camera. When called with no arguments, the defaults\nprovided are equivalent to\nperspective(PI/3.0, width/height, cameraZ/10.0, cameraZ<em>10.0)\nwhere cameraZ is ((height/2.0) / tan(PI</em>60.0/360.0));</p>\n", 16402 "itemtype": "method", 16403 "name": "perspective", 16404 "params": [ 16405 { 16406 "name": "fovy", 16407 "description": "<p>camera frustum vertical field of view,\n from bottom to top of view, in angleMode units</p>\n", 16408 "type": "Number", 16409 "optional": true 16410 }, 16411 { 16412 "name": "aspect", 16413 "description": "<p>camera frustum aspect ratio</p>\n", 16414 "type": "Number", 16415 "optional": true 16416 }, 16417 { 16418 "name": "near", 16419 "description": "<p>frustum near plane length</p>\n", 16420 "type": "Number", 16421 "optional": true 16422 }, 16423 { 16424 "name": "far", 16425 "description": "<p>frustum far plane length</p>\n", 16426 "type": "Number", 16427 "optional": true 16428 } 16429 ], 16430 "chainable": 1, 16431 "example": [ 16432 "\n<div>\n<code>
16432\n//drag mouse to toggle the world!\n//you will see there's a vanish point\nfunction setup() {\n createCanvas(100, 100, WEBGL);\n var fov = 60 / 180 * PI;\n var cameraZ = height / 2.0 / tan(fov / 2.0);\n perspective(60 / 180 * PI, width / height, cameraZ * 0.1, cameraZ * 10);\n}\nfunction draw() {\n background(200);\n orbitControl();\n for (var i = -1; i < 2; i++) {\n for (var j = -2; j < 3; j++) {\n push();\n translate(i * 160, 0, j * 160);\n box(40, 40, 40);\n pop();\n }\n }\n}\n</code>\n</div>" 16433 ], 16434 "alt": "colored 3d boxes toggleable with mouse position", 16435 "class": "p5", 16436 "module": "Lights, Camera", 16437 "submodule": "Camera" 16438 }, 16439 { 16440 "file": "src/webgl/camera.js", 16441 "line": 243, 16442 "description": "<p>Setup ortho camera</p>\n", 16443 "itemtype": "method", 16444 "name": "ortho", 16445 "params": [ 16446 { 16447 "name": "left", 16448 "description": "<p>camera frustum left plane</p>\n", 16449 "type": "Number", 16450 "optional": true 16451 }, 16452 { 16453 "name": "right", 16454 "description": "<p>camera frustum right plane</p>\n", 16455 "type": "Number", 16456 "optional": true 16457 }, 16458 { 16459 "name": "bottom", 16460 "description": "<p>camera frustum bottom plane</p>\n", 16461 "type": "Number", 16462 "optional": true 16463 }, 16464 { 16465 "name": "top", 16466 "description": "<p>camera frustum top plane</p>\n", 16467 "type": "Number", 16468 "optional": true 16469 }, 16470 { 16471 "name": "near", 16472 "description": "<p>camera frustum near plane</p>\n", 16473 "type": "Number", 16474 "optional": true 16475 }, 16476 { 16477 "name": "far", 16478 "description": "<p>camera frustum far plane</p>\n", 16479 "type": "Number", 16480 "optional": true 16481 } 16482 ], 16483 "chainable": 1, 16484 "example": [ 16485 "\n<div>\n<code>\n//drag mouse to toggle the world!\n//there's no vanish point\nfunction setup() {\n createCanvas(100, 100, WEBGL);\n ortho(-width / 2, width / 2, height / 2, -height / 2, 0, 500);\n}\nfunction draw() {\n background(200);\n orbitControl();\n strokeWeight(0.1);\n for (var i = -1; i < 2;
16485 i++) {\n for (var j = -2; j < 3; j++) {\n push();\n translate(i * 160, 0, j * 160);\n box(40, 40, 40);\n pop();\n }\n }\n}\n</code>\n</div>" 16486 ], 16487 "alt": "3 3d boxes, reveal several more boxes on 3d plane when mouse used to toggle", 16488 "class": "p5", 16489 "module": "Lights, Camera", 16490 "submodule": "Camera" 16491 }, 16492 { 16493 "file": "src/webgl/interaction.js", 16494 "line": 5, 16495 "itemtype": "method", 16496 "name": "orbitControl", 16497 "chainable": 1, 16498 "example": [ 16499 "\n<div>\n<code>\nfunction setup() {\n createCanvas(100, 100, WEBGL);\n}\n\nfunction draw() {\n background(50);\n // Orbit control allows the camera to orbit around a target.\n orbitControl();\n box(30, 50);\n}\n</code>\n</div>" 16500 ], 16501 "alt": "Camera orbits around box when mouse is hold-clicked & then moved.", 16502 "class": "p5", 16503 "module": "Lights, Camera" 16504 }, 16505 { 16506 "file": "src/webgl/light.js", 16507 "line": 12, 16508 "description": "<p>Creates an ambient light with a color</p>\n", 16509 "itemtype": "method", 16510 "name": "ambientLight", 16511 "chainable": 1, 16512 "example": [ 16513 "\n<div>\n<code>\nfunction setup() {\n createCanvas(100, 100, WEBGL);\n}\nfunction draw() {\n background(0);\n ambientLight(150);\n ambientMaterial(250);\n noStroke();\n sphere(25);\n}\n</code>\n</div>" 16514 ], 16515 "alt": "evenly distributed light across a sphere", 16516 "class": "p5", 16517 "module": "Lights, Camera", 16518 "submodule": "Lights", 16519 "overloads": [ 16520 { 16521 "line": 12, 16522 "params": [ 16523 { 16524 "name": "v1", 16525 "description": "<p>red or hue value relative to\n the current color range</p>\n", 16526 "type": "Number" 16527 }, 16528 { 16529 "name": "v2", 16530 "description": "<p>green or saturation value\n relative to the current color range</p>\n", 16531 "type": "Number" 16532 }, 16533 { 16534 "name": "v3", 16535 "description": "<p>blue or brightness value\n relative to the current color range</p>\n", 16536 "type": "Number" 16537 }, 16538 { 16539 "name": "alpha", 16540 "description": "", 16541 "type": "Number", 16542 "optional": true 16543 } 16544 ], 16545 "chainable": 1 16546 }, 16547 { 16548 "line": 46, 16549 "params": [ 16550 { 16551 "name": "value", 16552 "description": "<p>a color string</p>\n", 16553 "type": "String" 16554 } 16555 ], 16556 "chainable": 1 16557 }, 16558 { 16559 "line": 52, 16560 "params": [ 16561 { 16562 "name": "gray", 16563 "description": "<p>a gray value</p>\n", 16564 "type": "Number" 16565 }, 16566 { 16567 "name": "alpha", 16568 "description": "", 16569 "type": "Number", 16570 "optional": true 16571 } 16572 ], 16573 "chainable": 1 16574 }, 16575 { 16576 "line": 59, 16577 "params": [ 16578 { 16579 "name": "values", 16580 "description": "<p>an array containing the red,green,blue &\n and alpha components of the color</p>\n", 16581 "type": "Number[]" 16582 } 16583 ], 16584 "chainable": 1 16585 }, 16586 { 16587 "line": 66, 16588 "params": [ 16589 { 16590 "name": "color", 16591 "description": "<p>the ambient light color</p>\n", 16592 "type": "p5.Color" 16593 } 16594 ], 16595 "chainable": 1 16596 } 16597 ] 16598 }, 16599 { 16600 "file": "src/webgl/light.js", 16601 "line": 101, 16602 "description": "<p>Creates a directional light with a color and a direction</p>\n", 16603 "itemtype": "method", 16604 "name": "directionalLight", 16605 "chainable": 1, 16606 "example": [ 16607 "\n<div>\n<code>\nfunction setup() {\n createCanvas(100, 100, WEBGL);\n}\nfunction draw() {\n background(0);\n //move your mouse to change light direction\n var dirX = (mouseX / width - 0.5) * 2;\n var dirY = (mouseY / height - 0.5) * 2;\n directionalLight(250, 250, 250, -dirX, -dirY, 0.25);\n ambientMaterial(250);\n noStroke();\n sphere(25);\n}\n</code>\n</div>" 16608 ], 16609 "alt": "light source on canvas changeable with mouse position", 16610 "class": "p5", 16611 "module": "Lights, Camera", 16612 "submodule": "Lights", 16613 "overloads": [ 16614 { 16615 "line": 101, 16616 "params": [ 16617 { 16618 "name": "v1", 16619 "description": "<p>red or hue value (depending on the current\ncolor mode),</p>\n", 16620 "type": "Number" 16621 }, 16622 { 16623 "name": "v2", 16624 "description": "<p>green or saturation value</p>\n", 16625 "type": "Number" 16626 }, 16627 { 16628 "name": "v3", 16629 "description": "<p>blue or brightness value</p>\n", 16630 "type": "Number" 16631 }, 16632 { 16633 "name": "position", 16634 "description": "<p>the direction of the light</p>\n", 16635 "type": "p5.Vector" 16636 } 16637 ], 16638 "chainable": 1 16639 }, 16640 { 16641 "line": 134, 16642 "params": [ 16643 { 16644 "name": "color", 16645 "description": "<p>color Array, CSS color string,\n or p5.Color value</p>\n", 16646 "type": "Number[]|String|p5.Color" 16647 }, 16648 { 16649 "name": "x", 16650 "description": "<p>x axis direction</p>\n", 16651 "type": "Number" 16652 }, 16653 { 16654 "name": "y", 16655 "description": "<p>y axis direction</p>\n", 16656 "type": "Number" 16657 }, 16658 { 16659 "name": "z", 16660 "description": "<p>z axis direction</p>\n", 16661 "type": "Number" 16662 } 16663 ], 16664 "chainable": 1 16665 }, 16666 { 16667 "line": 144, 16668 "params": [ 16669 { 16670 "name": "color", 16671 "description": "", 16672 "type": "Number[]|String|p5.Color" 16673 }, 16674 { 16675 "name": "position", 16676 "description": "", 16677 "type": "p5.Vector" 16678 } 16679 ], 16680 "chainable": 1 16681 }, 16682 { 16683 "line": 151, 16684 "params": [ 16685 { 16686 "name": "v1", 16687 "description": "", 16688 "type": "Number" 16689 }, 16690 { 16691 "name": "v2", 16692 "description": "", 16693 "type": "Number" 16694 }, 16695 { 16696 "name": "v3", 16697 "description": "", 16698 "type": "Number" 16699 }, 16700 { 16701 "name": "x", 16702 "description": "", 16703 "type": "Number" 16704 }, 16705 { 16706 "name": "y", 16707 "description": "", 16708 "type": "Number" 16709 }, 16710 { 16711 "name": "z", 16712 "description": "", 16713 "type": "Number" 16714 } 16715 ], 16716 "chainable": 1 16717 } 16718 ] 16719 }, 16720 { 16721 "file": "src/webgl/light.js", 16722 "line": 207, 16723 "description": "<p>Creates a point light with a color and a light position</p>\n", 16724 "itemtype": "method", 16725 "name": "pointLight", 16726 "chainable": 1, 16727 "example": [ 16728 "\n<div>\n<code>\nfunction setup() {\n createCanvas(100, 100, WEBGL);\n}\nfunction draw() {\n background(0);\n //move your mouse to change light position\n var locX = mouseX - width / 2;
16728\n var locY = mouseY - height / 2;\n // to set the light position,\n // think of the world's coordinate as:\n // -width/2,-height/2 -------- width/2,-height/2\n // | |\n // | 0,0 |\n // | |\n // -width/2,height/2--------width/2,height/2\n pointLight(250, 250, 250, locX, locY, 50);\n ambientMaterial(250);\n noStroke();\n sphere(25);\n}\n</code>\n</div>" 16729 ], 16730 "alt": "spot light on canvas changes position with mouse", 16731 "class": "p5", 16732 "module": "Lights, Camera", 16733 "submodule": "Lights", 16734 "overloads": [ 16735 { 16736 "line": 207, 16737 "params": [ 16738 { 16739 "name": "v1", 16740 "description": "<p>red or hue value (depending on the current\ncolor mode),</p>\n", 16741 "type": "Number" 16742 }, 16743 { 16744 "name": "v2", 16745 "description": "<p>green or saturation value</p>\n", 16746 "type": "Number" 16747 }, 16748 { 16749 "name": "v3", 16750 "description": "<p>blue or brightness value</p>\n", 16751 "type": "Number" 16752 }, 16753 { 16754 "name": "x", 16755 "description": "<p>x axis position</p>\n", 16756 "type": "Number" 16757 }, 16758 { 16759 "name": "y", 16760 "description": "<p>y axis position</p>\n", 16761 "type": "Number" 16762 }, 16763 { 16764 "name": "z", 16765 "description": "<p>z axis position</p>\n", 16766 "type": "Number" 16767 } 16768 ], 16769 "chainable": 1 16770 }, 16771 { 16772 "line": 249, 16773 "params": [ 16774 { 16775 "name": "v1", 16776 "description": "", 16777 "type": "Number" 16778 }, 16779 { 16780 "name": "v2", 16781 "description": "", 16782 "type": "Number" 16783 }, 16784 { 16785 "name": "v3", 16786 "description": "", 16787 "type": "Number" 16788 }, 16789 { 16790 "name": "position", 16791 "description": "<p>the position of the light</p>\n", 16792 "type": "p5.Vector" 16793 } 16794 ], 16795 "chainable": 1 16796 }, 16797 { 16798 "line": 258, 16799 "params": [ 16800 { 16801 "name": "color", 16802 "description": "<p>color Array, CSS color string,\nor p5.Color value</p>\n", 16803 "type": "Number[]|String|p5.Color" 16804 }, 16805 { 16806 "name": "x", 16807 "description": "", 16808 "type": "Number" 16809 }, 16810 { 16811 "name": "y", 16812 "description": "", 16813 "type": "Number" 16814 }, 16815 { 16816 "name": "z", 16817 "description": "", 16818 "type": "Number" 16819 } 16820 ], 16821 "chainable": 1 16822 }, 16823 { 16824 "line": 268, 16825 "params": [ 16826 { 16827 "name": "color", 16828 "description": "", 16829 "type": "Number[]|String|p5.Color" 16830 }, 16831 { 16832 "name": "position", 16833 "description": "", 16834 "type": "p5.Vector" 16835 } 16836 ], 16837 "chainable": 1 16838 } 16839 ] 16840 }, 16841 { 16842 "file": "src/webgl/loading.js", 16843 "line": 14, 16844 "description": "<p>Load a 3d model from an OBJ file.\n<br><br>\nOne of the limitations of the OBJ format is that it doesn't have a built-in\nsense of scale. This means that models exported from different programs might\nbe very different sizes. If your model isn't displaying, try calling\nloadModel() with the normalized parameter set to true. This will resize the\nmodel to a scale appropriate for p5. You can also make additional changes to\nthe final size of your model with the scale() function.</p>\n", 16845 "itemtype": "method", 16846 "name": "loadModel", 16847 "return": { 16848 "description": "the p5.Geometry object", 16849 "type": "p5.Geometry" 16850 }, 16851 "example": [ 16852 "\n<div>\n<code>
16852\n//draw a spinning teapot\nvar teapot;\n\nfunction preload() {\n teapot = loadModel('assets/teapot.obj');\n}\n\nfunction setup() {\n createCanvas(100, 100, WEBGL);\n}\n\nfunction draw() {\n background(200);\n rotateX(frameCount * 0.01);\n rotateY(frameCount * 0.01);\n model(teapot);\n}\n</code>\n</div>" 16853 ], 16854 "alt": "Vertically rotating 3-d teapot with red, green and blue gradient.", 16855 "class": "p5", 16856 "module": "Shape", 16857 "submodule": "3D Models", 16858 "overloads": [ 16859 { 16860 "line": 14, 16861 "params": [ 16862 { 16863 "name": "path", 16864 "description": "<p>Path of the model to be loaded</p>\n", 16865 "type": "String" 16866 }, 16867 { 16868 "name": "normalize", 16869 "description": "<p>If true, scale the model to a\n standardized size when loading</p>\n", 16870 "type": "Boolean" 16871 }, 16872 { 16873 "name": "successCallback", 16874 "description": "<p>Function to be called\n once the model is loaded. Will be passed\n the 3D model object.</p>\n", 16875 "type": "function(p5.Geometry)", 16876 "optional": true 16877 }, 16878 { 16879 "name": "failureCallback", 16880 "description": "<p>called with event error if\n the image fails to load.</p>\n", 16881 "type": "Function(Event)", 16882 "optional": true 16883 } 16884 ], 16885 "return": { 16886 "description": "the p5.Geometry object", 16887 "type": "p5.Geometry" 16888 } 16889 }, 16890 { 16891 "line": 61, 16892 "params": [ 16893 { 16894 "name": "path", 16895 "description": "", 16896 "type": "String" 16897 }, 16898 { 16899 "name": "successCallback", 16900 "description": "", 16901 "type": "function(p5.Geometry)", 16902 "optional": true 16903 }, 16904 { 16905 "name": "failureCallback", 16906 "description": "", 16907 "type": "Function(Event)", 16908 "optional": true 16909 } 16910 ], 16911 "return": { 16912 "description": "the p5.Geometry object", 16913 "type": "p5.Geometry" 16914 } 16915 } 16916 ] 16917 }, 16918 { 16919 "file": "src/webgl/loading.js", 16920 "line": 106, 16921 "description": "<p>Parse OBJ lines into model. For reference, this is what a simple model of a\nsquare might look like:</p>\n<p>v -0.5 -0.5 0.5\nv -0.5 -0.5 -0.5\nv -0.5 0.5 -0.5\nv -0.5 0.5 0.5</p>\n<p>f 4 3 2 1</p>\n", 16922 "class": "p5", 16923 "module": "Shape", 16924 "submodule": "3D Models" 16925 }, 16926 { 16927 "file": "src/webgl/loading.js", 16928 "line": 215, 16929 "description": "<p>Render a 3d model to the screen.</p>\n", 16930 "itemtype": "method", 16931 "name": "model", 16932 "params": [ 16933 { 16934 "name": "model", 16935 "description": "<p>Loaded 3d model to be rendered</p>\n", 16936 "type": "p5.Geometry" 16937 } 16938 ], 16939 "example": [ 16940 "\n<div>\n<code>\n//draw a spinning teapot\nvar teapot;\n\nfunction preload() {\n teapot = loadModel('assets/teapot.obj');\n}\n\nfunction setup() {\n createCanvas(100, 100, WEBGL);\n}\n\nfunction draw() {\n background(200);\n rotateX(frameCount * 0.01);\n rotateY(frameCount * 0.01);
16940\n model(teapot);\n}\n</code>\n</div>" 16941 ], 16942 "alt": "Vertically rotating 3-d teapot with red, green and blue gradient.", 16943 "class": "p5", 16944 "module": "Shape", 16945 "submodule": "3D Models" 16946 }, 16947 { 16948 "file": "src/webgl/material.js", 16949 "line": 14, 16950 "description": "<p>Loads a custom shader from the provided vertex and fragment\nshader paths. The shader files are loaded asynchronously in the\nbackground, so this method should be used in preload().</p>\n<p>For now, there are three main types of shaders. p5 will automatically\nsupply appropriate vertices, normals, colors, and lighting attributes\nif the parameters defined in the shader match the names.</p>\n", 16951 "itemtype": "method", 16952 "name": "loadShader", 16953 "params": [ 16954 { 16955 "name": "vertFilename", 16956 "description": "<p>path to file containing vertex shader\nsource code</p>\n", 16957 "type": "String", 16958 "optional": true 16959 }, 16960 { 16961 "name": "fragFilename", 16962 "description": "<p>path to file containing fragment shader\nsource code</p>\n", 16963 "type": "String", 16964 "optional": true 16965 } 16966 ], 16967 "return": { 16968 "description": "a shader object created from the provided\nvertex and fragment shader files.", 16969 "type": "p5.Shader" 16970 }, 16971 "class": "p5", 16972 "module": "Lights, Camera", 16973 "submodule": "Material" 16974 }, 16975 { 16976 "file": "src/webgl/material.js", 16977 "line": 57, 16978 "itemtype": "method", 16979 "name": "createShader", 16980 "params": [ 16981 { 16982 "name": "vertSrc", 16983 "description": "<p>source code for the vertex shader</p>\n", 16984 "type": "String" 16985 }, 16986 { 16987 "name": "fragSrc", 16988 "description": "<p>source code for the fragment shader</p>\n", 16989 "type": "String" 16990 } 16991 ], 16992 "return": { 16993 "description": "a shader object created from the provided\nvertex and fragment shaders.", 16994 "type": "p5.Shader" 16995 }, 16996 "example": [ 16997 "\n<div modernizr='webgl'>\n<code>\n// the 'varying's are shared between both vertex & fragment shaders\nvar varying = 'precision highp float; varying vec2 vPos;';\n\n// the vertex shader is called for each vertex\nvar vs =\n varying +\n 'attribute vec3 aPosition;' +\n 'void main() { vPos = (gl_Position = vec4(aPosition,1.0)).xy; }';\n\n// the fragment shader is called for each pixel\nvar fs =\n varying +\n 'uniform vec2 p;' +\n 'uniform float r;' +\n 'const int I = 500;' +\n 'void main() {' +\n ' vec2 c = p + vPos * r, z = c;' +\n ' float n = 0.0;' +\n ' for (int i = I; i > 0; i --) {' +\n ' if(z.x*z.x+z.y*z.y > 4.0) {' +\n ' n = float(i)/float(I);' +\n ' break;' +\n ' }' +\n ' z = vec2(z.x*z.x-z.y*z.y, 2.0*z.x*z.y) + c;' +\n ' }' +\n ' gl_FragColor = vec4(0.5-cos(n*17.0)/2.0,0.5-cos(n*13.0)/2.0,0.5-cos(n*23.0)/2.0,1.0);' +\n '}';\n\nvar mandel;\nfunction setup() {\n createCanvas(100, 100, WEBGL);\n\n // create and initialize the shader\n mandel = createShader(vs, fs);\n shader(mandel);\n noStroke();\n\n // 'p' is the center point of the Mandelbrot image\n mandel.setUniform('p', [-0.74364388703, 0.13182590421]);\n}\n\nfunction draw() {\n // 'r' is the size of the image in Mandelbrot-space\n mandel.setUniform('r', 1.5 * exp(-6.5 * (1 + sin(millis() / 2000))));\n quad(-1, -1, 1, -1, 1, 1, -1, 1);\n}\n</code>\n</div>" 16998 ], 16999 "alt": "zooming Mandelbrot set. a colorful, infinitely detailed fractal.", 17000 "class": "p5", 17001 "module": "Lights, Camera", 17002 "submodule": "Material" 17003 }, 17004 { 17005 "file": "src/webgl/material.js", 17006 "line": 125, 17007 "description": "<p>The shader() function lets the user provide a custom shader\nto fill in shapes in WEBGL mode. Users can create their\nown shaders by loading vertex and fragment shaders with\nloadShader().</p>\n", 17008 "itemtype": "method", 17009 "name": "shader", 17010 "chainable": 1, 17011 "params": [ 17012 { 17013 "name": "s", 17014 "description": "<p>the desired p5.Shader to use for rendering\nshapes.</p>\n", 17015 "type": "p5.Shader", 17016 "optional": true 17017 } 17018 ], 17019 "class": "p5", 17020 "module": "Lights, Camera", 17021 "submodule": "Material" 17022 }, 17023 { 17024 "file": "src/webgl/material.js", 17025 "line": 150, 17026 "description": "<p>Normal material for geometry. You can view all\npossible materials in this\n<a href=\"https://p5js.org/examples/3d-materials.html\">example</a>.</p>\n", 17027 "itemtype": "method", 17028 "name": "normalMaterial", 17029 "chainable": 1, 17030 "example": [ 17031 "\n<div>\n<code>\nfunction setup() {\n createCanvas(100, 100, WEBGL);\n}\n\nfunction draw() {\n background(200);\n normalMaterial();\n sphere(50);\n}\n</code>\n</div>" 17032 ], 17033 "alt": "Red, green and blue gradient.", 17034 "class": "p5", 17035 "module": "Lights, Camera", 17036 "submodule": "Material" 17037 }, 17038 { 17039 "file": "src/webgl/material.js", 17040 "line": 185, 17041 "description": "<p>Texture for geometry. You can view other possible materials in this\n<a href=\"https://p5js.org/examples/3d-materials.html\">example</a>.</p>\n", 17042 "itemtype": "method", 17043 "name": "texture", 17044 "params": [ 17045 { 17046 "name": "tex", 17047 "description": "<p>2-dimensional graphics\n to render as texture</p>\n", 17048 "type": "p5.Image|p5.MediaElement|p5.Graphics" 17049 } 17050 ], 17051 "chainable": 1, 17052 "example": [ 17053 "\n<div>\n<code>\nvar img;\nfunction preload() {\n img = loadImage('assets/laDefense.jpg');\n}\n\nfunction setup() {\n createCanvas(100, 100, WEBGL);\n}\n\nfunction draw() {\n background(0);\n rotateZ(frameCount * 0.01);\n rotateX(frameCount * 0.01);\n rotateY(frameCount * 0.01);\n //pass image as texture\n texture(img);\n box(200, 200, 200);\n}\n</code>\n</div>\n\n<div>\n<code>\nvar pg;\nfunction setup() {\n createCanvas(100, 100, WEBGL);\n pg = createGraphics(200, 200);\n pg.textSize(100);\n}\n\nfunction draw() {\n background(0);\n pg.background(255);\n pg.text('hello!', 0, 100);\n //pass image as texture\n texture(pg);\n plane(200);\n}\n</code>\n</div>\n\n<div>\n<code>\nvar vid;\nfunction preload() {\n vid = createVideo('assets/fingers.mov');\n vid.hide();\n vid.loop();\n}\nfunction setup() {\n createCanvas(100, 100, WEBGL);\n}\n\nfunction draw() {\n background(0);\n //pass video frame as texture\n texture(vid);\n plane(200);\n}\n</code>\n</div>" 17054 ], 17055 "alt": "Rotating view of many images umbrella and grid roof on a 3d plane\nblack canvas\nblack canvas", 17056 "class": "p5", 17057 "module": "Lights, Camera", 17058 "submodule": "Material" 17059 }, 17060 { 17061 "file": "src/webgl/material.js", 17062 "line": 275, 17063 "description": "<p>Ambient material for geometry with a given color. You can view all\npossible materials in this\n<a href=\"https://p5js.org/examples/3d-materials.html\">example</a>.</p>\n", 17064 "itemtype": "method", 17065 "name": "ambientMaterial", 17066 "chainable": 1, 17067 "example": [ 17068 "\n<div>\n<code>\nfunction setup() {\n createCanvas(100, 100, WEBGL);\n}\nfunction draw() {\n background(0);\n ambientLight(100);\n pointLight(250, 250, 250, 100, 100, 0);\n ambientMaterial(250);\n sphere(50);\n}\n</code>\n</div>" 17069 ], 17070 "alt": "radiating light source from top right of canvas", 17071 "class": "p5", 17072 "module": "Lights, Camera", 17073 "submodule": "Material", 17074 "overloads": [ 17075 { 17076 "line": 275, 17077 "params": [ 17078 { 17079 "name": "v1", 17080 "description": "<p>gray value, red or hue value\n (depending on the current color mode),</p>\n", 17081 "type": "Number" 17082 }, 17083 { 17084 "name": "v2", 17085 "description": "<p>green or saturation value</p>\n", 17086 "type": "Number", 17087 "optional": true 17088 }, 17089 { 17090 "name": "v3", 17091 "description": "<p>blue or brightness value</p>\n", 17092 "type": "Number", 17093 "optional": true 17094 }, 17095 { 17096 "name": "a", 17097 "description": "<p>opacity</p>\n", 17098 "type": "Number", 17099 "optional": true 17100 } 17101 ], 17102 "chainable": 1 17103 }, 17104 { 17105 "line": 306, 17106 "params": [ 17107 { 17108 "name": "color", 17109 "description": "<p>color, color Array, or CSS color string</p>\n", 17110 "type": "Number[]|String|p5.Color" 17111 } 17112 ], 17113 "chainable": 1 17114 } 17115 ] 17116 }, 17117 { 17118 "file": "src/webgl/material.js", 17119 "line": 324, 17120 "description": "<p>Specular material for geometry with a given color. You can view all\npossible materials in this\n<a href=\"https://p5js.org/examples/3d-materials.html\">example</a>.</p>\n", 17121 "itemtype": "method", 17122 "name": "specularMaterial", 17123 "chainable": 1, 17124 "example": [ 17125 "\n<div>\n<code>\nfunction setup() {\n createCanvas(100, 100, WEBGL);\n}\nfunction draw() {\n background(0);\n ambientLight(100);\n pointLight(250, 250, 250, 100, 100, 0);\n specularMaterial(250);\n sphere(50);\n}\n</code>\n</div>" 17126 ], 17127 "alt": "diffused radiating light source from top right of canvas", 17128 "class": "p5", 17129 "module": "Lights, Camera", 17130 "submodule": "Material", 17131 "overloads": [ 17132 { 17133 "line": 324, 17134 "params": [ 17135 { 17136 "name": "v1", 17137 "description": "<p>gray value, red or hue value\n (depending on the current color mode),</p>\n", 17138 "type": "Number" 17139 }, 17140 { 17141 "name": "v2", 17142 "description": "<p>green or saturation value</p>\n", 17143 "type": "Number", 17144 "optional": true 17145 }, 17146 { 17147 "name": "v3", 17148 "description": "<p>blue or brightness value</p>\n", 17149 "type": "Number", 17150 "optional": true 17151 }, 17152 { 17153 "name": "a", 17154 "description": "<p>opacity</p>\n", 17155 "type": "Number", 17156 "optional": true 17157 } 17158 ], 17159 "chainable": 1 17160 }, 17161 { 17162 "line": 355, 17163 "params": [ 17164 { 17165 "name": "color", 17166 "description": "<p>color Array, or CSS color string</p>\n", 17167 "type": "Number[]|String|p5.Color" 17168 } 17169 ], 17170 "chainable": 1 17171 } 17172 ] 17173 }, 17174 { 17175 "file": "src/webgl/p5.Geometry.js", 17176 "line": 52, 17177 "itemtype": "method", 17178 "name": "computeFaces", 17179 "chainable": 1, 17180 "class": "p5.Geometry", 17181 "module": "Lights, Camera" 17182 }, 17183 { 17184 "file": "src/webgl/p5.Geometry.js", 17185 "line": 94, 17186 "description": "<p>computes smooth normals per vertex as an average of each\nface.</p>\n", 17187 "itemtype": "method", 17188 "name": "computeNormals", 17189 "chainable": 1, 17190 "class": "p5.Geometry", 17191 "module": "Lights, Camera" 17192 }, 17193 { 17194 "file": "src/webgl/p5.Geometry.js", 17195 "line": 133, 17196 "description": "<p>Averages the vertex normals. Used in curved\nsurfaces</p>\n", 17197 "itemtype": "method", 17198 "name": "averageNormals", 17199 "chainable": 1, 17200 "class": "p5.Geometry", 17201 "module": "Lights, Camera" 17202 }, 17203 { 17204 "file": "src/webgl/p5.Geometry.js", 17205 "line": 154, 17206 "description": "<p>Averages pole normals. Used in spherical primitives</p>\n", 17207 "itemtype": "method", 17208 "name": "averagePoleNormals", 17209 "chainable": 1, 17210 "class": "p5.Geometry", 17211 "module": "Lights, Camera" 17212 }, 17213 { 17214 "file": "src/webgl/p5.Geometry.js", 17215 "line": 247, 17216 "description": "<p>Modifies all vertices to be centered within the range -100 to 100.</p>\n", 17217 "itemtype": "method", 17218 "name": "normalize", 17219 "chainable": 1, 17220 "class": "p5.Geometry", 17221 "module": "Lights, Camera" 17222 }, 17223 { 17224 "file": "src/webgl/p5.RendererGL.js", 17225 "line": 197, 17226 "description": "<p>Set attributes for the WebGL Drawing context.\nThis is a way of adjusting ways that the WebGL\nrenderer works to fine-tune the display and performance.\nThis should be put in setup().\nThe available attributes are:\n<br>\nalpha - indicates if the canvas contains an alpha buffer\ndefault is true\n<br><br>\ndepth - indicates whether the drawing buffer has a depth buffer\nof at least 16 bits - default is true\n<br><br>\nstencil - indicates whether the drawing buffer has a stencil buffer\nof at least 8 bits\n<br><br>
17226\nantialias - indicates whether or not to perform anti-aliasing\ndefault is false\n<br><br>\npremultipliedAlpha - indicates that the page compositor will assume\nthe drawing buffer contains colors with pre-multiplied alpha\ndefault is false\n<br><br>\npreserveDrawingBuffer - if true the buffers will not be cleared and\nand will preserve their values until cleared or overwritten by author\n(note that p5 clears automatically on draw loop)\ndefault is true\n<br><br>\nperPixelLighting - if true, per-pixel lighting will be used in the\nlighting shader.\ndefault is false\n<br><br></p>\n", 17227 "itemtype": "method", 17228 "name": "setAttributes", 17229 "example": [ 17230 "\n<div>\n<code>\nfunction setup() {\n createCanvas(100, 100, WEBGL);\n}\n\nfunction draw() {\n background(255);\n push();\n rotateZ(frameCount * 0.02);\n rotateX(frameCount * 0.02);\n rotateY(frameCount * 0.02);\n fill(0, 0, 0);\n box(50);\n pop();\n}\n</code>\n</div>\n<br>\nNow with the antialias attribute set to true.\n<br>\n<div>\n<code>\nfunction setup() {\n createCanvas(100, 100, WEBGL);\n setAttributes('antialias', true);\n}\n\nfunction draw() {\n background(255);\n push();\n rotateZ(frameCount * 0.02);\n rotateX(frameCount * 0.02);\n rotateY(frameCount * 0.02);\n fill(0, 0, 0);\n box(50);\n pop();\n}\n</code>\n</div>\n\n<div>\n<code>\n// press the mouse button to enable perPixelLighting\nfunction setup() {\n createCanvas(100, 100, WEBGL);\n noStroke();\n fill(255);\n}\n\nvar lights = [\n { c: '#f00', t: 1.12, p: 1.91, r: 0.2 },\n { c: '#0f0', t: 1.21, p: 1.31, r: 0.2 },\n { c: '#00f', t: 1.37, p: 1.57, r: 0.2 },\n { c: '#ff0', t: 1.12, p: 1.91, r: 0.7 },\n { c: '#0ff', t: 1.21, p: 1.31, r: 0.7 },\n { c: '#f0f', t: 1.37, p: 1.57, r: 0.7 }\n];\n\nfunction draw() {\n var t = millis() / 1000 + 1000;\n background(0);\n directionalLight(color('#222'), 1, 1, 1);\n\n for (var i = 0; i < lights.length; i++) {\n var light = lights[i];\n pointLight(\n color(light.c),\n p5.Vector.fromAngles(t * light.t, t * light.p, width * light.r)\n );\n }\n\n specularMaterial(255);\n sphere(width * 0.1);\n\n rotateX(t * 0.77);\n rotateY(t * 0.83);\n rotateZ(t * 0.91);\n torus(width * 0.3, width * 0.07, 30, 10);\n}\n\nfunction mousePressed() {\n setAttributes('perPixelLighting', true);\n noStroke();\n fill(255);\n}\nfunction mouseReleased() {\n setAttributes('perPixelLighting', false);\n noStroke();\n fill(255);\n}\n</code>\n</div>" 17231 ], 17232 "alt": "a rotating cube with smoother edges", 17233 "class": "p5", 17234 "module": "Rendering", 17235 "submodule": "Rendering", 17236 "overloads": [ 17237 { 17238 "line": 197, 17239 "params": [ 17240 { 17241 "name": "key", 17242 "description": "<p>Name of attribute</p>\n", 17243 "type": "String" 17244 }, 17245 { 17246 "name": "value", 17247 "description": "<p>New value of named attribute</p>\n", 17248 "type": "Boolean" 17249 } 17250 ] 17251 }, 17252 { 17253 "line": 330, 17254 "params": [ 17255 { 17256 "name": "obj", 17257 "description": "<p>object with key-value pairs</p>\n", 17258 "type": "Object" 17259 } 17260 ] 17261 } 17262 ] 17263 }, 17264 { 17265 "file": "src/webgl/p5.Shader.js", 17266 "line": 270, 17267 "description": "<p>Wrapper around gl.uniform functions.\nAs we store uniform info in the shader we can use that\nto do type checking on the supplied data and call\nthe appropriate function.</p>\n", 17268 "itemtype": "method", 17269 "name": "setUniform", 17270 "chainable": 1, 17271 "params": [ 17272 { 17273 "name": "uniformName", 17274 "description": "<p>the name of the uniform in the\nshader program</p>\n", 17275 "type": "String" 17276 }, 17277 { 17278 "name": "data", 17279 "description": "<p>the data to be associated\nwith that uniform; type varies (could be a single numerical value, array,\nmatrix, or texture / sampler reference)</p>\n", 17280 "type": "Object|Number|Boolean|Number[]" 17281 } 17282 ], 17283 "class": "p5.Shader", 17284 "module": "Lights, Camera", 17285 "submodule": "Shaders" 17286 }, 17287 { 17288 "file": "src/webgl/primitives.js", 17289 "line": 14, 17290 "description": "<p>Draw a plane with given a width and height</p>\n", 17291 "itemtype": "method", 17292 "name": "plane", 17293 "params": [ 17294 { 17295 "name": "width", 17296 "description": "<p>width of the plane</p>\n", 17297 "type": "Number", 17298 "optional": true 17299 }, 17300 { 17301 "name": "height", 17302 "description": "<p>height of the plane</p>\n", 17303 "type": "Number", 17304 "optional": true 17305 }, 17306 { 17307 "name": "detailX", 17308 "description": "<p>Optional number of triangle\n subdivisions in x-dimension</p>\n", 17309 "type": "Integer", 17310 "optional": true 17311 }, 17312 { 17313 "name": "detailY", 17314 "description": "<p>Optional number of triangle\n subdivisions in y-dimension</p>\n", 17315 "type": "Integer", 17316 "optional": true 17317 } 17318 ], 17319 "chainable": 1, 17320 "example": [ 17321 "\n<div>\n<code>
17321\n//draw a plane with width 50 and height 50\nfunction setup() {\n createCanvas(100, 100, WEBGL);\n}\n\nfunction draw() {\n background(200);\n plane(50, 50);\n}\n</code>\n</div>" 17322 ], 17323 "alt": "Nothing displayed on canvas\nRotating interior view of a box with sides that change color.\n3d red and green gradient.\nRotating interior view of a cylinder with sides that change color.\nRotating view of a cylinder with sides that change color.\n3d red and green gradient.\nrotating view of a multi-colored cylinder with concave sides.", 17324 "class": "p5", 17325 "module": "Shape", 17326 "submodule": "3D Primitives" 17327 }, 17328 { 17329 "file": "src/webgl/primitives.js", 17330 "line": 96, 17331 "description": "<p>Draw a box with given width, height and depth</p>\n", 17332 "itemtype": "method", 17333 "name": "box", 17334 "params": [ 17335 { 17336 "name": "width", 17337 "description": "<p>width of the box</p>\n", 17338 "type": "Number", 17339 "optional": true 17340 }, 17341 { 17342 "name": "Height", 17343 "description": "<p>height of the box</p>\n", 17344 "type": "Number", 17345 "optional": true 17346 }, 17347 { 17348 "name": "depth", 17349 "description": "<p>depth of the box</p>\n", 17350 "type": "Number", 17351 "optional": true 17352 }, 17353 { 17354 "name": "detailX", 17355 "description": "<p>Optional number of triangle\n subdivisions in x-dimension</p>\n", 17356 "type": "Integer", 17357 "optional": true 17358 }, 17359 { 17360 "name": "detailY", 17361 "description": "<p>Optional number of triangle\n subdivisions in y-dimension</p>\n", 17362 "type": "Integer", 17363 "optional": true 17364 } 17365 ], 17366 "chainable": 1, 17367 "example": [ 17368 "\n<div>\n<code>\n//draw a spinning box with width, height and depth 200\nfunction setup() {\n createCanvas(100, 100, WEBGL);\n}\n\nfunction draw() {\n background(200);\n rotateX(frameCount * 0.01);\n rotateY(frameCount * 0.01);\n box(50);\n}\n</code>\n</div>" 17369 ], 17370 "class": "p5", 17371 "module": "Shape", 17372 "submodule": "3D Primitives" 17373 }, 17374 { 17375 "file": "src/webgl/primitives.js", 17376 "line": 213, 17377 "description": "<p>Draw a sphere with given radius</p>\n", 17378 "itemtype": "method", 17379 "name": "sphere", 17380 "params": [ 17381 { 17382 "name": "radius", 17383 "description": "<p>radius of circle</p>\n", 17384 "type": "Number", 17385 "optional": true 17386 }, 17387 { 17388 "name": "detailX", 17389 "description": "<p>number of segments,\n the more segments the smoother geometry\n default is 24</p>\n", 17390 "type": "Integer", 17391 "optional": true 17392 }, 17393 { 17394 "name": "detailY", 17395 "description": "<p>number of segments,\n the more segments the smoother geometry\n default is 16</p>\n", 17396 "type": "Integer", 17397 "optional": true 17398 } 17399 ], 17400 "chainable": 1, 17401 "example": [ 17402 "\n<div>\n<code>\n// draw a sphere with radius 200\nfunction setup() {\n createCanvas(100, 100, WEBGL);\n}\n\nfunction draw() {\n background(200);\n sphere(40);\n}\n</code>\n</div>" 17403 ], 17404 "class": "p5", 17405 "module": "Shape", 17406 "submodule": "3D Primitives" 17407 }, 17408 { 17409 "file": "src/webgl/primitives.js", 17410 "line": 391, 17411 "description": "<p>Draw a cylinder with given radius and height</p>\n", 17412 "itemtype": "method", 17413 "name": "cylinder", 17414 "params": [ 17415 { 17416 "name": "radius", 17417 "description": "<p>radius of the surface</p>\n", 17418 "type": "Number", 17419 "optional": true 17420 }, 17421 { 17422 "name": "height", 17423 "description": "<p>height of the cylinder</p>\n", 17424 "type": "Number", 17425 "optional": true 17426 }, 17427 { 17428 "name": "detailX", 17429 "description": "<p>number of segments,\n the more segments the smoother geometry\n default is 24</p>\n", 17430 "type": "Integer", 17431 "optional": true 17432 }, 17433 { 17434 "name": "detailY", 17435 "description": "<p>number of segments in y-dimension,\n the more segments the smoother geometry\n default is 1</p>\n", 17436 "type": "Integer", 17437 "optional": true 17438 }, 17439 { 17440 "name": "bottomCap", 17441 "description": "<p>whether to draw the bottom of the cylinder</p>\n", 17442 "type": "Boolean", 17443 "optional": true 17444 }, 17445 { 17446 "name": "topCap", 17447 "description": "<p>whether to draw the top of the cylinder</p>\n", 17448 "type": "Boolean", 17449 "optional": true 17450 } 17451 ], 17452 "chainable": 1, 17453 "example": [ 17454 "\n<div>\n<code>
17454\n//draw a spinning cylinder with radius 20 and height 50\nfunction setup() {\n createCanvas(100, 100, WEBGL);\n}\n\nfunction draw() {\n background(200);\n rotateX(frameCount * 0.01);\n rotateZ(frameCount * 0.01);\n cylinder(20, 50);\n}\n</code>\n</div>" 17455 ], 17456 "class": "p5", 17457 "module": "Shape", 17458 "submodule": "3D Primitives" 17459 }, 17460 { 17461 "file": "src/webgl/primitives.js", 17462 "line": 482, 17463 "description": "<p>Draw a cone with given radius and height</p>\n", 17464 "itemtype": "method", 17465 "name": "cone", 17466 "params": [ 17467 { 17468 "name": "radius", 17469 "description": "<p>radius of the bottom surface</p>\n", 17470 "type": "Number", 17471 "optional": true 17472 }, 17473 { 17474 "name": "height", 17475 "description": "<p>height of the cone</p>\n", 17476 "type": "Number", 17477 "optional": true 17478 }, 17479 { 17480 "name": "detailX", 17481 "description": "<p>number of segments,\n the more segments the smoother geometry\n default is 24</p>\n", 17482 "type": "Integer", 17483 "optional": true 17484 }, 17485 { 17486 "name": "detailY", 17487 "description": "<p>number of segments,\n the more segments the smoother geometry\n default is 1</p>\n", 17488 "type": "Integer", 17489 "optional": true 17490 }, 17491 { 17492 "name": "cap", 17493 "description": "<p>whether to draw the base of the cone</p>\n", 17494 "type": "Boolean", 17495 "optional": true 17496 } 17497 ], 17498 "chainable": 1, 17499 "example": [ 17500 "\n<div>\n<code>\n//draw a spinning cone with radius 40 and height 70\nfunction setup() {\n createCanvas(100, 100, WEBGL);\n}\n\nfunction draw() {\n background(200);\n rotateX(frameCount * 0.01);\n rotateZ(frameCount * 0.01);\n cone(40, 70);\n}\n</code>\n</div>" 17501 ], 17502 "class": "p5", 17503 "module": "Shape", 17504 "submodule": "3D Primitives" 17505 }, 17506 { 17507 "file": "src/webgl/primitives.js", 17508 "line": 553, 17509 "description": "<p>Draw an ellipsoid with given radius</p>\n", 17510 "itemtype": "method", 17511 "name": "ellipsoid", 17512 "params": [ 17513 { 17514 "name": "radiusx", 17515 "description": "<p>xradius of circle</p>\n", 17516 "type": "Number", 17517 "optional": true 17518 }, 17519 { 17520 "name": "radiusy", 17521 "description": "<p>yradius of circle</p>\n", 17522 "type": "Number", 17523 "optional": true 17524 }, 17525 { 17526 "name": "radiusz", 17527 "description": "<p>zradius of circle</p>\n", 17528 "type": "Number", 17529 "optional": true 17530 }, 17531 { 17532 "name": "detailX", 17533 "description": "<p>number of segments,\n the more segments the smoother geometry\n default is 24. Avoid detail number above\n 150, it may crash the browser.</p>\n", 17534 "type": "Integer", 17535 "optional": true 17536 }, 17537 { 17538 "name": "detailY", 17539 "description": "<p>number of segments,\n the more segments the smoother geometry\n default is 16. Avoid detail number above\n 150, it may crash the browser.</p>\n", 17540 "type": "Integer", 17541 "optional": true 17542 } 17543 ], 17544 "chainable": 1, 17545 "example": [ 17546 "\n<div>\n<code>\n// draw an ellipsoid with radius 20, 30 and 40.\nfunction setup() {\n createCanvas(100, 100, WEBGL);\n}\n\nfunction draw() {\n background(200);\n ellipsoid(20, 30, 40);\n}\n</code>\n</div>" 17547 ], 17548 "class": "p5", 17549 "module": "Shape", 17550 "submodule": "3D Primitives" 17551 }, 17552 { 17553 "file": "src/webgl/primitives.js", 17554 "line": 643, 17555 "description": "<p>Draw a torus with given radius and tube radius</p>\n", 17556 "itemtype": "method", 17557 "name": "torus", 17558 "params": [ 17559 { 17560 "name": "radius", 17561 "description": "<p>radius of the whole ring</p>\n", 17562 "type": "Number", 17563 "optional": true 17564 }, 17565 { 17566 "name": "tubeRadius", 17567 "description": "<p>radius of the tube</p>\n", 17568 "type": "Number", 17569 "optional": true 17570 }, 17571 { 17572 "name": "detailX", 17573 "description": "<p>number of segments in x-dimension,\n the more segments the smoother geometry\n default is 24</p>\n", 17574 "type": "Integer", 17575 "optional": true 17576 }, 17577 { 17578 "name": "detailY", 17579 "description": "<p>number of segments in y-dimension,\n the more segments the smoother geometry\n default is 16</p>\n", 17580 "type": "Integer", 17581 "optional": true 17582 } 17583 ], 17584 "chainable": 1, 17585 "example": [ 17586 "\n<div>\n<code>
17586\n//draw a spinning torus with radius 200 and tube radius 60\nfunction setup() {\n createCanvas(100, 100, WEBGL);\n}\n\nfunction draw() {\n background(200);\n rotateX(frameCount * 0.01);\n rotateY(frameCount * 0.01);\n torus(50, 15);\n}\n</code>\n</div>" 17587 ], 17588 "class": "p5", 17589 "module": "Shape", 17590 "submodule": "3D Primitives" 17591 }, 17592 { 17593 "file": "lib/addons/p5.dom.js", 17594 "line": 40, 17595 "description": "<p>Searches the page for an element with the given ID, class, or tag name (using the '#' or '.'\nprefixes to specify an ID or class respectively, and none for a tag) and returns it as\na p5.Element. If a class or tag name is given with more than 1 element,\nonly the first element will be returned.\nThe DOM node itself can be accessed with .elt.\nReturns null if none found. You can also specify a container to search within.</p>\n", 17596 "itemtype": "method", 17597 "name": "select", 17598 "params": [ 17599 { 17600 "name": "name", 17601 "description": "<p>id, class, or tag name of element to search for</p>\n", 17602 "type": "String" 17603 }, 17604 { 17605 "name": "container", 17606 "description": "<p>id, p5.Element, or\n HTML element to search within</p>\n", 17607 "type": "String|p5.Element|HTMLElement", 17608 "optional": true 17609 } 17610 ], 17611 "return": { 17612 "description": "p5.Element containing node found", 17613 "type": "Object|p5.Element|null" 17614 }, 17615 "example": [ 17616 "\n<div ><code class='norender'>\nfunction setup() {\n createCanvas(100, 100);\n //translates canvas 50px down\n select('canvas').position(100, 100);\n}\n</code></div>\n<div><code class='norender'>\n// these are all valid calls to select()\nvar a = select('#moo');\nvar b = select('#blah', '#myContainer');\nvar c, e;\nif (b) {\n c = select('#foo', b);\n}\nvar d = document.getElementById('beep');\nif (d) {\n e = select('p', d);\n}\n[a, b, c, d, e]; // unused\n</code></div>\n" 17617 ], 17618 "class": "p5.dom", 17619 "module": "p5.dom", 17620 "submodule": "p5.dom" 17621 }, 17622 { 17623 "file": "lib/addons/p5.dom.js", 17624 "line": 107, 17625 "description": "<p>Searches the page for elements with the given class or tag name (using the '.' prefix\nto specify a class and no prefix for a tag) and returns them as p5.Elements\nin an array.\nThe DOM node itself can be accessed with .elt.\nReturns an empty array if none found.\nYou can also specify a container to search within.</p>\n", 17626 "itemtype": "method", 17627 "name": "selectAll", 17628 "params": [ 17629 { 17630 "name": "name", 17631 "description": "<p>class or tag name of elements to search for</p>\n", 17632 "type": "String" 17633 }, 17634 { 17635 "name": "container", 17636 "description": "<p>id, p5.Element, or HTML element to search within</p>\n", 17637 "type": "String", 17638 "optional": true 17639 } 17640 ], 17641 "return": { 17642 "description": "Array of p5.Elements containing nodes found", 17643 "type": "Array" 17644 }, 17645 "example": [ 17646 "\n<div class='norender'><code>\nfunction setup() {\n createButton('btn');\n createButton('2nd btn');\n createButton('3rd btn');\n var buttons = selectAll('button');\n\n for (var i = 0; i < buttons.length; i++) {\n buttons[i].size(100, 100);\n }\n}\n</code></div>\n<div class='norender'><code>\n// these are all valid calls to selectAll()\nvar a = selectAll('.moo');\na = selectAll('div');\na = selectAll('button', '#myContainer');\n\nvar d = select('#container');\na = selectAll('p', d);\n\nvar f = document.getElementById('beep');\na = select('.blah', f);\n\na; // unused\n</code></div>\n" 17647 ], 17648 "class": "p5.dom", 17649 "module": "p5.dom", 17650 "submodule": "p5.dom" 17651 }, 17652 { 17653 "file": "lib/addons/p5.dom.js", 17654 "line": 168, 17655 "description": "<p>Helper function for select and selectAll</p>\n", 17656 "class": "p5.dom", 17657 "module": "p5.dom", 17658 "submodule": "p5.dom" 17659 }, 17660 { 17661 "file": "lib/addons/p5.dom.js", 17662 "line": 184, 17663 "description": "<p>Helper function for getElement and getElements.</p>\n", 17664 "class": "p5.dom", 17665 "module": "p5.dom", 17666 "submodule": "p5.dom" 17667 }, 17668 { 17669 "file": "lib/addons/p5.dom.js", 17670 "line": 218, 17671 "description": "<p>Removes all elements created by p5, except any canvas / graphics\nelements created by createCanvas or createGraphics.\nEvent handlers are removed, and element is removed from the DOM.</p>\n", 17672 "itemtype": "method", 17673 "name": "removeElements", 17674 "example": [ 17675 "\n<div class='norender'><code>\nfunction setup() {\n createCanvas(100, 100);\n createDiv('this is some text');\n createP('this is a paragraph');\n}\nfunction mousePressed() {\n removeElements(); // this will remove the div and p, not canvas\n}\n</code></div>\n" 17676 ], 17677 "class": "p5.dom", 17678 "module": "p5.dom", 17679 "submodule": "p5.dom" 17680 }, 17681 { 17682 "file": "lib/addons/p5.dom.js", 17683 "line": 245, 17684 "description": "<p>Helpers for create methods.</p>\n", 17685 "class": "p5.dom", 17686 "module": "p5.dom", 17687 "submodule": "p5.dom" 17688 }, 17689 { 17690 "file": "lib/addons/p5.dom.js", 17691 "line": 256, 17692 "description": "<p>Creates a <div></div> element in the DOM with given inner HTML.\nAppends to the container node if one is specified, otherwise\nappends to body.</p>\n", 17693 "itemtype": "method", 17694 "name": "createDiv", 17695 "params": [ 17696 { 17697 "name": "html", 17698 "description": "<p>inner HTML for element created</p>\n", 17699 "type": "String", 17700 "optional": true 17701 } 17702 ], 17703 "return": { 17704 "description": "pointer to p5.Element holding created node", 17705 "type": "Object|p5.Element" 17706 }, 17707 "example": [ 17708 "\n<div class='norender'><code>\ncreateDiv('this is some text');\n</code></div>" 17709 ], 17710 "class": "p5.dom", 17711 "module": "p5.dom", 17712 "submodule": "p5.dom" 17713 }, 17714 { 17715 "file": "lib/addons/p5.dom.js", 17716 "line": 270, 17717 "description": "<p>Creates a <p></p> element in the DOM with given inner HTML. Used\nfor paragraph length text.\nAppends to the container node if one is specified, otherwise\nappends to body.</p>\n", 17718 "itemtype": "method", 17719 "name": "createP", 17720 "params": [ 17721 { 17722 "name": "html", 17723 "description": "<p>inner HTML for element created</p>\n", 17724 "type": "String", 17725 "optional": true 17726 } 17727 ], 17728 "return": { 17729 "description": "pointer to p5.Element holding created node", 17730 "type": "Object|p5.Element" 17731 }, 17732 "example": [ 17733 "\n<div class='norender'><code>\ncreateP('this is some text');\n</code></div>" 17734 ], 17735 "class": "p5.dom", 17736 "module": "p5.dom", 17737 "submodule": "p5.dom" 17738 }, 17739 { 17740 "file": "lib/addons/p5.dom.js", 17741 "line": 285, 17742 "description": "<p>Creates a <span></span> element in the DOM with given inner HTML.\nAppends to the container node if one is specified, otherwise\nappends to body.</p>\n", 17743 "itemtype": "method", 17744 "name": "createSpan", 17745 "params": [ 17746 { 17747 "name": "html", 17748 "description": "<p>inner HTML for element created</p>\n", 17749 "type": "String", 17750 "optional": true 17751 } 17752 ], 17753 "return": { 17754 "description": "pointer to p5.Element holding created node", 17755 "type": "Object|p5.Element" 17756 }, 17757 "example": [ 17758 "\n<div class='norender'><code>\ncreateSpan('this is some text');\n</code></div>" 17759 ], 17760 "class": "p5.dom", 17761 "module": "p5.dom", 17762 "submodule": "p5.dom" 17763 }, 17764 { 17765 "file": "lib/addons/p5.dom.js", 17766 "line": 308, 17767 "description": "<p>Creates an <img> element in the DOM with given src and\nalternate text.\nAppends to the container node if one is specified, otherwise\nappends to body.</p>\n", 17768 "itemtype": "method", 17769 "name": "createImg", 17770 "params": [ 17771 { 17772 "name": "src", 17773 "description": "<p>src path or url for image</p>\n", 17774 "type": "String" 17775 }, 17776 { 17777 "name": "alt", 17778 "description": "<p>alternate text to be used if image does not load</p>\n", 17779 "type": "String", 17780 "optional": true 17781 }, 17782 { 17783 "name": "successCallback", 17784 "description": "<p>callback to be called once image data is loaded</p>\n", 17785 "type": "Function", 17786 "optional": true 17787 } 17788 ], 17789 "return": { 17790 "description": "pointer to p5.Element holding created node", 17791 "type": "Object|p5.Element" 17792 }, 17793 "example": [ 17794 "\n<div class='norender'><code>\ncreateImg('http://p5js.org/img/asterisk-01.png');\n</code></div>" 17795 ], 17796 "class": "p5.dom", 17797 "module": "p5.dom", 17798 "submodule": "p5.dom" 17799 }, 17800 { 17801 "file": "lib/addons/p5.dom.js", 17802 "line": 351, 17803 "description": "<p>Creates an <a></a> element in the DOM for including a hyperlink.\nAppends to the container node if one is specified, otherwise\nappends to body.</p>\n", 17804 "itemtype": "method", 17805 "name": "createA", 17806 "params": [ 17807 { 17808 "name": "href", 17809 "description": "<p>url of page to link to</p>\n", 17810 "type": "String" 17811 }, 17812 { 17813 "name": "html", 17814 "description": "<p>inner html of link element to display</p>\n", 17815 "type": "String" 17816 }, 17817 { 17818 "name": "target", 17819 "description": "<p>target where new link should open,\n could be _blank, _self, _parent, _top.</p>\n", 17820 "type": "String", 17821 "optional": true 17822 } 17823 ], 17824 "return": { 17825 "description": "pointer to p5.Element holding created node", 17826 "type": "Object|p5.Element" 17827 }, 17828 "example": [ 17829 "\n<div class='norender'><code>\ncreateA('http://p5js.org/', 'this is a link');\n</code></div>" 17830 ], 17831 "class": "p5.dom", 17832 "module": "p5.dom", 17833 "submodule": "p5.dom" 17834 }, 17835 { 17836 "file": "lib/addons/p5.dom.js", 17837 "line": 376, 17838 "class": "p5.dom", 17839 "module": "p5.dom", 17840 "submodule": "p5.dom" 17841 }, 17842 { 17843 "file": "lib/addons/p5.dom.js", 17844 "line": 378, 17845 "description": "<p>Creates a slider <input></input> element in the DOM.\nUse .size() to set the display length of the slider.\nAppends to the container node if one is specified, otherwise\nappends to body.</p>\n", 17846 "itemtype": "method", 17847 "name": "createSlider", 17848 "params": [ 17849 { 17850 "name": "min", 17851 "description": "<p>minimum value of the slider</p>\n", 17852 "type": "Number" 17853 }, 17854 { 17855 "name": "max", 17856 "description": "<p>maximum value of the slider</p>\n", 17857 "type": "Number" 17858 }, 17859 { 17860 "name": "value", 17861 "description": "<p>default value of the slider</p>\n", 17862 "type": "Number", 17863 "optional": true 17864 }, 17865 { 17866 "name": "step", 17867 "description": "<p>step size for each tick of the slider (if step is set to 0, the slider will move continuously from the minimum to the maximum value)</p>\n", 17868 "type": "Number", 17869 "optional": true 17870 } 17871 ], 17872 "return": { 17873 "description": "pointer to p5.Element holding created node", 17874 "type": "Object|p5.Element" 17875 }, 17876 "example": [ 17877 "\n<div><code>\nvar slider;\nfunction setup() {\n slider = createSlider(0, 255, 100);\n slider.position(10, 10);\n slider.style('width', '80px');\n}\n\nfunction draw() {\n var val = slider.value();\n background(val);\n}\n</code></div>\n\n<div><code>\nvar slider;\nfunction setup() {\n colorMode(HSB);\n slider = createSlider(0, 360, 60, 40);\n slider.position(10, 10);\n slider.style('width', '80px');\n}\n\nfunction draw() {\n var val = slider.value();
17877\n background(val, 100, 100, 1);\n}\n</code></div>" 17878 ], 17879 "class": "p5.dom", 17880 "module": "p5.dom", 17881 "submodule": "p5.dom" 17882 }, 17883 { 17884 "file": "lib/addons/p5.dom.js", 17885 "line": 435, 17886 "description": "<p>Creates a <button></button> element in the DOM.\nUse .size() to set the display size of the button.\nUse .mousePressed() to specify behavior on press.\nAppends to the container node if one is specified, otherwise\nappends to body.</p>\n", 17887 "itemtype": "method", 17888 "name": "createButton", 17889 "params": [ 17890 { 17891 "name": "label", 17892 "description": "<p>label displayed on the button</p>\n", 17893 "type": "String" 17894 }, 17895 { 17896 "name": "value", 17897 "description": "<p>value of the button</p>\n", 17898 "type": "String", 17899 "optional": true 17900 } 17901 ], 17902 "return": { 17903 "description": "pointer to p5.Element holding created node", 17904 "type": "Object|p5.Element" 17905 }, 17906 "example": [ 17907 "\n<div class='norender'><code>\nvar button;\nfunction setup() {\n createCanvas(100, 100);\n background(0);\n button = createButton('click me');\n button.position(19, 19);\n button.mousePressed(changeBG);\n}\n\nfunction changeBG() {\n var val = random(255);\n background(val);\n}\n</code></div>" 17908 ], 17909 "class": "p5.dom", 17910 "module": "p5.dom", 17911 "submodule": "p5.dom" 17912 }, 17913 { 17914 "file": "lib/addons/p5.dom.js", 17915 "line": 471, 17916 "description": "<p>Creates a checkbox <input></input> element in the DOM.\nCalling .checked() on a checkbox returns if it is checked or not</p>\n", 17917 "itemtype": "method", 17918 "name": "createCheckbox", 17919 "params": [ 17920 { 17921 "name": "label", 17922 "description": "<p>label displayed after checkbox</p>\n", 17923 "type": "String", 17924 "optional": true 17925 }, 17926 { 17927 "name": "value", 17928 "description": "<p>value of the checkbox; checked is true, unchecked is false</p>\n", 17929 "type": "Boolean", 17930 "optional": true 17931 } 17932 ], 17933 "return": { 17934 "description": "pointer to p5.Element holding created node", 17935 "type": "Object|p5.Element" 17936 }, 17937 "example": [ 17938 "\n<div class='norender'><code>\nvar checkbox;\n\nfunction setup() {\n checkbox = createCheckbox('label', false);\n checkbox.changed(myCheckedEvent);\n}\n\nfunction myCheckedEvent() {\n if (this.checked()) {\n console.log('Checking!');\n } else {\n console.log('Unchecking!');\n }\n}\n</code></div>" 17939 ], 17940 "class": "p5.dom", 17941 "module": "p5.dom", 17942 "submodule": "p5.dom" 17943 }, 17944 { 17945 "file": "lib/addons/p5.dom.js", 17946 "line": 539, 17947 "description": "<p>Creates a dropdown menu <select></select> element in the DOM.\nIt also helps to assign select-box methods to p5.Element when selecting existing select box</p>\n", 17948 "itemtype": "method", 17949 "name": "createSelect", 17950 "return": { 17951 "description": "", 17952 "type": "p5.Element" 17953 }, 17954 "example": [ 17955 "\n<div><code>\nvar sel;\n\nfunction setup() {\n textAlign(CENTER);\n background(200);\n sel = createSelect();\n sel.position(10, 10);\n sel.option('pear');\n sel.option('kiwi');\n sel.option('grape');\n sel.changed(mySelectEvent);\n}\n\nfunction mySelectEvent() {\n var item = sel.value();\n background(200);\n text('it is a' + item + '!', 50, 50);\n}\n</code></div>" 17956 ], 17957 "class": "p5.dom", 17958 "module": "p5.dom", 17959 "submodule": "p5.dom", 17960 "overloads": [ 17961 { 17962 "line": 539, 17963 "params": [ 17964 { 17965 "name": "multiple", 17966 "description": "<p>true if dropdown should support multiple selections</p>\n", 17967 "type": "Boolean", 17968 "optional": true 17969 } 17970 ], 17971 "return": { 17972 "description": "", 17973 "type": "p5.Element" 17974 } 17975 }, 17976 { 17977 "line": 567, 17978 "params": [ 17979 { 17980 "name": "existing", 17981 "description": "<p>DOM select element</p>\n", 17982 "type": "Object" 17983 } 17984 ], 17985 "return": { 17986 "description": "", 17987 "type": "p5.Element" 17988 } 17989 } 17990 ] 17991 }, 17992 { 17993 "file": "lib/addons/p5.dom.js", 17994 "line": 643, 17995 "description": "<p>Creates a radio button <input></input> element in the DOM.\nThe .option() method can be used to set options for the radio after it is\ncreated. The .value() method will return the currently selected option.</p>\n", 17996 "itemtype": "method", 17997 "name": "createRadio", 17998 "params": [ 17999 { 18000 "name": "divId", 18001 "description": "<p>the id and name of the created div and input field respectively</p>\n", 18002 "type": "String", 18003 "optional": true 18004 } 18005 ], 18006 "return": { 18007 "description": "pointer to p5.Element holding created node", 18008 "type": "Object|p5.Element" 18009 }, 18010 "example": [ 18011 "\n<div><code>\nvar radio;\n\nfunction setup() {\n radio = createRadio();\n radio.option('black');\n radio.option('white');\n radio.option('gray');\n radio.style('width', '60px');\n textAlign(CENTER);\n fill(255, 0, 0);\n}
18011\n\nfunction draw() {\n var val = radio.value();\n background(val);\n text(val, width / 2, height / 2);\n}\n</code></div>\n<div><code>\nvar radio;\n\nfunction setup() {\n radio = createRadio();\n radio.option('apple', 1);\n radio.option('bread', 2);\n radio.option('juice', 3);\n radio.style('width', '60px');\n textAlign(CENTER);\n}\n\nfunction draw() {\n background(200);\n var val = radio.value();\n if (val) {\n text('item cost is $' + val, width / 2, height / 2);\n }\n}\n</code></div>" 18012 ], 18013 "class": "p5.dom", 18014 "module": "p5.dom", 18015 "submodule": "p5.dom" 18016 }, 18017 { 18018 "file": "lib/addons/p5.dom.js", 18019 "line": 781, 18020 "description": "<p>Creates an <input></input> element in the DOM for text input.\nUse .size() to set the display length of the box.\nAppends to the container node if one is specified, otherwise\nappends to body.</p>\n", 18021 "itemtype": "method", 18022 "name": "createInput", 18023 "params": [ 18024 { 18025 "name": "value", 18026 "description": "<p>default value of the input box</p>\n", 18027 "type": "String", 18028 "optional": true 18029 }, 18030 { 18031 "name": "type", 18032 "description": "<p>type of text, ie text, password etc. Defaults to text</p>\n", 18033 "type": "String", 18034 "optional": true 18035 } 18036 ], 18037 "return": { 18038 "description": "pointer to p5.Element holding created node", 18039 "type": "Object|p5.Element" 18040 }, 18041 "example": [ 18042 "\n<div class='norender'><code>\nfunction setup() {\n var inp = createInput('');\n inp.input(myInputEvent);\n}\n\nfunction myInputEvent() {\n console.log('you are typing: ', this.value());\n}\n</code></div>" 18043 ], 18044 "class": "p5.dom", 18045 "module": "p5.dom", 18046 "submodule": "p5.dom" 18047 }, 18048 { 18049 "file": "lib/addons/p5.dom.js", 18050 "line": 811, 18051 "description": "<p>Creates an <input></input> element in the DOM of type 'file'.\nThis allows users to select local files for use in a sketch.</p>\n", 18052 "itemtype": "method", 18053 "name": "createFileInput", 18054 "params": [ 18055 { 18056 "name": "callback", 18057 "description": "<p>callback function for when a file loaded</p>\n", 18058 "type": "Function", 18059 "optional": true 18060 }, 18061 { 18062 "name": "multiple", 18063 "description": "<p>optional to allow multiple files selected</p>\n", 18064 "type": "String", 18065 "optional": true 18066 } 18067 ], 18068 "return": { 18069 "description": "pointer to p5.Element holding created DOM element", 18070 "type": "Object|p5.Element" 18071 }, 18072 "example": [ 18073 "\nvar input;\nvar img;\n\nfunction setup() {\n input = createFileInput(handleFile);\n input.position(0, 0);\n}\n\nfunction draw() {\n if (img) {\n image(img, 0, 0, width, height);\n }\n}\n\nfunction handleFile(file) {\n print(file);\n if (file.type === 'image') {\n img = createImg(file.data);\n img.hide();\n }\n}" 18074 ], 18075 "class": "p5.dom", 18076 "module": "p5.dom", 18077 "submodule": "p5.dom" 18078 }, 18079 { 18080 "file": "lib/addons/p5.dom.js", 18081 "line": 897, 18082 "class": "p5.dom", 18083 "module": "p5.dom", 18084 "submodule": "p5.dom" 18085 }, 18086 { 18087 "file": "lib/addons/p5.dom.js", 18088 "line": 934, 18089 "description": "<p>Creates an HTML5 <video> element in the DOM for simple playback\nof audio/video. Shown by default, can be hidden with .hide()\nand drawn into canvas using video(). Appends to the container\nnode if one is specified, otherwise appends to body. The first parameter\ncan be either a single str
18089ing path to a video file, or an array of string\npaths to different formats of the same video. This is useful for ensuring\nthat your video can play across different browsers, as each supports\ndifferent formats. See <a href='https://developer.mozilla.org/en-US/docs/Web/HTML/Supported_media_formats'>this\npage</a> for further information about supported formats.</p>\n", 18090 "itemtype": "method", 18091 "name": "createVideo", 18092 "params": [ 18093 { 18094 "name": "src", 18095 "description": "<p>path to a video file, or array of paths for\n supporting different browsers</p>\n", 18096 "type": "String|Array" 18097 }, 18098 { 18099 "name": "callback", 18100 "description": "<p>callback function to be called upon\n '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", 18101 "type": "Object", 18102 "optional": true 18103 } 18104 ], 18105 "return": { 18106 "description": "pointer to video p5.Element", 18107 "type": "p5.MediaElement|p5.Element" 18108 }, 18109 "example": [ 18110 "\n<div><code>\nvar vid;\nfunction setup() {\n vid = createVideo(['small.mp4', 'small.ogv', 'small.webm'], vidLoad);\n}\n\n// This function is called when the video loads\nfunction vidLoad() {\n vid.play();\n}\n</code></div>" 18111 ], 18112 "class": "p5.dom", 18113 "module": "p5.dom", 18114 "submodule": "p5.dom" 18115 }, 18116 { 18117 "file": "lib/addons/p5.dom.js", 18118 "line": 973, 18119 "class": "p5.dom", 18120 "module": "p5.dom", 18121 "submodule": "p5.dom" 18122 }, 18123 { 18124 "file": "lib/addons/p5.dom.js", 18125 "line": 975, 18126 "description": "<p>Creates a hidden HTML5 <audio> element in the DOM for simple audio\nplayback. Appends to the container node if one is specified,\notherwise appends to body. The first parameter\ncan be either a single string path to a audio file, or an array of string\npaths to different formats of the same audio. This is useful for ensuring\nthat your audio can play across different browsers, as each supports\ndifferent formats. See <a href='https://developer.mozilla.org/en-US/docs/Web/HTML/Supported_media_formats'>this\npage for further information about supported formats</a>.</p>\n", 18127 "itemtype": "method", 18128 "name": "createAudio", 18129 "params": [ 18130 { 18131 "name": "src", 18132 "description": "<p>path to an audio file, or array of paths\n for supporting different browsers</p>\n", 18133 "type": "String|String[]", 18134 "optional": true 18135 }, 18136 { 18137 "name": "callback", 18138 "description": "<p>callback function to be called upon\n '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", 18139 "type": "Object", 18140 "optional": true 18141 } 18142 ], 18143 "return": { 18144 "description": "pointer to audio p5.Element /**", 18145 "type": "p5.MediaElement|p5.Element" 18146 }, 18147 "example": [ 18148 "\n<div><code>\nvar ele;\nfunction setup() {\n ele = createAudio('assets/beat.mp3');
18148\n\n // here we set the element to autoplay\n // The element will play as soon\n // as it is able to do so.\n ele.autoplay(true);\n}\n</code></div>" 18149 ], 18150 "class": "p5.dom", 18151 "module": "p5.dom", 18152 "submodule": "p5.dom" 18153 }, 18154 { 18155 "file": "lib/addons/p5.dom.js", 18156 "line": 1013, 18157 "class": "p5.dom", 18158 "module": "p5.dom", 18159 "submodule": "p5.dom" 18160 }, 18161 { 18162 "file": "lib/addons/p5.dom.js", 18163 "line": 1048, 18164 "description": "<p>Creates a new HTML5 <video> element that contains the audio/video\nfeed from a webcam. The element is separate from the canvas and is\ndisplayed by default. The element can be hidden using .hide(). The feed\ncan be drawn onto the canvas using image().</p>\n<p>More specific properties of the feed can be passing in a Constraints object.\nSee the\n<a href='http://w3c.github.io/mediacapture-main/getusermedia.html#media-track-constraints'> W3C\nspec</a> for possible properties. Note that not all of these are supported\nby all browsers.</p>\n<p>Security note: A new browser security specification requires that getUserMedia,\nwhich is behind createCapture(), only works when you're running the code locally,\nor on HTTPS. Learn more <a href='http://stackoverflow.com/questions/34197653/getusermedia-in-chrome-47-without-using-https'>here</a>\nand <a href='https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia'>here</a>.</p>", 18165 "itemtype": "method", 18166 "name": "createCapture", 18167 "params": [ 18168 { 18169 "name": "type", 18170 "description": "<p>type of capture, either VIDEO or\n AUDIO if none specified, default both,\n or a Constraints object</p>\n", 18171 "type": "String|Constant|Object" 18172 }, 18173 { 18174 "name": "callback", 18175 "description": "<p>function to be called once\n stream has loaded</p>\n", 18176 "type": "Function" 18177 } 18178 ], 18179 "return": { 18180 "description": "capture video p5.Element", 18181 "type": "Object|p5.Element" 18182 }, 18183 "example": [ 18184 "\n<div class='norender notest'><code>\nvar capture;\n\nfunction setup() {\n createCanvas(480, 480);\n capture = createCapture(VIDEO);\n capture.hide();\n}\n\nfunction draw() {\n image(capture, 0, 0, width, width * capture.height / capture.width);\n filter(INVERT);\n}\n</code></div>\n<div class='norender notest'><code>\nfunction setup() {\n createCanvas(480, 120);\n var constraints = {\n video: {\n mandatory: {\n minWidth: 1280,\n minHeight: 720\n },\n optional: [{ maxFrameRate: 10 }]\n },\n audio: true\n };\n createCapture(constraints, function(stream) {\n console.log(stream);\n });\n}\n</code></div>" 18185 ], 18186 "class": "p5.dom", 18187 "module": "p5.dom", 18188 "submodule": "p5.dom" 18189 }, 18190 { 18191 "file": "lib/addons/p5.dom.js", 18192 "line": 1167, 18193 "description": "<p>Creates element with given tag in the DOM with given content.\nAppends to the container node if one is specified, otherwise\nappends to body.</p>\n", 18194 "itemtype": "method", 18195 "name": "createElement", 18196 "params": [ 18197 { 18198 "name": "tag", 18199 "description": "<p>tag for the new element</p>\n", 18200 "type": "String" 18201 }, 18202 { 18203 "name": "content", 18204 "description": "<p>html content to be inserted into the element</p>\n", 18205 "type": "String", 18206 "optional": true 18207 } 18208 ], 18209 "return": { 18210 "description": "pointer to p5.Element holding created node", 18211 "type": "Object|p5.Element" 18212 }, 18213 "example": [ 18214 "\n<div class='norender'><code>\ncreateElement('h2', 'im an h2 p5.element!');\n</code></div>" 18215 ], 18216 "class": "p5.dom", 18217 "module": "p5.dom", 18218 "submodule": "p5.dom" 18219 }, 18220 { 18221 "file": "lib/addons/p5.dom.js", 18222 "line": 1193, 18223 "description": "<p>Adds specified class to the element.</p>\n", 18224 "itemtype": "method", 18225 "name": "addClass", 18226 "params": [ 18227 { 18228 "name": "class", 18229 "description": "<p>name of class to add</p>\n", 18230 "type": "String" 18231 } 18232 ], 18233 "return": { 18234 "description": "", 18235 "type": "Object|p5.Element" 18236 }, 18237 "example": [ 18238 "\n <div class='norender'><code>\n var div = createDiv('div');\n div.addClass('myClass');\n </code></div>" 18239 ], 18240 "class": "p5.Element", 18241 "module": "p5.dom", 18242 "submodule": "p5.dom" 18243 }, 18244 { 18245 "file": "lib/addons/p5.dom.js", 18246 "line": 1220, 18247 "description": "<p>Removes specified class from the element.</p>\n", 18248 "itemtype": "method", 18249 "name": "removeClass", 18250 "params": [ 18251 { 18252 "name": "class", 18253 "description": "<p>name of class to remove</p>\n", 18254 "type": "String" 18255 } 18256 ], 18257 "return": { 18258 "description": "* @example\n <div class='norender'><code>\n // In this example, a class is set when the div is created\n // and removed when mouse is pressed. This could link up\n // with a CSS style rule to toggle style properties.\nvar div;\nfunction setup() {\n div = createDiv('div');\n div.addClass('myClass');\n }\nfunction mousePressed() {\n div.removeClass('myClass');\n }\n </code></div>", 18259 "type": "Object|p5.Element" 18260 }, 18261 "class": "p5.Element", 18262 "module": "p5.dom", 18263 "submodule": "p5.dom" 18264 }, 18265 { 18266 "file": "lib/addons/p5.dom.js", 18267 "line": 1251, 18268 "description": "<p>Attaches the element as a child to the parent specified.\n Accepts either a string ID, DOM node, or p5.Element.\n If no argument is specified, an array of children DOM nodes is returned.</p>\n", 18269 "itemtype": "method", 18270 "name": "child", 18271 "params": [ 18272 { 18273 "name": "child", 18274 "description": "<p>the ID, DOM node, or p5.Element\n to add to the current element</p>\n", 18275 "type": "String|Object|p5.Element", 18276 "optional": true 18277 } 18278 ], 18279 "return": { 18280 "description": "", 18281 "type": "p5.Element" 18282 }, 18283 "example": [ 18284 "\n <div class='norender'><code>\n var div0 = createDiv('this is the parent');\n var div1 = createDiv('this is the child');\n div0.child(div1); // use p5.Element\n </code></div>\n <div class='norender'><code>\n var div0 = createDiv('this is the parent');\n var div1 = createDiv('this is the child');\n div1.id('apples');\n div0.child('apples'); // use id\n </code></div>\n <div class='norender notest'><code>\n var div0 = createDiv('this is the parent');\n var elt = document.getElementById('myChildDiv');\n div0.child(elt);
18284 // use element from page\n </code></div>" 18285 ], 18286 "class": "p5.Element", 18287 "module": "p5.dom", 18288 "submodule": "p5.dom" 18289 }, 18290 { 18291 "file": "lib/addons/p5.dom.js", 18292 "line": 1295, 18293 "description": "<p>Centers a p5 Element either vertically, horizontally,\nor both, relative to its parent or according to\nthe body if the Element has no parent. If no argument is passed\nthe Element is aligned both vertically and horizontally.</p>\n", 18294 "itemtype": "method", 18295 "name": "center", 18296 "params": [ 18297 { 18298 "name": "align", 18299 "description": "<p>passing 'vertical', 'horizontal' aligns element accordingly</p>\n", 18300 "type": "String", 18301 "optional": true 18302 } 18303 ], 18304 "return": { 18305 "description": "pointer to p5.Element", 18306 "type": "Object|p5.Element" 18307 }, 18308 "example": [ 18309 "\n<div><code>\nfunction setup() {\n var div = createDiv('').size(10, 10);\n div.style('background-color', 'orange');\n div.center();\n}\n</code></div>" 18310 ], 18311 "class": "p5.Element", 18312 "module": "p5.dom", 18313 "submodule": "p5.dom" 18314 }, 18315 { 18316 "file": "lib/addons/p5.dom.js", 18317 "line": 1348, 18318 "description": "<p>If an argument is given, sets the inner HTML of the element,\n replacing any existing html. If true is included as a second\n argument, html is appended instead of replacing existing html.\n If no arguments are given, returns\n the inner HTML of the element.</p>\n", 18319 "itemtype": "method", 18320 "name": "html", 18321 "params": [ 18322 { 18323 "name": "html", 18324 "description": "<p>the HTML to be placed inside the element</p>\n", 18325 "type": "String", 18326 "optional": true 18327 }, 18328 { 18329 "name": "append", 18330 "description": "<p>whether to append HTML to existing</p>\n", 18331 "type": "Boolean", 18332 "optional": true 18333 } 18334 ], 18335 "return": { 18336 "description": "", 18337 "type": "Object|p5.Element|String" 18338 }, 18339 "example": [ 18340 "\n <div class='norender'><code>\n var div = createDiv('').size(100, 100);\n div.html('hi');\n </code></div>\n <div class='norender'><code>\n var div = createDiv('Hello ').size(100, 100);\n div.html('World', true);\n </code></div>" 18341 ], 18342 "class": "p5.Element", 18343 "module": "p5.dom", 18344 "submodule": "p5.dom" 18345 }, 18346 { 18347 "file": "lib/addons/p5.dom.js", 18348 "line": 1383, 18349 "description": "<p>Sets the position of the element relative to (0, 0) of the\n window. Essentially, set
18349s position:absolute and left and top\n properties of style. If no arguments given returns the x and y position\n of the element in an object.</p>\n", 18350 "itemtype": "method", 18351 "name": "position", 18352 "params": [ 18353 { 18354 "name": "x", 18355 "description": "<p>x-position relative to upper left of window</p>\n", 18356 "type": "Number", 18357 "optional": true 18358 }, 18359 { 18360 "name": "y", 18361 "description": "<p>y-position relative to upper left of window</p>\n", 18362 "type": "Number", 18363 "optional": true 18364 } 18365 ], 18366 "return": { 18367 "description": "", 18368 "type": "Object|p5.Element" 18369 }, 18370 "example": [ 18371 "\n <div><code class='norender'>\n function setup() {\n var cnv = createCanvas(100, 100);\n // positions canvas 50px to the right and 100px\n // below upper left corner of the window\n cnv.position(50, 100);\n }\n </code></div>" 18372 ], 18373 "class": "p5.Element", 18374 "module": "p5.dom", 18375 "submodule": "p5.dom" 18376 }, 18377 { 18378 "file": "lib/addons/p5.dom.js", 18379 "line": 1473, 18380 "description": "<p>Sets the given style (css) property (1st arg) of the element with the\ngiven value (2nd arg). If a single argument is given, .style()\nreturns the value of the given property; however, if the single argument\nis given in css syntax ('text-align:center'), .style() sets the css\nappropriatly. .style() also handles 2d and 3d css transforms. If\nthe 1st arg is 'rotate', 'translate', or 'position', the following arguments\naccept Numbers as values. ('translate', 10, 100, 50);</p>\n", 18381 "itemtype": "method", 18382 "name": "style", 18383 "params": [ 18384 { 18385 "name": "property", 18386 "description": "<p>property to be set</p>\n", 18387 "type": "String" 18388 }, 18389 { 18390 "name": "value", 18391 "description": "<p>value to assign to property (only String|Number for rotate/translate)</p>\n", 18392 "type": "String|Number|p5.Color", 18393 "optional": true 18394 }, 18395 { 18396 "name": "value2", 18397 "description": "<p>position can take a 2nd value</p>\n", 18398 "type": "String|Number|p5.Color", 18399 "optional": true 18400 }, 18401 { 18402 "name": "value3", 18403 "description": "<p>translate can take a 2nd & 3rd value</p>\n", 18404 "type": "String|Number|p5.Color", 18405 "optional": true 18406 } 18407 ], 18408 "return": { 18409 "description": "value of property, if no value is specified\nor p5.Element", 18410 "type": "String|Object|p5.Element" 18411 }, 18412 "example": [ 18413 "\n<div><code class='norender'>\nvar myDiv = createDiv('I like pandas.');\nmyDiv.style('font-size', '18px');\nmyDiv.style('color', '#ff0000');\n</code></div>\n<div><code class='norender'>\nvar col = color(25, 23, 200, 50);\nvar button = createButton('button');\nbutton.style('background-color', col);\nbutton.position(10, 10);\n</code></div>\n<div><code class='norender'>\nvar myDiv = createDiv('I like lizards.');\nmyDiv.style('position', 20, 20);\nmyDiv.style('rotate', 45);\n</code></div>\n<div><code class='norender'>\nvar myDiv;\nfunction setup() {\n background(200);\n myDiv = createDiv('I like gray.');\n myDiv.position(20, 20);\n}\n\nfunction draw() {\n myDiv.style('font-size', mouseX + 'px');\n}\n</code></div>" 18414 ], 18415 "class": "p5.Element", 18416 "module": "p5.dom", 18417 "submodule": "p5.dom" 18418 }, 18419 { 18420 "file": "lib/addons/p5.dom.js", 18421 "line": 1570, 18422 "description": "<p>Adds a new attribute or changes the value of an existing attribute\n on the specified element. If no value is specified, returns the\n value of the given attribute, or null if attribute is not set.</p>\n", 18423 "itemtype": "method", 18424 "name": "attribute", 18425 "params": [ 18426 { 18427 "name": "attr", 18428 "description": "<p>attribute to set</p>\n", 18429 "type": "String" 18430 }, 18431 { 18432 "name": "value", 18433 "description": "<p>value to assign to attribute</p>\n", 18434 "type": "String", 18435 "optional": true 18436 } 18437 ], 18438 "return": { 18439 "description": "value of attribute, if no value is\n specified or p5.Element", 18440 "type": "String|Object|p5.Element" 18441 }, 18442 "example": [ 18443 "\n <div class='norender'><code>\n var myDiv = createDiv('I like pandas.');\n myDiv.attribute('align', 'center');\n </code></div>" 18444 ], 18445 "class": "p5.Element", 18446 "module": "p5.dom", 18447 "submodule": "p5.dom" 18448 }, 18449 { 18450 "file": "lib/addons/p5.dom.js", 18451 "line": 1610, 18452 "description": "<p>Removes an attribute on the specified element.</p>\n", 18453 "itemtype": "method", 18454 "name": "removeAttribute", 18455 "params": [ 18456 { 18457 "name": "attr", 18458 "description": "<p>attribute to remove</p>\n", 18459 "type": "String" 18460 } 18461 ], 18462 "return": { 18463 "description": "", 18464 "type": "Object|p5.Element" 18465 }, 18466 "example": [ 18467 "\n <div><code>\n var button;\n var checkbox;\nfunction setup() {\n checkbox = createCheckbox('enable', true);\n checkbox.changed(enableButton);\n button = createButton('button');\n button.position(10, 10);\n }\nfunction enableButton() {\n if (this.checked()) {\n // Re-enable the button\n button.removeAttribute('disabled');\n } else {\n // Disable the button\n button.attribute('disabled', '');\n }\n }\n </code></div>" 18468 ], 18469 "class": "p5.Element", 18470 "module": "p5.dom", 18471 "submodule": "p5.dom" 18472 }, 18473 { 18474 "file": "lib/addons/p5.dom.js", 18475 "line": 1655, 18476 "description": "<p>Either returns the value of the element if no arguments\ngiven, or sets the value of the element.</p>\n", 18477 "itemtype": "method", 18478 "name": "value", 18479 "params": [ 18480 { 18481 "name": "value", 18482 "description": "", 18483 "type": "String|Number", 18484 "optional": true 18485 } 18486 ], 18487 "return": { 18488 "description": "value of element if no value is specified or p5.Element", 18489 "type": "String|Object|p5.Element" 18490 }, 18491 "example": [ 18492 "\n<div class='norender'><code>\n// gets the value\nvar inp;\nfunction setup() {\n inp = createInput('');\n}
18492\n\nfunction mousePressed() {\n print(inp.value());\n}\n</code></div>\n<div class='norender'><code>\n// sets the value\nvar inp;\nfunction setup() {\n inp = createInput('myValue');\n}\n\nfunction mousePressed() {\n inp.value('myValue');\n}\n</code></div>" 18493 ], 18494 "class": "p5.Element", 18495 "module": "p5.dom", 18496 "submodule": "p5.dom" 18497 }, 18498 { 18499 "file": "lib/addons/p5.dom.js", 18500 "line": 1697, 18501 "description": "<p>Shows the current element. Essentially, setting display:block for the style.</p>\n", 18502 "itemtype": "method", 18503 "name": "show", 18504 "return": { 18505 "description": "", 18506 "type": "Object|p5.Element" 18507 }, 18508 "example": [ 18509 "\n <div class='norender'><code>\n var div = createDiv('div');\n div.style('display', 'none');\n div.show(); // turns display to block\n </code></div>" 18510 ], 18511 "class": "p5.Element", 18512 "module": "p5.dom", 18513 "submodule": "p5.dom" 18514 }, 18515 { 18516 "file": "lib/addons/p5.dom.js", 18517 "line": 1715, 18518 "description": "<p>Hides the current element. Essentially, setting display:none for the style.</p>\n", 18519 "itemtype": "method", 18520 "name": "hide", 18521 "return": { 18522 "description": "", 18523 "type": "Object|p5.Element" 18524 }, 18525 "example": [ 18526 "\n<div class='norender'><code>\nvar div = createDiv('this is a div');\ndiv.hide();\n</code></div>" 18527 ], 18528 "class": "p5.Element", 18529 "module": "p5.dom", 18530 "submodule": "p5.dom" 18531 }, 18532 { 18533 "file": "lib/addons/p5.dom.js", 18534 "line": 1731, 18535 "description": "<p>Sets the width and height of the element. AUTO can be used to\n only adjust one dimension. If no arguments given returns the width and height\n of the element in an object.</p>\n", 18536 "itemtype": "method", 18537 "name": "size", 18538 "params": [ 18539 { 18540 "name": "w", 18541 "description": "<p>width of the element, either AUTO, or a number</p>\n", 18542 "type": "Number|Constant", 18543 "optional": true 18544 }, 18545 { 18546 "name": "h", 18547 "description": "<p>height of the element, either AUTO, or a number</p>\n", 18548 "type": "Number|Constant", 18549 "optional": true 18550 } 18551 ], 18552 "return": { 18553 "description": "", 18554 "type": "Object|p5.Element" 18555 }, 18556 "example": [ 18557 "\n <div class='norender'><code>\n var div = createDiv('this is a div');\n div.size(100, 100);\n </code></div>" 18558 ], 18559 "class": "p5.Element", 18560 "module": "p5.dom", 18561 "submodule": "p5.dom" 18562 }, 18563 { 18564 "file": "lib/addons/p5.dom.js", 18565 "line": 1805, 18566 "description": "<p>Removes the element and deregisters all listeners.</p>\n", 18567 "itemtype": "method", 18568 "name": "remove", 18569 "example": [ 18570 "\n<div class='norender'><code>\nvar myDiv = createDiv('this is some text');\nmyDiv.remove();\n</code></div>" 18571 ], 18572 "class": "p5.Element", 18573 "module": "p5.dom", 18574 "submodule": "p5.dom" 18575 }, 18576 { 18577 "file": "lib/addons/p5.dom.js", 18578 "line": 1851, 18579 "description": "<p>Path to the media element source.</p>\n", 18580 "itemtype": "property", 18581 "name": "src", 18582 "return": { 18583 "description": "src", 18584 "type": "String" 18585 }, 18586 "example": [ 18587 "\n<div><code>\nvar ele;\n\nfunction setup() {\n background(250);\n\n //p5.MediaElement objects are usually created\n //by calling the createAudio(), createVideo(),\n //and createCapture() functions.\n\n //In this example we create\n //a new p5.MediaElement via createAudio().\n ele = createAudio('assets/beat.mp3');\n\n //We'll set up our example so that\n //when you click on the text,\n //an alert box displays the MediaElement's\n //src field.\n textAlign(CENTER);\n text('Click Me!', width / 2, height / 2);\n}\n\nfunction mouseClicked() {\n //here we test if the mouse is over the\n //canvas element when it's clicked\n if (mouseX >= 0 && mouseX <= width && mouseY >= 0 && mouseY <= height) {\n //Show our p5.MediaElement's src field\n alert(ele.src);\n }\n}\n</code></div>" 18588 ], 18589 "class": "p5.MediaElement", 18590 "module": "p5.dom", 18591 "submodule": "p5.dom" 18592 }, 18593 { 18594 "file": "lib/addons/p5.dom.js", 18595 "line": 1917, 18596 "description": "<p>Play an HTML5 media element.</p>\n", 18597 "itemtype": "method", 18598 "name": "play", 18599 "return": { 18600 "description": "", 18601 "type": "Object|p5.Element" 18602 }, 18603 "example": [ 18604 "\n<div><code>\nvar ele;\n\nfunction setup() {\n //p5.MediaElement objects are usually created\n //by calling the createAudio(), createVideo(),\n //and createCapture() functions.\n\n //In this example we create\n //a new p5.MediaElement via createAudio().\n ele = createAudio('assets/beat.mp3');\n\n background(250);\n textAlign(CENTER);\n text('Click to Play!', width / 2, height / 2);\n}\n\nfunction mouseClicked() {\n //here we test if the mouse is over the\n //canvas element when it's clicked\n if (mouseX >= 0 && mouseX <= width && mouseY >= 0 && mouseY <= height) {\n //Here we call the play() function on\n //the p5.MediaElement we created above.\n //This will start the audio sample.\n ele.play();\n\n background(200);\n text('You clicked Play!', width / 2, height / 2);\n }\n}\n</code></div>" 18605 ], 18606 "class": "p5.MediaElement", 18607 "module": "p5.dom", 18608 "submodule": "p5.dom" 18609 }, 18610 { 18611 "file": "lib/addons/p5.dom.js", 18612 "line": 1970, 18613 "description": "<p>Stops an HTML5 media element (sets current time to zero).</p>\n", 18614 "itemtype": "method", 18615 "name": "stop", 18616 "return": { 18617 "description": "", 18618 "type": "Object|p5.Element" 18619 }, 18620 "example": [ 18621 "\n<div><code>\n//This example both starts\n//and stops a sound sample\n//when the user clicks the canvas\n\n//We will store the p5.MediaElement\n//object in here\nvar ele;\n\n//while our audio is playing,\n//this will be set to true\nvar sampleIsPlaying = false;\n\nfunction setup() {\n //Here we create a p5.MediaElement object\n //using the createAudio() function.\n ele = createAudio('assets/beat.mp3');\n background(200);\n textAlign(CENTER);\n text('Click to play!', width / 2, height / 2);\n}\n\nfunction mouseClicked() {\n //here we test if the mouse is over the\n //canvas element when it's clicked\n if (mouseX >= 0 && mouseX <= width && mouseY >= 0 && mouseY <= height) {\n background(200);\n\n if (sampleIsPlaying) {\n //if the sample is currently playing\n //calling the stop() function on\n //our p5.MediaElement will stop\n //it and reset its current\n //time to 0 (i.e. it will start\n //at the beginning the next time\n //you play it)\n ele.stop();\n\n sampleIsPlaying = false;\n text('Click to play!', width / 2, height / 2);\n } else {\n //loop our sound element until we\n //call ele.stop() on it.\n ele.loop();\n\n sampleIsPlaying = true;\n text('Click to stop!', width / 2, height / 2);\n }\n }\n}\n</code></div>" 18622 ], 18623 "class": "p5.MediaElement", 18624 "module": "p5.dom", 18625 "submodule": "p5.dom" 18626 }, 18627 { 18628 "file": "lib/addons/p5.dom.js", 18629 "line": 2034, 18630 "description": "<p>Pauses an HTML5 media element.</p>\n", 18631 "itemtype": "method", 18632 "name": "pause", 18633 "return": { 18634 "description": "", 18635 "type": "Object|p5.Element" 18636 }, 18637 "example": [ 18638 "\n<div><code>\n//This example both starts\n//and pauses a sound sample\n//when the user clicks the canvas\n\n//We will store the p5.MediaElement\n//object in here\nvar ele;\n\n//while our audio is playing,\n//this will be set to true\nvar sampleIsPlaying = false;\n\nfunction setup() {\n //Here we create a p5.MediaElement object\n //using the createAudio() function.\n ele = createAudio('assets/lucky_dragons.mp3');\n background(200);\n textAlign(CENTER);\n text('Click to play!', width / 2, height / 2);\n}\n\nfunction mouseClicked() {\n //here we test if the mouse is over the\n //canvas element when it's clicked\n if (mouseX >= 0 && mouseX <= width && mouseY >= 0 && mouseY <= height) {\n background(200);\n\n if (sampleIsPlaying) {\n //Calling pause() on our\n //p5.MediaElement will stop it\n //playing, but when we call the\n //loop() or play() functions\n //the sample will start from\n //where we paused it.\n ele.pause();\n\n sampleIsPlaying = false;\n text('Click to resume!', width / 2, height / 2);\n } else {\n //loop our sound element until we\n //call ele.pause() on it.\n ele.loop();\n\n sampleIsPlaying = true;\n text('Click to pause!', width / 2, height / 2);\n }\n }\n}\n</code></div>" 18639 ], 18640 "class": "p5.MediaElement", 18641 "module": "p5.dom", 18642 "submodule": "p5.dom" 18643 }, 18644 { 18645 "file": "lib/addons/p5.dom.js", 18646 "line": 2096, 18647 "description": "<p>Set 'loop' to true for an HTML5 media element, and starts playing.</p>\n", 18648 "itemtype": "method", 18649 "name": "loop", 18650 "return": { 18651 "description": "", 18652 "type": "Object|p5.Element" 18653 }, 18654 "example": [ 18655 "\n<div><code>\n//Clicking the canvas will loop\n//the audio sample until the user\n//clicks again to stop it\n\n//We will store the p5.MediaElement\n//object in here\nvar ele;\n\n//while our audio is playing,\n//this will be set to true\nvar sampleIsLooping = false;\n\nfunction setup() {\n //Here we create a p5.MediaElement object\n //using the createAudio() function.\n ele = createAudio('assets/lucky_dragons.mp3');\n background(200);\n textAlign(CENTER);\n text('Click to loop!', width / 2, height / 2);\n}\n\nfunction mouseClicked() {\n //here we test if the mouse is over the\n //canvas element when it's clicked\n if (mouseX >= 0 && mouseX <= width && mouseY >= 0 && mouseY <= height) {\n background(200);\n\n if (!sampleIsLooping) {\n //loop our sound element until we\n //call ele.stop() on it.\n ele.loop();\n\n sampleIsLooping = true;\n text('Click to stop!', width / 2, height / 2);\n } else {\n ele.stop();\n\n sampleIsLooping = false;\n text('Click to loop!', width / 2, height / 2);\n }\n }\n}\n</code></div>" 18656 ], 18657 "class": "p5.MediaElement", 18658 "module": "p5.dom", 18659 "submodule": "p5.dom" 18660 }, 18661 { 18662 "file": "lib/addons/p5.dom.js", 18663 "line": 2152, 18664 "description": "<p>Set 'loop' to false for an HTML5 media element. Element will stop\nwhen it reaches the end.</p>\n", 18665 "itemtype": "method", 18666 "name": "noLoop", 18667 "return": { 18668 "description": "", 18669 "type": "Object|p5.Element" 18670 }, 18671 "example": [ 18672 "\n<div><code>\n//This example both starts\n//and stops loop of sound sample\n//when the user clicks the canvas\n\n//We will store the p5.MediaElement\n//object in here\nvar ele;\n//while our audio is playing,\n//this will be set to true\nvar sampleIsPlaying = false;\n\nfunction setup() {\n //Here we create a p5.MediaElement object\n //using the createAudio() function.\n ele = createAudio('assets/beat.mp3');\n background(200);\n textAlign(CENTER);\n text('Click to play!', width / 2, height / 2);\n}\n\nfunction mouseClicked() {\n //here we test if the mouse is over the\n //canvas element when it's clicked\n if (mouseX >= 0 && mouseX <= width && mouseY >= 0 && mouseY <= height) {\n background(200);\n\n if (sampleIsPlaying) {\n ele.noLoop();\n text('No more Loops!', width / 2, height / 2);\n } else {\n ele.loop();\n sampleIsPlaying = true;\n text('Click to stop looping!', width / 2, height / 2);\n }\n }\n}\n</code></div>\n" 18673 ], 18674 "class": "p5.MediaElement", 18675 "module": "p5.dom", 18676 "submodule": "p5.dom" 18677 }, 18678 { 18679 "file": "lib/addons/p5.dom.js", 18680 "line": 2204, 18681 "description": "<p>
18681Set HTML5 media element to autoplay or not.</p>\n", 18682 "itemtype": "method", 18683 "name": "autoplay", 18684 "params": [ 18685 { 18686 "name": "autoplay", 18687 "description": "<p>whether the element should autoplay</p>\n", 18688 "type": "Boolean" 18689 } 18690 ], 18691 "return": { 18692 "description": "", 18693 "type": "Object|p5.Element" 18694 }, 18695 "class": "p5.MediaElement", 18696 "module": "p5.dom", 18697 "submodule": "p5.dom" 18698 }, 18699 { 18700 "file": "lib/addons/p5.dom.js", 18701 "line": 2216, 18702 "description": "<p>Sets volume for this HTML5 media element. If no argument is given,\nreturns the current volume.</p>\n", 18703 "params": [ 18704 { 18705 "name": "val", 18706 "description": "<p>volume between 0.0 and 1.0</p>\n", 18707 "type": "Number", 18708 "optional": true 18709 } 18710 ], 18711 "return": { 18712 "description": "current volume or p5.MediaElement", 18713 "type": "Number|p5.MediaElement" 18714 }, 18715 "itemtype": "method", 18716 "name": "volume", 18717 "example": [ 18718 "\n<div><code>\nvar ele;\nfunction setup() {\n // p5.MediaElement objects are usually created\n // by calling the createAudio(), createVideo(),\n // and createCapture() functions.\n // In this example we create\n // a new p5.MediaElement via createAudio().\n ele = createAudio('assets/lucky_dragons.mp3');\n background(250);\n textAlign(CENTER);\n text('Click to Play!', width / 2, height / 2);\n}\nfunction mouseClicked() {\n // Here we call the volume() function\n // on the sound element to set its volume\n // Volume must be between 0.0 and 1.0\n ele.volume(0.2);\n ele.play();\n background(200);\n text('You clicked Play!', width / 2, height / 2);\n}\n</code></div>\n<div><code>\nvar audio;\nvar counter = 0;\n\nfunction loaded() {\n audio.play();\n}\n\nfunction setup() {\n audio = createAudio('assets/lucky_dragons.mp3', loaded);\n textAlign(CENTER);\n}\n\nfunction draw() {\n if (counter === 0) {\n background(0, 255, 0);\n text('volume(0.9)', width / 2, height / 2);\n } else if (counter === 1) {\n background(255, 255, 0);\n text('volume(0.5)', width / 2, height / 2);\n } else if (counter === 2) {\n background(255, 0, 0);\n text('volume(0.1)', width / 2, height / 2);\n }\n}\n\nfunction mousePressed() {\n counter++;\n if (counter === 0) {\n audio.volume(0.9);\n } else if (counter === 1) {\n audio.volume(0.5);\n } else if (counter === 2) {\n audio.volume(0.1);\n } else {\n counter = 0;\n audio.volume(0.9);\n }\n}\n</code>\n</div>" 18719 ], 18720 "class": "p5.MediaElement", 18721 "module": "p5.dom", 18722 "submodule": "p5.dom" 18723 }, 18724 { 18725 "file": "lib/addons/p5.dom.js", 18726 "line": 2298, 18727 "description": "<p>If no arguments are given, returns the current playback speed of the\nelement. The speed parameter sets the speed where 2.0 will play the\nelement twice as fast, 0.5 will play at half the speed, and -1 will play\nthe element in normal speed in reverse.(Note that not all browsers support\nbackward playback and even if they do, playback might not be smooth.)</p>\n", 18728 "itemtype": "method", 18729 "name": "speed", 18730 "params": [ 18731 { 18732 "name": "speed", 18733 "description": "<p>speed multiplier for element playback</p>\n", 18734 "type": "Number", 18735 "optional": true 18736 } 18737 ], 18738 "return": { 18739 "description": "current playback speed or p5.MediaElement", 18740 "type": "Number|Object|p5.MediaElement" 18741 }, 18742 "example": [ 18743 "\n<div class='norender notest'><code>\n//Clicking the canvas will loop\n//the audio sample until the user\n//clicks again to stop it\n\n//We will store the p5.MediaElement\n//object in here\nvar ele;\nvar button;\n\nfunction setup() {\n createCanvas(710, 400);\n //Here we create a p5.MediaElement object\n //using the createAudio() function.\n ele = createAudio('assets/beat.mp3');\n ele.loop();\n background(200);\n\n button = createButton('2x speed');\n button.position(100, 68);\n button.mousePressed(twice_speed);\n\n button = createButton('half speed');\n button.position(200, 68);\n button.mousePressed(half_speed);\n\n button = createButton('reverse play');\n button.position(300, 68);\n button.mousePressed(reverse_speed);\n\n button = createButton('STOP');\n button.position(400, 68);\n button.mousePressed(stop_song);\n\n button = createButton('PLAY!');\n button.position(500, 68);\n button.mousePressed(play_speed);\n}
18743\n\nfunction twice_speed() {\n ele.speed(2);\n}\n\nfunction half_speed() {\n ele.speed(0.5);\n}\n\nfunction reverse_speed() {\n ele.speed(-1);\n}\n\nfunction stop_song() {\n ele.stop();\n}\n\nfunction play_speed() {\n ele.play();\n}\n</code></div>" 18744 ], 18745 "class": "p5.MediaElement", 18746 "module": "p5.dom", 18747 "submodule": "p5.dom" 18748 }, 18749 { 18750 "file": "lib/addons/p5.dom.js", 18751 "line": 2377, 18752 "description": "<p>If no arguments are given, returns the current time of the element.\nIf an argument is given the current time of the element is set to it.</p>\n", 18753 "itemtype": "method", 18754 "name": "time", 18755 "params": [ 18756 { 18757 "name": "time", 18758 "description": "<p>time to jump to (in seconds)</p>\n", 18759 "type": "Number", 18760 "optional": true 18761 } 18762 ], 18763 "return": { 18764 "description": "current time (in seconds)\n or p5.MediaElement", 18765 "type": "Number|Object|p5.MediaElement" 18766 }, 18767 "example": [ 18768 "\n<div><code>\nvar ele;\nvar beginning = true;\nfunction setup() {\n //p5.MediaElement objects are usually created\n //by calling the createAudio(), createVideo(),\n //and createCapture() functions.\n\n //In this example we create\n //a new p5.MediaElement via createAudio().\n ele = createAudio('assets/lucky_dragons.mp3');\n background(250);\n textAlign(CENTER);\n text('start at beginning', width / 2, height / 2);\n}\n\n// this function fires with click anywhere\nfunction mousePressed() {\n if (beginning === true) {\n // here we start the sound at the beginning\n // time(0) is not necessary here\n // as this produces the same result as\n // play()\n ele.play().time(0);\n background(200);\n text('jump 2 sec in', width / 2, height / 2);\n beginning = false;\n } else {\n // here we jump 2 seconds into the sound\n ele.play().time(2);\n background(250);\n text('start at beginning', width / 2, height / 2);\n beginning = true;\n }\n}\n</code></div>" 18769 ], 18770 "class": "p5.MediaElement", 18771 "module": "p5.dom", 18772 "submodule": "p5.dom" 18773 }, 18774 { 18775 "file": "lib/addons/p5.dom.js", 18776 "line": 2432, 18777 "description": "<p>Returns the duration of the HTML5 media element.</p>\n", 18778 "itemtype": "method", 18779 "name": "duration", 18780 "return": { 18781 "description": "duration", 18782 "type": "Number" 18783 }, 18784 "example": [ 18785 "\n<div><code>\nvar ele;\nfunction setup() {\n //p5.MediaElement objects are usually created\n //by calling the createAudio(), createVideo(),\n //and createCapture() functions.\n //In this example we create\n //a new p5.MediaElement via createAudio().\n ele = createAudio('assets/doorbell.mp3');\n background(250);\n textAlign(CENTER);\n text('Click to know the duration!', 10, 25, 70, 80);\n}\nfunction mouseClicked() {\n ele.play();\n background(200);\n //ele.duration dislpays the duration\n text(ele.duration() + ' seconds', width / 2, height / 2);\n}\n</code></div>" 18786 ], 18787 "class": "p5.MediaElement", 18788 "module": "p5.dom", 18789 "submodule": "p5.dom" 18790 }, 18791 { 18792 "file": "lib/addons/p5.dom.js", 18793 "line": 2550, 18794 "description": "<p>Schedule an event to be called when the audio or video\nelement reaches the end. If the element is looping,\nthis will not be called. The element is passed in\nas the argument to the onended callback.</p>\n", 18795 "itemtype": "method", 18796 "name": "onended", 18797 "params": [ 18798 { 18799 "name": "callback", 18800 "description": "<p>function to call when the\n soundfile has ended. The\n media element will be passed\n in as the argument to the\n callback.</p>\n", 18801 "type": "Function" 18802 } 18803 ], 18804 "return": { 18805 "description": "", 18806 "type": "Object|p5.MediaElement" 18807 }, 18808 "example": [ 18809 "\n<div><code>\nfunction setup() {\n var audioEl = createAudio('assets/beat.mp3');\n audioEl.showControls();\n audioEl.onended(sayDone);\n}\n\nfunction sayDone(elt) {\n alert('done playing ' + elt.src);\n}\n</code></div>" 18810 ], 18811 "class": "p5.MediaElement", 18812 "module": "p5.dom", 18813 "submodule": "p5.dom" 18814 }, 18815 { 18816 "file": "lib/addons/p5.dom.js", 18817 "line": 2581, 18818 "class": "p5.MediaElement", 18819 "module": "p5.dom", 18820 "submodule": "p5.dom" 18821 }, 18822 { 18823 "file": "lib/addons/p5.dom.js", 18824 "line": 2583, 18825 "description": "<p>Send the audio output of this element to a specified audioNode or\np5.sound object. If no element is provided, connects to p5's master\noutput. That connection is established when this method is first called.\nAll connections are removed by the .disconnect() method.</p>\n<p>This method is meant to be used with the p5.sound.js addon library.</p>\n", 18826 "itemtype": "method", 18827 "name": "connect", 18828 "params": [ 18829 { 18830 "name": "audioNode", 18831 "description": "<p>AudioNode from the Web Audio API,\nor an object from the p5.sound library</p>\n", 18832 "type": "AudioNode|Object" 18833 } 18834 ], 18835 "class": "p5.MediaElement", 18836 "module": "p5.dom", 18837 "submodule": "p5.dom" 18838 }, 18839 { 18840 "file": "lib/addons/p5.dom.js", 18841 "line": 2632, 18842 "description": "<p>Disconnect all Web Audio routing, including to master output.\nThis is useful if you want to re-route the output through\naudio effects, for example.</p>\n", 18843 "itemtype": "method", 18844 "name": "disconnect", 18845 "class": "p5.MediaElement", 18846 "module": "p5.dom", 18847 "submodule": "p5.dom" 18848 }, 18849 { 18850 "file": "lib/addons/p5.dom.js", 18851 "line": 2647, 18852 "class": "p5.MediaElement", 18853 "module": "p5.dom", 18854 "submodule": "p5.dom" 18855 }, 18856 { 18857 "file": "lib/addons/p5.dom.js", 18858 "line": 2649, 18859 "description": "<p>Show the default MediaElement controls, as determined by the web browser.</p>\n", 18860 "itemtype": "method", 18861 "name": "showControls", 18862 "example": [ 18863 "\n<div><code>\nvar ele;\nfunction setup() {\n //p5.MediaElement objects are usually created\n //by calling the createAudio(), createVideo(),\n //and createCapture() functions.\n //In this example we create\n //a new p5.MediaElement via createAudio()\n ele = createAudio('assets/lucky_dragons.mp3');\n background(200);\n textAlign(CENTER);\n text('Click to Show Controls!', 10, 25, 70, 80);\n}\nfunction mousePressed() {\n ele.showControls();\n background(200);\n text('Controls Shown', width / 2, height / 2);\n}\n</code></div>" 18864 ], 18865 "class": "p5.MediaElement", 18866 "module": "p5.dom", 18867 "submodule": "p5.dom" 18868 }, 18869 { 18870 "file": "lib/addons/p5.dom.js", 18871 "line": 2680, 18872 "description": "<p>Hide the default mediaElement controls.</p>\n", 18873 "itemtype": "method", 18874 "name": "hideControls", 18875 "example": [ 18876 "\n<div><code>\nvar ele;\nfunction setup() {\n //p5.MediaElement objects are usually created\n //by calling the createAudio(), createVideo(),\n //and createCapture() functions.\n //In this example we create\n //a new p5.MediaElement via createAudio()\n ele = createAudio('assets/lucky_dragons.mp3');\n ele.showControls();\n background(200);\n textAlign(CENTER);\n text('Click to hide Controls!', 10, 25, 70, 80);\n}\nfunction mousePressed() {\n ele.hideControls();\n background(200);\n text('Controls hidden', width / 2, height / 2);\n}\n</code></div>" 18877 ], 18878 "class": "p5.MediaElement", 18879 "module": "p5.dom", 18880 "submodule": "p5.dom" 18881 }, 18882 { 18883 "file": "lib/addons/p5.dom.js", 18884 "line": 2709, 18885 "class": "p5.MediaElement", 18886 "module": "p5.dom", 18887 "submodule": "p5.dom" 18888 }, 18889 { 18890 "file": "lib/addons/p5.dom.js", 18891 "line": 2720, 18892 "description": "<p>Schedule events to trigger every time a MediaElement\n(audio/video) reaches a playback cue point.</p>\n<p>Accepts a callback function, a time (in seconds) at which to trigger\nthe callback, and an optional parameter for the callback.</p>\n<p>Time will be passed as the first parameter to the callback function,\nand param will be the second parameter.</p>\n", 18893 "itemtype": "method", 18894 "name": "addCue", 18895 "params": [ 18896 { 18897 "name": "time", 18898 "description": "<p>Time in seconds, relative to this media\n element's playback. For example, to trigger\n an event every time playback reaches two\n seconds, pass in the number 2. This will be\n passed as the first parameter to\n the callback function.</p>\n", 18899 "type": "Number" 18900 }, 18901 { 18902 "name": "callback", 18903 "description": "<p>Name of a function that will be\n called at the given time. The callback will\n receive time and (optionally) param as its\n two parameters.</p>\n", 18904 "type": "Function" 18905 }, 18906 { 18907 "name": "value", 18908 "description": "<p>An object to be passed as the\n second parameter to the\n callback function.</p>\n", 18909 "type": "Object", 18910 "optional": true 18911 } 18912 ], 18913 "return": { 18914 "description": "id ID of this cue,\n useful for removeCue(id)", 18915 "type": "Number" 18916 }, 18917 "example": [ 18918 "\n<div><code>\nfunction setup() {\n background(255, 255, 255);\n\n var audioEl = createAudio('assets/beat.mp3');\n audioEl.showControls();
18918\n\n // schedule three calls to changeBackground\n audioEl.addCue(0.5, changeBackground, color(255, 0, 0));\n audioEl.addCue(1.0, changeBackground, color(0, 255, 0));\n audioEl.addCue(2.5, changeBackground, color(0, 0, 255));\n audioEl.addCue(3.0, changeBackground, color(0, 255, 255));\n audioEl.addCue(4.2, changeBackground, color(255, 255, 0));\n audioEl.addCue(5.0, changeBackground, color(255, 255, 0));\n}\n\nfunction changeBackground(val) {\n background(val);\n}\n</code></div>" 18919 ], 18920 "class": "p5.MediaElement", 18921 "module": "p5.dom", 18922 "submodule": "p5.dom" 18923 }, 18924 { 18925 "file": "lib/addons/p5.dom.js", 18926 "line": 2782, 18927 "description": "<p>Remove a callback based on its ID. The ID is returned by the\naddCue method.</p>\n", 18928 "itemtype": "method", 18929 "name": "removeCue", 18930 "params": [ 18931 { 18932 "name": "id", 18933 "description": "<p>ID of the cue, as returned by addCue</p>\n", 18934 "type": "Number" 18935 } 18936 ], 18937 "example": [ 18938 "\n<div><code>\nvar audioEl, id1, id2;\nfunction setup() {\n background(255, 255, 255);\n audioEl = createAudio('assets/beat.mp3');\n audioEl.showControls();\n // schedule five calls to changeBackground\n id1 = audioEl.addCue(0.5, changeBackground, color(255, 0, 0));\n audioEl.addCue(1.0, changeBackground, color(0, 255, 0));\n audioEl.addCue(2.5, changeBackground, color(0, 0, 255));\n audioEl.addCue(3.0, changeBackground, color(0, 255, 255));\n id2 = audioEl.addCue(4.2, changeBackground, color(255, 255, 0));\n text('Click to remove first and last Cue!', 10, 25, 70, 80);\n}\nfunction mousePressed() {\n audioEl.removeCue(id1);\n audioEl.removeCue(id2);\n}\nfunction changeBackground(val) {\n background(val);\n}\n</code></div>" 18939 ], 18940 "class": "p5.MediaElement", 18941 "module": "p5.dom", 18942 "submodule": "p5.dom" 18943 }, 18944 { 18945 "file": "lib/addons/p5.dom.js", 18946 "line": 2824, 18947 "description": "<p>Remove all of the callbacks that had originally been scheduled\nvia the addCue method.</p>\n", 18948 "itemtype": "method", 18949 "name": "clearCues", 18950 "params": [ 18951 { 18952 "name": "id", 18953 "description": "<p>ID of the cue, as returned by addCue</p>\n", 18954 "type": "Number" 18955 } 18956 ], 18957 "example": [ 18958 "\n<div><code>\nvar audioEl;\nfunction setup() {\n background(255, 255, 255);\n audioEl = createAudio('assets/beat.mp3');\n //Show the default MediaElement controls, as determined by the web browser\n audioEl.showControls();\n // schedule calls to changeBackground\n background(200);\n text('Click to change Cue!', 10, 25, 70, 80);\n audioEl.addCue(0.5, changeBackground, color(255, 0, 0));\n audioEl.addCue(1.0, changeBackground, color(0, 255, 0));\n audioEl.addCue(2.5, changeBackground, color(0, 0, 255));\n audioEl.addCue(3.0, changeBackground, color(0, 255, 255));\n audioEl.addCue(4.2, changeBackground, color(255, 255, 0));\n}\nfunction mousePressed() {\n // here we clear the scheduled callbacks\n audioEl.clearCues();\n // then we add some more callbacks\n audioEl.addCue(1, changeBackground, color(2, 2, 2));\n audioEl.addCue(3, changeBackground, color(255, 255, 0));\n}\nfunction changeBackground(val) {\n background(val);\n}\n</code></div>" 18959 ], 18960 "class": "p5.MediaElement", 18961 "module": "p5.dom", 18962 "submodule": "p5.dom" 18963 }, 18964 { 18965 "file": "lib/addons/p5.dom.js", 18966 "line": 2894, 18967 "description": "<p>Underlying File object. All normal File methods can be called on this.</p>\n", 18968 "itemtype": "property", 18969 "name": "file", 18970 "class": "p5.File", 18971 "module": "p5.dom", 18972 "submodule": "p5.dom" 18973 }, 18974 { 18975 "file": "lib/addons/p5.dom.js", 18976 "line": 2906, 18977 "description": "<p>File type (image, text, etc.)</p>\n", 18978 "itemtype": "property", 18979 "name": "type", 18980 "class": "p5.File", 18981 "module": "p5.dom", 18982 "submodule": "p5.dom" 18983 }, 18984 { 18985 "file": "lib/addons/p5.dom.js", 18986 "line": 2912, 18987 "description": "<p>File subtype (usually the file extension jpg, png, xml, etc.)</p>\n", 18988 "itemtype": "property", 18989 "name": "subtype", 18990 "class": "p5.File", 18991 "module": "p5.dom", 18992 "submodule": "p5.dom" 18993 }, 18994 { 18995 "file": "lib/addons/p5.dom.js", 18996 "line": 2918, 18997 "description": "<p>File name</p>\n", 18998 "itemtype": "property", 18999 "name": "name", 19000 "class": "p5.File", 19001 "module": "p5.dom", 19002 "submodule": "p5.dom" 19003 }, 19004 { 19005 "file": "lib/addons/p5.dom.js", 19006 "line": 2924, 19007 "description": "<p>File size</p>\n", 19008 "itemtype": "property", 19009 "name": "size", 19010 "class": "p5.File", 19011 "module": "p5.dom", 19012 "submodule": "p5.dom" 19013 }, 19014 { 19015 "file": "lib/addons/p5.dom.js", 19016 "line": 2931, 19017 "description": "<p>URL string containing image data.</p>\n", 19018 "itemtype": "property", 19019 "name": "data", 19020 "class": "p5.File", 19021 "module": "p5.dom", 19022 "submodule": "p5.dom" 19023 }, 19024 { 19025 "file": "lib/addons/p5.sound.js", 19026 "line": 46, 19027 "description": "<p>p5.sound\n<a href=\"https://p5js.org/reference/#/libraries/p5.sound\">https://p5js.org/reference/#/libraries/p5.sound</a></p>\n<p>From the Processing Foundation and contributors\n<a href=\"https://github.com/processing/p5.js-sound/graphs/contributors\">https://github.com/processing/p5.js-sound/graphs/contributors</a></p>\n<p>MIT License (MIT)\n<a href=\"https://github.com/processing/p5.js-sound/blob/master/LICENSE\">https://github.com/processing/p5.js-sound/blob/master/LICENSE</a></p>\n<p>Some of the many audio libraries & resources that inspire p5.sound:</p>\n<ul>\n<li>TONE.js (c) Yotam Mann. Licensed under The MIT License (MIT). <a href=\"https://github.com/TONEnoTONE/Tone.js\">https://github.com/TONEnoTONE/Tone.js</a></li>\n<li>buzz.js (c) Jay Salvat. Licensed under The MIT License (MIT). <a href=\"http://buzz.jaysalvat.com/\">http://buzz.jaysalvat.com/</a></li>\n<li>Boris Smus Web Audio API book, 2013. Licensed under the Apache License <a href=\"http://www.apache.org/licenses/LICENSE-2.0\">http://www.apache.org/licenses/LICENSE-2.0</a></li>\n<li>wavesurfer.js <a href=\"https://github.com/katspaugh/wavesurfer.js\">https://github.com/katspaugh/wavesurfer.js</a></li>\n<li>Web Audio Components by Jordan Santell <a href=\"https://github.com/web-audio-components\">https://github.com/web-audio-components</a></li>\n<li><p>Wilm Thoben's Sound library for Processing <a href=\"https://github.com/processing/processing/tree/master/java/libraries/sound\">https://github.com/processing/processing/tree/master/java/libraries/sound</a></p>\n<p>Web Audio API: <a href=\"http://w3.org/TR/webaudio/\">http://w3.org/TR/webaudio/</a></p>\n</li>\n</ul>\n", 19028 "class": "p5.sound", 19029 "module": "p5.sound", 19030 "submodule": "p5.sound" 19031 }, 19032 { 19033 "file": "lib/addons/p5.sound.js", 19034 "line": 212, 19035 "description": "<p>Returns the Audio Context for this sketch. Useful for users\nwho would like to dig deeper into the <a target='_blank' href=\n'http://webaudio.github.io/web-audio-api/'>Web Audio API\n</a>.</p>", 19036 "itemtype": "method", 19037 "name": "getAudioContext", 19038 "return": { 19039 "description": "AudioContext for this sketch", 19040 "type": "Object" 19041 }, 19042 "class": "p5.sound", 19043 "module": "p5.sound", 19044 "submodule": "p5.sound" 19045 }, 19046 { 19047 "file": "lib/addons/p5.sound.js", 19048 "line": 226, 19049 "description": "<p>Determine which filetypes are supported (inspired by buzz.js)\nThe audio element (el) will only be used to test browser support for various audio formats</p>\n", 19050 "class": "p5.sound", 19051 "module": "p5.sound", 19052 "submodule": "p5.sound" 19053 }, 19054 { 19055 "file": "lib/addons/p5.sound.js", 19056 "line": 296, 19057 "description": "<p>Master contains AudioContext and the master sound output.</p>\n", 19058 "class": "p5.sound", 19059 "module": "p5.sound", 19060 "submodule": "p5.sound" 19061 }, 19062 { 19063 "file": "lib/addons/p5.sound.js", 19064 "line": 329, 19065 "description": "<p>Returns a number representing the master amplitude (volume) for sound\nin this sketch.</p>\n", 19066 "itemtype": "method", 19067 "name": "getMasterVolume", 19068 "return": { 19069 "description": "Master amplitude (volume) for sound in this sketch.\n Should be between 0.0 (silence) and 1.0.", 19070 "type": "Number" 19071 }, 19072 "class": "p5.sound", 19073 "module": "p5.sound", 19074 "submodule": "p5.sound" 19075 }, 19076 { 19077 "file": "lib/addons/p5.sound.js", 19078 "line": 340, 19079 "description": "<p>Scale the output of all sound in this sketch</p>\nScaled between 0.0 (silence) and 1.0 (full volume).\n1.0 is the maximum amplitude of a digital sound, so multiplying\nby greater than 1.0 may cause digital distortion. To\nfade, provide a <code>rampTime</code> parameter. For more\ncomplex fades, see the Env class.\n\nAlternately, you can pass in a signal source such as an\noscillator to modulate the amplitude with an audio signal.\n\n<p><b>How This Works</b>: When you load the p5.sound module, it\ncreates a single instance of p5sound. All sound objects in this\nmodule output to p5sound before reaching your computer's output.\nSo if you change the amplitude of p5sound, it impacts all of the\nsound in this module.</p>\n\n<p>If no value is provided, returns a Web Audio API Gain Node</p>", 19080 "itemtype": "method", 19081 "name": "masterVolume", 19082 "params": [ 19083 { 19084 "name": "volume", 19085 "description": "<p>Volume (amplitude) between 0.0\n and 1.0 or modulating signal/oscillator</p>\n", 19086 "type": "Number|Object" 19087 }, 19088 { 19089 "name": "rampTime", 19090 "description": "<p>Fade for t seconds</p>\n", 19091 "type": "Number", 19092 "optional": true 19093 }, 19094 { 19095 "name": "timeFromNow", 19096 "description": "<p>Schedule this event to happen at\n t seconds
19096in the future</p>\n", 19097 "type": "Number", 19098 "optional": true 19099 } 19100 ], 19101 "class": "p5.sound", 19102 "module": "p5.sound", 19103 "submodule": "p5.sound" 19104 }, 19105 { 19106 "file": "lib/addons/p5.sound.js", 19107 "line": 382, 19108 "description": "<p><code>p5.soundOut</code> is the p5.sound master output. It sends output to\nthe destination of this window's web audio context. It contains\nWeb Audio API nodes including a dyanmicsCompressor (<code>.limiter</code>),\nand Gain Nodes for <code>.input</code> and <code>.output</code>.</p>\n", 19109 "itemtype": "property", 19110 "name": "soundOut", 19111 "type": "Object", 19112 "class": "p5.sound", 19113 "module": "p5.sound", 19114 "submodule": "p5.sound" 19115 }, 19116 { 19117 "file": "lib/addons/p5.sound.js", 19118 "line": 407, 19119 "class": "p5", 19120 "module": "p5.sound", 19121 "submodule": "p5.sound" 19122 }, 19123 { 19124 "file": "lib/addons/p5.sound.js", 19125 "line": 410, 19126 "description": "<p>Returns a number representing the sample rate, in samples per second,\nof all sound objects in this audio context. It is determined by the\nsampling rate of your operating system's sound card, and it is not\ncurrently possile to change.\nIt is often 44100, or twice the range of human hearing.</p>\n", 19127 "itemtype": "method", 19128 "name": "sampleRate", 19129 "return": { 19130 "description": "samplerate samples per second", 19131 "type": "Number" 19132 }, 19133 "class": "p5", 19134 "module": "p5.sound", 19135 "submodule": "p5.sound" 19136 }, 19137 { 19138 "file": "lib/addons/p5.sound.js", 19139 "line": 423, 19140 "description": "<p>Returns the closest MIDI note value for\na given frequency.</p>\n", 19141 "itemtype": "method", 19142 "name": "freqToMidi", 19143 "params": [ 19144 { 19145 "name": "frequency", 19146 "description": "<p>A freqeuncy, for example, the "A"\n above Middle C is 440Hz</p>\n", 19147 "type": "Number" 19148 } 19149 ], 19150 "return": { 19151 "description": "MIDI note value", 19152 "type": "Number" 19153 }, 19154 "class": "p5", 19155 "module": "p5.sound", 19156 "submodule": "p5.sound" 19157 }, 19158 { 19159 "file": "lib/addons/p5.sound.js", 19160 "line": 437, 19161 "description": "<p>Returns the frequency value of a MIDI note value.\nGeneral MIDI treats notes as integers where middle C\nis 60, C# is 61, D is 62 etc. Useful for generating\nmusical frequencies with oscillators.</p>\n", 19162 "itemtype": "method", 19163 "name": "midiToFreq", 19164 "params": [ 19165 { 19166 "name": "midiNote", 19167 "description": "<p>The number of a MIDI note</p>\n", 19168 "type": "Number" 19169 } 19170 ], 19171 "return": { 19172 "description": "Frequency value of the given MIDI note", 19173 "type": "Number" 19174 }, 19175 "example": [ 19176 "\n<div><code>\nvar notes = [60, 64, 67, 72];\nvar i = 0;\n\nfunction setup() {\n osc = new p5.Oscillator('Triangle');\n osc.start();\n frameRate(1);\n}\n\nfunction draw() {\n var freq = midiToFreq(notes[i]);\n osc.freq(freq);\n i++;\n if (i >= notes.length){\n i = 0;\n }\n}\n</code></div>" 19177 ], 19178 "class": "p5", 19179 "module": "p5.sound", 19180 "submodule": "p5.sound" 19181 }, 19182 { 19183 "file": "lib/addons/p5.sound.js", 19184 "line": 470, 19185 "description": "<p>List the SoundFile formats that you will include. LoadSound\nwill search your directory for these extensions, and will pick\na format that is compatable with the client's web browser.\n<a href=\"http://media.io/\">Here</a> is a free online file\nconverter.</p>\n", 19186 "itemtype": "method", 19187 "name": "soundFormats", 19188 "params": [ 19189 { 19190 "name": "formats", 19191 "description": "<p>i.e. 'mp3', 'wav', 'ogg'</p>\n", 19192 "type": "String", 19193 "optional": true, 19194 "multiple": true 19195 } 19196 ], 19197 "example": [ 19198 "\n<div><code>\nfunction preload() {\n // set the global sound formats\n soundFormats('mp3', 'ogg');\n\n // load either beatbox.mp3, or .ogg, depending on browser\n mySound = loadSound('assets/beatbox.mp3');\n}\n\nfunction setup() {\n mySound.play();\n}\n</code></div>" 19199 ], 19200 "class": "p5", 19201 "module": "p5.sound", 19202 "submodule": "p5.sound" 19203 }, 19204 { 19205 "file": "lib/addons/p5.sound.js", 19206 "line": 583, 19207 "description": "<p>Used by Osc and Env to chain signal math</p>\n", 19208 "class": "p5", 19209 "module": "p5.sound", 19210 "submodule": "p5.sound" 19211 }, 19212 { 19213 "file": "lib/addons/p5.sound.js", 19214 "line": 855, 19215 "description": "<p>loadSound() returns a new p5.SoundFile from a specified\npath. If called during preload(), the p5.SoundFile will be ready\nto play in time for setup() and draw(). If called outside of\npreload, the p5.SoundFile will not be ready immediately, so\nloadSound accepts a callback as the second parameter. Using a\n<a href=\"https://github.com/processing/p5.js/wiki/Local-server\">\nlocal server</a> is recommended when loading external files.</p>\n", 19216 "itemtype": "method", 19217 "name": "loadSound", 19218 "params": [ 19219 { 19220 "name": "path", 19221 "description": "<p>Path to the sound file, or an array with\n paths to soundfiles in multiple formats\n i.e. ['sound.ogg', 'sound.mp3'].\n Alternately, accepts an object: either\n from the HTML5 File API, or a p5.File.</p>\n", 19222 "type": "String|Array" 19223 }, 19224 { 19225 "name": "successCallback", 19226 "description": "<p>Name of a function to call once file loads</p>\n", 19227 "type": "Function", 19228 "optional": true 19229 }, 19230 { 19231 "name": "errorCallback", 19232 "description": "<p>Name of a function to call if there is\n an error loading the file.</p>\n", 19233 "type": "Function", 19234 "optional": true 19235 }, 19236 { 19237 "name": "whileLoading", 19238 "description": "<p>Name of a function to call while file is loading.\n This function will receive the percentage loaded\n so far, from 0.0 to 1.0.</p>\n", 19239 "type": "Function", 19240 "optional": true 19241 } 19242 ], 19243 "return": { 19244 "description": "Returns a p5.SoundFile", 19245 "type": "SoundFile" 19246 }, 19247 "example": [ 19248 "\n<div><code>\nfunction preload() {\n mySound = loadSound('assets/doorbell.mp3');\n}\n\nfunction setup() {\n mySound.setVolume(0.1);\n mySound.play();\n}\n</code></div>" 19249 ], 19250 "class": "p5.SoundFile", 19251 "module": "p5.sound", 19252 "submodule": "p5.sound" 19253 }, 19254 { 19255 "file": "lib/addons/p5.sound.js", 19256 "line": 995, 19257 "description": "<p>Returns true if the sound file finished loading successfully.</p>\n", 19258 "itemtype": "method", 19259 "name": "isLoaded", 19260 "return": { 19261 "description": "", 19262 "type": "Boolean" 19263 }, 19264 "class": "p5.SoundFile", 19265 "module": "p5.sound", 19266 "submodule": "p5.sound" 19267 }, 19268 { 19269 "file": "lib/addons/p5.sound.js", 19270 "line": 1008, 19271 "description": "<p>Play the p5.SoundFile</p>\n", 19272 "itemtype": "method", 19273 "name": "play", 19274 "params": [ 19275 { 19276 "name": "startTime", 19277 "description": "<p>(optional) schedule playback to start (in seconds from now).</p>\n", 19278 "type": "Number", 19279 "optional": true 19280 }, 19281 { 19282 "name": "rate", 19283 "description": "<p>(optional) playback rate</p>\n", 19284 "type": "Number", 19285 "optional": true 19286 }, 19287 { 19288 "name": "amp", 19289 "description": "<p>(optional) amplitude (volume)\n of playback</p>\n", 19290 "type": "Number", 19291 "optional": true 19292 }, 19293 { 19294 "name": "cueStart", 19295 "description": "<p>(optional) cue start time in seconds</p>\n", 19296 "type": "Number", 19297 "optional": true 19298 }, 19299 { 19300 "name": "duration", 19301 "description": "<p>(optional) duration of playback in seconds</p>\n", 19302 "type": "Number", 19303 "optional": true 19304 } 19305 ], 19306 "class": "p5.SoundFile", 19307 "module": "p5.sound", 19308 "submodule": "p5.sound" 19309 }, 19310 { 19311 "file": "lib/addons/p5.sound.js", 19312 "line": 1109, 19313 "description": "<p>p5.SoundFile has two play modes: <code>restart</code> and\n<code>sustain</code>. Play Mode determines what happens to a\np5.SoundFile if it is triggered while in the middle of playback.\nIn sustain mode, playback will continue simultaneous to the\nnew playback. In restart mode, play() will stop playback\nand start over. With untilDone, a sound will play only if it's\nnot already playing. Sustain is the default mode.</p>\n", 19314 "itemtype": "method", 19315 "name": "playMode", 19316 "params": [ 19317 { 19318 "name": "str", 19319 "description": "<p>'restart' or 'sustain' or 'untilDone'</p>\n", 19320 "type": "String" 19321 } 19322 ], 19323 "example": [ 19324 "\n<div><code>\nfunction setup(){\n mySound = loadSound('assets/Damscray_DancingTiger.mp3');\n}\nfunction mouseClicked() {\n mySound.playMode('sustain');\n mySound.play();\n}\nfunction keyPressed() {\n mySound.playMode('restart');\n mySound.play();\n}\n\n </code></div>" 19325 ], 19326 "class": "p5.SoundFile", 19327 "module": "p5.sound", 19328 "submodule": "p5.sound" 19329 }, 19330 { 19331 "file": "lib/addons/p5.sound.js", 19332 "line": 1152, 19333 "description": "<p>Pauses a file that is currently playing. If the file is not\nplaying, then nothing will happen.</p>\n<p>After pausing, .play() will resume from the paused\nposition.\nIf p5.SoundFile had been set to loop before it was paused,\nit will continue to loop after it is unpaused with .play().</p>\n", 19334 "itemtype": "method", 19335 "name": "pause", 19336 "params": [ 19337 { 19338 "name": "startTime", 19339 "description": "<p>(optional) schedule event to occur\n seconds from now</p>\n", 19340 "type": "Number", 19341 "optional": true 19342 } 19343 ], 19344 "example": [ 19345 "\n<div><code>\nvar soundFile;\n\nfunction preload() {\n soundFormats('ogg', 'mp3');\n soundFile = loadSound('assets/Damscray_02.mp3');\n}\nfunction setup() {\n background(0, 255, 0);\n soundFile.setVolume(0.1);\n soundFile.loop();\n}\nfunction keyTyped() {\n if (key == 'p') {\n soundFile.pause();\n background(255, 0, 0);\n }\n}\n\nfunction keyReleased() {\n if (key == 'p') {\n soundFile.play();\n background(0, 255, 0);\n }\n}\n</code>\n</div>" 19346 ], 19347 "class": "p5.SoundFile", 19348 "module": "p5.sound", 19349 "submodule": "p5.sound" 19350 }, 19351 { 19352 "file": "lib/addons/p5.sound.js", 19353 "line": 1208, 19354 "description": "<p>
19354Loop the p5.SoundFile. Accepts optional parameters to set the\nplayback rate, playback volume, loopStart, loopEnd.</p>\n", 19355 "itemtype": "method", 19356 "name": "loop", 19357 "params": [ 19358 { 19359 "name": "startTime", 19360 "description": "<p>(optional) schedule event to occur\n seconds from now</p>\n", 19361 "type": "Number", 19362 "optional": true 19363 }, 19364 { 19365 "name": "rate", 19366 "description": "<p>(optional) playback rate</p>\n", 19367 "type": "Number", 19368 "optional": true 19369 }, 19370 { 19371 "name": "amp", 19372 "description": "<p>(optional) playback volume</p>\n", 19373 "type": "Number", 19374 "optional": true 19375 }, 19376 { 19377 "name": "cueLoopStart", 19378 "description": "<p>(optional) startTime in seconds</p>\n", 19379 "type": "Number", 19380 "optional": true 19381 }, 19382 { 19383 "name": "duration", 19384 "description": "<p>(optional) loop duration in seconds</p>\n", 19385 "type": "Number", 19386 "optional": true 19387 } 19388 ], 19389 "class": "p5.SoundFile", 19390 "module": "p5.sound", 19391 "submodule": "p5.sound" 19392 }, 19393 { 19394 "file": "lib/addons/p5.sound.js", 19395 "line": 1224, 19396 "description": "<p>Set a p5.SoundFile's looping flag to true or false. If the sound\nis currently playing, this change will take effect when it\nreaches the end of the current playback.</p>\n", 19397 "itemtype": "method", 19398 "name": "setLoop", 19399 "params": [ 19400 { 19401 "name": "Boolean", 19402 "description": "<p>set looping to true or false</p>\n", 19403 "type": "Boolean" 19404 } 19405 ], 19406 "class": "p5.SoundFile", 19407 "module": "p5.sound", 19408 "submodule": "p5.sound" 19409 }, 19410 { 19411 "file": "lib/addons/p5.sound.js", 19412 "line": 1245, 19413 "description": "<p>Returns 'true' if a p5.SoundFile is currently looping and playing, 'false' if not.</p>\n", 19414 "itemtype": "method", 19415 "name": "isLooping", 19416 "return": { 19417 "description": "", 19418 "type": "Boolean" 19419 }, 19420 "class": "p5.SoundFile", 19421 "module": "p5.sound", 19422 "submodule": "p5.sound" 19423 }, 19424 { 19425 "file": "lib/addons/p5.sound.js", 19426 "line": 1260, 19427 "description": "<p>Returns true if a p5.SoundFile is playing, false if not (i.e.\npaused or stopped).</p>\n", 19428 "itemtype": "method", 19429 "name": "isPlaying", 19430 "return": { 19431 "description": "", 19432 "type": "Boolean" 19433 }, 19434 "class": "p5.SoundFile", 19435 "module": "p5.sound", 19436 "submodule": "p5.sound" 19437 }, 19438 { 19439 "file": "lib/addons/p5.sound.js", 19440 "line": 1270, 19441 "description": "<p>Returns true if a p5.SoundFile is paused, false if not (i.e.\nplaying or stopped).</p>\n", 19442 "itemtype": "method", 19443 "name": "isPaused", 19444 "return": { 19445 "description": "", 19446 "type": "Boolean" 19447 }, 19448 "class": "p5.SoundFile", 19449 "module": "p5.sound", 19450 "submodule": "p5.sound" 19451 }, 19452 { 19453 "file": "lib/addons/p5.sound.js", 19454 "line": 1280, 19455 "description": "<p>Stop soundfile playback.</p>\n", 19456 "itemtype": "method", 19457 "name": "stop", 19458 "params": [ 19459 { 19460 "name": "startTime", 19461 "description": "<p>(optional) schedule event to occur\n in seconds from now</p>\n", 19462 "type": "Number", 19463 "optional": true 19464 } 19465 ], 19466 "class": "p5.SoundFile", 19467 "module": "p5.sound", 19468 "submodule": "p5.sound" 19469 }, 19470 { 19471 "file": "lib/addons/p5.sound.js", 19472 "line": 1326, 19473 "description": "<p>Multiply the output volume (amplitude) of a sound file\nbetween 0.0 (silence) and 1.0 (full volume).\n1.0 is the maximum amplitude of a digital sound, so multiplying\nby greater than 1.0 may cause digital distortion. To\nfade, provide a <code>rampTime</code> parameter. For more\ncomplex fades, see the Env class.</p>\n<p>Alternately, you can pass in a signal source such as an\noscillator to modulate the amplitude with an audio signal.</p>\n", 19474 "itemtype": "method", 19475 "name": "setVolume", 19476 "params": [ 19477 { 19478 "name": "volume", 19479 "description": "<p>Volume (amplitude) between 0.0\n and 1.0 or modulating signal/oscillator</p>\n", 19480 "type": "Number|Object" 19481 }, 19482 { 19483 "name": "rampTime", 19484 "description": "<p>Fade for t seconds</p>\n", 19485 "type": "Number", 19486 "optional": true 19487 }, 19488 { 19489 "name": "timeFromNow", 19490 "description": "<p>Schedule this event to happen at\n t seconds
19490in the future</p>\n", 19491 "type": "Number", 19492 "optional": true 19493 } 19494 ], 19495 "class": "p5.SoundFile", 19496 "module": "p5.sound", 19497 "submodule": "p5.sound" 19498 }, 19499 { 19500 "file": "lib/addons/p5.sound.js", 19501 "line": 1367, 19502 "description": "<p>Set the stereo panning of a p5.sound object to\na floating point number between -1.0 (left) and 1.0 (right).\nDefault is 0.0 (center).</p>\n", 19503 "itemtype": "method", 19504 "name": "pan", 19505 "params": [ 19506 { 19507 "name": "panValue", 19508 "description": "<p>Set the stereo panner</p>\n", 19509 "type": "Number", 19510 "optional": true 19511 }, 19512 { 19513 "name": "timeFromNow", 19514 "description": "<p>schedule this event to happen\n seconds from now</p>\n", 19515 "type": "Number", 19516 "optional": true 19517 } 19518 ], 19519 "example": [ 19520 "\n<div><code>\n\n var ball = {};\n var soundFile;\n\n function setup() {\n soundFormats('ogg', 'mp3');\n soundFile = loadSound('assets/beatbox.mp3');\n }\n\n function draw() {\n background(0);\n ball.x = constrain(mouseX, 0, width);\n ellipse(ball.x, height/2, 20, 20)\n }\n\n function mousePressed(){\n // map the ball's x location to a panning degree\n // between -1.0 (left) and 1.0 (right)\n var panning = map(ball.x, 0., width,-1.0, 1.0);\n soundFile.pan(panning);\n soundFile.play();\n }\n </div></code>" 19521 ], 19522 "class": "p5.SoundFile", 19523 "module": "p5.sound", 19524 "submodule": "p5.sound" 19525 }, 19526 { 19527 "file": "lib/addons/p5.sound.js", 19528 "line": 1406, 19529 "description": "<p>Returns the current stereo pan position (-1.0 to 1.0)</p>\n", 19530 "itemtype": "method", 19531 "name": "getPan", 19532 "return": { 19533 "description": "Returns the stereo pan setting of the Oscillator\n as a number between -1.0 (left) and 1.0 (right).\n 0.0 is center and default.", 19534 "type": "Number" 19535 }, 19536 "class": "p5.SoundFile", 19537 "module": "p5.sound", 19538 "submodule": "p5.sound" 19539 }, 19540 { 19541 "file": "lib/addons/p5.sound.js", 19542 "line": 1417, 19543 "description": "<p>Set the playback rate of a sound file. Will change the speed and the pitch.\nValues less than zero will reverse the audio buffer.</p>\n", 19544 "itemtype": "method", 19545 "name": "rate", 19546 "params": [ 19547 { 19548 "name": "playbackRate", 19549 "description": "<p>Set the playback rate. 1.0 is normal,\n .5 is half-speed, 2.0 is twice as fast.\n Values less than zero play backwards.</p>\n", 19550 "type": "Number", 19551 "optional": true 19552 } 19553 ], 19554 "example": [ 19555 "\n<div><code>\nvar song;\n\nfunction preload() {\n song = loadSound('assets/Damscray_DancingTiger.mp3');\n}\n\nfunction setup() {\n song.loop();\n}\n\nfunction draw() {\n background(200);\n\n // Set the rate to a range between 0.1 and 4\n // Changing the rate also alters the pitch\n var speed = map(mouseY, 0.1, height, 0, 2);\n speed = constrain(speed, 0.01, 4);\n song.rate(speed);\n\n // Draw a circle to show what is going on\n stroke(0);\n fill(51, 100);\n ellipse(mouseX, 100, 48, 48);\n}\n\n </code>\n </div>\n" 19556 ], 19557 "class": "p5.SoundFile", 19558 "module": "p5.sound", 19559 "submodule": "p5.sound" 19560 }, 19561 { 19562 "file": "lib/addons/p5.sound.js", 19563 "line": 1490, 19564 "description": "<p>Returns the duration of a sound file in seconds.</p>\n", 19565 "itemtype": "method", 19566 "name": "duration", 19567 "return": { 19568 "description": "The duration of the soundFile in seconds.", 19569 "type": "Number" 19570 }, 19571 "class": "p5.SoundFile", 19572 "module": "p5.sound", 19573 "submodule": "p5.sound" 19574 }, 19575 { 19576 "file": "lib/addons/p5.sound.js", 19577 "line": 1504, 19578 "description": "<p>Return the current position of the p5.SoundFile playhead, in seconds.\nTime is relative to the normal buffer direction, so if <code>reverseBuffer</code>\nhas been called, currentTime will count backwards.</p>\n", 19579 "itemtype": "method", 19580 "name": "currentTime", 19581 "return": { 19582 "description": "currentTime of the soundFile in seconds.", 19583 "type": "Number" 19584 }, 19585 "class": "p5.SoundFile", 19586 "module": "p5.sound", 19587 "submodule": "p5.sound" 19588 }, 19589 { 19590 "file": "lib/addons/p5.sound.js", 19591 "line": 1515, 19592 "description": "<p>Move the playhead of the song to a position, in seconds. Start timing\nand playback duration. If none are given, will reset the file to play\nentire duration from start to finish.</p>\n", 19593 "itemtype": "method", 19594 "name": "jump", 19595 "params": [ 19596 { 19597 "name": "cueTime", 19598 "description": "<p>cueTime of the soundFile in seconds.</p>\n", 19599 "type": "Number" 19600 }, 19601 { 19602 "name": "duration", 19603 "description": "<p>duration in seconds.</p>\n", 19604 "type": "Number" 19605 } 19606 ], 19607 "class": "p5.SoundFile", 19608 "module": "p5.sound", 19609 "submodule": "p5.sound" 19610 }, 19611 { 19612 "file": "lib/addons/p5.sound.js", 19613 "line": 1538, 19614 "description": "<p>Return the number of channels in a sound file.\nFor example, Mono = 1, Stereo = 2.</p>\n", 19615 "itemtype": "method", 19616 "name": "channels", 19617 "return": { 19618 "description": "[channels]", 19619 "type": "Number" 19620 }, 19621 "class": "p5.SoundFile", 19622 "module": "p5.sound", 19623 "submodule": "p5.sound" 19624 }, 19625 { 19626 "file": "lib/addons/p5.sound.js", 19627 "line": 1548, 19628 "description": "<p>Return the sample rate of the sound file.</p>\n", 19629 "itemtype": "method", 19630 "name": "sampleRate", 19631 "return": { 19632 "description": "[sampleRate]", 19633 "type": "Number" 19634 }, 19635 "class": "p5.SoundFile", 19636 "module": "p5.sound", 19637 "submodule": "p5.sound" 19638 }, 19639 { 19640 "file": "lib/addons/p5.sound.js", 19641 "line": 1557, 19642 "description": "<p>Return the number of samples in a sound file.\nEqual to sampleRate * duration.</p>\n", 19643 "itemtype": "method", 19644 "name": "frames", 19645 "return": {
19646 "description": "[sampleCount]", 19647 "type": "Number" 19648 }, 19649 "class": "p5.SoundFile", 19650 "module": "p5.sound", 19651 "submodule": "p5.sound" 19652 }, 19653 { 19654 "file": "lib/addons/p5.sound.js", 19655 "line": 1567, 19656 "description": "<p>Returns an array of amplitude peaks in a p5.SoundFile that can be\nused to draw a static waveform. Scans through the p5.SoundFile's\naudio buffer to find the greatest amplitudes. Accepts one\nparameter, 'length', which determines size of the array.\nLarger arrays result in more precise waveform visualizations.</p>\n<p>Inspired by Wavesurfer.js.</p>\n", 19657 "itemtype": "method", 19658 "name": "getPeaks", 19659 "params": [ 19660 { 19661 "name": "length", 19662 "description": "<p>length is the size of the returned array.\n Larger length results in more precision.\n Defaults to 5*width of the browser window.</p>\n", 19663 "type": "Number", 19664 "optional": true 19665 } 19666 ], 19667 "return": { 19668 "description": "Array of peaks.", 19669 "type": "Float32Array" 19670 }, 19671 "class": "p5.SoundFile", 19672 "module": "p5.sound", 19673 "submodule": "p5.sound" 19674 }, 19675 { 19676 "file": "lib/addons/p5.sound.js", 19677 "line": 1619, 19678 "description": "<p>Reverses the p5.SoundFile's buffer source.\nPlayback must be handled separately (see example).</p>\n", 19679 "itemtype": "method", 19680 "name": "reverseBuffer", 19681 "example": [ 19682 "\n<div><code>\nvar drum;\n\nfunction preload() {\n drum = loadSound('assets/drum.mp3');\n}\n\nfunction setup() {\n drum.reverseBuffer();\n drum.play();\n}\n\n </code>\n </div>" 19683 ], 19684 "class": "p5.SoundFile", 19685 "module": "p5.sound", 19686 "submodule": "p5.sound" 19687 }, 19688 { 19689 "file": "lib/addons/p5.sound.js", 19690 "line": 1659, 19691 "description": "<p>Schedule an event to be called when the soundfile\nreaches the end of a buffer. If the soundfile is\nplaying through once, this will be called when it\nends. If it is looping, it will be called when\nstop is called.</p>\n", 19692 "itemtype": "method", 19693 "name": "onended", 19694 "params": [ 19695 { 19696 "name": "callback", 19697 "description": "<p>function to call when the\n soundfile has ended.</p>\n", 19698 "type": "Function" 19699 } 19700 ], 19701 "class": "p5.SoundFile", 19702 "module": "p5.sound", 19703 "submodule": "p5.sound" 19704 }, 19705 { 19706 "file": "lib/addons/p5.sound.js", 19707 "line": 1712, 19708 "description": "<p>Connects the output of a p5sound object to input of another\np5.sound object. For example, you may connect a p5.SoundFile to an\nFFT or an Effect. If no parameter is given, it will connect to\nthe master output. Most p5sound objects connect to the master\noutput when they are created.</p>\n", 19709 "itemtype": "method", 19710 "name": "connect", 19711 "params": [ 19712 { 19713 "name": "object", 19714 "description": "<p>Audio object that accepts an input</p>\n", 19715 "type": "Object", 19716 "optional": true 19717 } 19718 ], 19719 "class": "p5.SoundFile", 19720 "module": "p5.sound", 19721 "submodule": "p5.sound" 19722 }, 19723 { 19724 "file": "lib/addons/p5.sound.js", 19725 "line": 1733, 19726 "description": "<p>Disconnects the output of this p5sound object.</p>\n", 19727 "itemtype": "method", 19728 "name": "disconnect", 19729 "class": "p5.SoundFile", 19730 "module": "p5.sound", 19731 "submodule": "p5.sound" 19732 }, 19733 { 19734 "file": "lib/addons/p5.sound.js", 19735 "line": 1741, 19736 "class": "p5.SoundFile", 19737 "module": "p5.sound", 19738 "submodule": "p5.sound" 19739 }, 19740 { 19741 "file": "lib/addons/p5.sound.js", 19742 "line": 1746, 19743 "description": "<p>
19743Reset the source for this SoundFile to a\nnew path (URL).</p>\n", 19744 "itemtype": "method", 19745 "name": "setPath", 19746 "params": [ 19747 { 19748 "name": "path", 19749 "description": "<p>path to audio file</p>\n", 19750 "type": "String" 19751 }, 19752 { 19753 "name": "callback", 19754 "description": "<p>Callback</p>\n", 19755 "type": "Function" 19756 } 19757 ], 19758 "class": "p5.SoundFile", 19759 "module": "p5.sound", 19760 "submodule": "p5.sound" 19761 }, 19762 { 19763 "file": "lib/addons/p5.sound.js", 19764 "line": 1759, 19765 "description": "<p>Replace the current Audio Buffer with a new Buffer.</p>\n", 19766 "itemtype": "method", 19767 "name": "setBuffer", 19768 "params": [ 19769 { 19770 "name": "buf", 19771 "description": "<p>Array of Float32 Array(s). 2 Float32 Arrays\n will create a stereo source. 1 will create\n a mono source.</p>\n", 19772 "type": "Array" 19773 } 19774 ], 19775 "class": "p5.SoundFile", 19776 "module": "p5.sound", 19777 "submodule": "p5.sound" 19778 }, 19779 { 19780 "file": "lib/addons/p5.sound.js", 19781 "line": 1831, 19782 "description": "<p>processPeaks returns an array of timestamps where it thinks there is a beat.</p>\n<p>This is an asynchronous function that processes the soundfile in an offline audio context,\nand sends the results to your callback function.</p>\n<p>The process involves running the soundfile through a lowpass filter, and finding all of the\npeaks above the initial threshold. If the total number of peaks are below the minimum number of peaks,\nit decreases the threshold and re-runs the analysis until either minPeaks or minThreshold are reached.</p>\n", 19783 "itemtype": "method", 19784 "name": "processPeaks", 19785 "params": [ 19786 { 19787 "name": "callback", 19788 "description": "<p>a function to call once this data is returned</p>\n", 19789 "type": "Function" 19790 }, 19791 { 19792 "name": "initThreshold", 19793 "description": "<p>initial threshold defaults to 0.9</p>\n", 19794 "type": "Number", 19795 "optional": true 19796 }, 19797 { 19798 "name": "minThreshold", 19799 "description": "<p>minimum threshold defaults to 0.22</p>\n", 19800 "type": "Number", 19801 "optional": true 19802 }, 19803 { 19804 "name": "minPeaks", 19805 "description": "<p>minimum number of peaks defaults to 200</p>\n", 19806 "type": "Number", 19807 "optional": true 19808 } 19809 ], 19810 "return": { 19811 "description": "Array of timestamped peaks", 19812 "type": "Array" 19813 }, 19814 "class": "p5.SoundFile", 19815 "module": "p5.sound", 19816 "submodule": "p5.sound" 19817 }, 19818 { 19819 "file": "lib/addons/p5.sound.js", 19820 "line": 2022, 19821 "class": "p5.SoundFile", 19822 "module": "p5.sound", 19823 "submodule": "p5.sound" 19824 }, 19825 { 19826 "file": "lib/addons/p5.sound.js", 19827 "line": 2031, 19828 "description": "<p>Schedule events to trigger every time a MediaElement\n(audio/video) reaches a playback cue point.</p>\n<p>Accepts a callback function, a time (in seconds) at which to trigger\nthe callback, and an optional parameter for the callback.</p>\n<p>Time will be passed as the first parameter to the callback function,\nand param will be the second parameter.</p>\n", 19829 "itemtype": "method", 19830 "name": "addCue", 19831 "params": [ 19832 { 19833 "name": "time", 19834 "description": "<p>Time in seconds, relative to this media\n element's playback. For example, to trigger\n an event every time playback reaches two\n seconds, pass in the number 2. This will be\n passed as the first parameter to\n the callback function.</p>\n", 19835 "type": "Number" 19836 }, 19837 { 19838 "name": "callback", 19839 "description": "<p>Name of a function that will be\n called at the given time. The callback will\n receive time and (optionally) param as its\n two parameters.</p>\n", 19840 "type": "Function" 19841 }, 19842 { 19843 "name": "value", 19844 "description": "<p>An object to be passed as the\n second parameter to the\n callback function.</p>\n", 19845 "type": "Object", 19846 "optional": true 19847 } 19848 ], 19849 "return": { 19850 "description": "id ID of this cue,\n useful for removeCue(id)", 19851 "type": "Number" 19852 }, 19853 "example": [ 19854 "\n<div><code>\nfunction setup() {\n background(0);\n noStroke();\n fill(255);\n textAlign(CENTER);\n text('click to play', width/2, height/2);\n\n mySound = loadSound('assets/beat.mp3');\n\n // schedule calls to changeText\n mySound.addCue(0.50, changeText, \"hello\" );\n mySound.addCue(1.00, changeText, \"p5\" );\n mySound.addCue(1.50, changeText, \"what\" );\n mySound.addCue(2.00, changeText, \"do\" );\n mySound.addCue(2.50, changeText, \"you\" );\n mySound.addCue(3.00, changeText, \"want\" );\n mySound.addCue(4.00, changeText, \"to\" );\n mySound.addCue(5.00, changeText, \"make\" );
19854\n mySound.addCue(6.00, changeText, \"?\" );\n}\n\nfunction changeText(val) {\n background(0);\n text(val, width/2, height/2);\n}\n\nfunction mouseClicked() {\n if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {\n if (mySound.isPlaying() ) {\n mySound.stop();\n } else {\n mySound.play();\n }\n }\n}\n</code></div>" 19855 ], 19856 "class": "p5.SoundFile", 19857 "module": "p5.sound", 19858 "submodule": "p5.sound" 19859 }, 19860 { 19861 "file": "lib/addons/p5.sound.js", 19862 "line": 2106, 19863 "description": "<p>Remove a callback based on its ID. The ID is returned by the\naddCue method.</p>\n", 19864 "itemtype": "method", 19865 "name": "removeCue", 19866 "params": [ 19867 { 19868 "name": "id", 19869 "description": "<p>ID of the cue, as returned by addCue</p>\n", 19870 "type": "Number" 19871 } 19872 ], 19873 "class": "p5.SoundFile", 19874 "module": "p5.sound", 19875 "submodule": "p5.sound" 19876 }, 19877 { 19878 "file": "lib/addons/p5.sound.js", 19879 "line": 2124, 19880 "description": "<p>Remove all of the callbacks that had originally been scheduled\nvia the addCue method.</p>\n", 19881 "itemtype": "method", 19882 "name": "clearCues", 19883 "class": "p5.SoundFile", 19884 "module": "p5.sound", 19885 "submodule": "p5.sound" 19886 }, 19887 { 19888 "file": "lib/addons/p5.sound.js", 19889 "line": 2232, 19890 "description": "<p>Connects to the p5sound instance (master output) by default.\nOptionally, you can pass in a specific source (i.e. a soundfile).</p>\n", 19891 "itemtype": "method", 19892 "name": "setInput", 19893 "params": [ 19894 { 19895 "name": "snd", 19896 "description": "<p>set the sound source\n (optional, defaults to\n master output)</p>\n", 19897 "type": "SoundObject|undefined", 19898 "optional": true 19899 }, 19900 { 19901 "name": "smoothing", 19902 "description": "<p>a range between 0.0 and 1.0\n to smooth amplitude readings</p>\n", 19903 "type": "Number|undefined", 19904 "optional": true 19905 } 19906 ], 19907 "example": [ 19908 "\n<div><code>\nfunction preload(){\n sound1 = loadSound('assets/beat.mp3');\n sound2 = loadSound('assets/drum.mp3');\n}\nfunction setup(){\n amplitude = new p5.Amplitude();\n sound1.play();\n sound2.play();\n amplitude.setInput(sound2);\n}\nfunction draw() {\n background(0);\n fill(255);\n var level = amplitude.getLevel();\n var size = map(level, 0, 1, 0, 200);\n ellipse(width/2, height/2, size, size);\n}\nfunction mouseClicked(){\n sound1.stop();\n sound2.stop();\n}\n</code></div>" 19909 ], 19910 "class": "p5.Amplitude", 19911 "module": "p5.sound", 19912 "submodule": "p5.sound" 19913 }, 19914 { 19915 "file": "lib/addons/p5.sound.js", 19916 "line": 2337, 19917 "description": "<p>Returns a single Amplitude reading at the moment it is called.\nFor continuous readings, run in the draw loop.</p>\n", 19918 "itemtype": "method", 19919 "name": "getLevel", 19920 "params": [ 19921 { 19922 "name": "channel", 19923 "description": "<p>Optionally return only channel 0 (left) or 1 (right)</p>\n", 19924 "type": "Number", 19925 "optional": true 19926 } 19927 ], 19928 "return": { 19929 "description": "Amplitude as a number between 0.0 and 1.0", 19930 "type": "Number" 19931 }, 19932 "example": [ 19933 "\n<div><code>\nfunction preload(){\n sound = loadSound('assets/beat.mp3');\n}\nfunction setup() {\n amplitude = new p5.Amplitude();\n sound.play();\n}\nfunction draw() {\n background(0);\n fill(255);\n var level = amplitude.getLevel();\n var size = map(level, 0, 1, 0, 200);\n ellipse(width/2, height/2, size, size);\n}\nfunction mouseClicked(){\n sound.stop();\n}\n</code></div>" 19934 ], 19935 "class": "p5.Amplitude", 19936 "module": "p5.sound", 19937 "submodule": "p5.sound" 19938 }, 19939 { 19940 "file": "lib/addons/p5.sound.js", 19941 "line": 2378, 19942 "description": "<p>Determines whether the results of Amplitude.process() will be\nNormalized. To normalize, Amplitude finds the difference the\nloudest reading it has processed and the maximum amplitude of\n1.0. Amplitude adds this difference to all values to produce\nresults that will reliably map between 0.0 and 1.0. However,\nif a louder moment occurs, the amount that Normalize adds to\nall the values will change. Accepts an optional boolean parameter\n(true or false). Normalizing is off by default.</p>\n", 19943 "itemtype": "method", 19944 "name": "toggleNormalize", 19945 "params": [ 19946 { 19947 "name": "boolean", 19948 "description": "<p>set normalize to true (1) or false (0)</p>\n", 19949 "type": "Boolean", 19950 "optional": true 19951 } 19952 ], 19953 "class": "p5.Amplitude", 19954 "module": "p5.sound", 19955 "submodule": "p5.sound" 19956 }, 19957 { 19958 "file": "lib/addons/p5.sound.js", 19959 "line": 2398, 19960 "description": "<p>Smooth Amplitude analysis by averaging with the last analysis\nframe. Off by default.</p>\n", 19961 "itemtype": "method", 19962 "name": "smooth", 19963 "params": [ 19964 { 19965 "name": "set", 19966 "description": "<p>smoothing from 0.0 <= 1</p>\n", 19967 "type": "Number" 19968 } 19969 ], 19970 "class": "p5.Amplitude", 19971 "module": "p5.sound", 19972 "submodule": "p5.sound" 19973 }, 19974 { 19975 "file": "lib/addons/p5.sound.js", 19976 "line": 2567, 19977 "description": "<p>Set the input source for the FFT analysis. If no source is\nprovided, FFT will analyze all sound in the sketch.</p>\n", 19978 "itemtype": "method", 19979 "name": "setInput", 19980 "params": [ 19981 { 19982 "name": "source", 19983 "description": "<p>p5.sound object (or web audio API source node)</p>\n", 19984 "type": "Object", 19985 "optional": true 19986 } 19987 ], 19988 "class": "p5.FFT", 19989 "module": "p5.sound", 19990 "submodule": "p5.sound" 19991 }, 19992 { 19993 "file": "lib/addons/p5.sound.js", 19994 "line": 2586, 19995 "description": "<p>Returns an array of amplitude values (between -1.0 and +1.0) that represent\na snapshot of amplitude readings in a single buffer. Length will be\nequal to bins (defaults to 1024). Can be used to draw the waveform\nof a sound.</p>\n", 19996 "itemtype": "method", 19997 "name": "waveform", 19998 "params": [ 19999 { 20000 "name": "bins", 20001 "description": "<p>Must be a power of two between\n 16 and 1024. Defaults to 1024.</p>\n", 20002 "type": "Number", 20003 "optional": true 20004 }, 20005 { 20006 "name": "precision", 20007 "description": "<p>If any value is provided, will return results\n in a Float32 Array which is more precise\n than a regular array.</p>\n", 20008 "type": "String", 20009 "optional": true 20010 } 20011 ], 20012 "return": { 20013 "description": "Array Array of amplitude values (-1 to 1)\n over time. Array length = bins.", 20014 "type": "Array" 20015 }, 20016 "class": "p5.FFT", 20017 "module": "p5.sound", 20018 "submodule": "p5.sound" 20019 }, 20020 { 20021 "file": "lib/addons/p5.sound.js", 20022 "line": 2629, 20023 "description": "<p>Returns an array of amplitude values (between 0 and 255)\nacross the frequency spectrum. Length is equal to FFT bins\n(1024 by default). The array indices correspond to frequencies\n(i.e. pitches), from the lowest to the highest that humans can\nhear. Each value represents amplitude at that slice of the\nfrequency spectrum. Must be called prior to using\n<code>getEnergy()</code>.</p>\n", 20024 "itemtype": "method", 20025 "name": "analyze", 20026 "params": [ 20027 { 20028 "name": "bins", 20029 "description": "<p>Must be a power of two between\n 16 and 1024. Defaults to 1024.</p>\n", 20030 "type": "Number", 20031 "optional": true 20032 }, 20033 { 20034 "name": "scale", 20035 "description": "<p>If "dB," returns decibel\n float measurements between\n -14
200350 and 0 (max).\n Otherwise returns integers from 0-255.</p>\n", 20036 "type": "Number", 20037 "optional": true 20038 } 20039 ], 20040 "return": { 20041 "description": "spectrum Array of energy (amplitude/volume)\n values across the frequency spectrum.\n Lowest energy (silence) = 0, highest\n possible is 255.", 20042 "type": "Array" 20043 }, 20044 "example": [ 20045 "\n<div><code>\nvar osc;\nvar fft;\n\nfunction setup(){\n createCanvas(100,100);\n osc = new p5.Oscillator();\n osc.amp(0);\n osc.start();\n fft = new p5.FFT();\n}\n\nfunction draw(){\n background(0);\n\n var freq = map(mouseX, 0, 800, 20, 15000);\n freq = constrain(freq, 1, 20000);\n osc.freq(freq);\n\n var spectrum = fft.analyze();\n noStroke();\n fill(0,255,0); // spectrum is green\n for (var i = 0; i< spectrum.length; i++){\n var x = map(i, 0, spectrum.length, 0, width);\n var h = -height + map(spectrum[i], 0, 255, height, 0);\n rect(x, height, width / spectrum.length, h );\n }\n\n stroke(255);\n text('Freq: ' + round(freq)+'Hz', 10, 10);\n\n isMouseOverCanvas();\n}\n\n// only play sound when mouse is over canvas\nfunction isMouseOverCanvas() {\n var mX = mouseX, mY = mouseY;\n if (mX > 0 && mX < width && mY < height && mY > 0) {\n osc.amp(0.5, 0.2);\n } else {\n osc.amp(0, 0.2);\n }\n}\n</code></div>\n\n" 20046 ], 20047 "class": "p5.FFT", 20048 "module": "p5.sound", 20049 "submodule": "p5.sound" 20050 }, 20051 { 20052 "file": "lib/addons/p5.sound.js", 20053 "line": 2721, 20054 "description": "<p>Returns the amount of energy (volume) at a specific\n<a href=\"https://en.wikipedia.org/wiki/Audio_frequency\" target=\"_blank\">\nfrequency</a>, or the average amount of energy between two\nfrequencies. Accepts Number(s) corresponding\nto frequency (in Hz), or a String corresponding to predefined\nfrequency ranges ("bass", "lowMid", "mid", "highMid", "treble").\nReturns a range between 0 (no energy/volume at that frequency) and\n255 (maximum energy).\n<em>NOTE: analyze() must be called prior to getEnergy(). Analyze()\ntells the FFT to analyze frequency data, and getEnergy() uses\nthe results determine the value at a specific frequency or\nrange of frequencies.</em></p></p>\n", 20055 "itemtype": "method", 20056 "name": "getEnergy", 20057 "params": [ 20058 { 20059 "name": "frequency1", 20060 "description": "<p>Will return a value representing\n energy at this frequency. Alternately,\n the strings "bass", "lowMid" "mid",\n "highMid", and "treble" will return\n predefined frequency ranges.</p>\n", 20061 "type": "Number|String" 20062 }, 20063 { 20064 "name": "frequency2", 20065 "description": "<p>If a second frequency is given,\n will return average amount of\n energy that exists between the\n two frequencies.</p>\n", 20066 "type": "Number", 20067 "optional": true 20068 } 20069 ], 20070 "return": { 20071 "description": "Energy Energy (volume/amplitude) from\n 0 and 255.", 20072 "type": "Number" 20073 }, 20074 "class": "p5.FFT", 20075 "module": "p5.sound", 20076 "submodule": "p5.sound" 20077 }, 20078 { 20079 "file": "lib/addons/p5.sound.js", 20080 "line": 2803, 20081 "description": "<p>Returns the\n<a href=\"http://en.wikipedia.org/wiki/Spectral_centroid\" target=\"_blank\">\nspectral centroid</a> of the input signal.\n<em>NOTE: analyze() must be called prior to getCentroid(). Analyze()\ntells the FFT to analyze frequency data, and getCentroid() uses\nthe results determine the spectral centroid.</em></p></p>\n", 20082 "itemtype": "method", 20083 "name": "getCentroid", 20084 "return": { 20085 "description": "Spectral Centroid Frequency Frequency of the spectral centroid in Hz.", 20086 "type": "Number" 20087 }, 20088 "example": [ 20089 "\n<div><code>\n\n\nfunction setup(){\ncnv = createCanvas(800,400);\nsound = new p5.AudioIn();\nsound.start();\nfft = new p5.FFT();\nsound.connect(fft);\n}\n\n\nfunction draw(){\n\nvar centroidplot = 0.0;\nvar spectralCentroid = 0;\n\n\nbackground(0);\nstroke(0,255,0);\nvar spectrum = fft.analyze();\nfill(0,255,0); // spectrum is green\n\n//draw the spectrum\n\nfor (var i = 0; i< spectrum.length; i++){\n var x = map(log(i), 0, log(spectrum.length), 0, width);
20089\n var h = map(spectrum[i], 0, 255, 0, height);\n var rectangle_width = (log(i+1)-log(i))*(width/log(spectrum.length));\n rect(x, height, rectangle_width, -h )\n}\n\nvar nyquist = 22050;\n\n// get the centroid\nspectralCentroid = fft.getCentroid();\n\n// the mean_freq_index calculation is for the display.\nvar mean_freq_index = spectralCentroid/(nyquist/spectrum.length);\n\ncentroidplot = map(log(mean_freq_index), 0, log(spectrum.length), 0, width);\n\n\nstroke(255,0,0); // the line showing where the centroid is will be red\n\nrect(centroidplot, 0, width / spectrum.length, height)\nnoStroke();\nfill(255,255,255); // text is white\ntextSize(40);\ntext(\"centroid: \"+round(spectralCentroid)+\" Hz\", 10, 40);\n}\n </code></div>" 20090 ], 20091 "class": "p5.FFT", 20092 "module": "p5.sound", 20093 "submodule": "p5.sound" 20094 }, 20095 { 20096 "file": "lib/addons/p5.sound.js", 20097 "line": 2884, 20098 "description": "<p>Smooth FFT analysis by averaging with the last analysis frame.</p>\n", 20099 "itemtype": "method", 20100 "name": "smooth", 20101 "params": [ 20102 { 20103 "name": "smoothing", 20104 "description": "<p>0.0 < smoothing < 1.0.\n Defaults to 0.8.</p>\n", 20105 "type": "Number" 20106 } 20107 ], 20108 "class": "p5.FFT", 20109 "module": "p5.sound", 20110 "submodule": "p5.sound" 20111 }, 20112 { 20113 "file": "lib/addons/p5.sound.js", 20114 "line": 2904, 20115 "description": "<p>Returns an array of average amplitude values for a given number\nof frequency bands split equally. N defaults to 16.\n<em>NOTE: analyze() must be called prior to linAverages(). Analyze()\ntells the FFT to analyze frequency data, and linAverages() uses\nthe results to group them into a smaller set of averages.</em></p></p>\n", 20116 "itemtype": "method", 20117 "name": "linAverages", 20118 "params": [ 20119 { 20120 "name": "N", 20121 "description": "<p>Number of returned frequency groups</p>\n", 20122 "type": "Number" 20123 } 20124 ], 20125 "return": { 20126 "description": "linearAverages Array of average amplitude values for each group", 20127 "type": "Array" 20128 }, 20129 "class": "p5.FFT", 20130 "module": "p5.sound", 20131 "submodule": "p5.sound" 20132 }, 20133 { 20134 "file": "lib/addons/p5.sound.js", 20135 "line": 2934, 20136 "description": "<p>Returns an array of average amplitude values of the spectrum, for a given\nset of <a href=\"https://en.wikipedia.org/wiki/Octave_band\" target=\"_blank\">\nOctave Bands</a>\n<em>NOTE: analyze() must be called prior to logAverages(). Analyze()\ntells the FFT to analyze frequency data, and logAverages() uses\nthe results to group them into a smaller set of averages.</em></p></p>\n", 20137 "itemtype": "method", 20138 "name": "logAverages", 20139 "params": [ 20140 { 20141 "name": "octaveBands", 20142 "description": "<p>Array of Octave Bands objects for grouping</p>\n", 20143 "type": "Array" 20144 } 20145 ], 20146 "return": { 20147 "description": "logAverages Array of average amplitude values for each group", 20148 "type": "Array" 20149 }, 20150 "class": "p5.FFT", 20151 "module": "p5.sound", 20152 "submodule": "p5.sound" 20153 }, 20154 { 20155 "file": "lib/addons/p5.sound.js", 20156 "line": 2964, 20157 "description": "<p>Calculates and Returns the 1/N\n<a href=\"https://en.wikipedia.org/wiki/Octave_band\" target=\"_blank\">Octave Bands</a>\nN defaults to 3 and minimum central frequency to 15.625Hz.\n(1/3 Octave Bands ~= 31 Frequency Bands)\nSetting fCtr0 to a central value of a higher octave will ignore the lower bands\nand produce less frequency groups.</p>\n", 20158 "itemtype": "method", 20159 "name": "getOctaveBands", 20160 "params": [ 20161 { 20162 "name": "N", 20163 "description": "<p>Specifies the 1/N type of generated octave bands</p>\n", 20164 "type": "Number" 20165 }, 20166 { 20167 "name": "fCtr0", 20168 "description": "<p>Minimum central frequency for the lowest band</p>\n", 20169 "type": "Number" 20170 } 20171 ], 20172 "return": { 20173 "description": "octaveBands Array of octave band objects with their bounds", 20174 "type": "Array" 20175 }, 20176 "class": "p5.FFT", 20177 "module": "p5.sound", 20178 "submodule": "p5.sound" 20179 }, 20180 { 20181 "file": "lib/addons/p5.sound.js", 20182 "line": 3022, 20183 "class": "p5.FFT", 20184 "module": "p5.sound", 20185 "submodule": "p5.sound" 20186 }, 20187 { 20188 "file": "lib/addons/p5.sound.js", 20189 "line": 3399, 20190 "class": "p5.FFT", 20191 "module": "p5.sound", 20192 "submodule": "p5.sound" 20193 }, 20194 { 20195 "file": "lib/addons/p5.sound.js", 20196 "line": 3420, 20197 "class": "p5.FFT", 20198 "module": "p5.sound", 20199 "submodule": "p5.sound" 20200 }, 20201 { 20202 "file": "lib/addons/p5.sound.js", 20203 "line": 3479, 20204 "class": "p5.FFT", 20205 "module": "p5.sound", 20206 "submodule": "p5.sound" 20207 }, 20208 { 20209 "file": "lib/addons/p5.sound.js", 20210 "line": 3797, 20211 "class": "p5.FFT", 20212 "module": "p5.sound", 20213 "submodule": "p5.sound" 20214 }, 20215 { 20216 "file": "lib/addons/p5.sound.js", 20217 "line": 3969, 20218 "class": "p5.FFT", 20219 "module": "p5.sound", 20220 "submodule": "p5.sound" 20221 }, 20222 { 20223 "file": "lib/addons/p5.sound.js", 20224 "line": 4127, 20225 "class": "p5.FFT", 20226 "module": "p5.sound", 20227 "submodule": "p5.sound" 20228 }, 20229 { 20230 "file": "lib/addons/p5.sound.js", 20231 "line": 4168, 20232 "class": "p5.FFT", 20233 "module": "p5.sound", 20234 "submodule": "p5.sound" 20235 }, 20236 { 20237 "file": "lib/addons/p5.sound.js", 20238 "line": 4238, 20239 "class": "p5.FFT", 20240 "module": "p5.sound", 20241 "submodule": "p5.sound" 20242 }, 20243 { 20244 "file": "lib/addons/p5.sound.js", 20245 "line": 4426, 20246 "class": "p5.FFT", 20247 "module": "p5.sound", 20248 "submodule": "p5.sound" 20249 }, 20250 { 20251 "file": "lib/addons/p5.sound.js", 20252 "line": 4483, 20253 "class": "p5.FFT", 20254 "module": "p5.sound", 20255 "submodule": "p5.sound" 20256 }, 20257 { 20258 "file": "lib/addons/p5.sound.js", 20259 "line": 4651, 20260 "class": "p5.FFT", 20261 "module": "p5.sound", 20262 "submodule": "p5.sound" 20263 }, 20264 { 20265 "file": "lib/addons/p5.sound.js", 20266 "line": 4699, 20267 "class": "p5.FFT", 20268 "module": "p5.sound", 20269 "submodule": "p5.sound" 20270 }, 20271 { 20272 "file": "lib/addons/p5.sound.js", 20273 "line": 4730, 20274 "class": "p5.FFT", 20275 "module": "p5.sound", 20276 "submodule": "p5.sound" 20277 }, 20278 { 20279 "file": "lib/addons/p5.sound.js", 20280 "line": 4751, 20281 "class": "p5.FFT", 20282 "module": "p5.sound", 20283 "submodule": "p5.sound" 20284 }, 20285 { 20286 "file": "lib/addons/p5.sound.js", 20287 "line": 4771, 20288 "class": "p5.FFT", 20289 "module": "p5.sound", 20290 "submodule": "p5.sound" 20291 }, 20292 { 20293 "file": "lib/addons/p5.sound.js", 20294 "line": 4873, 20295 "description": "<p>Fade to value, for smooth transitions</p>\n", 20296 "itemtype": "method", 20297 "name": "fade", 20298 "params": [ 20299 { 20300 "name": "value", 20301 "description": "<p>Value to set this signal</p>\n", 20302 "type": "Number" 20303 }, 20304 { 20305 "name": "secondsFromNow", 20306 "description": "<p>Length of fade, in seconds from now</p>\n", 20307 "type": "Number", 20308 "optional": true 20309 } 20310 ], 20311 "class": "p5.Signal", 20312 "module": "p5.sound", 20313 "submodule": "p5.sound" 20314 }, 20315 { 20316 "file": "lib/addons/p5.sound.js", 20317 "line": 4884, 20318 "description": "<p>Connect a p5.sound object or Web Audio node to this\np5.Signal so that its amplitude values can be scaled.</p>\n", 20319 "itemtype": "method", 20320 "name": "setInput", 20321 "params": [ 20322 { 20323 "name": "input", 20324 "description": "", 20325 "type": "Object" 20326 } 20327 ], 20328 "class": "p5.Signal", 20329 "module": "p5.sound", 20330 "submodule": "p5.sound" 20331 }, 20332 { 20333 "file": "lib/addons/p5.sound.js", 20334 "line": 4898, 20335 "description": "<p>Add a constant value to this audio signal,\nand return the resulting audio signal. Does\nnot change the value of the original signal,\ninstead it returns a new p5.SignalAdd.</p>\n", 20336 "itemtype": "method", 20337 "name": "add", 20338 "params": [ 20339 { 20340 "name": "number", 20341 "description": "", 20342 "type": "Number" 20343 } 20344 ], 20345 "return": { 20346 "description": "object", 20347 "type": "p5.Signal" 20348 }, 20349 "class": "p5.Signal", 20350 "module": "p5.sound", 20351 "submodule": "p5.sound" 20352 }, 20353 { 20354 "file": "lib/addons/p5.sound.js", 20355 "line": 4917, 20356 "description": "<p>
20356Multiply this signal by a constant value,\nand return the resulting audio signal. Does\nnot change the value of the original signal,\ninstead it returns a new p5.SignalMult.</p>\n", 20357 "itemtype": "method", 20358 "name": "mult", 20359 "params": [ 20360 { 20361 "name": "number", 20362 "description": "<p>to multiply</p>\n", 20363 "type": "Number" 20364 } 20365 ], 20366 "return": { 20367 "description": "object", 20368 "type": "p5.Signal" 20369 }, 20370 "class": "p5.Signal", 20371 "module": "p5.sound", 20372 "submodule": "p5.sound" 20373 }, 20374 { 20375 "file": "lib/addons/p5.sound.js", 20376 "line": 4936, 20377 "description": "<p>Scale this signal value to a given range,\nand return the result as an audio signal. Does\nnot change the value of the original signal,\ninstead it returns a new p5.SignalScale.</p>\n", 20378 "itemtype": "method", 20379 "name": "scale", 20380 "params": [ 20381 { 20382 "name": "number", 20383 "description": "<p>to multiply</p>\n", 20384 "type": "Number" 20385 }, 20386 { 20387 "name": "inMin", 20388 "description": "<p>input range minumum</p>\n", 20389 "type": "Number" 20390 }, 20391 { 20392 "name": "inMax", 20393 "description": "<p>input range maximum</p>\n", 20394 "type": "Number" 20395 }, 20396 { 20397 "name": "outMin", 20398 "description": "<p>input range minumum</p>\n", 20399 "type": "Number" 20400 }, 20401 { 20402 "name": "outMax", 20403 "description": "<p>input range maximum</p>\n", 20404 "type": "Number" 20405 } 20406 ], 20407 "return": { 20408 "description": "object", 20409 "type": "p5.Signal" 20410 }, 20411 "class": "p5.Signal", 20412 "module": "p5.sound", 20413 "submodule": "p5.sound" 20414 }, 20415 { 20416 "file": "lib/addons/p5.sound.js", 20417 "line": 5070, 20418 "description": "<p>Start an oscillator. Accepts an optional parameter to\ndetermine how long (in seconds from now) until the\noscillator starts.</p>\n", 20419 "itemtype": "method", 20420 "name": "start", 20421 "params": [ 20422 { 20423 "name": "time", 20424 "description": "<p>startTime in seconds from now.</p>\n", 20425 "type": "Number", 20426 "optional": true 20427 }, 20428 { 20429 "name": "frequency", 20430 "description": "<p>frequency in Hz.</p>\n", 20431 "type": "Number", 20432 "optional": true 20433 } 20434 ], 20435 "class": "p5.Oscillator", 20436 "module": "p5.sound", 20437 "submodule": "p5.sound" 20438 }, 20439 { 20440 "file": "lib/addons/p5.sound.js", 20441 "line": 5110, 20442 "description": "<p>Stop an oscillator. Accepts an optional parameter\nto determine how long (in seconds from now) until the\noscillator stops.</p>\n", 20443 "itemtype": "method", 20444 "name": "stop", 20445 "params": [ 20446 { 20447 "name": "secondsFromNow", 20448 "description": "<p>Time, in seconds from now.</p>\n", 20449 "type": "Number" 20450 } 20451 ], 20452 "class": "p5.Oscillator", 20453 "module": "p5.sound", 20454 "submodule": "p5.sound" 20455 }, 20456 { 20457 "file": "lib/addons/p5.sound.js", 20458 "line": 5126, 20459 "description": "<p>Set the amplitude between 0 and 1.0. Or, pass in an object\nsuch as an oscillator to modulate amplitude with an audio signal.</p>\n", 20460 "itemtype": "method", 20461 "name": "amp", 20462 "params": [ 20463 { 20464 "name": "vol", 20465 "description": "<p>between 0 and 1.0\n or a modulating signal/oscillator</p>\n", 20466 "type": "Number|Object" 20467 }, 20468 { 20469 "name": "rampTime", 20470 "description": "<p>create a fade that lasts rampTime</p>\n", 20471 "type": "Number", 20472 "optional": true 20473 }, 20474 { 20475 "name": "timeFromNow", 20476 "description": "<p>schedule this event to happen\n seconds from now</p>\n", 20477 "type": "Number", 20478 "optional": true 20479 } 20480 ], 20481 "return": { 20482 "description": "gain If no value is provided,\n returns the Web Audio API\n AudioParam that c
20482ontrols\n this oscillator's\n gain/amplitude/volume)", 20483 "type": "AudioParam" 20484 }, 20485 "class": "p5.Oscillator", 20486 "module": "p5.sound", 20487 "submodule": "p5.sound" 20488 }, 20489 { 20490 "file": "lib/addons/p5.sound.js", 20491 "line": 5161, 20492 "description": "<p>Set frequency of an oscillator to a value. Or, pass in an object\nsuch as an oscillator to modulate the frequency with an audio signal.</p>\n", 20493 "itemtype": "method", 20494 "name": "freq", 20495 "params": [ 20496 { 20497 "name": "Frequency", 20498 "description": "<p>Frequency in Hz\n or modulating signal/oscillator</p>\n", 20499 "type": "Number|Object" 20500 }, 20501 { 20502 "name": "rampTime", 20503 "description": "<p>Ramp time (in seconds)</p>\n", 20504 "type": "Number", 20505 "optional": true 20506 }, 20507 { 20508 "name": "timeFromNow", 20509 "description": "<p>Schedule this event to happen\n at x seconds from now</p>\n", 20510 "type": "Number", 20511 "optional": true 20512 } 20513 ], 20514 "return": { 20515 "description": "Frequency If no value is provided,\n returns the Web Audio API\n AudioParam that controls\n this oscillator's frequency", 20516 "type": "AudioParam" 20517 }, 20518 "example": [ 20519 "\n<div><code>\nvar osc = new p5.Oscillator(300);\nosc.start();\nosc.freq(40, 10);\n</code></div>" 20520 ], 20521 "class": "p5.Oscillator", 20522 "module": "p5.sound", 20523 "submodule": "p5.sound" 20524 }, 20525 { 20526 "file": "lib/addons/p5.sound.js", 20527 "line": 5220, 20528 "description": "<p>Set type to 'sine', 'triangle', 'sawtooth' or 'square'.</p>\n", 20529 "itemtype": "method", 20530 "name": "setType", 20531 "params": [ 20532 { 20533 "name": "type", 20534 "description": "<p>'sine', 'triangle', 'sawtooth' or 'square'.</p>\n", 20535 "type": "String" 20536 } 20537 ], 20538 "class": "p5.Oscillator", 20539 "module": "p5.sound", 20540 "submodule": "p5.sound" 20541 }, 20542 { 20543 "file": "lib/addons/p5.sound.js", 20544 "line": 5232, 20545 "description": "<p>Connect to a p5.sound / Web Audio object.</p>\n", 20546 "itemtype": "method", 20547 "name": "connect", 20548 "params": [ 20549 { 20550 "name": "unit", 20551 "description": "<p>A p5.sound or Web Audio object</p>\n", 20552 "type": "Object" 20553 } 20554 ], 20555 "class": "p5.Oscillator", 20556 "module": "p5.sound", 20557 "submodule": "p5.sound" 20558 }, 20559 { 20560 "file": "lib/addons/p5.sound.js", 20561 "line": 5249, 20562 "description": "<p>Disconnect all outputs</p>\n", 20563 "itemtype": "method", 20564 "name": "disconnect", 20565 "class": "p5.Oscillator", 20566 "module": "p5.sound", 20567 "submodule": "p5.sound" 20568 }, 20569 { 20570 "file": "lib/addons/p5.sound.js", 20571 "line": 5260, 20572 "description": "<p>Pan between Left (-1) and Right (1)</p>\n", 20573 "itemtype": "method", 20574 "name": "pan", 20575 "params": [ 20576 { 20577 "name": "panning", 20578 "description": "<p>Number between -1 and 1</p>\n", 20579 "type": "Number" 20580 }, 20581 { 20582 "name": "timeFromNow", 20583 "description": "<p>schedule this event to happen\n seconds from now</p>\n", 20584 "type": "Number" 20585 } 20586 ], 20587 "class": "p5.Oscillator", 20588 "module": "p5.sound", 20589 "submodule": "p5.sound" 20590 }, 20591 { 20592 "file": "lib/addons/p5.sound.js", 20593 "line": 5292, 20594 "description": "<p>Set the phase of an oscillator between 0.0 and 1.0.\nIn this implementation, phase is a delay time\nbased on the oscillator's current frequency.</p>\n", 20595 "itemtype": "method", 20596 "name": "phase", 20597 "params": [ 20598 { 20599 "name": "phase", 20600 "description": "<p>float between 0.0 and 1.0</p>\n", 20601 "type": "Number" 20602 } 20603 ], 20604 "class": "p5.Oscillator", 20605 "module": "p5.sound", 20606 "submodule": "p5.sound" 20607 }, 20608 { 20609 "file": "lib/addons/p5.sound.js", 20610 "line": 5346, 20611 "description": "<p>Add a value to the p5.Oscillator's output amplitude,\nand return the oscillator. Calling this method again\nwill override the initial add() with a new value.</p>\n", 20612 "itemtype": "method", 20613 "name": "add", 20614 "params": [ 20615 { 20616 "name": "number", 20617 "description": "<p>Constant number to add</p>\n", 20618 "type": "Number" 20619 } 20620 ], 20621 "return": { 20622 "description": "Oscillator Returns this oscillator\n with scaled output", 20623 "type": "p5.Oscillator" 20624 }, 20625 "class": "p5.Oscillator", 20626 "module": "p5.sound", 20627 "submodule": "p5.sound" 20628 }, 20629 { 20630 "file": "lib/addons/p5.sound.js", 20631 "line": 5363, 20632 "description": "<p>Multiply the p5.Oscillator's output amplitude\nby a fixed value (i.e. turn it up!). Calling this method\nagain will override the initial mult() with a new value.</p>\n", 20633 "itemtype": "method", 20634 "name": "mult", 20635 "params": [ 20636 { 20637 "name": "number", 20638 "description": "<p>Constant number to multiply</p>\n", 20639 "type": "Number" 20640 } 20641 ], 20642 "return": { 20643 "description": "Oscillator Returns this oscillator\n with multiplied output", 20644 "type": "p5.Oscillator" 20645 }, 20646 "class": "p5.Oscillator", 20647 "module": "p5.sound", 20648 "submodule": "p5.sound" 20649 }, 20650 { 20651 "file": "lib/addons/p5.sound.js", 20652 "line": 5379, 20653 "description": "<p>Scale this oscillator's amplitude values to a given\nrange, and return the oscillator. Calling this method\nagain will override the initial scale() with new values.</p>\n", 20654 "itemtype": "method", 20655 "name": "scale", 20656 "params": [ 20657 { 20658 "name": "inMin", 20659 "description": "<p>input range minumum</p>\n", 20660 "type": "Number" 20661 }, 20662 { 20663 "name": "inMax", 20664 "description": "<p>input range maximum</p>\n", 20665 "type": "Number" 20666 }, 20667 { 20668 "name": "outMin", 20669 "description": "<p>input range minumum</p>\n", 20670 "type": "Number" 20671 }, 20672 { 20673 "name": "outMax", 20674 "description": "<p>input range maximum</p>\n", 20675 "type": "Number" 20676 } 20677 ], 20678 "return": { 20679 "description": "Oscillator Returns this oscillator\n with scaled output", 20680 "type": "p5.Oscillator" 20681 }, 20682 "class": "p5.Oscillator", 20683 "module": "p5.sound", 20684 "submodule": "p5.sound" 20685 }, 20686 { 20687 "file": "lib/addons/p5.sound.js", 20688 "line": 5478, 20689 "class": "p5.SqrOsc", 20690 "module": "p5.sound", 20691 "submodule": "p5.sound" 20692 }, 20693 { 20694 "file": "lib/addons/p5.sound.js", 20695 "line": 5681, 20696 "class": "p5.SqrOsc", 20697 "module": "p5.sound", 20698 "submodule": "p5.sound" 20699 }, 20700 { 20701 "file": "lib/addons/p5.sound.js", 20702 "line": 5970, 20703 "description": "<p>Time until envelope reaches attackLevel</p>\n", 20704 "itemtype": "property", 20705 "name": "attackTime", 20706 "class": "p5.Env", 20707 "module": "p5.sound", 20708 "submodule": "p5.sound" 20709 }, 20710 { 20711 "file": "lib/addons/p5.sound.js", 20712 "line": 5975, 20713 "description": "<p>Level once attack is complete.</p>\n", 20714 "itemtype": "property", 20715 "name": "attackLevel", 20716 "class": "p5.Env", 20717 "module": "p5.sound", 20718 "submodule": "p5.sound" 20719 }, 20720 { 20721 "file": "lib/addons/p5.sound.js", 20722 "line": 5980, 20723 "description": "<p>Time until envelope reaches decayLevel.</p>\n", 20724 "itemtype": "property", 20725 "name": "decayTime", 20726 "class": "p5.Env", 20727 "module": "p5.sound", 20728 "submodule": "p5.sound" 20729 }, 20730 { 20731 "file": "lib/addons/p5.sound.js", 20732 "line": 5985, 20733 "description": "<p>Level after decay. The envelope will sustain here until it is released.</p>\n", 20734 "itemtype": "property", 20735 "name": "decayLevel", 20736 "class": "p5.Env", 20737 "module": "p5.sound", 20738 "submodule": "p5.sound" 20739 }, 20740 { 20741 "file": "lib/addons/p5.sound.js", 20742 "line": 5990, 20743 "description": "<p>Duration of the release portion of the envelope.</p>\n", 20744 "itemtype": "property", 20745 "name": "releaseTime", 20746 "class": "p5.Env", 20747 "module": "p5.sound", 20748 "submodule": "p5.sound" 20749 }, 20750 { 20751 "file": "lib/addons/p5.sound.js", 20752 "line": 5995, 20753 "description": "<p>Level at the end of the release.</p>\n", 20754 "itemtype": "property", 20755 "name": "releaseLevel", 20756 "class": "p5.Env", 20757 "module": "p5.sound", 20758 "submodule": "p5.sound" 20759 }, 20760 { 20761 "file": "lib/addons/p5.sound.js", 20762 "line": 6031, 20763 "description": "<p>Reset the envelope with a series of time/value pairs.</p>\n", 20764 "itemtype": "method", 20765 "name": "set", 20766 "params": [ 20767 { 20768 "name": "attackTime", 20769 "description": "<p>Time (in seconds) before level\n reaches attackLevel</p>\n", 20770 "type": "Number" 20771 }, 20772 { 20773 "name": "attackLevel", 20774 "description": "<p>Typically an amplitude between\n 0.0 and 1.0</p>\n", 20775 "type": "Number" 20776 }, 20777 { 20778 "name": "decayTime", 20779 "description": "<p>Time</p>\n", 20780 "type": "Number" 20781 }, 20782 { 20783 "name": "decayLevel", 20784 "description": "<p>Amplitude (In a standard ADSR envelope,\n decayLevel = sustainLevel)</p>\n", 20785 "type": "Number" 20786 }, 20787 { 20788 "name": "releaseTime", 20789 "description": "<p>Release Time (in seconds)</p>\n", 20790 "type": "Number" 20791 }, 20792 { 20793 "name": "releaseLevel", 20794 "description": "<p>Amplitude</p>\n", 20795 "type": "Number" 20796 } 20797 ], 20798 "example": [ 20799 "\n<div><code>\nvar t1 = 0.1;
20799 // attack time in seconds\nvar l1 = 0.7; // attack level 0.0 to 1.0\nvar t2 = 0.3; // decay time in seconds\nvar l2 = 0.1; // decay level 0.0 to 1.0\nvar t3 = 0.2; // sustain time in seconds\nvar l3 = 0.2; // sustain level 0.0 to 1.0\n// release level defaults to zero\n\nvar env;\nvar triOsc;\n\nfunction setup() {\n background(0);\n noStroke();\n fill(255);\n textAlign(CENTER);\n text('click to play', width/2, height/2);\n\n env = new p5.Env(t1, l1, t2, l2, t3, l3);\n triOsc = new p5.Oscillator('triangle');\n triOsc.amp(env); // give the env control of the triOsc's amp\n triOsc.start();\n}\n\n// mouseClick triggers envelope if over canvas\nfunction mouseClicked() {\n // is mouse over canvas?\n if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {\n env.play(triOsc);\n }\n}\n</code></div>\n" 20800 ], 20801 "class": "p5.Env", 20802 "module": "p5.sound", 20803 "submodule": "p5.sound" 20804 }, 20805 { 20806 "file": "lib/addons/p5.sound.js", 20807 "line": 6090, 20808 "description": "<p>Set values like a traditional\n<a href=\"https://en.wikipedia.org/wiki/Synthesizer#/media/File:ADSR_parameter.svg\">\nADSR envelope\n</a>.</p>\n", 20809 "itemtype": "method", 20810 "name": "setADSR", 20811 "params": [ 20812 { 20813 "name": "attackTime", 20814 "description": "<p>Time (in seconds before envelope\n reaches Attack Level</p>\n", 20815 "type": "Number" 20816 }, 20817 { 20818 "name": "decayTime", 20819 "description": "<p>Time (in seconds) before envelope\n reaches Decay/Sustain Level</p>\n", 20820 "type": "Number", 20821 "optional": true 20822 }, 20823 { 20824 "name": "susRatio", 20825 "description": "<p>Ratio between attackLevel and releaseLevel, on a scale from 0 to 1,\n where 1.0 = attackLevel, 0.0 = releaseLevel.\n The susRatio determines the decayLevel and the level at which the\n sustain portion of the envelope will sustain.\n For example, if attackLevel is 0.4, releaseLevel is 0,\n and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is\n increased to 1.0 (using <code>setRange</code>),\n then decayLevel would increase proportionally, to become 0.5.</p>\n", 20826 "type": "Number", 20827 "optional": true 20828 }, 20829 { 20830 "name": "releaseTime", 20831 "description": "<p>Time in seconds from now (defaults to 0)</p>\n", 20832 "type": "Number", 20833 "optional": true 20834 } 20835 ], 20836 "example": [ 20837 "\n<div><code>\nvar attackLevel = 1.0;\nvar releaseLevel = 0;\n\nvar attackTime = 0.001\nvar decayTime = 0.2;\nvar susPercent = 0.2;\nvar releaseTime = 0.5;\n\nvar env, triOsc;\n\nfunction setup() {\n var cnv = createCanvas(100, 100);\n\n textAlign(CENTER);\n text('click to play', width/2, height/2);\n\n env = new p5.Env();\n env.setADSR(attackTime, decayTime, susPercent, releaseTime);\n env.setRange(attackLevel, releaseLevel);\n\n triOsc = new p5.Oscillator('triangle');\n triOsc.amp(env);\n triOsc.start();\n triOsc.freq(220);\n\n cnv.mousePressed(playEnv);\n}\n\nfunction playEnv(){\n env.play();\n}\n</code></div>" 20838 ], 20839 "class": "p5.Env", 20840 "module": "p5.sound", 20841 "submodule": "p5.sound" 20842 }, 20843 { 20844 "file": "lib/addons/p5.sound.js", 20845 "line": 6155, 20846 "description": "<p>Set max (attackLevel) and min (releaseLevel) of envelope.</p>\n", 20847 "itemtype": "method", 20848 "name": "setRange", 20849 "params": [ 20850 { 20851 "name": "aLevel", 20852 "description": "<p>attack level (defaults to 1)</p>\n", 20853 "type": "Number" 20854 }, 20855 { 20856 "name": "rLevel", 20857 "description": "<p>release level (defaults to 0)</p>\n", 20858 "type": "Number" 20859 } 20860 ], 20861 "example": [ 20862 "\n<div><code>\nvar attackLevel = 1.0;\nvar releaseLevel = 0;\n\nvar attackTime = 0.001\nvar decayTime = 0.2;\nvar susPercent = 0.2;\nvar releaseTime = 0.5;\n\nvar env, triOsc;\n\nfunction setup() {\n var cnv = createCanvas(100, 100);\n\n textAlign(CENTER);\n text('click to play', width/2, height/2);\n\n env = new p5.Env();\n env.setADSR(attackTime, decayTime, susPercent, releaseTime);\n env.setRange(attackLevel, releaseLevel);\n\n triOsc = new p5.Oscillator('triangle');\n triOsc.amp(env);\n triOsc.start();\n triOsc.freq(220);\n\n cnv.mousePressed(playEnv);\n}\n\nfunction playEnv(){\n env.play();\n}\n</code></div>" 20863 ], 20864 "class": "p5.Env", 20865 "module": "p5.sound", 20866 "submodule": "p5.sound" 20867 }, 20868 { 20869 "file": "lib/addons/p5.sound.js", 20870 "line": 6234, 20871 "description": "<p>Assign a parameter to be controlled by this envelope.\nIf a p5.Sound object is given, then the p5.Env will c
20871ontrol its\noutput gain. If multiple inputs are provided, the env will\ncontrol all of them.</p>\n", 20872 "itemtype": "method", 20873 "name": "setInput", 20874 "params": [ 20875 { 20876 "name": "inputs", 20877 "description": "<p>A p5.sound object or\n Web Audio Param.</p>\n", 20878 "type": "Object", 20879 "optional": true, 20880 "multiple": true 20881 } 20882 ], 20883 "class": "p5.Env", 20884 "module": "p5.sound", 20885 "submodule": "p5.sound" 20886 }, 20887 { 20888 "file": "lib/addons/p5.sound.js", 20889 "line": 6249, 20890 "description": "<p>Set whether the envelope ramp is linear (default) or exponential.\nExponential ramps can be useful because we perceive amplitude\nand frequency logarithmically.</p>\n", 20891 "itemtype": "method", 20892 "name": "setExp", 20893 "params": [ 20894 { 20895 "name": "isExp", 20896 "description": "<p>true is exponential, false is linear</p>\n", 20897 "type": "Boolean" 20898 } 20899 ], 20900 "class": "p5.Env", 20901 "module": "p5.sound", 20902 "submodule": "p5.sound" 20903 }, 20904 { 20905 "file": "lib/addons/p5.sound.js", 20906 "line": 6267, 20907 "description": "<p>Play tells the envelope to start acting on a given input.\nIf the input is a p5.sound object (i.e. AudioIn, Oscillator,\nSoundFile), then Env will control its output volume.\nEnvelopes can also be used to control any <a href=\"\nhttp://docs.webplatform.org/wiki/apis/webaudio/AudioParam\">\nWeb Audio Audio Param.</a></p>\n", 20908 "itemtype": "method", 20909 "name": "play", 20910 "params": [ 20911 { 20912 "name": "unit", 20913 "description": "<p>A p5.sound object or\n Web Audio Param.</p>\n", 20914 "type": "Object" 20915 }, 20916 { 20917 "name": "startTime", 20918 "description": "<p>time from now (in seconds) at which to play</p>\n", 20919 "type": "Number", 20920 "optional": true 20921 }, 20922 { 20923 "name": "sustainTime", 20924 "description": "<p>time to sustain before releasing the envelope</p>\n", 20925 "type": "Number", 20926 "optional": true 20927 } 20928 ], 20929 "example": [ 20930 "\n<div><code>\nvar attackLevel = 1.0;\nvar releaseLevel = 0;\n\nvar attackTime = 0.001\nvar decayTime = 0.2;\nvar susPercent = 0.2;\nvar releaseTime = 0.5;\n\nvar env, triOsc;\n\nfunction setup() {\n var cnv = createCanvas(100, 100);\n\n textAlign(CENTER);\n text('click to play', width/2, height/2);\n\n env = new p5.Env();\n env.setADSR(attackTime, decayTime, susPercent, releaseTime);\n env.setRange(attackLevel, releaseLevel);\n\n triOsc = new p5.Oscillator('triangle');\n triOsc.amp(env);\n triOsc.start();\n triOsc.freq(220);\n\n cnv.mousePressed(playEnv);\n}\n\nfunction playEnv(){\n // trigger env on triOsc, 0 seconds from now\n // After decay, sustain for 0.2 seconds before release\n env.play(triOsc, 0, 0.2);\n}\n</code></div>" 20931 ], 20932 "class": "p5.Env", 20933 "module": "p5.sound", 20934 "submodule": "p5.sound" 20935 }, 20936 { 20937 "file": "lib/addons/p5.sound.js", 20938 "line": 6328, 20939 "description": "<p>Trigger the Attack, and Decay portion of the Envelope.\nSimilar to holding down a key on a piano, but it will\nhold the sustain level until you let go. Input can be\nany p5.sound object, or a <a href=\"\nhttp://docs.webplatform.org/wiki/apis/webaudio/AudioParam\">\nWeb Audio Param</a>.</p>\n", 20940 "itemtype": "method", 20941 "name": "triggerAttack", 20942 "params": [ 20943 { 20944 "name": "unit", 20945 "description": "<p>p5.sound Object or Web Audio Param</p>\n", 20946 "type": "Object" 20947 }, 20948 { 20949 "name": "secondsFromNow", 20950 "description": "<p>time from now (in seconds)</p>\n", 20951 "type": "Number" 20952 } 20953 ], 20954 "example": [ 20955 "\n<div><code>\n\nvar attackLevel = 1.0;\nvar releaseLevel = 0;\n\nvar attackTime = 0.001\nvar decayTime = 0.3;\nvar susPercent = 0.4;\nvar releaseTime = 0.5;\n\nvar env, triOsc;\n\nfunction setup() {\n var cnv = createCanvas(100, 100);\n background(200);\n textAlign(CENTER);\n text('click to play', width/2, height/2);\n\n env = new p5.Env();\n env.setADSR(attackTime, decayTime, susPercent, releaseTime);\n env.setRange(attackLevel, releaseLevel);\n\n triOsc = new p5.Oscillator('triangle');\n triOsc.amp(env);\n triOsc.start();\n triOsc.freq(220);\n\n cnv.mousePressed(envAttack);\n}\n\nfunction envAttack(){\n console.log('trigger attack');\n env.triggerAttack();\n\n background(0,255,0);\n text('attack!', width/2, height/2);\n}\n\nfunction mouseReleased() {\n env.triggerRelease();\n\n background(200);\n text('click to play', width/2, height/2);\n}\n</code></div>" 20956 ], 20957 "class": "p5.Env", 20958 "module": "p5.sound", 20959 "submodule": "p5.sound" 20960 }, 20961 { 20962 "file": "lib/addons/p5.sound.js", 20963 "line": 6435, 20964 "description": "<p>Trigger the Release of the Envelope. This is similar to releasing\nthe key on a piano and letting the sound fade according to the\nrelease level and release time.</p>\n", 20965 "itemtype": "method", 20966 "name": "triggerRelease", 20967 "params": [ 20968 { 20969 "name": "unit", 20970 "description": "<p>p5.sound Object or Web Audio Param</p>\n", 20971 "type": "Object" 20972 }, 20973 { 20974 "name": "secondsFromNow", 20975 "description": "<p>time to trigger the release</p>\n", 20976 "type": "Number" 20977 } 20978 ], 20979 "example": [ 20980 "\n<div><code>\n\nvar attackLevel = 1.0;\nvar releaseLevel = 0;\n\nvar attackTime = 0.001\nvar decayTime = 0.3;\nvar susPercent = 0.4;\nvar releaseTime = 0.5;\n\nvar env, triOsc;\n\nfunction setup() {\n var cnv = createCanvas(100, 100);\n background(200);\n textAlign(CENTER);\n text('click to play', width/2, height/2);\n\n env = new p5.Env();\n env.setADSR(attackTime, decayTime, susPercent, releaseTime);\n env.setRange(attackLevel, releaseLevel);\n\n triOsc = new p5.Oscillator('triangle');\n triOsc.amp(env);\n triOsc.start();\n triOsc.freq(220);\n\n cnv.mousePressed(envAttack);\n}\n\nfunction envAttack(){\n console.log('trigger attack');\n env.triggerAttack();\n\n background(0,255,0);\n text('attack!', width/2, height/2);\n}\n\nfunction mouseReleased() {\n env.triggerRelease();\n\n background(200);\n text('click to play', width/2, height/2);\n}\n</code></div>" 20981 ], 20982 "class": "p5.Env", 20983 "module": "p5.sound", 20984 "submodule": "p5.sound" 20985 }, 20986 { 20987 "file": "lib/addons/p5.sound.js", 20988 "line": 6532, 20989 "description": "<p>Exponentially ramp to a value using the first two\nvalues from <code><a href=\"#/p5.Env/setADSR\">setADSR(attackTime, decayTime)</a></code>\nas <a href=\"https://en.wikipedia.org/wiki/RC_time_constant\">\ntime constants</a> for simple exponential ramps.\nIf the value is higher than current value, it uses attackTime,\nwhile a decrease uses decayTime.</p>\n", 20990 "itemtype": "method", 20991 "name": "ramp", 20992 "params": [ 20993 { 20994 "name": "unit", 20995 "description": "<p>p5.sound Object or Web Audio Param</p>\n", 20996 "type": "Object" 20997 }, 20998 { 20999 "name": "secondsFromNow", 21000 "description": "<p>When to trigger the ramp</p>\n", 21001 "type": "Number" 21002 }, 21003 { 21004 "name": "v", 21005 "description": "<p>Target value</p>\n", 21006 "type": "Number" 21007 }, 21008 { 21009 "name": "v2", 21010 "description": "<p>Second target value (optional)</p>\n", 21011 "type": "Number", 21012 "optional": true 21013 } 21014 ], 21015 "example": [ 21016 "\n<div><code>\nvar env, osc, amp, cnv;\n\nvar attackTime = 0.001;\nvar decayTime = 0.2;\nvar attackLevel = 1;\nvar decayLevel = 0;\n\nfunction setup() {\n cnv = createCanvas(100, 100);\n fill(0,255,0);\n noStroke();\n\n env = new p5.Env();\n env.setADSR(attackTime, decayTime);\n\n osc = new p5.Oscillator();\n osc.amp(env);\n osc.start();\n\n amp = new p5.Amplitude();\n\n cnv.mousePressed(triggerRamp);\n}\n\nfunction triggerRamp() {\n env.ramp(osc, 0, attackLevel, decayLevel);\n}\n\nfunction draw() {\n background(20,20,20);\n text('click me', 10, 20);
21016\n var h = map(amp.getLevel(), 0, 0.4, 0, height);;\n\n rect(0, height, width, -h);\n}\n</code></div>" 21017 ], 21018 "class": "p5.Env", 21019 "module": "p5.sound", 21020 "submodule": "p5.sound" 21021 }, 21022 { 21023 "file": "lib/addons/p5.sound.js", 21024 "line": 6637, 21025 "description": "<p>Add a value to the p5.Oscillator's output amplitude,\nand return the oscillator. Calling this method\nagain will override the initial add() with new values.</p>\n", 21026 "itemtype": "method", 21027 "name": "add", 21028 "params": [ 21029 { 21030 "name": "number", 21031 "description": "<p>Constant number to add</p>\n", 21032 "type": "Number" 21033 } 21034 ], 21035 "return": { 21036 "description": "Envelope Returns this envelope\n with scaled output", 21037 "type": "p5.Env" 21038 }, 21039 "class": "p5.Env", 21040 "module": "p5.sound", 21041 "submodule": "p5.sound" 21042 }, 21043 { 21044 "file": "lib/addons/p5.sound.js", 21045 "line": 6653, 21046 "description": "<p>Multiply the p5.Env's output amplitude\nby a fixed value. Calling this method\nagain will override the initial mult() with new values.</p>\n", 21047 "itemtype": "method", 21048 "name": "mult", 21049 "params": [ 21050 { 21051 "name": "number", 21052 "description": "<p>Constant number to multiply</p>\n", 21053 "type": "Number" 21054 } 21055 ], 21056 "return": { 21057 "description": "Envelope Returns this envelope\n with scaled output", 21058 "type": "p5.Env" 21059 }, 21060 "class": "p5.Env", 21061 "module": "p5.sound", 21062 "submodule": "p5.sound" 21063 }, 21064 { 21065 "file": "lib/addons/p5.sound.js", 21066 "line": 6669, 21067 "description": "<p>Scale this envelope's amplitude values to a given\nrange, and return the envelope. Calling this method\nagain will override the initial scale() with new values.</p>\n", 21068 "itemtype": "method", 21069 "name": "scale", 21070 "params": [ 21071 { 21072 "name": "inMin", 21073 "description": "<p>input range minumum</p>\n", 21074 "type": "Number" 21075 }, 21076 { 21077 "name": "inMax", 21078 "description": "<p>input range maximum</p>\n", 21079 "type": "Number" 21080 }, 21081 { 21082 "name": "outMin", 21083 "description": "<p>input range minumum</p>\n", 21084 "type": "Number" 21085 }, 21086 { 21087 "name": "outMax", 21088 "description": "<p>input range maximum</p>\n", 21089 "type": "Number" 21090 } 21091 ], 21092 "return": { 21093 "description": "Envelope Returns this envelope\n with scaled output", 21094 "type": "p5.Env" 21095 }, 21096 "class": "p5.Env", 21097 "module": "p5.sound", 21098 "submodule": "p5.sound" 21099 }, 21100 { 21101 "file": "lib/addons/p5.sound.js", 21102 "line": 6773, 21103 "description": "<p>Set the width of a Pulse object (an oscillator that implements\nPulse Width Modulation).</p>\n", 21104 "itemtype": "method", 21105 "name": "width", 21106 "params": [ 21107 { 21108 "name": "width", 21109 "description": "<p>Width between the pulses (0 to 1.0,\n defaults to 0)</p>\n", 21110 "type": "Number", 21111 "optional": true 21112 } 21113 ], 21114 "class": "p5.Pulse", 21115 "module": "p5.sound", 21116 "submodule": "p5.sound" 21117 }, 21118 { 21119 "file": "lib/addons/p5.sound.js", 21120 "line": 6958, 21121 "description": "<p>Set type of noise to 'white', 'pink' or 'brown'.\nWhite is the default.</p>\n", 21122 "itemtype": "method", 21123 "name": "setType", 21124 "params": [ 21125 { 21126 "name": "type", 21127 "description": "<p>'white', 'pink' or 'brown'</p>\n", 21128 "type": "String", 21129 "optional": true 21130 } 21131 ], 21132 "class": "p5.Noise", 21133 "module": "p5.sound", 21134 "submodule": "p5.sound" 21135 }, 21136 { 21137 "file": "lib/addons/p5.sound.js", 21138 "line": 6988, 21139 "description": "<p>Start the noise</p>\n", 21140 "itemtype": "method", 21141 "name": "start", 21142 "class": "p5.Noise", 21143 "module": "p5.sound", 21144 "submodule": "p5.sound" 21145 }, 21146 { 21147 "file": "lib/addons/p5.sound.js", 21148 "line": 7005, 21149 "description": "<p>Stop the noise.</p>\n", 21150 "itemtype": "method", 21151 "name": "stop", 21152 "class": "p5.Noise", 21153 "module": "p5.sound", 21154 "submodule": "p5.sound" 21155 }, 21156 { 21157 "file": "lib/addons/p5.sound.js", 21158 "line": 7017, 21159 "description": "<p>Pan the noise.</p>\n", 21160 "itemtype": "method", 21161 "name": "pan", 21162 "params": [ 21163 { 21164 "name": "panning", 21165 "description": "<p>Number between -1 (left)\n and 1 (right)</p>\n", 21166 "type": "Number" 21167 }, 21168 { 21169 "name": "timeFromNow", 21170 "description": "<p>schedule this event to happen\n seconds from now</p>\n", 21171 "type": "Number" 21172 } 21173 ], 21174 "class": "p5.Noise", 21175 "module": "p5.sound", 21176 "submodule": "p5.sound" 21177 }, 21178 { 21179 "file": "lib/addons/p5.sound.js", 21180 "line": 7026, 21181 "description": "<p>Set the amplitude of the noise between 0 and 1.0. Or,\nmodulate amplitude with an audio signal such as an oscillator.</p>\n", 21182 "itemtype": "method", 21183 "name": "amp", 21184 "params": [ 21185 { 21186 "name": "volume", 21187 "description": "<p>amplitude between 0 and 1.0\n or modulating signal/oscillator</p>\n", 21188 "type": "Number|Object" 21189 }, 21190 { 21191 "name": "rampTime", 21192 "description": "<p>create a fade that lasts rampTime</p>\n", 21193 "type": "Number", 21194 "optional": true 21195 }, 21196 { 21197 "name": "timeFromNow", 21198 "description": "<p>schedule this event to happen\n seconds from now</p>\n", 21199 "type": "Number", 21200 "optional": true 21201 } 21202 ], 21203 "class": "p5.Noise", 21204 "module": "p5.sound", 21205 "submodule": "p5.sound" 21206 }, 21207 { 21208 "file": "lib/addons/p5.sound.js", 21209 "line": 7037, 21210 "description": "<p>Send output to a p5.sound or web audio object</p>\n", 21211 "itemtype": "method", 21212 "name": "connect", 21213 "params": [ 21214 { 21215 "name": "unit", 21216 "description": "", 21217 "type": "Object" 21218 } 21219 ], 21220 "class": "p5.Noise", 21221 "module": "p5.sound", 21222 "submodule": "p5.sound" 21223 }, 21224 { 21225 "file": "lib/addons/p5.sound.js", 21226 "line": 7043, 21227 "description": "<p>Disconnect all output.</p>\n", 21228 "itemtype": "method", 21229 "name": "disconnect", 21230 "class": "p5.Noise", 21231 "module": "p5.sound", 21232 "submodule": "p5.sound" 21233 }, 21234 { 21235 "file": "lib/addons/p5.sound.js", 21236 "line": 7117, 21237 "description": "<p>Client must allow browser to access their microphone / audioin source.\nDefault: false. Will become true when the client enables acces.</p>\n", 21238 "itemtype": "property", 21239 "name": "enabled", 21240 "type": "Boolean", 21241 "class": "p5.AudioIn", 21242 "module": "p5.sound", 21243 "submodule": "p5.sound" 21244 }, 21245 { 21246 "file": "lib/addons/p5.sound.js", 21247 "line": 7133, 21248 "description": "<p>Start processing audio input. This enables the use of other\nAudioIn methods like getLevel(). Note that by default, AudioIn\nis not connected to p5.sound's output. So you won't hear\nanything unless you use the connect() method.<br/></p>\n<p>Certain browsers limit access to the user's microphone. For example,\nChrome only allows access from localhost and over https. For this reason,\nyou may want to include an errorCallbackâa function that is called
21248in case\nthe browser won't provide mic access.</p>\n", 21249 "itemtype": "method", 21250 "name": "start", 21251 "params": [ 21252 { 21253 "name": "successCallback", 21254 "description": "<p>Name of a function to call on\n success.</p>\n", 21255 "type": "Function", 21256 "optional": true 21257 }, 21258 { 21259 "name": "errorCallback", 21260 "description": "<p>Name of a function to call if\n there was an error. For example,\n some browsers do not support\n getUserMedia.</p>\n", 21261 "type": "Function", 21262 "optional": true 21263 } 21264 ], 21265 "class": "p5.AudioIn", 21266 "module": "p5.sound", 21267 "submodule": "p5.sound" 21268 }, 21269 { 21270 "file": "lib/addons/p5.sound.js", 21271 "line": 7186, 21272 "description": "<p>Turn the AudioIn off. If the AudioIn is stopped, it cannot getLevel().\nIf re-starting, the user may be prompted for permission access.</p>\n", 21273 "itemtype": "method", 21274 "name": "stop", 21275 "class": "p5.AudioIn", 21276 "module": "p5.sound", 21277 "submodule": "p5.sound" 21278 }, 21279 { 21280 "file": "lib/addons/p5.sound.js", 21281 "line": 7202, 21282 "description": "<p>Connect to an audio unit. If no parameter is provided, will\nconnect to the master output (i.e. your speakers).<br/></p>\n", 21283 "itemtype": "method", 21284 "name": "connect", 21285 "params": [ 21286 { 21287 "name": "unit", 21288 "description": "<p>An object that accepts audio input,\n such as an FFT</p>\n", 21289 "type": "Object", 21290 "optional": true 21291 } 21292 ], 21293 "class": "p5.AudioIn", 21294 "module": "p5.sound", 21295 "submodule": "p5.sound" 21296 }, 21297 { 21298 "file": "lib/addons/p5.sound.js", 21299 "line": 7223, 21300 "description": "<p>Disconnect the AudioIn from all audio units. For example, if\nconnect() had been called, disconnect() will stop sending\nsignal to your speakers.<br/></p>\n", 21301 "itemtype": "method", 21302 "name": "disconnect", 21303 "class": "p5.AudioIn", 21304 "module": "p5.sound", 21305 "submodule": "p5.sound" 21306 }, 21307 { 21308 "file": "lib/addons/p5.sound.js", 21309 "line": 7235, 21310 "description": "<p>Read the Amplitude (volume level) of an AudioIn. The AudioIn\nclass contains its own instance of the Amplitude class to help\nmake it easy to get a microphone's volume level. Accepts an\noptional smoothing value (0.0 < 1.0). <em>NOTE: AudioIn must\n.start() before using .getLevel().</em><br/></p>\n", 21311 "itemtype": "method", 21312 "name": "getLevel", 21313 "params": [ 21314 { 21315 "name": "smoothing", 21316 "description": "<p>Smoothing is 0.0 by default.\n Smooths values based on previous values.</p>\n", 21317 "type": "Number", 21318 "optional": true 21319 } 21320 ], 21321 "return": { 21322 "description": "Volume level (between 0.0 and 1.0)", 21323 "type": "Number" 21324 }, 21325 "class": "p5.AudioIn", 21326 "module": "p5.sound", 21327 "submodule": "p5.sound" 21328 }, 21329 { 21330 "file": "lib/addons/p5.sound.js", 21331 "line": 7253, 21332 "description": "<p>Set amplitude (volume) of a mic input between 0 and 1.0. <br/></p>\n", 21333 "itemtype": "method", 21334 "name": "amp", 21335 "params": [ 21336 { 21337 "name": "vol", 21338 "description": "<p>between 0 and 1.0</p>\n", 21339 "type": "Number" 21340 }, 21341 { 21342 "name": "time", 21343 "description": "<p>ramp time (optional)</p>\n", 21344 "type": "Number", 21345 "optional": true 21346 } 21347 ], 21348 "class": "p5.AudioIn", 21349 "module": "p5.sound", 21350 "submodule": "p5.sound" 21351 }, 21352 { 21353 "file": "lib/addons/p5.sound.js", 21354 "line": 7272, 21355 "description": "<p>Returns a list of available input sources. This is a wrapper\nfor <a title="MediaDevices.enumerateDevices() - Web APIs | MDN" target="_blank" href=\n "<a href=\"https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/enumerateDevices\">https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/enumerateDevices</a>"</p>\n<blockquote>\n<p>and it returns a Promise.</p>\n</blockquote>\n", 21356 "itemtype": "method", 21357 "name": "getSources", 21358 "params": [ 21359 { 21360 "name": "successCallback", 21361 "description": "<p>This callback function handles the sources when they\n have been enumerated. The callback function\n receives the deviceList array as its only argument</p>\n", 21362 "type": "Function", 21363 "optional": true 21364 }, 21365 { 21366 "name": "errorCallback", 21367 "description": "<p>This optional callback receives the error\n message as its argument.</p>\n", 21368 "type": "Function", 21369 "optional": true 21370 } 21371 ], 21372 "return": { 21373 "description": "Returns a Promise that can be used in place of the callbacks, similar\n to the enumerateDevices() method", 21374 "type": "Object" 21375 }, 21376 "example": [ 21377 "\n <div><code>\n var audiograb;
21377\n\n function setup(){\n //new audioIn\n audioGrab = new p5.AudioIn();\n\n audioGrab.getSources(function(deviceList) {\n //print out the array of available sources\n console.log(deviceList);\n //set the source to the first item in the deviceList array\n audioGrab.setSource(0);\n });\n }\n </code></div>" 21378 ], 21379 "class": "p5.AudioIn", 21380 "module": "p5.sound", 21381 "submodule": "p5.sound" 21382 }, 21383 { 21384 "file": "lib/addons/p5.sound.js", 21385 "line": 7323, 21386 "description": "<p>Set the input source. Accepts a number representing a\nposition in the array returned by getSources().\nThis is only available in browsers that support\n<a title="MediaDevices.enumerateDevices() - Web APIs | MDN" target="_blank" href=\n"<a href=\"https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/enumerateDevices\">https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/enumerateDevices</a>"</p>\n<blockquote>\n<p>navigator.mediaDevices.enumerateDevices()</a>.<br/></p>\n</blockquote>\n", 21387 "itemtype": "method", 21388 "name": "setSource", 21389 "params": [ 21390 { 21391 "name": "num", 21392 "description": "<p>position of input source in the array</p>\n", 21393 "type": "Number" 21394 } 21395 ], 21396 "class": "p5.AudioIn", 21397 "module": "p5.sound", 21398 "submodule": "p5.sound" 21399 }, 21400 { 21401 "file": "lib/addons/p5.sound.js", 21402 "line": 7363, 21403 "class": "p5.AudioIn", 21404 "module": "p5.sound", 21405 "submodule": "p5.sound" 21406 }, 21407 { 21408 "file": "lib/addons/p5.sound.js", 21409 "line": 7379, 21410 "class": "p5.AudioIn", 21411 "module": "p5.sound", 21412 "submodule": "p5.sound" 21413 }, 21414 { 21415 "file": "lib/addons/p5.sound.js", 21416 "line": 7403, 21417 "class": "p5.AudioIn", 21418 "module": "p5.sound", 21419 "submodule": "p5.sound" 21420 }, 21421 { 21422 "file": "lib/addons/p5.sound.js", 21423 "line": 7429, 21424 "class": "p5.AudioIn", 21425 "module": "p5.sound", 21426 "submodule": "p5.sound" 21427 }, 21428 { 21429 "file": "lib/addons/p5.sound.js", 21430 "line": 7451, 21431 "class": "p5.AudioIn", 21432 "module": "p5.sound", 21433 "submodule": "p5.sound" 21434 }, 21435 { 21436 "file": "lib/addons/p5.sound.js", 21437 "line": 7473, 21438 "class": "p5.AudioIn", 21439 "module": "p5.sound", 21440 "submodule": "p5.sound" 21441 }, 21442 { 21443 "file": "lib/addons/p5.sound.js", 21444 "line": 7519, 21445 "class": "p5.AudioIn", 21446 "module": "p5.sound", 21447 "submodule": "p5.sound" 21448 }, 21449 { 21450 "file": "lib/addons/p5.sound.js", 21451 "line": 7550, 21452 "class": "p5.AudioIn", 21453 "module": "p5.sound", 21454 "submodule": "p5.sound" 21455 }, 21456 { 21457 "file": "lib/addons/p5.sound.js", 21458 "line": 7568, 21459 "class": "p5.AudioIn", 21460 "module": "p5.sound", 21461 "submodule": "p5.sound" 21462 }, 21463 { 21464 "file": "lib/addons/p5.sound.js", 21465 "line": 7905, 21466 "class": "p5.AudioIn", 21467 "module": "p5.sound", 21468 "submodule": "p5.sound" 21469 }, 21470 { 21471 "file": "lib/addons/p5.sound.js", 21472 "line": 7927, 21473 "class": "p5.AudioIn", 21474 "module": "p5.sound", 21475 "submodule": "p5.sound" 21476 }, 21477 { 21478 "file": "lib/addons/p5.sound.js", 21479 "line": 8003, 21480 "description": "<p>In classes that extend\np5.Effect, connect effect nodes\nto the wet parameter</p>\n", 21481 "class": "p5.Effect", 21482 "module": "p5.sound", 21483 "submodule": "p5.sound" 21484 }, 21485 { 21486 "file": "lib/addons/p5.sound.js", 21487 "line": 8016, 21488 "description": "<p>Set the output volume of the filter.</p>\n", 21489 "itemtype": "method", 21490 "name": "amp", 21491 "params": [ 21492 { 21493 "name": "vol", 21494 "description": "<p>amplitude between 0 and 1.0</p>\n", 21495 "type": "Number", 21496 "optional": true 21497 }, 21498 { 21499 "name": "rampTime", 21500 "description": "<p>create a fade that lasts until rampTime</p>\n", 21501 "type": "Number", 21502 "optional": true 21503 }, 21504 { 21505 "name": "tFromNow", 21506 "description": "<p>schedule this event to happen in tFromNow seconds</p>\n", 21507 "type": "Number", 21508 "optional": true 21509 } 21510 ],
21511 "class": "p5.Effect", 21512 "module": "p5.sound", 21513 "submodule": "p5.sound" 21514 }, 21515 { 21516 "file": "lib/addons/p5.sound.js", 21517 "line": 8033, 21518 "description": "<p>Link effects together in a chain\nExample usage: filter.chain(reverb, delay, panner);\nMay be used with an open-ended number of arguments</p>\n", 21519 "itemtype": "method", 21520 "name": "chain", 21521 "params": [ 21522 { 21523 "name": "arguments", 21524 "description": "<p>Chain together multiple sound objects</p>\n", 21525 "type": "Object", 21526 "optional": true 21527 } 21528 ], 21529 "class": "p5.Effect", 21530 "module": "p5.sound", 21531 "submodule": "p5.sound" 21532 }, 21533 { 21534 "file": "lib/addons/p5.sound.js", 21535 "line": 8050, 21536 "description": "<p>Adjust the dry/wet value.</p>\n", 21537 "itemtype": "method", 21538 "name": "drywet", 21539 "params": [ 21540 { 21541 "name": "fade", 21542 "description": "<p>The desired drywet value (0 - 1.0)</p>\n", 21543 "type": "Number", 21544 "optional": true 21545 } 21546 ], 21547 "class": "p5.Effect", 21548 "module": "p5.sound", 21549 "submodule": "p5.sound" 21550 }, 21551 { 21552 "file": "lib/addons/p5.sound.js", 21553 "line": 8062, 21554 "description": "<p>Send output to a p5.js-sound, Web Audio Node, or use signal to\ncontrol an AudioParam</p>\n", 21555 "itemtype": "method", 21556 "name": "connect", 21557 "params": [ 21558 { 21559 "name": "unit", 21560 "description": "", 21561 "type": "Object" 21562 } 21563 ], 21564 "class": "p5.Effect", 21565 "module": "p5.sound", 21566 "submodule": "p5.sound" 21567 }, 21568 { 21569 "file": "lib/addons/p5.sound.js", 21570 "line": 8073, 21571 "description": "<p>Disconnect all output.</p>\n", 21572 "itemtype": "method", 21573 "name": "disconnect", 21574 "class": "p5.Effect", 21575 "module": "p5.sound", 21576 "submodule": "p5.sound" 21577 }, 21578 { 21579 "file": "lib/addons/p5.sound.js", 21580 "line": 8181, 21581 "description": "<p>The p5.Filter is built with a\n<a href=\"http://www.w3.org/TR/webaudio/#BiquadFilterNode\">\nWeb Audio BiquadFilter Node</a>.</p>\n", 21582 "itemtype": "property", 21583 "name": "biquadFilter", 21584 "type": "DelayNode", 21585 "class": "p5.Filter", 21586 "module": "p5.sound", 21587 "submodule": "p5.sound" 21588 }, 21589 { 21590 "file": "lib/addons/p5.sound.js", 21591 "line": 8199, 21592 "description": "<p>Filter an audio signal according to a set\nof filter parameters.</p>\n", 21593 "itemtype": "method", 21594 "name": "process", 21595 "params": [ 21596 { 21597 "name": "Signal", 21598 "description": "<p>An object that outputs audio</p>\n", 21599 "type": "Object" 21600 }, 21601 { 21602 "name": "freq", 21603 "description": "<p>Frequency in Hz, from 10 to 22050</p>\n", 21604 "type": "Number", 21605 "optional": true 21606 }, 21607 { 21608 "name": "res", 21609 "description": "<p>Resonance/Width of the filter frequency\n from 0.001 to 1000</p>\n", 21610 "type": "Number", 21611 "optional": true 21612 } 21613 ], 21614 "class": "p5.Filter", 21615 "module": "p5.sound", 21616 "submodule": "p5.sound" 21617 }, 21618 { 21619 "file": "lib/addons/p5.sound.js", 21620 "line": 8213, 21621 "description": "<p>Set the frequency and the resonance of the filter.</p>\n", 21622 "itemtype": "method", 21623 "name": "set", 21624 "params": [ 21625 { 21626 "name": "freq", 21627 "description": "<p>Frequency in Hz, from 10 to 22050</p>\n", 21628 "type": "Number", 21629 "optional": true 21630 }, 21631 { 21632 "name": "res", 21633 "description": "<p>Resonance (Q) from 0.001 to 1000</p>\n", 21634 "type": "Number", 21635 "optional": true 21636 }, 21637 { 21638 "name": "timeFromNow", 21639 "description": "<p>schedule this event to happen\n seconds from now</p>\n", 21640 "type": "Number", 21641 "optional": true 21642 } 21643 ], 21644 "class": "p5.Filter", 21645 "module": "p5.sound", 21646 "submodule": "p5.sound" 21647 }, 21648 { 21649 "file": "lib/addons/p5.sound.js", 21650 "line": 8230, 21651 "description": "<p>Set the filter frequency, in Hz, from 10 to 22050 (the range of\
21651nhuman hearing, although in reality most people hear in a narrower\nrange).</p>\n", 21652 "itemtype": "method", 21653 "name": "freq", 21654 "params": [ 21655 { 21656 "name": "freq", 21657 "description": "<p>Filter Frequency</p>\n", 21658 "type": "Number" 21659 }, 21660 { 21661 "name": "timeFromNow", 21662 "description": "<p>schedule this event to happen\n seconds from now</p>\n", 21663 "type": "Number", 21664 "optional": true 21665 } 21666 ], 21667 "return": { 21668 "description": "value Returns the current frequency value", 21669 "type": "Number" 21670 }, 21671 "class": "p5.Filter", 21672 "module": "p5.sound", 21673 "submodule": "p5.sound" 21674 }, 21675 { 21676 "file": "lib/addons/p5.sound.js", 21677 "line": 8255, 21678 "description": "<p>Controls either width of a bandpass frequency,\nor the resonance of a low/highpass cutoff frequency.</p>\n", 21679 "itemtype": "method", 21680 "name": "res", 21681 "params": [ 21682 { 21683 "name": "res", 21684 "description": "<p>Resonance/Width of filter freq\n from 0.001 to 1000</p>\n", 21685 "type": "Number" 21686 }, 21687 { 21688 "name": "timeFromNow", 21689 "description": "<p>schedule this event to happen\n seconds from now</p>\n", 21690 "type": "Number", 21691 "optional": true 21692 } 21693 ], 21694 "return": { 21695 "description": "value Returns the current res value", 21696 "type": "Number" 21697 }, 21698 "class": "p5.Filter", 21699 "module": "p5.sound", 21700 "submodule": "p5.sound" 21701 }, 21702 { 21703 "file": "lib/addons/p5.sound.js", 21704 "line": 8277, 21705 "description": "<p>Controls the gain attribute of a Biquad Filter.\nThis is distinctly different from .amp() which is inherited from p5.Effect\n.amp() controls the volume via the output gain node\np5.Filter.gain() controls the gain parameter of a Biquad Filter node.</p>\n", 21706 "itemtype": "method", 21707 "name": "gain", 21708 "params": [ 21709 { 21710 "name": "gain", 21711 "description": "", 21712 "type": "Number" 21713 } 21714 ], 21715 "return": { 21716 "description": "Returns the current or updated gain value", 21717 "type": "Number" 21718 }, 21719 "class": "p5.Filter", 21720 "module": "p5.sound", 21721 "submodule": "p5.sound" 21722 }, 21723 { 21724 "file": "lib/addons/p5.sound.js", 21725 "line": 8298, 21726 "description": "<p>Toggle function. Switches between the specified type and allpass</p>\n", 21727 "itemtype": "method", 21728 "name": "toggle", 21729 "return": { 21730 "description": "[Toggle value]", 21731 "type": "Boolean" 21732 }, 21733 "class": "p5.Filter", 21734 "module": "p5.sound", 21735 "submodule": "p5.sound" 21736 }, 21737 { 21738 "file": "lib/addons/p5.sound.js", 21739 "line": 8313, 21740 "description": "<p>Set the type of a p5.Filter. Possible types include:\n"lowpass" (default), "highpass", "bandpass",\n"lowshelf", "highshelf", "peaking", "notch",\n"allpass".</p>\n", 21741 "itemtype": "method", 21742 "name": "setType", 21743 "params": [ 21744 { 21745 "name": "t", 21746 "description": "", 21747 "type": "String" 21748 } 21749 ], 21750 "class": "p5.Filter", 21751 "module": "p5.sound", 21752 "submodule": "p5.sound" 21753 }, 21754 { 21755 "file": "lib/addons/p5.sound.js", 21756 "line": 8516, 21757 "description": "<p>The p5.EQ is built with abstracted p5.Filter objects.\nTo modify any bands, use methods of the <a\nhref=\"/reference/#/p5.Filter\" title=\"p5.Filter reference\">\np5.Filter</a> API, especially <code>gain</code> and <code>freq</code>.\nBands are stored in an array, with indices 0 - 3, or 0 - 7</p>\n", 21758 "itemtype": "property", 21759 "name": "bands", 21760 "type": "Array", 21761 "class": "p5.EQ", 21762 "module": "p5.sound", 21763 "submodule": "p5.sound" 21764 }, 21765 { 21766 "file": "lib/addons/p5.sound.js", 21767 "line": 8551, 21768 "description": "<p>Process an input by connecting it to the EQ</p>\n", 21769 "itemtype": "method", 21770 "name": "process", 21771 "params": [ 21772 { 21773 "name": "src", 21774 "description": "<p>Audio source</p>\n", 21775 "type": "Object" 21776 } 21777 ], 21778 "class": "p5.EQ", 21779 "module": "p5.sound", 21780 "submodule": "p5.sound" 21781 }, 21782 { 21783 "file": "lib/addons/p5.sound.js", 21784 "line": 8637, 21785 "description": "<p><a title=\"Web Audio Panner docs\" href=\n\"https://developer.mozilla.org/en-US/docs/Web/API/PannerNode\">\nWeb Audio Spatial Panner Node</a></p>\n<p>Properties include</p>\n<ul>\n<li><a title="w3 spec for Panning Model"\nhref="<a href=\"https://www.w3.org/TR/webaudio/#idl-def-PanningModelType\">https://www.w3.org/TR/webaudio/#idl-def-PanningModelType</a>"<blockquote>\n<p>panningModel</a>: "equal power" or "HRTF"</p>\n</blockquote>\n</li>\n<li><a title="w3 spec for Distance Model"\nhref="<a href=\"https://www.w3.org/TR/webaudio/#idl-def-DistanceModelType\">https://www.w3.org/TR/webaudio/#idl-def-DistanceModelType</a>"<blockquote>\n<p>distanceModel</a>: "linear", "inverse", or "exponential"</p>\n</blockquote>\n</li>\n</ul>\n", 21786 "itemtype": "property", 21787 "name": "panner", 21788 "type": "AudioNode", 21789 "class": "p5.Panner3D", 21790 "module": "p5.sound", 21791 "submodule": "p5.sound" 21792 }, 21793 { 21794 "file": "lib/addons/p5.sound.js", 21795 "line": 8660, 21796 "description": "<p>Connect an audio sorce</p>\n", 21797 "itemtype": "method", 21798 "name": "process", 21799 "params": [ 21800 { 21801 "name": "src", 21802 "description": "<p>Input source</p>\n", 21803 "type": "Object" 21804 } 21805 ], 21806 "class": "p5.Panner3D", 21807 "module": "p5.sound", 21808 "submodule": "p5.sound" 21809 }, 21810 { 21811 "file": "lib/addons/p5.sound.js", 21812 "line": 8669, 21813 "description": "<p>Set the X,Y,Z position of the Panner</p>\n", 21814 "itemtype": "method", 21815 "name": "set", 21816 "params": [ 21817 { 21818 "name": "xVal", 21819 "description": "", 21820 "type": "Number" 21821 }, 21822 { 21823 "name": "yVal", 21824 "description": "", 21825 "type": "Number" 21826 }, 21827 { 21828 "name": "zVal", 21829 "description": "", 21830 "type": "Number" 21831 }, 21832 { 21833 "name": "time", 21834 "description": "", 21835 "type": "Number" 21836 } 21837 ], 21838 "return": { 21839 "description": "Updated x, y, z values as an array", 21840 "type": "Array" 21841 }, 21842 "class": "p5.Panner3D", 21843 "module": "p5.sound", 21844 "submodule": "p5.sound" 21845 }, 21846 { 21847 "file": "lib/addons/p5.sound.js", 21848 "line": 8688, 21849 "description": "<p>Getter and setter methods for position coordinates</p>\n", 21850 "itemtype": "method", 21851 "name": "positionX", 21852 "return": { 21853 "description": "updated coordinate value", 21854 "type": "Number" 21855 }, 21856 "class": "p5.Panner3D", 21857 "module": "p5.sound", 21858 "submodule": "p5.sound" 21859 }, 21860 { 21861 "file": "lib/addons/p5.sound.js", 21862 "line": 8693, 21863 "description": "<p>Getter and setter methods for position coordinates</p>\n", 21864 "itemtype": "method", 21865 "name": "positionY", 21866 "return": { 21867 "description": "updated coordinate value", 21868 "type": "Number" 21869 }, 21870 "class": "p5.Panner3D", 21871 "module": "p5.sound", 21872 "submodule": "p5.sound" 21873 }, 21874 { 21875 "file": "lib/addons/p5.sound.js", 21876 "line": 8698, 21877 "description": "<p>Getter and setter methods for position coordinates</p>\n", 21878 "itemtype": "method", 21879 "name": "positionZ", 21880 "return": { 21881 "description": "updated coordinate value", 21882 "type": "Number" 21883 }, 21884 "class": "p5.Panner3D", 21885 "module": "p5.sound", 21886 "submodule": "p5.sound" 21887 }, 21888 { 21889 "file": "lib/addons/p5.sound.js", 21890 "line": 8736, 21891 "description": "<p>Set the X,Y,Z position of the Panner</p>\n", 21892 "itemtype": "method", 21893 "name": "orient", 21894 "params": [ 21895 { 21896 "name": "xVal", 21897 "description": "", 21898 "type": "Number" 21899 }, 21900 { 21901 "name": "yVal", 21902 "description": "", 21903 "type": "Number" 21904 }, 21905 { 21906 "name": "zVal", 21907 "description": "", 21908 "type": "Number" 21909 }, 21910 { 21911 "name": "time", 21912 "description": "", 21913 "type": "Number" 21914 } 21915 ], 21916 "return": { 21917 "description": "Updated x, y, z values as an array", 21918 "type": "Array" 21919 }, 21920 "class": "p5.Panner3D", 21921 "module": "p5.sound", 21922 "submodule": "p5.sound" 21923 }, 21924 { 21925 "file": "lib/addons/p5.sound.js", 21926 "line": 8755, 21927 "description": "<p>Getter and setter methods for orient coordinates</p>\n", 21928 "itemtype": "method", 21929 "name": "orientX", 21930 "return": { 21931 "description": "updated coordinate value", 21932 "type": "Number" 21933 }, 21934 "class": "p5.Panner3D", 21935 "module": "p5.sound", 21936 "submodule": "p5.sound" 21937 }, 21938 { 21939 "file": "lib/addons/p5.sound.js", 21940 "line": 8760, 21941 "description": "<p>Getter and setter methods for orient coordinates</p>\n", 21942 "itemtype": "method", 21943 "name": "orientY", 21944 "return": { 21945 "description": "updated coordinate value", 21946 "type": "Number" 21947 }, 21948 "class": "p5.Panner3D", 21949 "module": "p5.sound", 21950 "submodule": "p5.sound" 21951 }, 21952 { 21953 "file": "lib/addons/p5.sound.js", 21954 "line": 8765, 21955 "description": "<p>Getter and setter methods for orient coordinates</p>\n", 21956 "itemtype": "method", 21957 "name": "orientZ", 21958 "return": { 21959 "description": "updated coordinate value", 21960 "type": "Number" 21961 }, 21962 "class": "p5.Panner3D", 21963 "module": "p5.sound", 21964 "submodule": "p5.sound" 21965 }, 21966 { 21967 "file": "lib/addons/p5.sound.js", 21968 "line": 8803, 21969 "description": "<p>Set the rolloff factor and max distance</p>\n", 21970 "itemtype": "method", 21971 "name": "setFalloff", 21972 "params": [ 21973 { 21974 "name": "maxDistance", 21975 "description": "", 21976 "type": "Number", 21977 "optional": true 21978 }, 21979 { 21980 "name": "rolloffFactor", 21981 "description": "", 21982 "type": "Number", 21983 "optional": true 21984 } 21985 ], 21986 "class": "p5.Panner3D", 21987 "module": "p5.sound", 21988 "submodule": "p5.sound" 21989 }, 21990 { 21991 "file": "lib/addons/p5.sound.js", 21992 "line": 8813, 21993 "description": "<p>Maxium distance between the source and the listener</p>\n", 21994 "itemtype": "method", 21995 "name": "maxDist", 21996 "params": [ 21997 { 21998 "name": "maxDistance", 21999 "description": "", 22000 "type": "Number" 22001 } 22002 ], 22003 "return": { 22004 "description": "updated value", 22005 "type": "Number" 22006 }, 22007 "class": "p5.Panner3D", 22008 "module": "p5.sound", 22009 "submodule": "p5.sound" 22010 }, 22011 { 22012 "file": "lib/addons/p5.sound.js", 22013 "line": 8825, 22014 "description": "<p>How quickly the volume is reduced as the source moves away from the listener</p>\n", 22015 "itemtype": "method", 22016 "name": "rollof", 22017 "params": [ 22018 { 22019 "name": "rolloffFactor", 22020 "description": "", 22021 "type": "Number" 22022 } 22023 ], 22024 "return": { 22025 "description": "updated value", 22026 "type": "Number" 22027 }, 22028 "class": "p5.Panner3D", 22029 "module": "p5.sound", 22030 "submodule": "p5.sound" 22031 }, 22032 { 22033 "file": "lib/addons/p5.sound.js", 22034 "line": 9128, 22035 "description": "<p>The p5.Delay is built with two\n<a href=\"http://www.w3.org/TR/webaudio/#DelayNode\">\nWeb Audio Delay Nodes</a>, one for each stereo channel.</p>\n", 22036 "itemtype": "property", 22037 "name": "leftDelay", 22038 "type": "DelayNode", 22039 "class": "p5.Delay", 22040 "module": "p5.sound", 22041 "submodule": "p5.sound" 22042 }, 22043 { 22044 "file": "lib/addons/p5.sound.js", 22045 "line": 9136, 22046 "description": "<p>The p5.Delay is built with two\n<a href=\"http://www.w3.org/TR/webaudio/#DelayNode\">\nWeb Audio Delay Nodes</a>, one for each stereo channel.</p>\n", 22047 "itemtype": "property", 22048 "name": "rightDelay", 22049 "type": "DelayNode", 22050 "class": "p5.Delay", 22051 "module": "p5.sound", 22052 "submodule": "p5.sound" 22053 }, 22054 { 22055 "file": "lib/addons/p5.sound.js", 22056 "line": 9168, 22057 "description": "<p>Add delay to an audio signal according to a set\nof delay parameters.</p>\n", 22058 "itemtype": "method", 22059 "name": "process", 22060 "params": [ 22061 { 22062 "name": "Signal", 22063 "description": "<p>An object that outputs audio</p>\n", 22064 "type": "Object" 22065 }, 22066 { 22067 "name": "delayTime", 22068 "description": "<p>Time (in seconds) of the delay/echo.\n Some browsers limit delayTime to\n 1 second.</p>\n", 22069 "type": "Number", 22070 "optional": true 22071 }, 22072 { 22073 "name": "feedback", 22074 "description": "<p>sends the delay back through itself\n in a loop that decreases in volume\n each time.</p>\n", 22075 "type": "Number", 22076 "optional": true 22077 }, 22078 { 22079 "name": "lowPass", 22080
22080 "description": "<p>Cutoff frequency. Only frequencies\n below the lowPass will be part of the\n delay.</p>\n", 22081 "type": "Number", 22082 "optional": true 22083 } 22084 ], 22085 "class": "p5.Delay", 22086 "module": "p5.sound", 22087 "submodule": "p5.sound" 22088 }, 22089 { 22090 "file": "lib/addons/p5.sound.js", 22091 "line": 9203, 22092 "description": "<p>Set the delay (echo) time, in seconds. Usually this value will be\na floating point number between 0.0 and 1.0.</p>\n", 22093 "itemtype": "method", 22094 "name": "delayTime", 22095 "params": [ 22096 { 22097 "name": "delayTime", 22098 "description": "<p>Time (in seconds) of the delay</p>\n", 22099 "type": "Number" 22100 } 22101 ], 22102 "class": "p5.Delay", 22103 "module": "p5.sound", 22104 "submodule": "p5.sound" 22105 }, 22106 { 22107 "file": "lib/addons/p5.sound.js", 22108 "line": 9222, 22109 "description": "<p>Feedback occurs when Delay sends its signal back through its input\nin a loop. The feedback amount determines how much signal to send each\ntime through the loop. A feedback greater than 1.0 is not desirable because\nit will increase the overall output each time through the loop,\ncreating an infinite feedback loop. The default value is 0.5</p>\n", 22110 "itemtype": "method", 22111 "name": "feedback", 22112 "params": [ 22113 { 22114 "name": "feedback", 22115 "description": "<p>0.0 to 1.0, or an object such as an\n Oscillator that can be used to\n modulate this param</p>\n", 22116 "type": "Number|Object" 22117 } 22118 ], 22119 "return": { 22120 "description": "Feedback value", 22121 "type": "Number" 22122 }, 22123 "class": "p5.Delay", 22124 "module": "p5.sound", 22125 "submodule": "p5.sound" 22126 }, 22127 { 22128 "file": "lib/addons/p5.sound.js", 22129 "line": 9250, 22130 "description": "<p>Set a lowpass filter frequency for the delay. A lowpass filter\nwill cut off any frequencies higher than the filter frequency.</p>\n", 22131 "itemtype": "method", 22132 "name": "filter", 22133 "params": [ 22134 { 22135 "name": "cutoffFreq", 22136 "description": "<p>A lowpass filter will cut off any\n frequencies higher than the filter frequency.</p>\n", 22137 "type": "Number|Object" 22138 }, 22139 { 22140 "name": "res", 22141 "description": "<p>Resonance of the filter frequency\n cutoff, or an object (i.e. a p5.Oscillator)\n that can be used to modulate this parameter.\n High numbers (i.e. 15) will produce a resonance,\n low numbers (i.e. .2) will produce a slope.</p>\n", 22142 "type": "Number|Object" 22143 } 22144 ], 22145 "class": "p5.Delay", 22146 "module": "p5.sound", 22147 "submodule": "p5.sound" 22148 }, 22149 { 22150 "file": "lib/addons/p5.sound.js", 22151 "line": 9267, 22152 "description": "<p>Choose a preset type of delay. 'pingPong' bounces the signal\nfrom the left to the right channel to produce a stereo effect.\nAny other parameter will revert to the default delay setting.</p>\n", 22153 "itemtype": "method", 22154 "name": "setType", 22155 "params": [ 22156 { 22157 "name": "type", 22158 "description": "<p>'pingPong' (1) or 'default' (0)</p>\n", 22159 "type": "String|Number" 22160 } 22161 ], 22162 "class": "p5.Delay", 22163 "module": "p5.sound", 22164 "submodule": "p5.sound" 22165 }, 22166 { 22167 "file": "lib/addons/p5.sound.js", 22168 "line": 9300, 22169 "description": "<p>Set the output level of the delay effect.</p>\n", 22170 "itemtype": "method", 22171 "name": "amp", 22172 "params": [ 22173 { 22174 "name": "volume", 22175 "description": "<p>amplitude between 0 and 1.0</p>\n", 22176 "type": "Number" 22177 }, 22178 { 22179 "name": "rampTime", 22180 "description": "<p>create a fade that lasts rampTime</p>\n", 22181 "type": "Number", 22182 "optional": true 22183 }, 22184 { 22185 "name": "timeFromNow", 22186 "description": "<p>schedule this event to happen\n seconds from now</p>\n", 22187 "type": "Number", 22188 "optional": true 22189 } 22190 ], 22191 "class": "p5.Delay", 22192 "module": "p5.sound", 22193 "submodule": "p5.sound" 22194 }, 22195 { 22196 "file": "lib/addons/p5.sound.js", 22197 "line": 9309, 22198 "description": "<p>Send output to a p5.sound or web audio object</p>\n", 22199 "itemtype": "method", 22200 "name": "connect", 22201 "params": [ 22202 { 22203 "name": "unit", 22204 "description": "", 22205 "type": "Object" 22206 } 22207 ], 22208 "class": "p5.Delay", 22209 "module": "p5.sound", 22210 "submodule": "p5.sound" 22211 }, 22212 { 22213 "file": "lib/addons/p5.sound.js", 22214 "line": 9315, 22215 "description": "<p>Disconnect all output.</p>\n", 22216 "itemtype": "method", 22217 "name": "disconnect", 22218 "class": "p5.Delay", 22219 "module": "p5.sound", 22220 "submodule": "p5.sound" 22221 }, 22222 { 22223 "file": "lib/addons/p5.sound.js", 22224 "line": 9394, 22225 "description": "<p>Connect a source to the reverb, and assign reverb parameters.</p>\n", 22226 "itemtype": "method", 22227 "name": "process", 22228 "params": [ 22229 { 22230 "name": "src", 22231 "description": "<p>p5.sound / Web Audio object with a sound\n output.</p>\n", 22232 "type": "Object" 22233 }, 22234 { 22235 "name": "seconds", 22236 "description": "<p>Duration of the reverb, in seconds.\n Min: 0, Max: 10. Defaults to 3.</p>\n", 22237 "type": "Number", 22238 "optional": true 22239 }, 22240 { 22241 "name": "decayRate", 22242 "description": "<p>Percentage of decay with each echo.\n Min: 0, Max: 100. Defaults to 2.</p>\n", 22243 "type": "Number", 22244 "optional": true 22245 }, 22246 { 22247 "name": "reverse", 22248 "description": "<p>Play the reverb backwards or forwards.</p>\n", 22249 "type": "Boolean", 22250 "optional": true 22251 } 22252 ], 22253 "class": "p5.Reverb", 22254 "module": "p5.sound", 22255 "submodule": "p5.sound" 22256 }, 22257 { 22258 "file": "lib/addons/p5.sound.js", 22259 "line": 9423, 22260 "description": "<p>Set the reverb settings. Similar to .process(), but without\nassigning a new input.</p>\n", 22261 "itemtype": "method", 22262 "name": "set", 22263 "params": [ 22264 { 22265 "name": "seconds", 22266 "description": "<p>Duration of the reverb, in seconds.\n Min: 0, Max: 10. Defaults to 3.</p>\n", 22267 "type": "Number", 22268 "optional": true 22269 }, 22270 { 22271 "name": "decayRate", 22272 "description": "<p>Percentage of decay with each echo.\n Min: 0, Max: 100. Defaults to 2.</p>\n", 22273 "type": "Number", 22274 "optional": true 22275 }, 22276 { 22277 "name": "reverse", 22278 "description": "<p>Play the reverb backwards or forwards.</p>\n", 22279 "type": "Boolean", 22280 "optional": true 22281 } 22282 ], 22283 "class": "p5.Reverb", 22284 "module": "p5.sound", 22285 "submodule": "p5.sound" 22286 }, 22287 { 22288 "file": "lib/addons/p5.sound.js", 22289 "line": 9451, 22290 "description": "<p>Set the output level of the reverb effect.</p>\n", 22291 "itemtype": "method", 22292 "name": "amp", 22293 "params": [ 22294 { 22295 "name": "volume", 22296 "description": "<p>amplitude between 0 and 1.0</p>\n", 22297 "type": "Number" 22298 }, 22299 { 22300 "name": "rampTime", 22301 "description": "<p>create a fade that lasts rampTime</p>\n", 22302 "type": "Number", 22303 "optional": true 22304 }, 22305 { 22306 "name": "timeFromNow", 22307 "description": "<p>schedule this event to happen\n seconds from now</p>\n", 22308 "type": "Number", 22309 "optional": true 22310 } 22311 ], 22312 "class": "p5.Reverb", 22313 "module": "p5.sound", 22314 "submodule": "p5.sound" 22315 }, 22316 { 22317 "file": "lib/addons/p5.sound.js", 22318 "line": 9460, 22319 "description": "<p>Send output to a p5.sound or web audio object</p>\n", 22320 "itemtype": "method", 22321 "name": "connect", 22322 "params": [ 22323 { 22324 "name": "unit", 22325 "description": "", 22326 "type": "Object" 22327 } 22328 ], 22329 "class": "p5.Reverb", 22330 "module": "p5.sound", 22331 "submodule": "p5.sound" 22332 }, 22333 { 22334 "file": "lib/addons/p5.sound.js", 22335 "line": 9466, 22336 "description": "<p>Disconnect all output.</p>\n", 22337 "itemtype": "method", 22338 "name": "disconnect", 22339 "class": "p5.Reverb", 22340 "module": "p5.sound", 22341 "submodule": "p5.sound" 22342 }, 22343 { 22344 "file": "lib/addons/p5.sound.js", 22345 "line": 9560, 22346 "description": "<p>Internally, the p5.Convolver uses the a\n<a href=\"http://www.w3.org/TR/webaudio/#ConvolverNode\">\nWeb Audio Convolver Node</a>.</p>\n", 22347 "itemtype": "property", 22348 "name": "convolverNod", 22349 "type": "ConvolverNode", 22350 "class": "p5.Convolver", 22351 "module": "p5.sound", 22352 "submodule": "p5.sound" 22353 }, 22354 { 22355 "file": "lib/addons/p5.sound.js", 22356 "line": 9585, 22357 "description": "<p>Create a p5.Convolver. Accepts a path to a soundfile\nthat will be used to generate an impulse response.</p>\n", 22358 "itemtype": "method", 22359 "name": "createConvolver", 22360 "params": [ 22361 { 22362 "name": "path", 22363 "description": "<p>
22363path to a sound file</p>\n", 22364 "type": "String" 22365 }, 22366 { 22367 "name": "callback", 22368 "description": "<p>function to call if loading is successful.\n The object will be passed in as the argument\n to the callback function.</p>\n", 22369 "type": "Function", 22370 "optional": true 22371 }, 22372 { 22373 "name": "errorCallback", 22374 "description": "<p>function to call if loading is not successful.\n A custom error will be passed in as the argument\n to the callback function.</p>\n", 22375 "type": "Function", 22376 "optional": true 22377 } 22378 ], 22379 "return": { 22380 "description": "", 22381 "type": "p5.Convolver" 22382 }, 22383 "example": [ 22384 "\n<div><code>\nvar cVerb, sound;\nfunction preload() {\n // We have both MP3 and OGG versions of all sound assets\n soundFormats('ogg', 'mp3');\n\n // Try replacing 'bx-spring' with other soundfiles like\n // 'concrete-tunnel' 'small-plate' 'drum' 'beatbox'\n cVerb = createConvolver('assets/bx-spring.mp3');\n\n // Try replacing 'Damscray_DancingTiger' with\n // 'beat', 'doorbell', lucky_dragons'\n sound = loadSound('assets/Damscray_DancingTiger.mp3');\n}\n\nfunction setup() {\n // disconnect from master output...\n sound.disconnect();\n\n // ...and process with cVerb\n // so that we only hear the convolution\n cVerb.process(sound);\n\n sound.play();\n}\n</code></div>" 22385 ], 22386 "class": "p5.Convolver", 22387 "module": "p5.sound", 22388 "submodule": "p5.sound" 22389 }, 22390 { 22391 "file": "lib/addons/p5.sound.js", 22392 "line": 9701, 22393 "description": "<p>Connect a source to the reverb, and assign reverb parameters.</p>\n", 22394 "itemtype": "method", 22395 "name": "process", 22396 "params": [ 22397 { 22398 "name": "src", 22399 "description": "<p>p5.sound / Web Audio object with a sound\n output.</p>\n", 22400 "type": "Object" 22401 } 22402 ], 22403 "example": [ 22404 "\n<div><code>\nvar cVerb, sound;\nfunction preload() {\n soundFormats('ogg', 'mp3');\n\n cVerb = createConvolver('assets/concrete-tunnel.mp3');\n\n sound = loadSound('assets/beat.mp3');\n}\n\nfunction setup() {\n // disconnect from master output...\n sound.disconnect();\n\n // ...and process with (i.e. connect to) cVerb\n // so that we only hear the convolution\n cVerb.process(sound);\n\n sound.play();\n}\n</code></div>" 22405 ], 22406 "class": "p5.Convolver", 22407 "module": "p5.sound", 22408 "submodule": "p5.sound" 22409 }, 22410 { 22411 "file": "lib/addons/p5.sound.js", 22412 "line": 9733, 22413 "description": "<p>If you load multiple impulse files using the .addImpulse method,\nthey will be stored as Objects in this Array. Toggle between them\nwith the <code>toggleImpulse(id)</code> method.</p>\n", 22414 "itemtype": "property", 22415 "name": "impulses", 22416 "type": "Array", 22417 "class": "p5.Convolver", 22418 "module": "p5.sound", 22419 "submodule": "p5.sound" 22420 }, 22421 { 22422 "file": "lib/addons/p5.sound.js", 22423 "line": 9741, 22424 "description": "<p>Load and assign a new Impulse Response to the p5.Convolver.\nThe impulse is added to the <code>.impulses</code> array. Previous\nimpulses can be accessed with the <code>.toggleImpulse(id)</code>\nmethod.</p>\n", 22425 "itemtype": "method", 22426 "name": "addImpulse", 22427 "params": [ 22428 { 22429 "name": "path", 22430 "description": "<p>path to a sound file</p>\n", 22431 "type": "String" 22432 }, 22433 { 22434 "name": "callback", 22435 "description": "<p>function (optional)</p>\n", 22436 "type": "Function" 22437 }, 22438 { 22439 "name": "errorCallback", 22440 "description": "<p>function (optional)</p>\n", 22441 "type": "Function" 22442 } 22443 ], 22444 "class": "p5.Convolver", 22445 "module": "p5.sound", 22446 "submodule": "p5.sound" 22447 }, 22448 { 22449 "file": "lib/addons/p5.sound.js", 22450 "line": 9759, 22451 "description": "<p>Similar to .addImpulse, except that the <code>.impulses</code>\nArray is reset to save memory. A new <code>.impulses</code>\narray is created with this impulse as the only item.</p>\n", 22452 "itemtype": "method", 22453 "name": "resetImpulse", 22454 "params": [ 22455 { 22456 "name": "path", 22457 "description": "<p>
22457path to a sound file</p>\n", 22458 "type": "String" 22459 }, 22460 { 22461 "name": "callback", 22462 "description": "<p>function (optional)</p>\n", 22463 "type": "Function" 22464 }, 22465 { 22466 "name": "errorCallback", 22467 "description": "<p>function (optional)</p>\n", 22468 "type": "Function" 22469 } 22470 ], 22471 "class": "p5.Convolver", 22472 "module": "p5.sound", 22473 "submodule": "p5.sound" 22474 }, 22475 { 22476 "file": "lib/addons/p5.sound.js", 22477 "line": 9777, 22478 "description": "<p>If you have used <code>.addImpulse()</code> to add multiple impulses\nto a p5.Convolver, then you can use this method to toggle between\nthe items in the <code>.impulses</code> Array. Accepts a parameter\nto identify which impulse you wish to use, identified either by its\noriginal filename (String) or by its position in the <code>.impulses\n</code> Array (Number).<br/>\nYou can access the objects in the .impulses Array directly. Each\nObject has two attributes: an <code>.audioBuffer</code> (type:\nWeb Audio <a href=\"\nhttp://webaudio.github.io/web-audio-api/#the-audiobuffer-interface\">\nAudioBuffer)</a> and a <code>.name</code>, a String that corresponds\nwith the original filename.</p>\n", 22479 "itemtype": "method", 22480 "name": "toggleImpulse", 22481 "params": [ 22482 { 22483 "name": "id", 22484 "description": "<p>Identify the impulse by its original filename\n (String), or by its position in the\n <code>.impulses</code> Array (Number).</p>\n", 22485 "type": "String|Number" 22486 } 22487 ], 22488 "class": "p5.Convolver", 22489 "module": "p5.sound", 22490 "submodule": "p5.sound" 22491 }, 22492 { 22493 "file": "lib/addons/p5.sound.js", 22494 "line": 9821, 22495 "class": "p5.Convolver", 22496 "module": "p5.sound", 22497 "submodule": "p5.sound" 22498 }, 22499 { 22500 "file": "lib/addons/p5.sound.js", 22501 "line": 9846, 22502 "class": "p5.Convolver", 22503 "module": "p5.sound", 22504 "submodule": "p5.sound" 22505 }, 22506 { 22507 "file": "lib/addons/p5.sound.js", 22508 "line": 10041, 22509 "description": "<p>Set the global tempo, in beats per minute, for all\np5.Parts. This method will impact all active p5.Parts.</p>\n", 22510 "itemtype": "method", 22511 "name": "setBPM", 22512 "params": [ 22513 { 22514 "name": "BPM", 22515 "description": "<p>Beats Per Minute</p>\n", 22516 "type": "Number" 22517 }, 22518 { 22519 "name": "rampTime", 22520 "description": "<p>Seconds from now</p>\n", 22521 "type": "Number" 22522 } 22523 ], 22524 "class": "p5.Convolver", 22525 "module": "p5.sound", 22526 "submodule": "p5.sound" 22527 }, 22528 { 22529 "file": "lib/addons/p5.sound.js", 22530 "line": 10131, 22531 "description": "<p>Array of values to pass into the callback\nat each step of the phrase. Depending on the callback\nfunction's requirements, these values may be numbers,\nstrings, or an object with multiple parameters.\nZero (0) indicates a rest.</p>\n", 22532 "itemtype": "property", 22533 "name": "sequence", 22534 "type": "Array", 22535 "class": "p5.Phrase", 22536 "module": "p5.sound", 22537 "submodule": "p5.sound" 22538 }, 22539 { 22540 "file": "lib/addons/p5.sound.js", 22541 "line": 10219, 22542 "description": "<p>Set the tempo of this part, in Beats Per Minute.</p>\n", 22543 "itemtype": "method", 22544 "name": "setBPM", 22545 "params": [ 22546 { 22547 "name": "BPM", 22548 "description": "<p>Beats Per Minute</p>\n", 22549 "type": "Number" 22550 }, 22551 { 22552 "name": "rampTime", 22553 "description": "<p>Seconds from now</p>\n", 22554 "type": "Number", 22555 "optional": true 22556 } 22557 ], 22558 "class": "p5.Part", 22559 "module": "p5.sound", 22560 "submodule": "p5.sound" 22561 }, 22562 { 22563 "file": "lib/addons/p5.sound.js", 22564 "line": 10229, 22565 "description": "<p>Returns the Beats Per Minute of this currently part.</p>\n", 22566 "itemtype": "method", 22567 "name": "getBPM", 22568 "return": { 22569 "description": "", 22570 "type": "Number" 22571 }, 22572 "class": "p5.Part", 22573 "module": "p5.sound", 22574 "submodule": "p5.sound" 22575 }, 22576 { 22577 "file": "lib/addons/p5.sound.js", 22578 "line": 10238, 22579 "description": "<p>Start playback of this part. It will play\nthrough all of its phrases at a speed\ndetermined by setBPM.</p>\n", 22580 "itemtype": "method", 22581 "name": "start", 22582 "params": [ 22583 { 22584 "name": "time", 22585 "description": "<p>seconds from now</p>\n", 22586 "type": "Number", 22587 "optional": true 22588 } 22589 ], 22590 "class": "p5.Part", 22591 "module": "p5.sound", 22592 "submodule": "p5.sound" 22593 }, 22594 { 22595 "file": "lib/addons/p5.sound.js", 22596 "line": 10254, 22597 "description": "<p>Loop playback of this part. It will begin\nlooping through all of its phrases at a speed\ndetermined by setBPM.</p>\n", 22598 "itemtype": "method", 22599 "name": "loop", 22600 "params": [ 22601 { 22602 "name": "time", 22603 "description": "<p>seconds from now</p>\n", 22604 "type": "Number", 22605 "optional": true 22606 } 22607 ], 22608 "class": "p5.Part", 22609 "module": "p5.sound", 22610 "submodule": "p5.sound" 22611 }, 22612 { 22613 "file": "lib/addons/p5.sound.js", 22614 "line": 10271, 22615 "description": "<p>Tell the part to stop looping.</p>\n", 22616 "itemtype": "method", 22617 "name": "noLoop", 22618 "class": "p5.Part", 22619 "module": "p5.sound", 22620 "submodule": "p5.sound" 22621 }, 22622 { 22623 "file": "lib/addons/p5.sound.js", 22624 "line": 10283, 22625 "description": "<p>Stop the part and cue it to step 0.</p>\n", 22626 "itemtype": "method", 22627 "name": "stop", 22628 "params": [ 22629 { 22630 "name": "time", 22631 "description": "<p>seconds from now</p>\n", 22632 "type": "Number", 22633 "optional": true 22634 } 22635 ], 22636 "class": "p5.Part", 22637 "module": "p5.sound", 22638 "submodule": "p5.sound" 22639 }, 22640 { 22641 "file": "lib/addons/p5.sound.js", 22642 "line": 10293, 22643 "description": "<p>Pause the part. Playback will resume\nfrom the current step.</p>\n", 22644 "itemtype": "method", 22645 "name": "pause", 22646 "params": [ 22647 { 22648 "name": "time", 22649 "description": "<p>seconds from now</p>\n", 22650 "type": "Number" 22651 } 22652 ], 22653 "class": "p5.Part", 22654 "module": "p5.sound", 22655 "submodule": "p5.sound" 22656 }, 22657 { 22658 "file": "lib/addons/p5.sound.js", 22659 "line": 10305, 22660 "description": "<p>Add a p5.Phrase to this Part.</p>\n", 22661 "itemtype": "method", 22662 "name": "addPhrase", 22663 "params": [ 22664 { 22665 "name": "phrase", 22666 "description": "<p>reference to a p5.Phrase</p>\n", 22667 "type": "p5.Phrase" 22668 } 22669 ], 22670 "class": "p5.Part", 22671 "module": "p5.sound", 22672 "submodule": "p5.sound" 22673 }, 22674 { 22675 "file": "lib/addons/p5.sound.js", 22676 "line": 10326, 22677 "description": "<p>Remove a phrase from this part, based on the name it was\ngiven when it was created.</p>\n", 22678 "itemtype": "method", 22679 "name": "removePhrase", 22680 "params": [ 22681 { 22682 "name": "phraseName", 22683 "description": "", 22684 "type": "String" 22685 } 22686 ], 22687 "class": "p5.Part", 22688 "module": "p5.sound", 22689 "submodule": "p5.sound" 22690 }, 22691 { 22692 "file": "lib/addons/p5.sound.js", 22693 "line": 10340, 22694 "description": "<p>Get a phrase from this part, based on the name it was\ngiven when it was created. Now you can modify its array.</p>\n", 22695 "itemtype": "method", 22696 "name": "getPhrase", 22697 "params": [ 22698 { 22699 "name": "phraseName", 22700 "description": "", 22701 "type": "String" 22702 } 22703 ], 22704 "class": "p5.Part", 22705 "module": "p5.sound", 22706 "submodule": "p5.sound" 22707 }, 22708 { 22709 "file": "lib/addons/p5.sound.js", 22710 "line": 10354, 22711 "description": "<p>Get a phrase from this part, based on the name it was\ngiven when it was created. Now you can modify its array.</p>\n", 22712 "itemtype": "method", 22713 "name": "replaceSequence", 22714 "params": [ 22715 { 22716 "name": "phraseName", 22717 "description": "", 22718 "type": "String" 22719 }, 22720 { 22721 "name": "sequence", 22722 "description": "<p>Array of values to pass into the callback\n at each step of the phrase.</p>\n", 22723 "type": "Array" 22724 } 22725 ], 22726 "class": "p5.Part", 22727 "module": "p5.sound", 22728 "submodule": "p5.sound" 22729 }, 22730 { 22731 "file": "lib/addons/p5.sound.js", 22732 "line": 10382, 22733 "description": "<p>Fire a callback function at every step.</p>\n", 22734 "itemtype": "method", 22735 "name": "onStep", 22736 "params": [ 22737 { 22738 "name": "callback", 22739 "description": "<p>The name of the callback\n you want to fire\n on every beat/tatum.</p>\n", 22740 "type": "Function" 22741 } 22742 ], 22743 "class": "p5.Part", 22744 "module": "p5.sound", 22745 "submodule": "p5.sound" 22746 }, 22747 { 22748 "file": "lib/addons/p5.sound.js", 22749 "line": 10435, 22750 "description": "<p>Start playback of the score.</p>\n", 22751 "itemtype": "method", 22752 "name": "start", 22753 "class": "p5.Score", 22754 "module": "p5.sound", 22755 "submodule": "p5.sound" 22756 }, 22757 { 22758 "file": "lib/addons/p5.sound.js", 22759 "line": 10444, 22760 "description": "<p>Stop playback of the score.</p>\n", 22761 "itemtype": "method", 22762 "name": "stop", 22763 "class": "p5.Score", 22764 "module": "p5.sound", 22765 "submodule": "p5.sound" 22766 }, 22767 { 22768 "file": "lib/addons/p5.sound.js", 22769 "line": 10454, 22770 "description": "<p>Pause playback of the score.</p>\n", 22771 "itemtype": "method", 22772 "name": "pause", 22773 "class": "p5.Score", 22774 "module": "p5.sound", 22775 "submodule": "p5.sound" 22776 }, 22777 { 22778 "file": "lib/addons/p5.sound.js", 22779 "line": 10462, 22780 "description": "<p>Loop playback of the score.</p>\n", 22781 "itemtype": "method", 22782 "name": "loop", 22783 "class": "p5.Score", 22784 "module": "p5.sound", 22785 "submodule": "p5.sound" 22786 }, 22787 { 22788 "file": "lib/addons/p5.sound.js", 22789 "line": 10471, 22790 "description": "<p>Stop looping playback of the score. If it\nis currently playing, this will go into effect\nafter the current roun
22790d of playback completes.</p>\n", 22791 "itemtype": "method", 22792 "name": "noLoop", 22793 "class": "p5.Score", 22794 "module": "p5.sound", 22795 "submodule": "p5.sound" 22796 }, 22797 { 22798 "file": "lib/addons/p5.sound.js", 22799 "line": 10496, 22800 "description": "<p>Set the tempo for all parts in the score</p>\n", 22801 "itemtype": "method", 22802 "name": "setBPM", 22803 "params": [ 22804 { 22805 "name": "BPM", 22806 "description": "<p>Beats Per Minute</p>\n", 22807 "type": "Number" 22808 }, 22809 { 22810 "name": "rampTime", 22811 "description": "<p>Seconds from now</p>\n", 22812 "type": "Number" 22813 } 22814 ], 22815 "class": "p5.Score", 22816 "module": "p5.sound", 22817 "submodule": "p5.sound" 22818 }, 22819 { 22820 "file": "lib/addons/p5.sound.js", 22821 "line": 10564, 22822 "description": "<p>musicalTimeMode uses <a href = \"https://github.com/Tonejs/Tone.js/wiki/Time\">Tone.Time</a> convention\ntrue if string, false if number</p>\n", 22823 "itemtype": "property", 22824 "name": "musicalTimeMode", 22825 "type": "Boolean", 22826 "class": "p5.SoundLoop", 22827 "module": "p5.sound", 22828 "submodule": "p5.sound" 22829 }, 22830 { 22831 "file": "lib/addons/p5.sound.js", 22832 "line": 10571, 22833 "description": "<p>musicalTimeMode variables\nmodify these only when the interval is specified in musicalTime format as a string</p>\n", 22834 "class": "p5.SoundLoop", 22835 "module": "p5.sound", 22836 "submodule": "p5.sound" 22837 }, 22838 { 22839 "file": "lib/addons/p5.sound.js", 22840 "line": 10578, 22841 "description": "<p>Set a limit to the number of loops to play. defaults to Infinity</p>\n", 22842 "itemtype": "property", 22843 "name": "maxIterations", 22844 "type": "Number", 22845 "class": "p5.SoundLoop", 22846 "module": "p5.sound", 22847 "submodule": "p5.sound" 22848 }, 22849 { 22850 "file": "lib/addons/p5.sound.js", 22851 "line": 10587, 22852 "description": "<p>Do not initiate the callback if timeFromNow is < 0\nThis ususually occurs for a few milliseconds when the page\nis not fully loaded</p>\n<p>The callback should only be called until maxIterations is reached</p>\n", 22853 "class": "p5.SoundLoop", 22854 "module": "p5.sound", 22855 "submodule": "p5.sound" 22856 }, 22857 { 22858 "file": "lib/addons/p5.sound.js", 22859 "line": 10601, 22860 "description": "<p>Start the loop</p>\n", 22861 "itemtype": "method", 22862 "name": "start", 22863 "params": [ 22864 { 22865 "name": "timeFromNow", 22866 "description": "<p>schedule a starting time</p>\n", 22867 "type": "Number", 22868 "optional": true 22869 } 22870 ], 22871 "class": "p5.SoundLoop", 22872 "module": "p5.sound", 22873 "submodule": "p5.sound" 22874 }, 22875 { 22876 "file": "lib/addons/p5.sound.js", 22877 "line": 10614, 22878 "description": "<p>Stop the loop</p>\n", 22879 "itemtype": "method", 22880 "name": "stop", 22881 "params": [ 22882 { 22883 "name": "timeFromNow", 22884 "description": "<p>schedule a stopping time</p>\n", 22885 "type": "Number", 22886 "optional": true 22887 } 22888 ], 22889 "class": "p5.SoundLoop", 22890 "module": "p5.sound", 22891 "submodule": "p5.sound" 22892 }, 22893 { 22894 "file": "lib/addons/p5.sound.js", 22895 "line": 10627, 22896 "description": "<p>Pause the loop</p>\n", 22897 "itemtype": "method", 22898 "name": "pause", 22899 "params": [ 22900 { 22901 "name": "timeFromNow", 22902 "description": "<p>schedule a pausing time</p>\n", 22903 "type": "Number", 22904 "optional": true 22905 } 22906 ], 22907 "class": "p5.SoundLoop", 22908 "module": "p5.sound", 22909 "submodule": "p5.sound" 22910 }, 22911 { 22912 "file": "lib/addons/p5.sound.js", 22913 "line": 10639, 22914 "description": "<p>Synchronize loops. Use this method to start two more more loops in synchronization\nor to start a loop in synchronization with a loop that is already playing\nThis method will schedule the implicit loop in sync with the explicit master loop\ni.e. loopToStart.syncedStart(loopToSyncWith)</p>\n", 22915 "itemtype": "method", 22916 "name": "syncedStart", 22917 "params": [ 22918 { 22919 "name": "otherLoop", 22920 "description": "<p>a p5.SoundLoop to sync with</p>\n", 22921 "type": "Object" 22922 }, 22923 { 22924 "name": "timeFromNow", 22925 "description": "<p>Start the loops in sync after timeFromNow seconds</p>\n", 22926 "type": "Number", 22927 "optional": true 22928 } 22929 ], 22930 "class": "p5.SoundLoop", 22931 "module": "p5.sound", 22932 "submodule": "p5.sound" 22933 }, 22934 { 22935 "file": "lib/addons/p5.sound.js", 22936 "line": 10720, 22937 "description": "<p>Getters and Setters, setting any paramter will result in a change in the clock's\nfrequency, that will be reflected after the next callback\nbeats per minute (defaults to 60)</p>\n", 22938 "itemtype": "property", 22939 "name": "bpm", 22940 "type": "Number", 22941 "class": "p5.SoundLoop", 22942 "module": "p5.sound", 22943 "submodule": "p5.sound" 22944 }, 22945 { 22946 "file": "lib/addons/p5.sound.js", 22947 "line": 10738, 22948 "description": "<p>number of quarter notes in a measure (defaults to 4)</p>\n", 22949 "itemtype": "property", 22950 "name": "timeSignature", 22951 "type": "Number", 22952 "class": "p5.SoundLoop", 22953 "module": "p5.sound", 22954 "submodule": "p5.sound" 22955 }, 22956 { 22957 "file": "lib/addons/p5.sound.js", 22958 "line": 10754, 22959 "description": "<p>length of the loops interval</p>\n", 22960 "itemtype": "property", 22961 "name": "interval", 22962 "type": "Number|String", 22963 "class": "p5.SoundLoop", 22964 "module": "p5.sound", 22965 "submodule": "p5.sound" 22966 }, 22967 { 22968 "file": "lib/addons/p5.sound.js", 22969 "line": 10768, 22970 "description": "<p>how many times the callback has been called so far</p>\n", 22971 "itemtype": "property", 22972 "name": "iterations", 22973 "type": "Number", 22974 "readonly": "", 22975 "class": "p5.SoundLoop", 22976 "module": "p5.sound", 22977 "submodule": "p5.sound" 22978 }, 22979 { 22980 "file": "lib/addons/p5.sound.js", 22981 "line": 10809, 22982 "description": "<p>The p5.Compressor is built with a <a href=\"https://www.w3.org/TR/webaudio/#the-dynamicscompressornode-interface\"\n target=\"_blank\" title=\"W3 spec for Dynamics Compressor Node\">
22982Web Audio Dynamics Compressor Node\n </a></p>\n", 22983 "itemtype": "property", 22984 "name": "compressor", 22985 "type": "AudioNode", 22986 "class": "p5.Compressor", 22987 "module": "p5.sound", 22988 "submodule": "p5.sound" 22989 }, 22990 { 22991 "file": "lib/addons/p5.sound.js", 22992 "line": 10820, 22993 "description": "<p>Performs the same function as .connect, but also accepts\noptional parameters to set compressor's audioParams</p>\n", 22994 "itemtype": "method", 22995 "name": "process", 22996 "params": [ 22997 { 22998 "name": "src", 22999 "description": "<p>Sound source to be connected</p>\n", 23000 "type": "Object" 23001 }, 23002 { 23003 "name": "attack", 23004 "description": "<p>The amount of time (in seconds) to reduce the gain by 10dB,\n default = .003, range 0 - 1</p>\n", 23005 "type": "Number", 23006 "optional": true 23007 }, 23008 { 23009 "name": "knee", 23010 "description": "<p>A decibel value representing the range above the\n threshold where the curve smoothly transitions to the "ratio" portion.\n default = 30, range 0 - 40</p>\n", 23011 "type": "Number", 23012 "optional": true 23013 }, 23014 { 23015 "name": "ratio", 23016 "description": "<p>The amount of dB change in input for a 1 dB change in output\n default = 12, range 1 - 20</p>\n", 23017 "type": "Number", 23018 "optional": true 23019 }, 23020 { 23021 "name": "threshold", 23022 "description": "<p>The decibel value above which the compression will start taking effect\n default = -24, range -100 - 0</p>\n", 23023 "type": "Number", 23024 "optional": true 23025 }, 23026 { 23027 "name": "release", 23028 "description": "<p>The amount of time (in seconds) to increase the gain by 10dB\n default = .25, range 0 - 1</p>\n", 23029 "type": "Number", 23030 "optional": true 23031 } 23032 ], 23033 "class": "p5.Compressor", 23034 "module": "p5.sound", 23035 "submodule": "p5.sound" 23036 }, 23037 { 23038 "file": "lib/addons/p5.sound.js", 23039 "line": 10843, 23040 "description": "<p>Set the paramters of a compressor.</p>\n", 23041 "itemtype": "method", 23042 "name": "set", 23043 "params": [ 23044 { 23045 "name": "attack", 23046 "description": "<p>The amount of time (in seconds) to reduce the gain by 10dB,\n default = .003, range 0 - 1</p>\n", 23047 "type": "Number" 23048 }, 23049 { 23050 "name": "knee", 23051 "description": "<p>A decibel value representing the range above the\n threshold where the curve smoothly transitions to the "ratio" portion.\n default = 30, range 0 - 40</p>\n", 23052 "type": "Number" 23053 }, 23054 { 23055 "name": "ratio", 23056 "description": "<p>The amount of dB change in input for a 1 dB change in output\n default = 12, range 1 - 20</p>\n", 23057 "type": "Number" 23058 }, 23059 { 23060 "name": "threshold", 23061 "description": "<p>The decibel value above which the compression will start taking effect\n default = -24, range -100 - 0</p>\n", 23062 "type": "Number" 23063 }, 23064 { 23065 "name": "release", 23066 "description": "<p>The amount of time (in seconds) to increase the gain by 10dB\n default = .25, range 0 - 1</p>\n", 23067 "type": "Number" 23068 } 23069 ], 23070 "class": "p5.Compressor", 23071 "module": "p5.sound", 23072 "submodule": "p5.sound" 23073 }, 23074 { 23075 "file": "lib/addons/p5.sound.js", 23076 "line": 10875, 23077 "description": "<p>Get current attack or set value w/ time ramp</p>\n", 23078 "itemtype": "method", 23079 "name": "attack", 23080 "params": [ 23081 { 23082 "name": "attack", 23083 "description": "<p>Attack is the amount of time (in seconds) to reduce the gain by 10dB,\n default = .003, range 0 - 1</p>\n", 23084 "type": "Number", 23085 "optional": true 23086 }, 23087 { 23088 "name": "time", 23089 "description": "<p>Assign time value to schedule the change in value</p>\n", 23090 "type": "Number", 23091 "optional": true 23092 } 23093 ], 23094 "class": "p5.Compressor", 23095 "module": "p5.sound", 23096 "submodule": "p5.sound" 23097 }, 23098 { 23099 "file": "lib/addons/p5.sound.js", 23100 "line": 10895, 23101 "description": "<p>Get current knee or set value w/ time ramp</p>\n", 23102 "itemtype": "method", 23103 "name": "knee", 23104 "params": [ 23105 { 23106 "name": "knee", 23107 "description": "<p>A decibel value representing the range above the\n threshold where the curve smoothly transitions to the "ratio" portion.\n default = 30, range 0 - 40</p>\n", 23108 "type": "Number", 23109 "optional": true 23110 }, 23111 { 23112 "name": "time", 23113 "description": "<p>Assign time value to schedule the change in value</p>\n", 23114 "type": "Number", 23115 "optional": true 23116 } 23117 ], 23118 "class": "p5.Compressor", 23119 "module": "p5.sound", 23120 "submodule": "p5.sound" 23121 }, 23122 { 23123 "file": "lib/addons/p5.sound.js", 23124 "line": 10915, 23125 "description": "<p>Get current ratio or set value w/ time ramp</p>\n", 23126 "itemtype": "method", 23127 "name": "ratio", 23128 "params": [ 23129 { 23130 "name": "ratio", 23131 "description": "<p>The amount of dB change in input for a 1 dB change in output\n default = 12, range 1 - 20</p>\n", 23132 "type": "Number", 23133 "optional": true 23134 }, 23135 { 23136 "name": "time", 23137 "description": "<p>Assign time value to schedule the change in value</p>\n", 23138 "type": "Number", 23139 "optional": true 23140 } 23141 ], 23142 "class": "p5.Compressor", 23143 "module": "p5.sound", 23144 "submodule": "p5.sound" 23145 }, 23146 { 23147 "file": "lib/addons/p5.sound.js", 23148 "line": 10934, 23149 "description": "<p>Get current threshold or set value w/ time ramp</p>\n", 23150 "itemtype": "method", 23151 "name": "threshold", 23152 "params": [ 23153 { 23154 "name": "threshold", 23155 "description": "<p>The decibel value above which the compression will start taking effect\n default = -24, range -100 - 0</p>\n", 23156 "type": "Number" 23157 }, 23158 { 23159 "name": "time", 23160 "description": "<p>Assign time value to schedule the change in value</p>\n", 23161 "type": "Number", 23162 "optional": true 23163 } 23164 ], 23165 "class": "p5.Compressor", 23166 "module": "p5.sound", 23167 "submodule": "p5.sound" 23168 }, 23169 { 23170 "file": "lib/addons/p5.sound.js", 23171 "line": 10953, 23172 "description": "<p>Get current release or set value w/ time ramp</p>\n", 23173 "itemtype": "method", 23174 "name": "release", 23175 "params": [ 23176 { 23177 "name": "release", 23178 "description": "<p>The amount of time (in seconds) to increase the gain by 10dB\n default = .25, range 0 - 1</p>\n", 23179 "type": "Number" 23180 }, 23181 { 23182 "name": "time", 23183 "description": "<p>Assign time value to schedule the change in value</p>\n", 23184 "type": "Number", 23185 "optional": true 23186 } 23187 ], 23188 "class": "p5.Compressor", 23189 "module": "p5.sound", 23190 "submodule": "p5.sound" 23191 }, 23192 { 23193 "file": "lib/addons/p5.sound.js", 23194 "line": 10973, 23195 "description": "<p>Return the current reduction value</p>\n", 23196 "itemtype": "method", 23197 "name": "reduction", 23198 "return": { 23199 "description": "Value of the amount of gain reduction that is applied to the signal", 23200 "type": "Number" 23201 }, 23202 "class": "p5.Compressor", 23203 "module": "p5.sound", 23204 "submodule": "p5.sound" 23205 }, 23206 { 23207 "file": "lib/addons/p5.sound.js", 23208 "line": 11085, 23209 "description": "<p>Connect a specific device to the p5.SoundRecorder.\nIf no parameter is given, p5.SoundRecorer will record\nall audible p5.sound from your sketch.</p>\n", 23210 "itemtype": "method", 23211 "name": "setInput", 23212 "params": [ 23213 { 23214 "name": "unit", 23215 "description": "<p>p5.sound object or a web audio unit\n that outputs sound</p>\n", 23216 "type": "Object", 23217 "optional": true 23218 } 23219 ], 23220 "class": "p5.SoundRecorder", 23221 "module": "p5.sound", 23222 "submodule": "p5.sound" 23223 }, 23224 { 23225 "file": "lib/addons/p5.sound.js", 23226 "line": 11106, 23227 "description": "<p>Start recording. To access the recording, provide\na p5.SoundFile as the first parameter. The p5.SoundRecorder\nwill send its recording to that p5.SoundFile for playback once\nrecording is complete. Optional parameters include duration\n(in seconds) of the recording, and a callback function that\nwill be called once the complete recording has been\ntransfered to the p5.SoundFile.</p>\n", 23228 "itemtype": "method", 23229 "name": "record", 23230 "params": [ 23231 { 23232 "name": "soundFile", 23233 "description": "<p>p5.SoundFile</p>\n", 23234 "type": "p5.SoundFile" 23235 }, 23236 { 23237 "name": "duration", 23238 "description": "<p>Time (in seconds)</p>\n", 23239 "type": "Number", 23240 "optional": true 23241 }, 23242 { 23243 "name": "callback", 23244 "description": "<p>The name of a function that will be\n called once the recording completes</p>\n", 23245 "type": "Function", 23246 "optional": true 23247 } 23248 ], 23249 "class": "p5.SoundRecorder", 23250 "module": "p5.sound", 23251 "submodule": "p5.sound" 23252 }, 23253 { 23254 "file": "lib/addons/p5.sound.js", 23255 "line": 11139, 23256 "description": "<p>Stop the recording. Once the recording is stopped,\nthe results will be sent to the p5.SoundFile that\nwas given on .record(), and if a callback function\nwas provided on record, that function will be called.</p>\n", 23257 "itemtype": "method", 23258 "name": "stop", 23259 "class": "p5.SoundRecorder", 23260 "module": "p5.sound", 23261 "submodule": "p5.sound" 23262 }, 23263 { 23264 "file": "lib/addons/p5.sound.js", 23265 "line": 11212, 23266 "description": "<p>Save a p5.SoundFile as a .wav audio file.</p>\n", 23267 "itemtype": "method", 23268 "name": "saveSound", 23269 "params": [ 23270 { 23271 "name": "soundFile", 23272 "description": "<p>
23272p5.SoundFile that you wish to save</p>\n", 23273 "type": "p5.SoundFile" 23274 }, 23275 { 23276 "name": "name", 23277 "description": "<p>name of the resulting .wav file.</p>\n", 23278 "type": "String" 23279 } 23280 ], 23281 "class": "p5.SoundRecorder", 23282 "module": "p5.sound", 23283 "submodule": "p5.sound" 23284 }, 23285 { 23286 "file": "lib/addons/p5.sound.js", 23287 "line": 11388, 23288 "description": "<p>isDetected is set to true when a peak is detected.</p>\n", 23289 "itemtype": "attribute", 23290 "name": "isDetected", 23291 "type": "Boolean", 23292 "default": "false", 23293 "class": "p5.PeakDetect", 23294 "module": "p5.sound", 23295 "submodule": "p5.sound" 23296 }, 23297 { 23298 "file": "lib/addons/p5.sound.js", 23299 "line": 11401, 23300 "description": "<p>The update method is run in the draw loop.</p>\n<p>Accepts an FFT object. You must call .analyze()\non the FFT object prior to updating the peakDetect\nbecause it relies on a completed FFT analysis.</p>\n", 23301 "itemtype": "method", 23302 "name": "update", 23303 "params": [ 23304 { 23305 "name": "fftObject", 23306 "description": "<p>A p5.FFT object</p>\n", 23307 "type": "p5.FFT" 23308 } 23309 ], 23310 "class": "p5.PeakDetect", 23311 "module": "p5.sound", 23312 "submodule": "p5.sound" 23313 }, 23314 { 23315 "file": "lib/addons/p5.sound.js", 23316 "line": 11432, 23317 "description": "<p>onPeak accepts two arguments: a function to call when\na peak is detected. The value of the peak,\nbetween 0.0 and 1.0, is passed to the callback.</p>\n", 23318 "itemtype": "method", 23319 "name": "onPeak", 23320 "params": [ 23321 { 23322 "name": "callback", 23323 "description": "<p>Name of a function that will\n be called when a peak is\n detected.</p>\n", 23324 "type": "Function" 23325 }, 23326 { 23327 "name": "val", 23328 "description": "<p>Optional value to pass\n into the function when\n a peak is detected.</p>\n", 23329 "type": "Object", 23330 "optional": true 23331 } 23332 ], 23333 "example": [ 23334 "\n<div><code>\nvar cnv, soundFile, fft, peakDetect;\nvar ellipseWidth = 0;\n\nfunction setup() {\n cnv = createCanvas(100,100);\n textAlign(CENTER);\n\n soundFile = loadSound('assets/beat.mp3');\n fft = new p5.FFT();\n peakDetect = new p5.PeakDetect();\n\n setupSound();\n\n // when a beat is detected, call triggerBeat()\n peakDetect.onPeak(triggerBeat);\n}\n\nfunction draw() {\n background(0);\n fill(255);\n text('click to play', width/2, height/2);\n\n fft.analyze();\n peakDetect.update(fft);\n\n ellipseWidth *= 0.95;\n ellipse(width/2, height/2, ellipseWidth, ellipseWidth);\n}\n\n// this function is called by peakDetect.onPeak\nfunction triggerBeat() {\n ellipseWidth = 50;\n}\n\n// mouseclick starts/stops sound\nfunction setupSound() {\n cnv.mouseClicked( function() {\n if (soundFile.isPlaying() ) {\n soundFile.stop();\n } else {\n soundFile.play();\n }\n });\n}\n</code></div>" 23335 ], 23336 "class": "p5.PeakDetect", 23337 "module": "p5.sound", 23338 "submodule": "p5.sound" 23339 }, 23340 { 23341 "file": "lib/addons/p5.sound.js", 23342 "line": 11578, 23343 "description": "<p>Connect a source to the gain node.</p>\n", 23344 "itemtype": "method", 23345 "name": "setInput", 23346 "params": [ 23347 { 23348 "name": "src", 23349 "description": "<p>p5.sound / Web Audio object with a sound\n output.</p>\n", 23350 "type": "Object" 23351 } 23352 ], 23353 "class": "p5.Gain", 23354 "module": "p5.sound", 23355 "submodule": "p5.sound" 23356 }, 23357 { 23358 "file": "lib/addons/p5.sound.js", 23359 "line": 11588, 23360 "description": "<p>Send output to a p5.sound or web audio object</p>\n", 23361 "itemtype": "method", 23362 "name": "connect", 23363 "params": [ 23364 { 23365 "name": "unit", 23366 "description": "", 23367 "type": "Object" 23368 } 23369 ], 23370 "class": "p5.Gain", 23371 "module": "p5.sound", 23372 "submodule": "p5.sound" 23373 }, 23374 { 23375 "file": "lib/addons/p5.sound.js", 23376 "line": 11598, 23377 "description": "<p>Disconnect all output.</p>\n", 23378 "itemtype": "method", 23379 "name": "disconnect", 23380 "class": "p5.Gain", 23381 "module": "p5.sound", 23382 "submodule": "p5.sound" 23383 }, 23384 { 23385 "file": "lib/addons/p5.sound.js", 23386 "line": 11606, 23387 "description": "<p>Set the output level of the gain node.</p>\n", 23388 "itemtype": "method", 23389 "name": "amp", 23390 "params": [ 23391 { 23392 "name": "volume", 23393 "description": "<p>amplitude between 0 and 1.0</p>\n", 23394 "type": "Number" 23395 }, 23396 { 23397 "name": "rampTime", 23398 "description": "<p>create a fade that lasts rampTime</p>\n", 23399 "type": "Number", 23400 "optional": true 23401 }, 23402 { 23403 "name": "timeFromNow", 23404 "description": "<p>schedule this event to happen\n seconds from now</p>\n", 23405 "type": "Number", 23406 "optional": true 23407 } 23408 ], 23409 "class": "p5.Gain", 23410 "module": "p5.sound", 23411 "submodule": "p5.sound" 23412 }, 23413 { 23414 "file": "lib/addons/p5.sound.js", 23415 "line": 11684, 23416 "description": "<p>Connect to p5 objects or Web Audio Nodes</p>\n", 23417 "itemtype": "method", 23418 "name": "connect", 23419 "params": [ 23420 { 23421 "name": "unit", 23422 "description": "", 23423 "type": "Object" 23424 } 23425 ], 23426 "class": "p5.AudioVoice", 23427 "module": "p5.sound", 23428 "submodule": "p5.sound" 23429 }, 23430 { 23431 "file": "lib/addons/p5.sound.js", 23432 "line": 11693, 23433 "description": "<p>Disconnect from soundOut</p>\n", 23434 "itemtype": "method", 23435 "name": "disconnect", 23436 "class": "p5.AudioVoice", 23437 "module": "p5.sound", 23438 "submodule": "p5.sound" 23439 }, 23440 { 23441 "file": "lib/addons/p5.sound.js", 23442 "line": 11761, 23443 "description": "<p>Play tells the MonoSynth to start playing a note. This method schedules\nthe calling of .triggerAttack and .triggerRelease.</p>\n", 23444 "itemtype": "method", 23445 "name": "play", 23446 "params": [ 23447 { 23448 "name": "note", 23449 "description": "<p>the note you want to play, specified as a\n frequency in Hertz (Number) or as a midi\n value in Note/Octave format ("C4", "Eb3"...etc")\n See <a href = \"https://github.com/Tonejs/Tone.js/wiki/Instruments\">\n Tone</a>. Defaults to 440 hz.</p>\n", 23450 "type": "String | Number" 23451 }, 23452 { 23453 "name": "velocity", 23454 "description": "<p>velocity of the note to play (ranging from 0 to 1)</p>\n", 23455 "type": "Number", 23456 "optional": true 23457 }, 23458 { 23459 "name": "secondsFromNow", 23460 "description": "<p>time from now (in seconds) at which to play</p>\n", 23461 "type": "Number", 23462 "optional": true 23463 }, 23464 { 23465 "name": "sustainTime", 23466 "description": "<p>time to sustain before releasing the envelope</p>\n", 23467 "type": "Number", 23468 "optional": true 23469 } 23470 ], 23471 "class": "p5.MonoSynth", 23472 "module": "p5.sound", 23473 "submodule": "p5.sound" 23474 }, 23475 { 23476 "file": "lib/addons/p5.sound.js", 23477 "line": 11783, 23478 "description": "<p>Trigger the Attack, and Decay portion of the Envelope.\nSimilar to holding down a key on a piano, but it will\nhold the sustain level until you let go.</p>\n", 23479 "params": [ 23480 { 23481 "name": "note", 23482 "description": "<p>the note you want to play, specified as a\n frequency in Hertz (Number) or as a midi\n value in Note/Octave format ("C4", "Eb3"...etc")\n See <a href = \"https://github.com/Tonejs/Tone.js/wiki/Instruments\">\n Tone</a>. Defaults to 440 hz</p>\n", 23483 "type": "String | Number" 23484 }, 23485 { 23486 "name": "velocity", 23487 "description": "<p>velocity of the note to play (ranging from 0 to 1)</p>\n", 23488 "type": "Number", 23489 "optional": true 23490 }, 23491 { 23492 "name": "secondsFromNow", 23493 "description": "<p>time from now (in seconds) at which to play</p>\n", 23494 "type": "Number", 23495 "optional": true 23496 } 23497 ], 23498 "itemtype": "method", 23499 "name": "triggerAttack", 23500 "class": "p5.MonoSynth", 23501 "module": "p5.sound", 23502 "submodule": "p5.sound" 23503 }, 23504 { 23505 "file": "lib/addons/p5.sound.js", 23506 "line": 11806, 23507 "description": "<p>Trigger the release of the Envelope. This is similar to releasing\nthe key on a piano and letting the sound fade according to the\nrelease level and release time.</p>\n", 23508 "params": [ 23509 { 23510 "name": "secondsFromNow", 23511 "description": "<p>time to trigger the release</p>\n", 23512 "type": "Number" 23513 } 23514 ], 23515 "itemtype": "method", 23516 "name": "triggerRelease", 23517 "class": "p5.MonoSynth", 23518 "module": "p5.sound", 23519 "submodule": "p5.sound" 23520 }, 23521 { 23522 "file": "lib/addons/p5.sound.js", 23523 "line": 11819, 23524 "description": "<p>Set values like a traditional\n<a href=\"https://en.wikipedia.org/wiki/Synthesizer#/media/File:ADSR_parameter.svg\">\nADSR envelope\n</a>.</p>\n", 23525 "itemtype": "method", 23526 "name": "setADSR", 23527 "params": [ 23528 { 23529 "name": "attackTime", 23530 "description": "<p>Time (in seconds before envelope\n reaches Attack Level</p>\n", 23531 "type": "Number" 23532 }, 23533 { 23534 "name": "decayTime", 23535 "description": "<p>Time (in seconds) before envelope\n reaches Decay/Sustain Level</p>\n", 23536 "type": "Number", 23537 "optional": true 23538 }, 23539 { 23540 "name": "susRatio", 23541 "description": "<p>Ratio between attackLevel and releaseLevel, on a scale from 0 to 1,\n where 1.0 = attackLevel, 0.0 = releaseLevel.\n The susRatio determines the decayLevel and the level at which the\n sustain portion of the envelope will sustain.\n For example, if attackLevel is 0.4, releaseLevel is 0,\n and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is\n increased to 1.0 (using <code>setRange</code>),\n then decayLevel would increase proportionally, to become 0.5.</p>\n", 23542 "type": "Number", 23543 "optional": true 23544 }, 23545 { 23546 "name": "releaseTime", 23547 "description": "<p>Time in seconds from now (defaults to 0)</p>\n", 23548 "type": "Number", 23549 "optional": true 23550 } 23551 ], 23552 "class": "p5.MonoSynth", 23553 "module": "p5.sound", 23554 "submodule": "p5.sound" 23555 }, 23556 { 23557 "file": "lib/addons/p5.sound.js", 23558 "line": 11843, 23559 "description": "<p>Getters and Setters</p>\n", 23560 "itemtype": "property", 23561 "name": "attack", 23562 "type": "Number", 23563 "class": "p5.MonoSynth", 23564 "module": "p5.sound", 23565 "submodule": "p5.sound" 23566 }, 23567 { 23568 "file": "lib/addons/p5.sound.js", 23569 "line": 11847, 23570 "itemtype": "property", 23571 "name": "decay", 23572 "type": "Number", 23573 "class": "p5.MonoSynth", 23574 "module": "p5.sound", 23575 "submodule": "p5.sound" 23576 }, 23577 { 23578 "file": "lib/addons/p5.sound.js", 23579 "line": 11850, 23580 "itemtype": "property", 23581 "name": "sustain", 23582 "type": "Number", 23583 "class": "p5.MonoSynth", 23584 "module": "p5.sound", 23585 "submodule": "p5.sound" 23586 }, 23587 { 23588 "file": "lib/addons/p5.sound.js", 23589 "line": 11853, 23590 "itemtype": "property", 23591 "name": "release", 23592 "type": "Number", 23593 "class": "p5.MonoSynth", 23594 "module": "p5.sound", 23595 "submodule": "p5.sound" 23596 }, 23597 { 23598 "file": "lib/addons/p5.sound.js", 23599 "line": 11890, 23600 "description": "<p>MonoSynth amp</p>\n", 23601 "itemtype": "method", 23602 "name": "amp", 23603 "params": [ 23604 { 23605 "name": "vol", 23606 "description": "<p>desired volume</p>\n", 23607 "type": "Number" 23608 }, 23609 { 23610 "name": "rampTime", 23611 "description": "<p>Time to reach new volume</p>\n", 23612 "type": "Number", 23613 "optional": true 23614 } 23615 ], 23616 "return": { 23617 "description": "new volume value", 23618 "type": "Number" 23619 }, 23620 "class": "p5.MonoSynth", 23621 "module": "p5.sound", 23622 "submodule": "p5.sound" 23623 }, 23624 { 23625 "file": "lib/addons/p5.sound.js", 23626 "line": 11904, 23627 "description": "<p>Connect to a p5.sound / Web Audio object.</p>\n", 23628 "itemtype": "method", 23629 "name": "connect", 23630 "params": [ 23631 { 23632 "name": "unit", 23633 "description": "<p>A p5.sound or Web Audio object</p>\n", 23634 "type": "Object" 23635 } 23636 ], 23637 "class": "p5.MonoSynth", 23638 "module": "p5.sound", 23639 "submodule": "p5.sound" 23640 }, 23641 { 23642 "file": "lib/addons/p5.sound.js", 23643 "line": 11914, 23644 "description": "<p>Disconnect all outputs</p>\n", 23645 "itemtype": "method", 23646 "name": "disconnect", 23647 "class": "p5.MonoSynth", 23648 "module": "p5.sound", 23649 "submodule": "p5.sound" 23650 }, 23651 { 23652 "file": "lib/addons/p5.sound.js", 23653 "line": 11922, 23654 "description": "<p>Get rid of the MonoSynth an
23654d free up its resources / memory.</p>\n", 23655 "itemtype": "method", 23656 "name": "dispose", 23657 "class": "p5.MonoSynth", 23658 "module": "p5.sound", 23659 "submodule": "p5.sound" 23660 }, 23661 { 23662 "file": "lib/addons/p5.sound.js", 23663 "line": 11974, 23664 "description": "<p>An object that holds information about which notes have been played and\nwhich notes are currently being played. New notes are added as keys\non the fly. While a note has been attacked, but not released, the value of the\nkey is the audiovoice which is generating that note. When notes are released,\nthe value of the key becomes undefined.</p>\n", 23665 "itemtype": "property", 23666 "name": "notes", 23667 "class": "p5.PolySynth", 23668 "module": "p5.sound", 23669 "submodule": "p5.sound" 23670 }, 23671 { 23672 "file": "lib/addons/p5.sound.js", 23673 "line": 11986, 23674 "description": "<p>A PolySynth must have at least 1 voice, defaults to 8</p>\n", 23675 "itemtype": "property", 23676 "name": "polyvalue", 23677 "class": "p5.PolySynth", 23678 "module": "p5.sound", 23679 "submodule": "p5.sound" 23680 }, 23681 { 23682 "file": "lib/addons/p5.sound.js", 23683 "line": 11991, 23684 "description": "<p>Monosynth that generates the sound for each note that is triggered. The\np5.PolySynth defaults to using the p5.MonoSynth as its voice.</p>\n", 23685 "itemtype": "property", 23686 "name": "AudioVoice", 23687 "class": "p5.PolySynth", 23688 "module": "p5.sound", 23689 "submodule": "p5.sound" 23690 }, 23691 { 23692 "file": "lib/addons/p5.sound.js", 23693 "line": 12022, 23694 "description": "<p>Play a note by triggering noteAttack and noteRelease with sustain time</p>\n", 23695 "itemtype": "method", 23696 "name": "play", 23697 "params": [ 23698 { 23699 "name": "note", 23700 "description": "<p>midi note to play (ranging from 0 to 127 - 60 being a middle C)</p>\n", 23701 "type": "Number", 23702 "optional": true 23703 }, 23704 { 23705 "name": "velocity", 23706 "description": "<p>velocity of the note to play (ranging from 0 to 1)</p>\n", 23707 "type": "Number", 23708 "optional": true 23709 }, 23710 { 23711 "name": "secondsFromNow", 23712 "description": "<p>time from now (in seconds) at which to play</p>\n", 23713 "type": "Number", 23714 "optional": true 23715 }, 23716 { 23717 "name": "sustainTime", 23718 "description": "<p>time to sustain before releasing the envelope</p>\n", 23719 "type": "Number", 23720 "optional": true 23721 } 23722 ], 23723 "class": "p5.PolySynth", 23724 "module": "p5.sound", 23725 "submodule": "p5.sound" 23726 }, 23727 { 23728 "file": "lib/addons/p5.sound.js", 23729 "line": 12036, 23730 "description": "<p>noteADSR sets the envelope for a specific note that has just been triggered.\nUsing this method modifies the envelope of whichever audiovoice is being used\nto play the desired note. The envelope should be reset before noteRelease is called\nin order to prevent the modified envelope from being used on other notes.</p>\n", 23731 "itemtype": "method", 23732 "name": "noteADSR", 23733 "params": [ 23734 { 23735 "name": "note", 23736 "description": "<p>Midi note on which ADSR should be set.</p>\n", 23737 "type": "Number", 23738 "optional": true 23739 }, 23740 { 23741 "name": "attackTime", 23742 "description": "<p>Time (in seconds before envelope\n reaches Attack Level</p>\n", 23743 "type": "Number", 23744 "optional": true 23745 }, 23746 { 23747 "name": "decayTime", 23748 "description": "<p>Time (in seconds) before envelope\n reaches Decay/Sustain Level</p>\n", 23749 "type": "Number", 23750 "optional": true 23751 }, 23752 { 23753 "name": "susRatio", 23754 "description": "<p>Ratio between attackLevel and releaseLevel, on a scale from 0 to 1,\n where 1.0 = attackLevel, 0.0 = releaseLevel.\n The susRatio determines the decayLevel and the level at which the\n sustain portion of the envelope will sustain.\n For example, if attackLevel is 0.4, releaseLevel is 0,\n and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is\n increased to 1.0 (using <code>setRange</code>),\n then decayLevel would increase proportionally, to become 0.5.</p>\n", 23755 "type": "Number", 23756 "optional": true 23757 }, 23758 { 23759 "name": "releaseTime", 23760 "description": "<p>Time in seconds from now (defaults to 0)</p>\n", 23761 "type": "Number", 23762 "optional": true 23763 } 23764 ], 23765 "class": "p5.PolySynth", 23766 "module": "p5.sound", 23767 "submodule": "p5.sound" 23768 }, 23769 { 23770 "file": "lib/addons/p5.sound.js", 23771 "line": 12064, 23772 "description": "<p>Set the PolySynths global envelope. This method modifies the envelopes of each\nmonosynth so that all notes are played with this envelope.</p>\n", 23773 "itemtype": "method", 23774 "name": "setADSR", 23775 "params": [ 23776 { 23777 "name": "note", 23778 "description": "<p>Midi note on which ADSR should be set.</p>\n", 23779 "type": "Number", 23780 "optional": true 23781 }, 23782 { 23783 "name": "attackTime", 23784 "description": "<p>Time (in seconds before envelope\n reaches Attack Level</p>\n", 23785 "type": "Number", 23786 "optional": true 23787 }, 23788 { 23789 "name": "decayTime", 23790 "description": "<p>Time (in seconds) before envelope\n reaches Decay/Sustain Level</p>\n", 23791 "type": "Number", 23792 "optional": true 23793 }, 23794 { 23795 "name": "susRatio", 23796 "description": "<p>Ratio between attackLevel and releaseLevel, on a scale from 0 to 1,\n where 1.0 = attackLevel, 0.0 = releaseLevel.\n The susRatio determines the decayLevel and the level at which the\n sustain portion of the envelope will sustain.\n For example, if attackLevel is 0.4, releaseLevel is 0,\n and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is\n increased to 1.0 (using <code>setRange</code>),\n then decayLevel would increase proportionally, to become 0.5.</p>\n", 23797 "type": "Number", 23798 "optional": true 23799 }, 23800 { 23801 "name": "releaseTime", 23802 "description": "<p>Time in seconds from now (defaults to 0)</p>\n", 23803 "type": "Number", 23804 "optional": true 23805 } 23806 ], 23807 "class": "p5.PolySynth", 23808 "module": "p5.sound", 23809 "submodule": "p5.sound" 23810 }, 23811 { 23812 "file": "lib/addons/p5.sound.js", 23813 "line": 12089, 23814 "description": "<p>Trigger the Attack, and Decay portion of a MonoSynth.\nSimilar to holding down a key on a piano, but it will\nhold the sustain level until you let go.</p>\n", 23815 "itemtype": "method", 23816 "name": "noteAttack", 23817 "params": [ 23818 { 23819 "name": "note", 23820 "description": "<p>midi note on which attack should be triggered.</p>\n", 23821 "type": "Number", 23822 "optional": true 23823 }, 23824 { 23825 "name": "velocity", 23826 "description": "<p>velocity of the note to play (ranging from 0 to 1)/</p>\n", 23827 "type": "Number", 23828 "optional": true 23829 }, 23830 { 23831 "name": "secondsFromNow", 23832 "description": "<p>time from now (in seconds)</p>\n", 23833 "type": "Number", 23834 "optional": true 23835 } 23836 ], 23837 "class": "p5.PolySynth", 23838 "module": "p5.sound", 23839 "submodule": "p5.sound" 23840 }, 23841 { 23842 "file": "lib/addons/p5.sound.js", 23843 "line": 12162, 23844 "description": "<p>Trigger the Release of an AudioVoice note. This is similar to releasing\nthe key on a piano and letting the sound fade according to the\nrelease level and release time.</p>\n", 23845 "itemtype": "method", 23846 "name": "noteRelease", 23847 "params": [ 23848 { 23849 "name": "note", 23850 "description": "<p>midi note on which attack should be triggered.</p>\n", 23851 "type": "Number", 23852 "optional": true 23853 }, 23854 { 23855 "name": "secondsFromNow", 23856 "description": "<p>time to trigger the release</p>\n", 23857 "type": "Number", 23858 "optional": true 23859 } 23860 ], 23861 "class": "p5.PolySynth", 23862 "module": "p5.sound", 23863 "submodule": "p5.sound" 23864 }, 23865 { 23866 "file": "lib/addons/p5.sound.js", 23867 "line": 12192, 23868 "description": "<p>Connect to a p5.sound / Web Audio object.</p>\n", 23869 "itemtype": "method", 23870 "name": "connect", 23871 "params": [ 23872 { 23873 "name": "unit", 23874 "description": "<p>A p5.sound or Web Audio object</p>\n", 23875 "type": "Object" 23876 } 23877 ], 23878 "class": "p5.PolySynth", 23879 "module": "p5.sound", 23880 "submodule": "p5.sound" 23881 }, 23882 { 23883 "file": "lib/addons/p5.sound.js", 23884 "line": 12202, 23885 "description": "<p>Disconnect all outputs</p>\n", 23886 "itemtype": "method", 23887 "name": "disconnect", 23888 "class": "p5.PolySynth", 23889 "module": "p5.sound", 23890 "submodule": "p5.sound" 23891 }, 23892 { 23893 "file": "lib/addons/p5.sound.js", 23894 "line": 12210, 23895 "description": "<p>Get rid of the MonoSynth and free up its resources / memory.</p>\n", 23896 "itemtype": "method", 23897 "name": "dispose", 23898 "class": "p5.PolySynth", 23899 "module": "p5.sound", 23900 "submodule": "p5.sound" 23901 }, 23902 { 23903 "file": "lib/addons/p5.sound.js", 23904 "line": 12276, 23905 "description": "<p>The p5.Distortion is built with a\n<a href=\"http://www.w3.org/TR/webaudio/#WaveShaperNode\">\nWeb Audio WaveShaper Node</a>.</p>\n", 23906 "itemtype": "property", 23907 "name": "WaveShaperNode", 23908 "type": "AudioNode", 23909 "class": "p5.Distortion", 23910 "module": "p5.sound", 23911 "submodule": "p5.sound" 23912 }, 23913 { 23914 "file": "lib/addons/p5.sound.js", 23915 "line": 12291, 23916 "description": "<p>Process a sound source, optionally specify amount and oversample values.</p>\n", 23917 "itemtype": "method", 23918 "name": "process", 23919 "params": [ 23920 { 23921 "name": "amount", 23922 "description": "<p>Unbounded distortion amount.\n Normal values range from 0-1.</p>\n", 23923 "type": "Number", 23924 "optional": true, 23925 "optdefault": "0.25" 23926 }, 23927 { 23928 "name": "oversample", 23929 "description": "<p>'none', '2x', or '4x'.</p>\n", 23930 "type": "String", 23931 "optional": true, 23932 "optdefault": "'none'" 23933 } 23934 ], 23935 "class": "p5.Distortion", 23936 "module": "p5.sound", 23937 "submodule": "p5.sound" 23938 }, 23939 { 23940 "file": "lib/addons/p5.sound.js", 23941 "line": 12303, 23942 "description": "<p>Set the amount and oversample of the waveshaper distortion.</p>\n", 23943 "itemtype": "method", 23944 "name": "set", 23945 "params": [ 23946 { 23947 "name": "amount", 23948 "description": "<p>Unbounded distortion amount.\n Normal values range from 0-1.</p>\n", 23949 "type": "Number", 23950 "optional": true, 23951 "optdefault": "0.25" 23952 }, 23953 { 23954 "name": "oversample", 23955 "description": "<p>'none', '2x', or '4x'.</p>\n", 23956 "type": "String", 23957 "optional": true, 23958 "optdefault": "'none'" 23959 } 23960 ], 23961 "class": "p5.Distortion", 23962 "module": "p5.sound", 23963 "submodule": "p5.sound" 23964 }, 23965 { 23966 "file": "lib/addons/p5.sound.js", 23967 "line": 12321, 23968 "description": "<p>Return the distortion amount, typically between 0-1.</p>\n", 23969 "itemtype": "method", 23970 "name": "getAmount", 23971 "return": { 23972 "description": "Unbounded distortion amount.\n Normal values range from 0-1.", 23973 "type": "Number" 23974 }, 23975 "class": "p5.Distortion", 23976 "module": "p5.sound", 23977 "submodule": "p5.sound" 23978 }, 23979 { 23980 "file": "lib/addons/p5.sound.js", 23981 "line": 12331, 23982 "description": "<p>Return the oversampling.</p>\n", 23983 "itemtype": "method", 23984 "name": "getOversample", 23985 "return": { 23986 "description": "Oversample can either be 'none', '2x', or '4x'.", 23987 "type": "String" 23988 }, 23989 "class": "p5.Distortion", 23990 "module": "p5.sound", 23991 "submodule": "p5.sound" 23992 } 23993 ], 23994 "warnings": [ 23995 { 23996 "message": "unknown tag: alt", 23997 "line": " src/color/creating_reading.js:16" 23998 }, 23999 { 24000 "message": "unknown tag: alt", 24001 "line": " src/color/creating_reading.js:61" 24002 }, 24003 { 24004 "message": "unknown tag: alt", 24005 "line": " src/color/creating_reading.js:91"
24006 }, 24007 { 24008 "message": "unknown tag: alt", 24009 "line": " src/color/creating_reading.js:121" 24010 }, 24011 { 24012 "message": "unknown tag: alt", 24013 "line": " src/color/creating_reading.js:319" 24014 }, 24015 { 24016 "message": "unknown tag: alt", 24017 "line": " src/color/creating_reading.js:350" 24018 }, 24019 { 24020 "message": "unknown tag: alt", 24021 "line": " src/color/creating_reading.js:387" 24022 }, 24023 { 24024 "message": "unknown tag: alt", 24025 "line": " src/color/creating_reading.js:484" 24026 }, 24027 { 24028 "message": "unknown tag: alt", 24029 "line": " src/color/creating_reading.js:514" 24030 }, 24031 { 24032 "message": "unknown tag: alt", 24033 "line": " src/color/creating_reading.js:554" 24034 }, 24035 { 24036 "message": "unknown tag: alt", 24037 "line": " src/color/p5.Color.js:52" 24038 }, 24039 { 24040 "message": "unknown tag: alt", 24041 "line": " src/color/p5.Color.js:247" 24042 }, 24043 { 24044 "message": "unknown tag: alt", 24045 "line": " src/color/p5.Color.js:274" 24046 }, 24047 { 24048 "message": "unknown tag: alt", 24049 "line": " src/color/p5.Color.js:301" 24050 }, 24051 { 24052 "message": "unknown tag: alt", 24053 "line": " src/color/p5.Color.js:328" 24054 }, 24055 { 24056 "message": "unknown tag: alt", 24057 "line": " src/color/p5.Color.js:759" 24058 }, 24059 { 24060 "message": "unknown tag: alt", 24061 "line": " src/color/setting.js:15" 24062 }, 24063 { 24064 "message": "unknown tag: alt", 24065 "line": " src/color/setting.js:185" 24066 }, 24067 { 24068 "message": "unknown tag: alt", 24069 "line": " src/color/setting.js:223" 24070 }, 24071 { 24072 "message": "unknown tag: alt", 24073 "line": " src/color/setting.js:344" 24074 }, 24075 { 24076 "message": "unknown tag: alt", 24077 "line": " src/color/setting.js:501" 24078 }, 24079 { 24080 "message": "unknown tag: alt", 24081 "line": " src/color/setting.js:542" 24082 }, 24083 { 24084 "message": "unknown tag: alt", 24085 "line": " src/color/setting.js:582" 24086 }, 24087 { 24088 "message": "unknown tag: alt", 24089 "line": " src/core/2d_primitives.js:16" 24090 }, 24091 { 24092 "message": "unknown tag: alt", 24093 "line": " src/core/2d_primitives.js:133" 24094 }, 24095 { 24096 "message": "unknown tag: alt", 24097 "line": " src/core/2d_primitives.js:188" 24098 }, 24099 { 24100 "message": "unknown tag: alt", 24101 "line": " src/core/2d_primitives.js:244" 24102 }, 24103 { 24104 "message": "unknown tag: alt", 24105 "line": " src/core/2d_primitives.js:279" 24106 }, 24107 { 24108 "message": "unknown tag: alt", 24109 "line": " src/core/2d_primitives.js:333" 24110 }, 24111 { 24112 "message": "unknown tag: alt", 24113 "line": " src/core/2d_primitives.js:416" 24114 }, 24115 { 24116 "message": "unknown tag: alt", 24117 "line": " src/core/attributes.js:14" 24118 }, 24119 { 24120 "message": "unknown tag: alt", 24121 "line": " src/core/attributes.js:83" 24122 }, 24123 { 24124 "message": "unknown tag: alt", 24125 "line": " src/core/attributes.js:111" 24126 }, 24127 { 24128 "message": "unknown tag: alt", 24129 "line": " src/core/attributes.js:180" 24130 }, 24131 { 24132 "message": "unknown tag: alt", 24133 "line": " src/core/attributes.js:209" 24134 }, 24135 { 24136 "message": "unknown tag: alt", 24137 "line": " src/core/attributes.js:246" 24138 }, 24139 { 24140 "message": "unknown tag: alt", 24141 "line": " src/core/attributes.js:313" 24142 }, 24143 { 24144 "message": "unknown tag: alt", 24145 "line": " src/core/constants.js:34" 24146 }, 24147 { 24148 "message": "unknown tag: alt", 24149 "line": " src/core/constants.js:53" 24150 }, 24151 { 24152 "message": "unknown tag: alt", 24153 "line": " src/core/constants.js:72" 24154 }, 24155 { 24156 "message": "unknown tag: alt", 24157 "line": " src/core/constants.js:91" 24158 }, 24159 { 24160 "message": "unknown tag: alt", 24161 "line": " src/core/constants.js:110" 24162 }, 24163 { 24164 "message": "unknown tag: alt", 24165 "line": " src/core/core.js:49" 24166 }, 24167 { 24168 "message": "unknown tag: alt", 24169 "line": " src/core/core.js:90" 24170 }, 24171 { 24172 "message": "unknown tag: alt", 24173 "line": " src/core/core.js:121" 24174 }, 24175 { 24176 "message": "unknown tag: alt", 24177 "line": " src/core/core.js:407" 24178 }, 24179 { 24180 "message": "unknown tag: alt", 24181 "line": " src/core/curves.js:13" 24182 }, 24183 { 24184 "message": "unknown tag: alt", 24185 "line": " src/core/curves.js:92" 24186 }, 24187 { 24188 "message": "unknown tag: alt", 24189 "line": " src/core/curves.js:135" 24190 }, 24191 { 24192 "message": "unknown tag: alt", 24193 "line": " src/core/curves.js:190" 24194 }, 24195 { 24196 "message": "unknown tag: alt", 24197 "line": " src/core/curves.js:269" 24198 }, 24199 { 24200 "message": "unknown tag: alt", 24201 "line": " src/core/curves.js:360" 24202 }, 24203 { 24204 "message": "unknown tag: alt", 24205 "line": " src/core/curves.js:402" 24206 }, 24207 { 24208 "message": "unknown tag: alt", 24209 "line": " src/core/curves.js:497" 24210 }, 24211 { 24212 "message": "unknown tag: alt", 24213 "line": " src/core/environment.js:22" 24214 }, 24215 { 24216 "message": "unknown tag: alt", 24217 "line": " src/core/environment.js:49" 24218 }, 24219 { 24220 "message": "unknown tag: alt", 24221 "line": " src/core/environment.js:77" 24222 }, 24223 { 24224 "message": "unknown tag: alt", 24225 "line": " src/core/environment.js:109" 24226 }, 24227 { 24228 "message": "unknown tag: alt", 24229 "line": " src/core/environment.js:170" 24230 }, 24231 { 24232 "message": "unknown tag: alt", 24233 "line": " src/core/environment.js:268" 24234 }, 24235 { 24236 "message": "unknown tag: alt", 24237 "line": " src/core/environment.js:293" 24238 }, 24239 { 24240 "message": "unknown tag: alt", 24241 "line": " src/core/environment.js:310" 24242 }, 24243 { 24244 "message": "unknown tag: alt", 24245 "line": " src/core/environment.js:327" 24246 }, 24247 { 24248 "message": "unknown tag: alt", 24249 "line": " src/core/environment.js:343" 24250 }, 24251 { 24252 "message": "unknown tag: alt", 24253 "line": " src/core/environment.js:359" 24254 }, 24255 { 24256 "message": "unknown tag: alt", 24257 "line": " src/core/environment.js:437" 24258 }, 24259 { 24260 "message": "replacing incorrect tag: returns with return", 24261 "line": " src/core/environment.js:488" 24262 }, 24263 { 24264 "message": "unknown tag: alt", 24265 "line": " src/core/environment.js:488" 24266 }, 24267 { 24268 "message": "replacing incorrect tag: returns with return", 24269 "line": " src/core/environment.js:534" 24270 }, 24271 { 24272 "message": "unknown tag: alt", 24273 "line": " src/core/environment.js:534" 24274 }, 24275 { 24276 "message": "unknown tag: alt", 24277 "line": " src/core/environment.js:591" 24278 }, 24279 { 24280 "message": "unknown tag: alt", 24281 "line": " src/core/environment.js:622" 24282 }, 24283 { 24284 "message": "unknown tag: alt", 24285 "line": " src/core/environment.js:645" 24286 }, 24287 { 24288 "message": "unknown tag: alt", 24289 "line": " src/core/p5.Element.js:51" 24290 }, 24291 { 24292 "message": "unknown tag: alt", 24293 "line": " src/core/p5.Element.js:116" 24294 }, 24295 { 24296 "message": "unknown tag: alt",
24297 "line": " src/core/p5.Element.js:153" 24298 }, 24299 { 24300 "message": "unknown tag: alt", 24301 "line": " src/core/p5.Element.js:188" 24302 }, 24303 { 24304 "message": "unknown tag: alt", 24305 "line": " src/core/p5.Element.js:238" 24306 }, 24307 { 24308 "message": "unknown tag: alt", 24309 "line": " src/core/p5.Element.js:287" 24310 }, 24311 { 24312 "message": "unknown tag: alt", 24313 "line": " src/core/p5.Element.js:353" 24314 }, 24315 { 24316 "message": "unknown tag: alt", 24317 "line": " src/core/p5.Element.js:406" 24318 }, 24319 { 24320 "message": "unknown tag: alt", 24321 "line": " src/core/p5.Element.js:460" 24322 }, 24323 { 24324 "message": "unknown tag: alt", 24325 "line": " src/core/p5.Element.js:519" 24326 }, 24327 { 24328 "message": "unknown tag: alt", 24329 "line": " src/core/p5.Element.js:562" 24330 }, 24331 { 24332 "message": "unknown tag: alt", 24333 "line": " src/core/p5.Element.js:629" 24334 }, 24335 { 24336 "message": "unknown tag: alt", 24337 "line": " src/core/p5.Element.js:664" 24338 }, 24339 { 24340 "message": "unknown tag: alt", 24341 "line": " src/core/p5.Element.js:706" 24342 }, 24343 { 24344 "message": "unknown tag: alt", 24345 "line": " src/core/p5.Element.js:755" 24346 }, 24347 { 24348 "message": "unknown tag: alt", 24349 "line": " src/core/p5.Element.js:796" 24350 }, 24351 { 24352 "message": "unknown tag: alt", 24353 "line": " src/core/p5.Element.js:846" 24354 }, 24355 { 24356 "message": "unknown tag: alt", 24357 "line": " src/core/p5.Element.js:884" 24358 }, 24359 { 24360 "message": "unknown tag: alt", 24361 "line": " src/core/p5.Element.js:922" 24362 }, 24363 { 24364 "message": "unknown tag: alt", 24365 "line": " src/core/p5.Graphics.js:65" 24366 }, 24367 { 24368 "message": "unknown tag: alt", 24369 "line": " src/core/rendering.js:17" 24370 }, 24371 { 24372 "message": "unknown tag: alt", 24373 "line": " src/core/rendering.js:119" 24374 }, 24375 { 24376 "message": "unknown tag: alt", 24377 "line": " src/core/rendering.js:172" 24378 }, 24379 { 24380 "message": "unknown tag: alt", 24381 "line": " src/core/rendering.js:195" 24382 }, 24383 { 24384 "message": "unknown tag: alt", 24385 "line": " src/core/rendering.js:234" 24386 }, 24387 { 24388 "message": "unknown tag: alt", 24389 "line": " src/core/structure.js:15" 24390 }, 24391 { 24392 "message": "unknown tag: alt", 24393 "line": " src/core/structure.js:77" 24394 }, 24395 { 24396 "message": "unknown tag: alt", 24397 "line": " src/core/structure.js:132" 24398 }, 24399 { 24400 "message": "unknown tag: alt", 24401 "line": " src/core/structure.js:197" 24402 }, 24403 { 24404 "message": "unknown tag: alt", 24405 "line": " src/core/structure.js:271" 24406 }, 24407 { 24408 "message": "unknown tag: alt", 24409 "line": " src/core/transform.js:13" 24410 }, 24411 { 24412 "message": "unknown tag: alt", 24413 "line": " src/core/transform.js:135" 24414 }, 24415 { 24416 "message": "unknown tag: alt", 24417 "line": " src/core/transform.js:161" 24418 }, 24419 { 24420 "message": "unknown tag: alt", 24421 "line": " src/core/transform.js:201" 24422 }, 24423 { 24424 "message": "unknown tag: alt", 24425 "line": " src/core/transform.js:231" 24426 }, 24427 { 24428 "message": "unknown tag: alt", 24429 "line": " src/core/transform.js:261" 24430 }, 24431 { 24432 "message": "unknown tag: alt", 24433 "line": " src/core/transform.js:291" 24434 }, 24435 { 24436 "message": "unknown tag: alt", 24437 "line": " src/core/transform.js:366" 24438 }, 24439 { 24440 "message": "unknown tag: alt", 24441 "line": " src/core/transform.js:405" 24442 }, 24443 { 24444 "message": "unknown tag: alt", 24445 "line": " src/core/transform.js:444" 24446 }, 24447 { 24448 "message": "unknown tag: alt", 24449 "line": " src/core/vertex.js:22" 24450 }, 24451 { 24452 "message": "unknown tag: alt", 24453 "line": " src/core/vertex.js:70" 24454 }, 24455 { 24456 "message": "unknown tag: alt", 24457 "line": " src/core/vertex.js:270" 24458 }, 24459 { 24460 "message": "unknown tag: alt", 24461 "line": " src/core/vertex.js:356" 24462 }, 24463 { 24464 "message": "unknown tag: alt",
24465 "line": " src/core/vertex.js:407" 24466 }, 24467 { 24468 "message": "unknown tag: alt", 24469 "line": " src/core/vertex.js:467" 24470 }, 24471 { 24472 "message": "unknown tag: alt", 24473 "line": " src/core/vertex.js:553" 24474 }, 24475 { 24476 "message": "unknown tag: alt", 24477 "line": " src/core/vertex.js:645" 24478 }, 24479 { 24480 "message": "unknown tag: alt", 24481 "line": " src/core/vertex.js:645" 24482 }, 24483 { 24484 "message": "unknown tag: alt", 24485 "line": " src/core/vertex.js:645" 24486 }, 24487 { 24488 "message": "unknown tag: alt", 24489 "line": " src/core/vertex.js:645" 24490 }, 24491 { 24492 "message": "unknown tag: alt", 24493 "line": " src/events/acceleration.js:91" 24494 }, 24495 { 24496 "message": "unknown tag: alt", 24497 "line": " src/events/acceleration.js:125" 24498 }, 24499 { 24500 "message": "unknown tag: alt", 24501 "line": " src/events/acceleration.js:158" 24502 }, 24503 { 24504 "message": "unknown tag: alt", 24505 "line": " src/events/acceleration.js:194" 24506 }, 24507 { 24508 "message": "unknown tag: alt", 24509 "line": " src/events/acceleration.js:239" 24510 }, 24511 { 24512 "message": "unknown tag: alt", 24513 "line": " src/events/acceleration.js:283" 24514 }, 24515 { 24516 "message": "unknown tag: alt", 24517 "line": " src/events/acceleration.js:374" 24518 }, 24519 { 24520 "message": "unknown tag: alt", 24521 "line": " src/events/acceleration.js:405" 24522 }, 24523 { 24524 "message": "unknown tag: alt", 24525 "line": " src/events/acceleration.js:464" 24526 }, 24527 { 24528 "message": "unknown tag: alt", 24529 "line": " src/events/keyboard.js:18" 24530 }, 24531 { 24532 "message": "unknown tag: alt", 24533 "line": " src/events/keyboard.js:45" 24534 }, 24535 { 24536 "message": "unknown tag: alt", 24537 "line": " src/events/keyboard.js:74" 24538 }, 24539 { 24540 "message": "unknown tag: alt", 24541 "line": " src/events/keyboard.js:107" 24542 }, 24543 { 24544 "message": "unknown tag: alt", 24545 "line": " src/events/keyboard.js:198" 24546 }, 24547 { 24548 "message": "unknown tag: alt", 24549 "line": " src/events/keyboard.js:254" 24550 }, 24551 { 24552 "message": "unknown tag: alt", 24553 "line": " src/events/keyboard.js:318" 24554 }, 24555 { 24556 "message": "unknown tag: alt", 24557 "line": " src/events/mouse.js:22" 24558 }, 24559 { 24560 "message": "unknown tag: alt", 24561 "line": " src/events/mouse.js:48" 24562 }, 24563 { 24564 "message": "unknown tag: alt", 24565 "line": " src/events/mouse.js:74" 24566 }, 24567 { 24568 "message": "unknown tag: alt", 24569 "line": " src/events/mouse.js:105" 24570 }, 24571 { 24572 "message": "unknown tag: alt", 24573 "line": " src/events/mouse.js:135" 24574 }, 24575 { 24576 "message": "unknown tag: alt", 24577 "line": " src/events/mouse.js:172" 24578 }, 24579 { 24580 "message": "unknown tag: alt", 24581 "line": " src/events/mouse.js:209" 24582 }, 24583 { 24584 "message": "unknown tag: alt", 24585 "line": " src/events/mouse.js:249" 24586 }, 24587 { 24588 "message": "unknown tag: alt", 24589 "line": " src/events/mouse.js:290" 24590 }, 24591 { 24592 "message": "unknown tag: alt", 24593 "line": " src/events/mouse.js:329" 24594 }, 24595 { 24596 "message": "unknown tag: alt", 24597 "line": " src/events/mouse.js:418" 24598 }, 24599 { 24600 "message": "unknown tag: alt", 24601 "line": " src/events/mouse.js:462" 24602 }, 24603 { 24604 "message": "unknown tag: alt", 24605 "line": " src/events/mouse.js:532" 24606 }, 24607 { 24608 "message": "unknown tag: alt", 24609 "line": " src/events/mouse.js:598" 24610 }, 24611 { 24612 "message": "unknown tag: alt", 24613 "line": " src/events/mouse.js:665" 24614 }, 24615 { 24616 "message": "unknown tag: alt", 24617 "line": " src/events/mouse.js:724" 24618 }, 24619 { 24620 "message": "unknown tag: alt", 24621 "line": " src/events/mouse.js:782" 24622 }, 24623 { 24624 "message": "unknown tag: alt", 24625 "line": " src/events/touch.js:57" 24626 }, 24627 { 24628 "message": "unknown tag: alt", 24629 "line": " src/events/touch.js:120" 24630 }, 24631 { 24632 "message": "unknown tag: alt", 24633 "line": " src/events/touch.js:182" 24634 }, 24635 { 24636 "message": "unknown tag: alt", 24637 "line": " src/image/image.js:18" 24638 }, 24639 { 24640 "message": "unknown tag: alt", 24641 "line": " src/image/image.js:98" 24642 }, 24643 { 24644 "message": "unknown tag: alt", 24645 "line": " src/image/image.js:193" 24646 }, 24647 { 24648 "message": "unknown tag: alt", 24649 "line": " src/image/loading_displaying.js:17" 24650 }, 24651 { 24652 "message": "replacing incorrect tag: returns with return", 24653 "line": " src/image/loading_displaying.js:108" 24654 }, 24655 { 24656 "message": "unknown tag: alt", 24657 "line": " src/image/loading_displaying.js:125" 24658 }, 24659 { 24660 "message": "unknown tag: alt", 24661 "line": " src/image/loading_displaying.js:296" 24662 }, 24663 { 24664 "message": "unknown tag: alt", 24665 "line": " src/image/loading_displaying.js:396" 24666 }, 24667 { 24668 "message": "unknown tag: alt", 24669 "line": " src/image/loading_displaying.js:462" 24670 }, 24671 { 24672 "message": "unknown tag: alt", 24673 "line": " src/image/p5.Image.js:90" 24674 }, 24675 { 24676 "message": "unknown tag: alt", 24677 "line": " src/image/p5.Image.js:117" 24678 }, 24679 { 24680 "message": "unknown tag: alt", 24681 "line": " src/image/p5.Image.js:151" 24682 }, 24683 { 24684 "message": "unknown tag: alt", 24685 "line": " src/image/p5.Image.js:230" 24686 }, 24687 { 24688 "message": "unknown tag: alt", 24689 "line": " src/image/p5.Image.js:266" 24690 }, 24691 { 24692 "message": "unknown tag: alt", 24693 "line": " src/image/p5.Image.js:314" 24694 }, 24695 { 24696 "message": "unknown tag: alt", 24697 "line": " src/image/p5.Image.js:359" 24698 }, 24699 { 24700 "message": "unknown tag: alt", 24701 "line": " src/image/p5.Image.js:397" 24702 }, 24703 { 24704 "message": "unknown tag: alt", 24705 "line": " src/image/p5.Image.js:481" 24706 }, 24707 { 24708 "message": "unknown tag: alt", 24709 "line": " src/image/p5.Image.js:561" 24710 }, 24711 { 24712 "message": "unknown tag: alt", 24713 "line": " src/image/p5.Image.js:624" 24714 }, 24715 { 24716 "message": "unknown tag: alt", 24717 "line": " src/image/p5.Image.js:660" 24718 }, 24719 { 24720 "message": "unknown tag: alt", 24721 "line": " src/image/p5.Image.js:782" 24722 }, 24723 { 24724 "message": "unknown tag: alt", 24725 "line": " src/image/pixels.js:14" 24726 }, 24727 { 24728 "message": "unknown tag: alt", 24729 "line": " src/image/pixels.js:83" 24730 }, 24731 { 24732 "message": "unknown tag: alt", 24733 "line": " src/image/pixels.js:177" 24734 }, 24735 { 24736 "message": "unknown tag: alt", 24737 "line": " src/image/pixels.js:236" 24738 }, 24739 { 24740 "message": "unknown tag: alt", 24741 "line": " src/image/pixels.js:415" 24742 }, 24743 { 24744 "message": "unknown tag: alt", 24745 "line": " src/image/pixels.js:491" 24746 }, 24747 { 24748 "message": "unknown tag: alt", 24749 "line": " src/image/pixels.js:528" 24750 }, 24751 { 24752 "message": "unknown tag: alt", 24753 "line": " src/image/pixels.js:602" 24754 }, 24755 { 24756 "message": "unknown tag: alt", 24757 "line": " src/io/files.js:19" 24758 }, 24759 { 24760 "message": "unknown tag: alt", 24761 "line": " src/io/files.js:170" 24762 }, 24763 { 24764 "message": "unknown tag: alt", 24765 "line": " src/io/files.js:271" 24766 }, 24767 { 24768 "message": "unknown tag: alt", 24769 "line": " src/io/files.js:603" 24770 }, 24771 { 24772 "message": "replacing incorrect tag: returns with return", 24773 "line": " src/io/files.js:704" 24774 }, 24775 { 24776 "message": "unknown tag: alt", 24777 "line": " src/io/files.js:704" 24778 }, 24779 { 24780 "message": "unknown tag: alt", 24781 "line": " src/io/files.js:1457" 24782 }, 24783 { 24784 "message": "unknown tag: alt", 24785 "line": " src/io/files.js:1509" 24786 }, 24787 { 24788 "message": "unknown tag: alt", 24789 "line": " src/io/files.js:1571" 24790 }, 24791 { 24792 "message": "unknown tag: alt", 24793 "line": " src/io/p5.Table.js:56" 24794 }, 24795 { 24796 "message": "unknown tag: alt", 24797 "line": " src/io/p5.Table.js:119" 24798 }, 24799 { 24800 "message": "unknown tag: alt", 24801 "line": " src/io/p5.Table.js:167" 24802 }, 24803 { 24804 "message": "unknown tag: alt", 24805 "line": " src/io/p5.Table.js:213" 24806 }, 24807 { 24808 "message": "unknown tag: alt", 24809 "line": " src/io/p5.Table.js:262" 24810 }, 24811 { 24812 "message": "unknown tag: alt", 24813 "line": " src/io/p5.Table.js:327" 24814 }, 24815 { 24816 "message": "unknown tag: alt", 24817 "line": " src/io/p5.Table.js:522" 24818 }, 24819 { 24820 "message": "unknown tag: alt", 24821 "line": " src/io/p5.Table.js:575" 24822 }, 24823 { 24824 "message": "unknown tag: alt", 24825 "line": " src/io/p5.Table.js:617" 24826 }, 24827 { 24828 "message": "unknown tag: alt", 24829 "line": " src/io/p5.Table.js:878" 24830 }, 24831 { 24832 "message": "unknown tag: alt", 24833 "line": " src/io/p5.Table.js:944" 24834 }, 24835 { 24836 "message": "unknown tag: alt", 24837 "line": " src/io/p5.Table.js:994" 24838 }, 24839 { 24840 "message": "unknown tag: alt", 24841 "line": " src/io/p5.Table.js:1040" 24842 }, 24843 { 24844 "message": "unknown tag: alt", 24845 "line": " src/io/p5.Table.js:1085" 24846 }, 24847 { 24848 "message": "unknown tag: alt", 24849 "line": " src/io/p5.Table.js:1132" 24850 }, 24851 { 24852 "message": "unknown tag: alt", 24853 "line": " src/io/p5.Table.js:1177" 24854 }, 24855 { 24856 "message": "unknown tag: alt", 24857 "line": " src/io/p5.Table.js:1230" 24858 }, 24859 { 24860 "message": "unknown tag: alt", 24861 "line": " src/io/p5.Table.js:1294" 24862 }, 24863 { 24864 "message": "unknown tag: alt", 24865 "line": " src/io/p5.TableRow.js:42" 24866 }, 24867 { 24868 "message": "unknown tag: alt", 24869 "line": " src/io/p5.TableRow.js:104" 24870 }, 24871 { 24872 "message": "unknown tag: alt", 24873 "line": " src/io/p5.TableRow.js:148" 24874 }, 24875 { 24876 "message": "unknown tag: alt", 24877 "line": " src/io/p5.TableRow.js:193" 24878 }, 24879 { 24880 "message": "unknown tag: alt", 24881 "line": " src/io/p5.TableRow.js:241" 24882 }, 24883 { 24884 "message": "unknown tag: alt", 24885 "line": " src/io/p5.TableRow.js:297" 24886 }, 24887 { 24888 "message": "unknown tag: alt", 24889 "line": " src/io/p5.XML.js:11" 24890 }, 24891 { 24892 "message": "unknown tag: alt", 24893 "line": " src/math/calculation.js:12" 24894 }, 24895 { 24896 "message": "unknown tag: alt", 24897 "line": " src/math/calculation.js:36" 24898 }, 24899 { 24900 "message": "unknown tag: alt", 24901 "line": " src/math/calculation.js:76" 24902 }, 24903 { 24904 "message": "unknown tag: alt", 24905 "line": " src/math/calculation.js:121" 24906 }, 24907 { 24908 "message": "unknown tag: alt", 24909 "line": " src/math/calculation.js:190" 24910 }, 24911 { 24912 "message": "unknown tag: alt", 24913 "line": " src/math/calculation.js:240" 24914 }, 24915 { 24916 "message": "unknown tag: alt", 24917 "line": " src/math/calculation.js:279" 24918 }, 24919 { 24920 "message": "unknown tag: alt", 24921 "line": " src/math/calculation.js:324" 24922 }, 24923 { 24924 "message": "unknown tag: alt", 24925 "line": " src/math/calculation.js:379" 24926 }, 24927 { 24928 "message": "unknown tag: alt", 24929 "line": " src/math/calculation.js:418" 24930 }, 24931 { 24932 "message": "unknown tag: alt", 24933 "line": " src/math/calculation.js:474" 24934 }, 24935 { 24936 "message": "unknown tag: alt", 24937 "line": " src/math/calculation.js:524" 24938 }, 24939 { 24940 "message": "unknown tag: alt", 24941 "line": " src/math/calculation.js:574" 24942 }, 24943 { 24944 "message": "unknown tag: alt", 24945 "line": " src/math/calculation.js:627" 24946 }, 24947 { 24948 "message": "unknown tag: alt", 24949 "line": " src/math/calculation.js:661" 24950 }, 24951 { 24952 "message": "unknown tag: alt", 24953 "line": " src/math/calculation.js:700" 24954 }, 24955 { 24956 "message": "unknown tag: alt", 24957 "line": " src/math/calculation.js:747" 24958 }, 24959 { 24960 "message": "unknown tag: alt", 24961 "line": " src/math/math.js:12" 24962 }, 24963 { 24964 "message": "unknown tag: alt", 24965 "line": " src/math/noise.js:40" 24966 }, 24967 { 24968 "message": "unknown tag: alt", 24969 "line": " src/math/noise.js:187" 24970 }, 24971 { 24972 "message": "unknown tag: alt", 24973 "line": " src/math/noise.js:253" 24974 }, 24975 { 24976 "message": "unknown tag: alt", 24977 "line": " src/math/p5.Vector.js:12" 24978 }, 24979 { 24980 "message": "unknown tag: alt", 24981 "line": " src/math/random.js:48" 24982 }, 24983 { 24984 "message": "unknown tag: alt", 24985 "line": " src/math/random.js:79" 24986 }, 24987 { 24988 "message": "unknown tag: alt", 24989 "line": " src/math/random.js:166" 24990 }, 24991 { 24992 "message": "unknown tag: alt", 24993 "line": " src/math/trigonometry.js:124" 24994 }, 24995 { 24996 "message": "unknown tag: alt", 24997 "line": " src/math/trigonometry.js:160" 24998 }, 24999 { 25000 "message": "unknown tag: alt", 25001 "line": " src/math/trigonometry.js:188" 25002 }, 25003 { 25004 "message": "unknown tag: alt", 25005 "line": " src/math/trigonometry.js:216" 25006 }, 25007 { 25008 "message": "unknown tag: alt",
25009 "line": " src/math/trigonometry.js:296" 25010 }, 25011 { 25012 "message": "replacing incorrect tag: returns with return", 25013 "line": " src/math/trigonometry.js:332" 25014 }, 25015 { 25016 "message": "replacing incorrect tag: returns with return", 25017 "line": " src/math/trigonometry.js:347" 25018 }, 25019 { 25020 "message": "replacing incorrect tag: returns with return", 25021 "line": " src/math/trigonometry.js:362" 25022 }, 25023 { 25024 "message": "unknown tag: alt", 25025 "line": " src/typography/attributes.js:13" 25026 }, 25027 { 25028 "message": "unknown tag: alt", 25029 "line": " src/typography/attributes.js:60" 25030 }, 25031 { 25032 "message": "unknown tag: alt", 25033 "line": " src/typography/attributes.js:98" 25034 }, 25035 { 25036 "message": "unknown tag: alt", 25037 "line": " src/typography/attributes.js:130" 25038 }, 25039 { 25040 "message": "unknown tag: alt", 25041 "line": " src/typography/attributes.js:165" 25042 }, 25043 { 25044 "message": "unknown tag: alt", 25045 "line": " src/typography/loading_displaying.js:16" 25046 }, 25047 { 25048 "message": "unknown tag: alt", 25049 "line": " src/typography/loading_displaying.js:143" 25050 }, 25051 { 25052 "message": "unknown tag: alt", 25053 "line": " src/typography/loading_displaying.js:202" 25054 }, 25055 { 25056 "message": "unknown tag: alt", 25057 "line": " src/typography/p5.Font.js:43" 25058 }, 25059 { 25060 "message": "unknown tag: alt", 25061 "line": " src/utilities/conversion.js:12" 25062 }, 25063 { 25064 "message": "unknown tag: alt", 25065 "line": " src/utilities/string_functions.js:15" 25066 }, 25067 { 25068 "message": "unknown tag: alt", 25069 "line": " src/utilities/string_functions.js:44" 25070 }, 25071 { 25072 "message": "unknown tag: alt", 25073 "line": " src/utilities/string_functions.js:132" 25074 }, 25075 { 25076 "message": "unknown tag: alt", 25077 "line": " src/utilities/string_functions.js:237" 25078 }, 25079 { 25080 "message": "unknown tag: alt", 25081 "line": " src/utilities/string_functions.js:313" 25082 }, 25083 { 25084 "message": "unknown tag: alt", 25085 "line": " src/utilities/string_functions.js:375" 25086 }, 25087 { 25088 "message": "unknown tag: alt", 25089 "line": " src/utilities/string_functions.js:437" 25090 }, 25091 { 25092 "message": "unknown tag: alt", 25093 "line": " src/utilities/string_functions.js:526" 25094 }, 25095 { 25096 "message": "unknown tag: alt", 25097 "line": " src/utilities/time_date.js:12" 25098 }, 25099 { 25100 "message": "unknown tag: alt", 25101 "line": " src/utilities/time_date.js:34" 25102 }, 25103 { 25104 "message": "unknown tag: alt", 25105 "line": " src/utilities/time_date.js:56" 25106 }, 25107 { 25108 "message": "unknown tag: alt", 25109 "line": " src/utilities/time_date.js:78" 25110 }, 25111 { 25112 "message": "unknown tag: alt", 25113 "line": " src/utilities/time_date.js:101" 25114 }, 25115 { 25116 "message": "unknown tag: alt", 25117 "line": " src/utilities/time_date.js:123" 25118 }, 25119 { 25120 "message": "unknown tag: alt", 25121 "line": " src/utilities/time_date.js:145" 25122 }, 25123 { 25124 "message": "unknown tag: alt", 25125 "line": " src/webgl/camera.js:12" 25126 }, 25127 { 25128 "message": "unknown tag: alt", 25129 "line": " src/webgl/camera.js:161" 25130 }, 25131 { 25132 "message": "unknown tag: alt", 25133 "line": " src/webgl/camera.js:243" 25134 }, 25135 { 25136 "message": "unknown tag: alt", 25137 "line": " src/webgl/interaction.js:5" 25138 }, 25139 { 25140 "message": "unknown tag: alt", 25141 "line": " src/webgl/light.js:12" 25142 }, 25143 { 25144 "message": "unknown tag: alt", 25145 "line": " src/webgl/light.js:101" 25146 }, 25147 { 25148 "message": "unknown tag: alt", 25149 "line": " src/webgl/light.js:207" 25150 }, 25151 { 25152 "message": "unknown tag: alt", 25153 "line": " src/webgl/loading.js:14" 25154 }, 25155 { 25156 "message": "unknown tag: alt", 25157 "line": " src/webgl/loading.js:215" 25158 }, 25159 { 25160 "message": "replacing incorrect tag: returns with return", 25161 "line": " src/webgl/material.js:57" 25162 }, 25163 { 25164 "message": "unknown tag: alt", 25165 "line": " src/webgl/material.js:57" 25166 }, 25167 { 25168 "message": "unknown tag: alt", 25169 "line": " src/webgl/material.js:150" 25170 }, 25171 { 25172 "message": "unknown tag: alt", 25173 "line": " src/webgl/material.js:185" 25174 }, 25175 { 25176 "message": "unknown tag: alt", 25177 "line": " src/webgl/material.js:275" 25178 }, 25179 { 25180 "message": "unknown tag: alt", 25181 "line": " src/webgl/material.js:324" 25182 }, 25183 { 25184 "message": "unknown tag: alt", 25185 "line": " src/webgl/p5.RendererGL.js:197" 25186 }, 25187 { 25188 "message": "unknown tag: alt", 25189 "line": " src/webgl/p5.RendererGL.js:439" 25190 }, 25191 { 25192 "message": "unknown tag: alt", 25193 "line": " src/webgl/p5.RendererGL.js:486" 25194 }, 25195 { 25196 "message": "unknown tag: alt", 25197 "line": " src/webgl/p5.RendererGL.js:526" 25198 }, 25199 { 25200 "message": "unknown tag: alt", 25201 "line": " src/webgl/primitives.js:14" 25202 }, 25203 { 25204 "message": "replacing incorrect tag: params with param", 25205 "line": " lib/addons/p5.sound.js:1567" 25206 }, 25207 { 25208 "message": "replacing incorrect tag: returns with return", 25209 "line": " lib/addons/p5.sound.js:1567" 25210 }, 25211 { 25212 "message": "replacing incorrect tag: returns with return", 25213 "line": " lib/addons/p5.sound.js:7272" 25214 }, 25215 { 25216 "message": "replacing incorrect tag: returns with return", 25217 "line": " lib/addons/p5.sound.js:9222" 25218 }, 25219 { 25220 "message": "Missing item type\nConversions adapted from <http://www.easyrgb.com/en/math.php>.\n\nIn these functions, hue is always in the range [0,1); all other components\nare in the range [0,1]. 'Brightness' and 'value' are used interchangeably.", 25221 "line": " src/color/color_conversion.js:10" 25222 }, 25223 { 25224 "message": "Missing item type\nConvert an HSBA array to HSLA.", 25225 "line": " src/color/color_conversion.js:20" 25226 }, 25227 { 25228 "message": "Missing item type\nConvert an HSBA array to RGBA.", 25229 "line": " src/color/color_conversion.js:46" 25230 }, 25231 { 25232 "message": "Missing item type\nConvert an HSLA array to HSBA.", 25233 "line": " src/color/color_conversion.js:101" 25234 }, 25235 { 25236 "message": "Missing item type\nConvert an HSLA array to RGBA.\n\nWe need to change basis from HSLA to something that can be more easily be\nprojected onto RGBA. We will choose hue and brightness as our first two\ncomponents, and pick a convenient third one ('zest') so that we don't need\nto calculate formal HSBA saturation.", 25237 "line": " src/color/color_conversion.js:124" 25238 }, 25239 { 25240 "message": "Missing item type\nConvert an RGBA array to HSBA.", 25241 "line": " src/color/color_conversion.js:188" 25242 }, 25243 { 25244 "message": "Missing item type\nConvert an RGBA array to HSLA.", 25245 "line": " src/color/color_conversion.js:227" 25246 }, 25247 { 25248 "message": "Missing item type\nHue is the same in HSB and HSL, but the maximum value may be different.\nThis function will return the HSB-normalized saturation when supplied with\nan HSB color object, but will default to the HSL-normalized saturation\notherwise.", 25249 "line": " src/color/p5.Color.js:406" 25250 }, 25251 { 25252 "message": "Missing item type\nSaturation is scaled differently in HSB and HSL. This function will return\nthe HSB saturation when supplied with an HSB color object, but will default\nto the HSL saturation otherwise.", 25253 "line": " src/color/p5.Color.js:437" 25254 }, 25255 { 25256 "message": "Missing item type\nCSS named colors.", 25257 "line": " src/color/p5.Color.js:456" 25258 }, 25259 { 25260 "message": "Missing item type\nThese regular expressions are used to build up the patterns for matching\nviable CSS color strings: fragmenting the regexes in this way increases the\nlegibility and comprehensibility of the code.\n\nNote that RGB values of .9 are not parsed by IE, but are supported here for\ncolor string consistency.", 25261 "line": " src/color/p5.Color.js:609" 25262 }, 25263 { 25264 "message": "Missing item type\nFull color string patterns. The capture groups are necessary.", 25265 "line": " src/color/p5.Color.js:622" 25266 }, 25267 { 25268 "message": "Missing item type\nFor a number of different inputs, returns a color formatted as [r, g, b, a]\narrays, with each component normalized between 0 and 1.", 25269 "line": " src/color/p5.Color.js:759" 25270 }, 25271 { 25272 "message": "Missing item type\nFor HSB and HSL, interpret the gray level as a brightness/lightness\nvalue (they are equivalent when chroma is zero). For RGB, normalize the\ngray level according to the blue maximum.", 25273 "line": " src/color/p5.Color.js:976" 25274 }, 25275 { 25276 "message": "Missing item type", 25277 "line": " src/core/canvas.js:1" 25278 }, 25279 { 25280 "message": "Missing item type\nReturns the current framerate.", 25281 "line": " src/core/environment.js:242" 25282 }, 25283 { 25284 "message": "Missing item type\nSpecifies the number of frames to be displayed every second. For example,\nthe function call frameRate(30) will attempt to refresh 30 times a second.\nIf the processor is not fast enough to maintain the specified rate, the\nframe rate will not be achieved. Setting the frame rate within setup() is\nrecommended. The default rate is 60 frames per second.\n\nCalling frameRate() with no arguments returns the current framerate.", 25285 "line": " src/core/environment.js:252" 25286 }, 25287 { 25288 "message": "Missing item type", 25289 "line": " src/core/error_helpers.js:1" 25290 }, 25291 { 25292 "message": "Missing item type\nPrints out a fancy, colorful message to the console log", 25293 "line": " src/core/error_helpers.js:65" 25294 }, 25295 { 25296 "message": "Missing item type\nValidates parameters\nparam {String} func the name of the function\nparam {Array} args user input arguments\n\nexample:\n var a;\n ellipse(10,10,a,5);\nconsole ouput:\n \"It looks like ellipse received an empty variable in spot #2.\"\n\nexample:\n ellipse(10,\"foo\",5,5);\nconsole output:\n \"ellipse was expecting a number for parameter #1,\n received \"foo\" instead.\"", 25297 "line": " src/core/error_helpers.js:405" 25298 }, 25299 { 25300 "message": "Missing item type\nPrints out all the colors in the color pallete with white text.\nFor color blindness testing.", 25301 "line": " src/core/error_helpers.js:457" 25302 }, 25303 { 25304 "message": "Missing item type\n_globalInit\n\nTODO: ???\nif sketch is on window\nassume \"global\" mode\nand instantiate p5 automatically\notherwise do nothing", 25305 "line": " src/core/init.js:5" 25306 }, 25307 { 25308 "message": "Missing item type\nHelper fxn for sharing pixel methods", 25309 "line": " src/core/p5.Element.js:1057" 25310 }, 25311 { 25312 "message": "Missing item type\nResize our canvas element.", 25313 "line": " src/core/p5.Renderer.js:113" 25314 }, 25315 { 25316 "message": "Missing item type\nHelper fxn to check font type (system or otf)", 25317 "line": " src/core/p5.Renderer.js:182" 25318 }, 25319 { 25320 "message": "Missing item type\nHelper fxn to measure ascent and desce
25320nt.\nAdapted from http://stackoverflow.com/a/25355178", 25321 "line": " src/core/p5.Renderer.js:235" 25322 }, 25323 { 25324 "message": "Missing item type\np5.Renderer2D\nThe 2D graphics canvas renderer class.\nextends p5.Renderer", 25325 "line": " src/core/p5.Renderer2D.js:10" 25326 }, 25327 { 25328 "message": "Missing item type\nGenerate a cubic Bezier representing an arc on the unit circle of total\nangle `size` radians, beginning `start` radians above the x-axis. Up to\nfour of these curves are combined to make a full arc.\n\nSee www.joecridge.me/bezier.pdf for an explanation of the method.", 25329 "line": " src/core/p5.Renderer2D.js:395" 25330 }, 25331 { 25332 "message": "Missing item type\nshim for Uint8ClampedArray.slice\n(allows arrayCopy to work with pixels[])\nwith thanks to http://halfpapstudios.com/blog/tag/html5-canvas/\nEnumerable set to false to protect for...in from\nUint8ClampedArray.prototype pollution.", 25333 "line": " src/core/shim.js:70" 25334 }, 25335 { 25336 "message": "Missing item type\nprivate helper function to handle the user passing objects in\nduring construction or calls to create()", 25337 "line": " src/data/p5.TypedDict.js:198" 25338 }, 25339 { 25340 "message": "Missing item type\nprivate helper function to ensure that the user passed in valid\nvalues for the Dictionary type", 25341 "line": " src/data/p5.TypedDict.js:378" 25342 }, 25343 { 25344 "message": "Missing item type\nprivate helper function to ensure that the user passed in valid\nvalues for the Dictionary type", 25345 "line": " src/data/p5.TypedDict.js:423" 25346 }, 25347 { 25348 "message": "Missing item type\nprivate helper function for finding lowest or highest value\nthe argument 'flip' is used to flip the comparison arrow\nfrom 'less than' to 'greater than'", 25349 "line": " src/data/p5.TypedDict.js:540" 25350 }, 25351 { 25352 "message": "Missing item type\nprivate helper function for finding lowest or highest key\nthe argument 'flip' is used to flip the comparison arrow\nfrom 'less than' to 'greater than'", 25353 "line": " src/data/p5.TypedDict.js:605" 25354 }, 25355 { 25356 "message": "Missing item type\n_updatePAccelerations updates the pAcceleration values", 25357 "line": " src/events/acceleration.js:80" 25358 }, 25359 { 25360 "message": "Missing item type\nHolds the key codes of currently pressed keys.", 25361 "line": " src/events/keyboard.js:12" 25362 }, 25363 { 25364 "message": "Missing item type\nThe onblur function is called when the user is no longer focused\non the p5 element. Because the keyup events will not fire if the user is\nnot focused on the element we must assume all keys currently down have\nbeen released.", 25365 "line": " src/events/keyboard.js:308" 25366 }, 25367 { 25368 "message": "Missing item type\nThe checkDownKeys function returns a boolean true if any keys pressed\nand a false if no keys are currently pressed.\n\nHelps avoid instances where a multiple keys are pressed simultaneously and\nreleasing a single key will then switch the\nkeyIsPressed property to true.", 25369 "line": " src/events/keyboard.js:370" 25370 }, 25371 { 25372 "message": "Missing item type\nThis module defines the filters for use with image buffers.\n\nThis module is basically a collection of functions stored in an object\nas opposed to modules. The functions are destructive, modifying\nthe passed in canvas rather than creating a copy.\n\nGenerally speaking users of this module will use the Filters.apply method\non a canvas to create an effect.\n\nA number of functions are borrowed/adapted from\nhttp://www.html5rocks.com/en/tutorials/canvas/imagefilters/\nor the java processing implementation.", 25373 "line": " src/image/filters.js:3" 25374 }, 25375 { 25376 "message": "Missing item type\nReturns the pixel buffer for a canvas", 25377 "line": " src/image/filters.js:26" 25378 }, 25379 { 25380 "message": "Missing item type\nReturns a 32 bit number containing ARGB data at ith pixel in the\n1D array containing pixels data.", 25381 "line": " src/image/filters.js:46" 25382 }, 25383 { 25384 "message": "Missing item type\nModifies pixels RGBA values to values contained in the data object.", 25385 "line": " src/image/filters.js:67" 25386 }, 25387 { 25388 "message": "Missing item type\nReturns the ImageData object for a canvas\nhttps://developer.mozilla.org/en-US/docs/Web/API/ImageData", 25389 "line": " src/image/filters.js:87" 25390 }, 25391 { 25392 "message": "Missing item type\nReturns a blank ImageData object.", 25393 "line": " src/image/filters.js:107" 25394 }, 25395 { 25396 "message": "Missing item type\nApplys a filter function to a canvas.\n\nThe difference between this and the actual filter functions defined below\nis that the filter functions generally modify the pixel buffer but do\nnot actually put that data back to the canvas (where it would actually\nupdate what is visible). By contrast this method does make the changes\nactually visible in the canvas.\n\nThe apply method is the method that callers of this module would generally\nuse. It has been separated from the actual filters to
25396support an advanced\nuse case of creating a filter chain that executes without actually updating\nthe canvas in between everystep.", 25397 "line": " src/image/filters.js:122" 25398 }, 25399 { 25400 "message": "Missing item type\nConverts the image to black and white pixels depending if they are above or\nbelow the threshold defined by the level parameter. The parameter must be\nbetween 0.0 (black) and 1.0 (white). If no level is specified, 0.5 is used.\n\nBorrowed from http://www.html5rocks.com/en/tutorials/canvas/imagefilters/", 25401 "line": " src/image/filters.js:159" 25402 }, 25403 { 25404 "message": "Missing item type\nConverts any colors in the image to grayscale equivalents.\nNo parameter is used.\n\nBorrowed from http://www.html5rocks.com/en/tutorials/canvas/imagefilters/", 25405 "line": " src/image/filters.js:193" 25406 }, 25407 { 25408 "message": "Missing item type\nSets the alpha channel to entirely opaque. No parameter is used.", 25409 "line": " src/image/filters.js:216" 25410 }, 25411 { 25412 "message": "Missing item type\nSets each pixel to its inverse value. No parameter is used.", 25413 "line": " src/image/filters.js:232" 25414 }, 25415 { 25416 "message": "Missing item type\nLimits each channel of the image to the number of colors specified as\nthe parameter. The parameter can be set to values between 2 and 255, but\nresults are most noticeable in the lower ranges.\n\nAdapted from java based processing implementation", 25417 "line": " src/image/filters.js:247" 25418 }, 25419 { 25420 "message": "Missing item type\nreduces the bright areas in an image", 25421 "line": " src/image/filters.js:279" 25422 }, 25423 { 25424 "message": "Missing item type\nincreases the bright areas in an image", 25425 "line": " src/image/filters.js:367" 25426 }, 25427 { 25428 "message": "Missing item type\nThis module defines the p5 methods for the p5.Image class\nfor drawing images to the main display canvas.", 25429 "line": " src/image/image.js:8" 25430 }, 25431 { 25432 "message": "Missing item type\nValidates clipping params. Per drawImage spec sWidth and sHight cannot be\nnegative or greater than image intrinsic width and height", 25433 "line": " src/image/loading_displaying.js:108" 25434 }, 25435 { 25436 "message": "Missing item type\nApply the current tint color to the input image, return the resulting\ncanvas.", 25437 "line": " src/image/loading_displaying.js:425" 25438 }, 25439 { 25440 "message": "Missing item type\nThis module defines the p5.Image class and P5 methods for\ndrawing images to the main display canvas.", 25441 "line": " src/image/p5.Image.js:9" 25442 }, 25443 { 25444 "message": "Missing item type\nHelper fxn for sharing pixel methods", 25445 "line": " src/image/p5.Image.js:221" 25446 }, 25447 { 25448 "message": "Missing item type\nGenerate a blob of file data as a url to prepare for download.\nAccepts an array of data, a filename, and an extension (optional).\nThis is a private function because it does not do any formatting,\nbut it is used by saveStrings, saveJSON, saveTable etc.", 25449 "line": " src/io/files.js:1697" 25450 }, 25451 { 25452 "message": "Missing item type\nReturns a file extension, or another string\nif the provided parameter has no extension.", 25453 "line": " src/io/files.js:1766" 25454 }, 25455 { 25456 "message": "Missing item type\nReturns true if the browser is Safari, false if not.\nSafari makes trouble for downloading files.", 25457 "line": " src/io/files.js:1799" 25458 }, 25459 { 25460 "message": "Missing item type\nHelper function, a callback for download that deletes\nan invisible anchor element from the DOM once the file\nhas been automatically downloaded.", 25461 "line": " src/io/files.js:1811" 25462 }, 25463 { 25464 "message": "Missing item type\nTable Options\n<p>Generic class for handling tabular data, typically from a\nCSV, TSV, or other sort of spreadsheet file.</p>\n<p>CSV files are\n<a href=\"http://en.wikipedia.org/wiki/Comma-separated_values\">\ncomma separated values</a>, often with the data in quotes. TSV\nfiles use tabs as separators, and usually don't bother with the\nquotes.</p>\n<p>File names should end with .csv if they're comma separated.</p>\n<p>A rough \"spec\" for CSV can be found\n<a href=\"http://tools.ietf.org/html/rfc4180\">here</a>.</p>\n<p>To load files, use the loadTable method.</p>\n<p>To save tables to your computer, use the save method\n or the saveTable method.</p>\n\nPossible options include:\n<ul>\n<li>csv - parse the table as comma-separated values\n<li>tsv - parse the table as tab-separated values\n<li>header - this table has a header (title) row\n</ul>", 25465 "line": " src/io/p5.Table.js:11" 25466 }, 25467 { 25468 "message": "Missing item type\nThis method is called while the parsing of XML (when loadXML() is\ncalled). The difference between this method and the setContent()\nmethod defined later is that this one is used to set the content\nwhen the node in question has more nodes under it and so on and\nnot directly text content. While in the other one is used when\nthe node in question directly has text inside it.", 25469 "line": " src/io/p5.XML.js:801" 25470 }, 25471 { 25472 "message": "Missing item type\nThis method is called while the parsing of XML (when loadXML() is\ncalled). The XML node is passed and its attributes are stored in the\np5.XML's attribute Object.", 25473 "line": " src/io/p5.XML.js:818" 25474 }, 25475 { 25476 "message": "Missing item type\nMultiplies a vector by a scalar and returns a new vector.", 25477 "line": " src/math/p5.Vector.js:1611" 25478 }, 25479 { 25480 "message": "Missing item type\nDivides a vector by a scalar and returns a new vector.", 25481 "line": " src/math/p5.Vector.js:1638" 25482 }, 25483 { 25484 "message": "Missing item type\nCalculates the dot product of two vectors.", 25485 "line": " src/math/p5.Vector.js:1665" 25486 }, 25487 { 25488 "message": "Missing item type\nCalculates the cross product of two vectors.", 25489 "line": " src/math/p5.Vector.js:1679" 25490 }, 25491 { 25492 "message": "Missing item type\nCalculates the Euclidean distance between two points (considering a\npoint as a vector object).", 25493 "line": " src/math/p5.Vector.js:1693" 25494 }, 25495 { 25496 "message": "Missing item type\nLinear interpolate a vector to another vector and return the result as a\nne
25496w vector.", 25497 "line": " src/math/p5.Vector.js:1708" 25498 }, 25499 { 25500 "message": "Missing item type\nHelper function to measure ascent and descent.", 25501 "line": " src/typography/attributes.js:258" 25502 }, 25503 { 25504 "message": "Missing item type\nReturns the set of opentype glyphs for the supplied string.\n\nNote that there is not a strict one-to-one mapping between characters\nand glyphs, so the list of returned glyphs can be larger or smaller\n than the length of the given string.", 25505 "line": " src/typography/p5.Font.js:257" 25506 }, 25507 { 25508 "message": "Missing item type\nReturns an opentype path for the supplied string and position.", 25509 "line": " src/typography/p5.Font.js:272" 25510 }, 25511 { 25512 "message": "Missing item type\nParse OBJ lines into model. For reference, this is what a simple model of a\nsquare might look like:\n\nv -0.5 -0.5 0.5\nv -0.5 -0.5 -0.5\nv -0.5 0.5 -0.5\nv -0.5 0.5 0.5\n\nf 4 3 2 1", 25513 "line": " src/webgl/loading.js:106" 25514 }, 25515 { 25516 "message": "Missing item type", 25517 "line": " src/webgl/material.js:373" 25518 }, 25519 { 25520 "message": "Missing item type\nCreate a 2D array for establishing stroke connections", 25521 "line": " src/webgl/p5.Geometry.js:192" 25522 }, 25523 { 25524 "message": "Missing item type\nCreate 4 vertices for each stroke line, two at the beginning position\nand two at the end position. These vertices are displaced relative to\nthat line's normal on the GPU", 25525 "line": " src/webgl/p5.Geometry.js:213" 25526 }, 25527 { 25528 "message": "Missing item type", 25529 "line": " src/webgl/p5.Matrix.js:1" 25530 }, 25531 { 25532 "message": "Missing item type\nPRIVATE", 25533 "line": " src/webgl/p5.Matrix.js:673" 25534 }, 25535 { 25536 "message": "Missing item type\nWelcome to RendererGL Immediate Mode.\nImmediate mode is used for drawing custom shapes\nfrom a set of vertices. Immediate Mode is activated\nwhen you call beginShape() & de-activated when you call endShape().\nImmediate mode is a style of programming borrowed\nfrom OpenGL's (now-deprecated) immediate mode.\nIt differs from p5.js' default, Retained Mode, which caches\ngeometries and buffers on the CPU to reduce the number of webgl\ndraw calls. Retained mode is more efficient & performative,\nhowever, Immediate Mode is useful for sketching quick\ngeometric ideas.", 25537 "line": " src/webgl/p5.RendererGL.Immediate.js:1" 25538 }, 25539 { 25540 "message": "Missing item type\nEnd shape drawing and render vertices to screen.", 25541 "line": " src/webgl/p5.RendererGL.Immediate.js:106" 25542 }, 25543 { 25544 "message": "Missing item type\ninitializes buffer defaults. runs each time a new geometry is\nregistered", 25545 "line": " src/webgl/p5.RendererGL.Retained.js:8" 25546 }, 25547 { 25548 "message": "Missing item type\ncreateBuffers description", 25549 "line": " src/webgl/p5.RendererGL.Retained.js:47" 25550 }, 25551 { 25552 "message": "Missing item type\nDraws buffers given a geometry key ID", 25553 "line": " src/webgl/p5.RendererGL.Retained.js:191" 25554 }, 25555 { 25556 "message": "Missing item type\nmodel view, projection, & normal\nmatrices", 25557 "line": " src/webgl/p5.RendererGL.js:77" 25558 }, 25559 { 25560 "message": "Missing item type\n[background description]", 25561 "line": " src/webgl/p5.RendererGL.js:417" 25562 }, 25563 { 25564 "message": "Missing item type\n[resize description]", 25565 "line": " src/webgl/p5.RendererGL.js:654" 25566 }, 25567 { 25568 "message": "Missing item type\nclears color and depth buffers\nwith r,g,b,a", 25569 "line": " src/webgl/p5.RendererGL.js:684" 25570 }, 25571 { 25572 "message": "Missing item type\n[translate description]", 25573 "line": " src/webgl/p5.RendererGL.js:702" 25574 }, 25575 { 25576 "message": "Missing item type\nScales the Model View Matrix by a vector", 25577 "line": " src/webgl/p5.RendererGL.js:721" 25578 }, 25579 { 25580 "message": "Missing item type\nturn a two dimensional array into one dimensional array", 25581 "line": " src/webgl/p5.RendererGL.js:1001" 25582 }, 25583 { 25584 "message": "Missing item type\nturn a p5.Vector Array into a one dimensional number array", 25585 "line": " src/webgl/p5.RendererGL.js:1038" 25586 }, 25587 { 25588 "message": "Missing item type\nensures that p5 is using a 3d renderer. throws an error if not.", 25589 "line": " src/webgl/p5.RendererGL.js:1054" 25590 }, 25591 { 25592 "message": "Missing item type", 25593 "line": " src/webgl/primitives.js:257" 25594 }, 25595 { 25596 "message": "Missing item type\nDraw a line given two points", 25597 "line": " src/webgl/primitives.js:1037" 25598 }, 25599 { 25600 "message": "Missing item type\nHelper function for select and selectAll", 25601 "line": " lib/addons/p5.dom.js:168" 25602 }, 25603 { 25604 "message": "Missing item type\nHelper function for getElement and getElements.", 25605 "line": " lib/addons/p5.dom.js:184" 25606 }, 25607 { 25608 "message": "Missing item type\nHelpers for create methods.", 25609 "line": " lib/addons/p5.dom.js:245" 25610 }, 25611 { 25612 "message": "Missing item type", 25613 "line": " lib/addons/p5.dom.js:376" 25614 }, 25615 { 25616 "message": "Missing item type", 25617 "line": " lib/addons/p5.dom.js:897" 25618 }, 25619 { 25620 "message": "Missing item type", 25621 "line": " lib/addons/p5.dom.js:973" 25622 }, 25623 { 25624 "message": "Missing item type", 25625 "line": " lib/addons/p5.dom.js:1013" 25626 }, 25627 { 25628 "message": "Missing item type", 25629 "line": " lib/addons/p5.dom.js:2581" 25630 }, 25631 { 25632 "message": "Missing item type", 25633 "line": " lib/addons/p5.dom.js:2647" 25634 }, 25635 { 25636 "message": "Missing item type", 25637 "line": " lib/addons/p5.dom.js:2709" 25638 }, 25639 { 25640 "message": "Missing item type\np5.sound\nhttps://p5js.org/reference/#/libraries/p5.sound\n\nFrom the Processing Foundation and contributors\nhttps://github.com/processing/p5.js-sound/graphs/contributors\n\nMIT License (MIT)\nhttps://github.com/processing/p5.js-sound/blob/master/LICENSE\n\nSome of the many audio libraries & resources that inspire p5.sound:\n - TONE.js (c) Yotam Mann. Licensed under The MIT License (MIT). https://github.com/TONEnoTONE/Tone.js\n - buzz.js (c) Jay Salvat. Licensed under The MIT License (MIT). http://buzz.jaysalvat.com/\n - Boris Smus Web Audio API book, 2013. Licensed under the Apache License http://www.apache.org/licenses/LICENSE-2.0\n - wavesurfer.js https://github.com/katspaugh/wavesurfer.js\n - Web Audio Components by Jordan Santell https://github.com/web-audio-components\n - Wilm Thoben's Sound library for Processing https://github.com/processing/processing/tree/master/java/libraries/sound\n\n Web Audio API: http://w3.org/TR/webaudio/", 25641 "line": " lib/addons/p5.sound.js:46" 25642 }, 25643 { 25644 "message": "Missing item type\nDetermine which filetypes are supported (inspired by buzz.js)\nThe audio element (el) will only be used to test browser support for various audio formats", 25645 "line": " lib/addons/p5.sound.js:226" 25646 }, 25647 { 25648 "message": "Missing item type\nMaster contains AudioContext and the master sound output.",
25649 "line": " lib/addons/p5.sound.js:296" 25650 }, 25651 { 25652 "message": "Missing item type\na silent connection to the DesinationNode\nwhich will ensure that anything connected to it\nwill not be garbage collected", 25653 "line": " lib/addons/p5.sound.js:391" 25654 }, 25655 { 25656 "message": "Missing item type", 25657 "line": " lib/addons/p5.sound.js:407" 25658 }, 25659 { 25660 "message": "Missing item type\nUsed by Osc and Env to chain signal math", 25661 "line": " lib/addons/p5.sound.js:583" 25662 }, 25663 { 25664 "message": "Missing item type\nThis is a helper function that the p5.SoundFile calls to load\nitself. Accepts a callback (the name of another function)\nas an optional parameter.", 25665 "line": " lib/addons/p5.sound.js:903" 25666 }, 25667 { 25668 "message": "Missing item type\nStop playback on all of this soundfile's sources.", 25669 "line": " lib/addons/p5.sound.js:1304" 25670 }, 25671 { 25672 "message": "Missing item type", 25673 "line": " lib/addons/p5.sound.js:1741" 25674 }, 25675 { 25676 "message": "Missing item type", 25677 "line": " lib/addons/p5.sound.js:2022" 25678 }, 25679 { 25680 "message": "Missing item type", 25681 "line": " lib/addons/p5.sound.js:3022" 25682 }, 25683 { 25684 "message": "Missing item type", 25685 "line": " lib/addons/p5.sound.js:3399" 25686 }, 25687 { 25688 "message": "Missing item type", 25689 "line": " lib/addons/p5.sound.js:3420" 25690 }, 25691 { 25692 "message": "Missing item type", 25693 "line": " lib/addons/p5.sound.js:3479" 25694 }, 25695 { 25696 "message": "Missing item type", 25697 "line": " lib/addons/p5.sound.js:3797" 25698 }, 25699 { 25700 "message": "Missing item type", 25701 "line": " lib/addons/p5.sound.js:3969" 25702 }, 25703 { 25704 "message": "Missing item type", 25705 "line": " lib/addons/p5.sound.js:4127" 25706 }, 25707 { 25708 "message": "Missing item type", 25709 "line": " lib/addons/p5.sound.js:4168" 25710 }, 25711 { 25712 "message": "Missing item type", 25713 "line": " lib/addons/p5.sound.js:4238" 25714 }, 25715 { 25716 "message": "Missing item type", 25717 "line": " lib/addons/p5.sound.js:4426" 25718 }, 25719 { 25720 "message": "Missing item type", 25721 "line": " lib/addons/p5.sound.js:4483" 25722 }, 25723 { 25724 "message": "Missing item type", 25725 "line": " lib/addons/p5.sound.js:4651" 25726 }, 25727 { 25728 "message": "Missing item type", 25729 "line": " lib/addons/p5.sound.js:4699" 25730 }, 25731 { 25732 "message": "Missing item type", 25733 "line": " lib/addons/p5.sound.js:4730" 25734 }, 25735 { 25736 "message": "Missing item type", 25737 "line": " lib/addons/p5.sound.js:4751" 25738 }, 25739 { 25740 "message": "Missing item type", 25741 "line": " lib/addons/p5.sound.js:4771" 25742 }, 25743 { 25744 "message": "Missing item type", 25745 "line": " lib/addons/p5.sound.js:5478" 25746 }, 25747 { 25748 "message": "Missing item type", 25749 "line": " lib/addons/p5.sound.js:5681" 25750 }, 25751 { 25752 "message": "Missing item type", 25753 "line": " lib/addons/p5.sound.js:7363" 25754 }, 25755 { 25756 "message": "Missing item type", 25757 "line": " lib/addons/p5.sound.js:7379" 25758 }, 25759 { 25760 "message": "Missing item type", 25761 "line": " lib/addons/p5.sound.js:7403" 25762 }, 25763 { 25764 "message": "Missing item type", 25765 "line": " lib/addons/p5.sound.js:7429" 25766 }, 25767 { 25768 "message": "Missing item type", 25769 "line": " lib/addons/p5.sound.js:7451" 25770 }, 25771 { 25772 "message": "Missing item type", 25773 "line": " lib/addons/p5.sound.js:7473" 25774 }, 25775 { 25776 "message": "Missing item type", 25777 "line": " lib/addons/p5.sound.js:7519" 25778 }, 25779 { 25780 "message": "Missing item type", 25781 "line": " lib/addons/p5.sound.js:7550" 25782 }, 25783 { 25784 "message": "Missing item type", 25785 "line": " lib/addons/p5.sound.js:7568" 25786 }, 25787 { 25788 "message": "Missing item type", 25789 "line": " lib/addons/p5.sound.js:7905" 25790 }, 25791 { 25792 "message": "Missing item type", 25793 "line": " lib/addons/p5.sound.js:7927" 25794 }, 25795 { 25796 "message": "Missing item type\nThe p5.Effect class is built\n using Tone.js CrossFade", 25797 "line": " lib/addons/p5.sound.js:7997" 25798 }, 25799 { 25800 "message": "Missing item type\nIn classes that extend\np5.Effect, connect effect nodes\nto the wet parameter", 25801 "line": " lib/addons/p5.sound.js:8003" 25802 }, 25803 { 25804 "message": "Missing item type\nEQFilter extends p5.Filter with constraints\nnecessary for the p5.EQ", 25805 "line": " lib/addons/p5.sound.js:8381" 25806 }, 25807 { 25808 "message": "Missing item type\nInspired by Simple Reverb by Jordan Santell\nhttps://github.com/web-audio-components/simple-reverb/blob/master/index.js\n\nUtility function for building an impulse response\nbased on the module parameters.", 25809 "line": " lib/addons/p5.sound.js:9471" 25810 }, 25811 { 25812 "message": "Missing item type\nPrivate method to load a buffer as an Impulse Response,\nassign it to the convolverNode, and add to the Array of .impulses.", 25813 "line": " lib/addons/p5.sound.js:9635" 25814 }, 25815 { 25816 "message": "Missing item type", 25817 "line": " lib/addons/p5.sound.js:9821" 25818 }, 25819 { 25820 "message": "Missing item type", 25821 "line": " lib/addons/p5.sound.js:9846" 25822 }, 25823 { 25824 "message": "Missing item type\nmusicalTimeMode variables\nmodify these only when the interval is specified in musicalTime format as a string", 25825 "line": " lib/addons/p5.sound.js:10571" 25826 }, 25827 { 25828 "message": "Missing item type\nDo not initiate the callback if timeFromNow is < 0\nThis ususually occurs for a few milliseconds when the page\
25828nis not fully loaded\n\nThe callback should only be called until maxIterations is reached", 25829 "line": " lib/addons/p5.sound.js:10587" 25830 }, 25831 { 25832 "message": "Missing item type\ncallback invoked when the recording is over", 25833 "line": " lib/addons/p5.sound.js:11072" 25834 }, 25835 { 25836 "message": "Missing item type\ninternal method called on audio process", 25837 "line": " lib/addons/p5.sound.js:11158" 25838 }, 25839 { 25840 "message": "Missing item type\nPrivate method to ensure accurate values of this._voicesInUse\nAny time a new value is scheduled, it is necessary to increment all subsequent\nscheduledValues after attack, and decrement all subsequent\nscheduledValues after release", 25841 "line": " lib/addons/p5.sound.js:12142" 25842 }, 25843 { 25844 "message": "Missing item type\np5.sound\nhttps://p5js.org/reference/#/libraries/p5.sound\n\nFrom the Processing Foundation and contributors\nhttps://github.com/processing/p5.js-sound/graphs/contributors\n\nMIT License (MIT)\nhttps://github.com/processing/p5.js-sound/blob/master/LICENSE\n\nSome of the many audio libraries & resources that inspire p5.sound:\n - TONE.js (c) Yotam Mann. Licensed under The MIT License (MIT). https://github.com/TONEnoTONE/Tone.js\n - buzz.js (c) Jay Salvat. Licensed under The MIT License (MIT). http://buzz.jaysalvat.com/\n - Boris Smus Web Audio API book, 2013. Licensed under the Apache License http://www.apache.org/licenses/LICENSE-2.0\n - wavesurfer.js https://github.com/katspaugh/wavesurfer.js\n - Web Audio Components by Jordan Santell https://github.com/web-audio-components\n - Wilm Thoben's Sound library for Processing https://github.com/processing/processing/tree/master/java/libraries/sound\n\n Web Audio API: http://w3.org/TR/webaudio/", 25845 "line": " lib/addons/p5.sound.min.js:3" 25846 } 25847 ], 25848 "consts": { 25849 "RGB": [ 25850 "p5.colorMode" 25851 ], 25852 "HSB": [ 25853 "p5.colorMode" 25854 ], 25855 "HSL": [ 25856 "p5.colorMode" 25857 ], 25858 "CHORD": [ 25859 "p5.arc" 25860 ], 25861 "PIE": [ 25862 "p5.arc" 25863 ], 25864 "OPEN": [ 25865 "p5.arc" 25866 ], 25867 "CENTER": [ 25868 "p5.ellipseMode", 25869 "p5.rectMode", 25870 "p5.imageMode", 25871 "p5.textAlign" 25872 ], 25873 "RADIUS": [ 25874 "p5.ellipseMode", 25875 "p5.rectMode" 25876 ], 25877 "CORNER": [ 25878 "p5.ellipseMode", 25879 "p5.rectMode", 25880 "p5.imageMode" 25881 ], 25882 "CORNERS": [ 25883 "p5.ellipseMode", 25884 "p5.rectMode", 25885 "p5.imageMode" 25886 ], 25887 "SQUARE": [ 25888 "p5.strokeCap" 25889 ], 25890 "PROJECT": [ 25891 "p5.strokeCap" 25892 ], 25893 "ROUND": [ 25894 "p5.strokeCap", 25895 "p5.strokeJoin" 25896 ], 25897 "MITER": [ 25898 "p5.strokeJoin" 25899 ], 25900 "BEVEL": [ 25901 "p5.strokeJoin" 25902 ], 25903 "ARROW": [ 25904 "p5.cursor" 25905 ], 25906 "CROSS": [ 25907 "p5.cursor" 25908 ], 25909 "HAND": [ 25910 "p5.cursor" 25911 ], 25912 "MOVE": [ 25913 "p5.cursor" 25914 ], 25915 "TEXT": [ 25916 "p5.cursor" 25917 ], 25918 "WAIT": [ 25919 "p5.cursor" 25920 ], 25921 "P2D": [ 25922 "p5.createCanvas", 25923 "p5.createGraphics" 25924 ], 25925 "WEBGL": [ 25926 "p5.createCanvas", 25927 "p5.createGraphics" 25928 ], 25929 "BLEND": [ 25930 "p5.blendMode", 25931 "p5.Image.blend", 25932 "p5.blend" 25933 ], 25934 "DARKEST": [ 25935 "p5.blendMode", 25936 "p5.Image.blend", 25937 "p5.blend" 25938 ], 25939 "LIGHTEST": [ 25940 "p5.blendMode", 25941 "p5.Image.blend", 25942 "p5.blend" 25943 ], 25944 "DIFFERENCE": [ 25945 "p5.blendMode", 25946 "p5.Image.blend", 25947 "p5.blend" 25948 ], 25949 "MULTIPLY": [ 25950 "p5.blendMode", 25951 "p5.Image.blend", 25952 "p5.blend" 25953 ], 25954 "EXCLUSION": [
vendor: 6,626 bytes, lines 25955-26223
25955 "p5.blendMode", 25956 "p5.Image.blend", 25957 "p5.blend" 25958 ], 25959 "SCREEN": [ 25960 "p5.blendMode", 25961 "p5.Image.blend", 25962 "p5.blend" 25963 ], 25964 "REPLACE": [ 25965 "p5.blendMode", 25966 "p5.Image.blend", 25967 "p5.blend" 25968 ], 25969 "OVERLAY": [ 25970 "p5.blendMode", 25971 "p5.Image.blend", 25972 "p5.blend" 25973 ], 25974 "HARD_LIGHT": [ 25975 "p5.blendMode", 25976 "p5.Image.blend", 25977 "p5.blend" 25978 ], 25979 "SOFT_LIGHT": [ 25980 "p5.blendMode", 25981 "p5.Image.blend", 25982 "p5.blend" 25983 ], 25984 "DODGE": [ 25985 "p5.blendMode", 25986 "p5.Image.blend", 25987 "p5.blend" 25988 ], 25989 "BURN": [ 25990 "p5.blendMode", 25991 "p5.Image.blend", 25992 "p5.blend" 25993 ], 25994 "ADD": [ 25995 "p5.blendMode", 25996 "p5.Image.blend", 25997 "p5.blend" 25998 ], 25999 "NORMAL": [ 26000 "p5.blendMode", 26001 "p5.Image.blend", 26002 "p5.blend", 26003 "p5.textStyle" 26004 ], 26005 "POINTS": [ 26006 "p5.beginShape" 26007 ], 26008 "LINES": [ 26009 "p5.beginShape" 26010 ], 26011 "TRIANGLES": [ 26012 "p5.beginShape" 26013 ], 26014 "TRIANGLE_FAN": [ 26015 "p5.beginShape" 26016 ], 26017 "TRIANGLE_STRIP": [ 26018 "p5.beginShape" 26019 ], 26020 "QUADS": [ 26021 "p5.beginShape" 26022 ], 26023 "QUAD_STRIP": [ 26024 "p5.beginShape" 26025 ], 26026 "CLOSE": [ 26027 "p5.endShape" 26028 ], 26029 "THRESHOLD": [ 26030 "p5.Image.filter", 26031 "p5.filter" 26032 ], 26033 "GRAY": [ 26034 "p5.Image.filter", 26035 "p5.filter" 26036 ], 26037 "OPAQUE": [ 26038 "p5.Image.filter", 26039 "p5.filter" 26040 ], 26041 "INVERT": [ 26042 "p5.Image.filter", 26043 "p5.filter" 26044 ], 26045 "POSTERIZE": [ 26046 "p5.Image.filter", 26047 "p5.filter" 26048 ], 26049 "BLUR": [ 26050 "p5.Image.filter", 26051 "p5.filter" 26052 ], 26053 "ERODE": [ 26054 "p5.Image.filter", 26055 "p5.filter" 26056 ], 26057 "DILATE": [ 26058 "p5.Image.filter", 26059 "p5.filter" 26060 ], 26061 "RADIANS": [ 26062 "p5.angleMode" 26063 ], 26064 "DEGREES": [ 26065 "p5.angleMode" 26066 ], 26067 "LEFT": [ 26068 "p5.textAlign" 26069 ], 26070 "RIGHT": [ 26071 "p5.textAlign" 26072 ], 26073 "TOP": [ 26074 "p5.textAlign" 26075 ], 26076 "BOTTOM": [ 26077 "p5.textAlign" 26078 ], 26079 "BASELINE": [ 26080 "p5.textAlign" 26081 ], 26082 "ITALIC": [ 26083 "p5.textStyle" 26084 ], 26085 "BOLD": [ 26086 "p5.textStyle" 26087 ], 26088 "VIDEO": [ 26089 "p5.dom.createCapture" 26090 ], 26091 "AUDIO": [ 26092 "p5.dom.createCapture" 26093 ], 26094 "AUTO": [ 26095 "p5.Element.size" 26096 ] 26097 } 26098} 26099},{}],2:[function(_dereq_,module,exports){ 26100var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; 26101 26102;(function (exports) { 26103 'use strict'; 26104 26105 var Arr = (typeof Uint8Array !== 'undefined') 26106 ? Uint8Array 26107 : Array 26108 26109 var PLUS = '+'.charCodeAt(0) 26110 var SLASH = '/'.charCodeAt(0) 26111 var NUMBER = '0'.charCodeAt(0) 26112 var LOWER = 'a'.charCodeAt(0) 26113 var UPPER = 'A'.charCodeAt(0) 26114 var PLUS_URL_SAFE = '-'.charCodeAt(0) 26115 var SLASH_URL_SAFE = '_'.charCodeAt(0) 26116 26117 function decode (elt) { 26118 var code = elt.charCodeAt(0) 26119 if (code === PLUS || 26120 code === PLUS_URL_SAFE) 26121 return 62 // '+' 26122 if (code === SLASH || 26123 code === SLASH_URL_SAFE) 26124 return 63 // '/' 26125 if (code < NUMBER) 26126 return -1 //no match 26127 if (code < NUMBER + 10) 26128 return code - NUMBER + 26 + 26 26129 if (code < UPPER + 26) 26130 return code - UPPER 26131 if (code < LOWER + 26) 26132 return code - LOWER + 26 26133 } 26134 26135 function b64ToByteArray (b64) { 26136 var i, j, l, tmp, placeHolders, arr 26137 26138 if (b64.length % 4 > 0) { 26139 throw new Error('Invalid string. Length must be a multiple of 4') 26140 } 26141 26142 // the number of equal signs (place holders) 26143 // if there are two placeholders, than the two characters before it 26144 // represent one byte 26145 // if there is only one, then the three characters before it represent 2 bytes 26146 // this is just a cheap hack to not do indexOf twice 26147 var len = b64.length 26148 placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0 26149 26150 // base64 is 4/3 + up to two characters of the original data 26151 arr = new Arr(b64.length * 3 / 4 - placeHolders) 26152 26153 // if there are placeholders, only get up to the last complete 4 chars 26154 l = placeHolders > 0 ? b64.length - 4 : b64.length 26155 26156 var L = 0 26157 26158 function push (v) { 26159 arr[L++] = v 26160 } 26161 26162 for (i = 0, j = 0; i < l; i += 4, j += 3) { 26163 tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3)) 26164 push((tmp & 0xFF0000) >> 16) 26165 push((tmp & 0xFF00) >> 8) 26166 push(tmp & 0xFF) 26167 } 26168 26169 if (placeHolders === 2) { 26170 tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4) 26171 push(tmp & 0xFF) 26172 } else if (placeHolders === 1) { 26173 tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2) 26174 push((tmp >> 8) & 0xFF) 26175 push(tmp & 0xFF) 26176 } 26177 26178 return arr 26179 } 26180 26181 function uint8ToBase64 (uint8) { 26182 var i, 26183 extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes 26184 output = "", 26185 temp, length 26186 26187 function encode (num) { 26188 return lookup.charAt(num) 26189 } 26190 26191 function tripletToBase64 (num) { 26192 return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F) 26193 } 26194 26195 // go through the array every three bytes, we'll deal with trailing stuff later 26196 for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) { 26197 temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]) 26198 output += tripletToBase64(temp) 26199 } 26200 26201 // pad the end with zeros, but make sure to not forget the extra bytes 26202 switch (extraBytes) { 26203 case 1: 26204 temp = uint8[uint8.length - 1] 26205 output += encode(temp >> 2) 26206 output += encode((temp << 4) & 0x3F) 26207 output += '==' 26208 break 26209 case 2: 26210 temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1]) 26211 output += encode(temp >> 10) 26212 output += encode((temp >> 4) & 0x3F) 26213 output += encode((temp << 2) & 0x3F) 26214 output += '=' 26215 break 26216 } 26217 26218 return output 26219 } 26220 26221 exports.toByteArray = b64ToByteArray 26222 exports.fromByteArray = uint8ToBase64 26223}(typeof exports === 'undefined' ? (this.base64js = {}
26223) : exports)) 26224 26225},{}],3:[function(_dereq_,module,exports){ 26226 26227},{}],4:[function(_dereq_,module,exports){ 26228(function (global){ 26229/*! 26230 * The buffer module from node.js, for the browser. 26231 * 26232 * @author Feross Aboukhadijeh <[email protected]> <http://feross.org> 26233 * @license MIT 26234 */ 26235/* eslint-disable no-proto */ 26236 26237'use strict' 26238 26239var base64 = _dereq_('base64-js') 26240var ieee754 = _dereq_('ieee754') 26241var isArray = _dereq_('isarray') 26242 26243exports.Buffer = Buffer 26244exports.SlowBuffer = SlowBuffer 26245exports.INSPECT_MAX_BYTES = 50 26246Buffer.poolSize = 8192 // not used by this implementation 26247 26248var rootParent = {} 26249 26250/** 26251 * If `Buffer.TYPED_ARRAY_SUPPORT`: 26252 * === true Use Uint8Array implementation (fastest) 26253 * === false Use Object implementation (most compatible, even IE6) 26254 * 26255 * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, 26256 * Opera 11.6+, iOS 4.2+. 26257 * 26258 * Due to various browser bugs, sometimes the Object implementation will be used even 26259 * when the browser supports typed arrays. 26260 * 26261 * Note: 26262 * 26263 * - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances, 26264 * See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438. 26265 * 26266 * - Safari 5-7 lacks support for changing the `Object.prototype.constructor` property 26267 * on objects. 26268 * 26269 * - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function. 26270 * 26271 * - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of 26272 * incorrect length in some situations. 26273 26274 * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they 26275 * get the Object implementation, which is slower but behaves correctly. 26276 */ 26277Buffer.TYPED_ARRAY_SUPPORT = global.TYPED_ARRAY_SUPPORT !== undefined 26278 ? global.TYPED_ARRAY_SUPPORT 26279 : typedArraySupport() 26280 26281function typedArraySupport () { 26282 function Bar () {} 26283 try { 26284 var arr = new Uint8Array(1) 26285 arr.foo = function () { return 42 } 26286 arr.constructor = Bar 26287 return arr.foo() === 42 && // typed array instances can be augmented 26288 arr.constructor === Bar && // constructor can be set 26289 typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray` 26290 arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray` 26291 } catch (e) { 26292 return false 26293 } 26294} 26295 26296function kMaxLength () { 26297 return Buffer.TYPED_ARRAY_SUPPORT 26298 ? 0x7fffffff 26299 : 0x3fffffff 26300} 26301 26302/** 26303 * Class: Buffer 26304 * ============= 26305 * 26306 * The Buffer constructor returns instances of `Uint8Array` that are augmented 26307 * with function properties for all the node `Buffer` API functions. We use 26308 * `Uint8Array` so that square bracket notation works as expected -- it returns 26309 * a single octet. 26310 * 26311 * By augmenting the instances, we can avoid modifying the `Uint8Array` 26312 * prototype. 26313 */ 26314function Buffer (arg) { 26315 if (!(this instanceof Buffer)) { 26316 // Avoid going through an ArgumentsAdaptorTrampoline in the common case. 26317 if (arguments.length > 1) return new Buffer(arg, arguments[1]) 26318 return new Buffer(arg) 26319 } 26320 26321 if (!Buffer.TYPED_ARRAY_SUPPORT) { 26322 this.length = 0 26323 this.parent = undefined 26324 } 26325 26326 // Common case. 26327 if (typeof arg === 'number') { 26328 return fromNumber(this, arg) 26329 } 26330 26331 // Slightly less common case. 26332 if (typeof arg === 'string') { 26333 return fromString(this, arg, arguments.length > 1 ? arguments[1] : 'utf8') 26334 } 26335 26336 // Unusual. 26337 return fromObject(this, arg) 26338} 26339 26340function fromNumber (that, length) { 26341 that = allocate(that, length < 0 ? 0 : checked(length) | 0) 26342 if (!Buffer.TYPED_ARRAY_SUPPORT) { 26343 for (var i = 0; i < length; i++) { 26344 that[i] = 0 26345 } 26346 } 26347 return that 26348} 26349 26350function fromString (that, string, encoding) { 26351 if (typeof encoding !== 'string' || encoding === '') encoding = 'utf8' 26352 26353 // Assumption: byteLength() return value is always < kMaxLength. 26354 var length = byteLength(string, encoding) | 0 26355 that = allocate(that, length) 26356 26357 that.write(string, encoding) 26358 return that 26359} 26360 26361function fromObject (that, object) { 26362 if (Buffer.isBuffer(object)) return fromBuffer(that, object) 26363 26364 if (isArray(object)) return fromArray(that, object) 26365 26366 if (object == null) { 26367 throw new TypeError('must start with number, buffer, array or string') 26368 } 26369 26370 if (typeof ArrayBuffer !== 'undefined') { 26371 if (object.buffer instanceof ArrayBuffer) { 26372 return fromTypedArray(that, object) 26373 } 26374 if (object instanceof ArrayBuffer) { 26375 return fromArrayBuffer(that, object) 26376 } 26377 } 26378 26379 if (object.length) return fromArrayLike(that, object) 26380 26381 return fromJsonObject(that, object) 26382} 26383 26384function fromBuffer (that, buffer) { 26385 var length = checked(buffer.length) | 0 26386 that = allocate(that, length) 26387 buffer.copy(that, 0, 0, length) 26388 return that 26389} 26390 26391function fromArray (that, array) { 26392 var length = checked(array.length) | 0 26393 that = allocate(that, length) 26394 for (var i = 0; i < length; i += 1) { 26395 that[i] = array[i] & 255 26396 } 26397 return that 26398} 26399 26400// Duplicate of fromArray() to keep fromArray() monomorphic. 26401function fromTypedArray (that, array) { 26402 var length = checked(array.length) | 0 26403 that = allocate(that, length) 26404 // Truncating the elements is probably not what people expect from typed 26405 // arrays with BYTES_PER_ELEMENT > 1 but it's compatible with the behavior 26406 // of the old Buffer constructor. 26407 for (var i = 0; i < length; i += 1) { 26408 that[i] = array[i] & 255 26409 } 26410 return that 26411} 26412 26413function fromArrayBuffer (that, array) { 26414 if (Buffer.TYPED_ARRAY_SUPPORT) { 26415 // Return an augmented `Uint8Array` instance, for best performance 26416 array.byteLength
26417 that = Buffer._augment(new Uint8Array(array)) 26418 } else { 26419 // Fallback: Return an object instance of the Buffer class 26420 that = fromTypedArray(that, new Uint8Array(array)) 26421 } 26422 return that 26423} 26424 26425function fromArrayLike (that, array) { 26426 var length = checked(array.length) | 0 26427 that = allocate(that, length) 26428 for (var i = 0; i < length; i += 1) { 26429 that[i] = array[i] & 255 26430 } 26431 return that 26432} 26433 26434// Deserialize { type: 'Buffer', data: [1,2,3,...] } into a Buffer object. 26435// Returns a zero-length buffer for inputs that don't conform to the spec. 26436function fromJsonObject (that, object) { 26437 var array 26438 var length = 0 26439 26440 if (object.type === 'Buffer' && isArray(object.data)) { 26441 array = object.data 26442 length = checked(array.length) | 0 26443 } 26444 that = allocate(that, length) 26445 26446 for (var i = 0; i < length; i += 1) { 26447 that[i] = array[i] & 255 26448 } 26449 return that 26450} 26451 26452if (Buffer.TYPED_ARRAY_SUPPORT) { 26453 Buffer.prototype.__proto__ = Uint8Array.prototype 26454 Buffer.__proto__ = Uint8Array 26455} else { 26456 // pre-set for values that may exist in the future 26457 Buffer.prototype.length = undefined 26458 Buffer.prototype.parent = undefined 26459} 26460 26461function allocate (that, length) { 26462 if (Buffer.TYPED_ARRAY_SUPPORT) { 26463 // Return an augmented `Uint8Array` instance, for best performance 26464 that = Buffer._augment(new Uint8Array(length)) 26465 that.__proto__ = Buffer.prototype 26466 } else { 26467 // Fallback: Return an object instance of the Buffer class 26468 that.length = length 26469 that._isBuffer = true 26470 } 26471 26472 var fromPool = length !== 0 && length <= Buffer.poolSize >>> 1 26473 if (fromPool) that.parent = rootParent 26474 26475 return that 26476} 26477 26478function checked (length) { 26479 // Note: cannot use `length < kMaxLength` here because that fails when 26480 // length is NaN (which is otherwise coerced to zero.) 26481 if (length >= kMaxLength()) { 26482 throw new RangeError('Attempt to allocate Buffer larger than maximum ' + 26483 'size: 0x' + kMaxLength().toString(16) + ' bytes') 26484 } 26485 return length | 0 26486} 26487 26488function SlowBuffer (subject, encoding) { 26489 if (!(this instanceof SlowBuffer)) return new SlowBuffer(subject, encoding) 26490 26491 var buf = new Buffer(subject, encoding) 26492 delete buf.parent 26493 return buf 26494} 26495 26496Buffer.isBuffer = function isBuffer (b) { 26497 return !!(b != null && b._isBuffer) 26498} 26499 26500Buffer.compare = function compare (a, b) { 26501 if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { 26502 throw new TypeError('Arguments must be Buffers') 26503 } 26504 26505 if (a === b) return 0 26506 26507 var x = a.length 26508 var y = b.length 26509 26510 var i = 0 26511 var len = Math.min(x, y) 26512 while (i < len) { 26513 if (a[i] !== b[i]) break 26514 26515 ++i 26516 } 26517 26518 if (i !== len) { 26519 x = a[i] 26520 y = b[i] 26521 } 26522 26523 if (x < y) return -1 26524 if (y < x) return 1 26525 return 0 26526} 26527 26528Buffer.isEncoding = function isEncoding (encoding) { 26529 switch (String(encoding).toLowerCase()) { 26530 case 'hex': 26531 case 'utf8': 26532 case 'utf-8': 26533 case 'ascii': 26534 case 'binary': 26535 case 'base64': 26536 case 'raw': 26537 case 'ucs2': 26538 case 'ucs-2': 26539 case 'utf16le': 26540 case 'utf-16le': 26541 return true 26542 default: 26543 return false 26544 } 26545} 26546 26547Buffer.concat = function concat (list, length) { 26548 if (!isArray(list)) throw new TypeError('list argument must be an Array of Buffers.') 26549 26550 if (list.length === 0) { 26551 return new Buffer(0) 26552 } 26553 26554 var i 26555 if (length === undefined) { 26556 length = 0 26557 for (i = 0; i < list.length; i++) { 26558 length += list[i].length 26559 } 26560 } 26561 26562 var buf = new Buffer(length) 26563 var pos = 0 26564 for (i = 0; i < list.length; i++) { 26565 var item = list[i] 26566 item.copy(buf, pos) 26567 pos += item.length 26568 } 26569 return buf 26570} 26571 26572function byteLength (string, encoding) { 26573 if (typeof string !== 'string') string = '' + string 26574 26575 var len = string.length 26576 if (len === 0) return 0 26577 26578 // Use a for loop to avoid recursion 26579 var loweredCase = false 26580 for (;;) { 26581 switch (encoding) { 26582 case 'ascii': 26583 case 'binary': 26584 // Deprecated 26585 case 'raw': 26586 case 'raws': 26587 return len 26588 case 'utf8': 26589 case 'utf-8': 26590 return utf8ToBytes(string).length 26591 case 'ucs2': 26592 case 'ucs-2': 26593 case 'utf16le': 26594 case 'utf-16le': 26595 return len * 2 26596 case 'hex': 26597 return len >>> 1 26598 case 'base64': 26599 return base64ToBytes(string).length 26600 default: 26601 if (loweredCase) return utf8ToBytes(string).length // assume utf8 26602 encoding = ('' + encoding).toLowerCase() 26603 loweredCase = true 26604 } 26605 } 26606} 26607Buffer.byteLength = byteLength 26608 26609function slowToString (encoding, start, end) { 26610 var loweredCase = false 26611 26612 start = start | 0 26613 end = end === undefined || end === Infinity ? this.length : end | 0 26614 26615 if (!encoding) encoding = 'utf8' 26616 if (start < 0) start = 0 26617 if (end > this.length) end = this.length 26618 if (end <= start) return '' 26619 26620 while (true) { 26621 switch (encoding) { 26622 case 'hex': 26623 return hexSlice(this, start, end) 26624 26625 case 'utf8': 26626 case 'utf-8': 26627 return utf8Slice(this, start, end) 26628 26629 case 'ascii': 26630 return asciiSlice(this, start, end) 26631 26632 case 'binary': 26633 return binarySlice(this, start, end) 26634 26635 case 'base64': 26636 return base64Slice(this, start, end) 26637 26638 case 'ucs2': 26639 case 'ucs-2': 26640 case 'utf16le': 26641 case 'utf-16le': 26642 return utf16leSlice(this, start, end) 26643 26644 default: 26645 if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) 26646 encoding = (encoding + '').toLowerCase() 26647 loweredCase = true 26648 } 26649 } 26650} 26651 26652Buffer.prototype.toString = function toString () { 26653 var length = this.length | 0 26654 if (length === 0) return '' 26655 if (arguments.length === 0) return utf8Slice(this, 0, length) 26656 return slowToString.apply(this, arguments) 26657} 26658 26659Buffer.prototype.equals = function equals (b) { 26660 if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') 26661 if (this === b) return true 26662 return Buffer.compare(this, b) === 0 26663} 26664 26665Buffer.prototype.inspect = function inspect () { 26666 var str = ''
26667 var max = exports.INSPECT_MAX_BYTES 26668 if (this.length > 0) { 26669 str = this.toString('hex', 0, max).match(/.{2}/g).join(' ') 26670 if (this.length > max) str += ' ... ' 26671 } 26672 return '<Buffer ' + str + '>' 26673} 26674 26675Buffer.prototype.compare = function compare (b) { 26676 if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') 26677 if (this === b) return 0 26678 return Buffer.compare(this, b) 26679} 26680 26681Buffer.prototype.indexOf = function indexOf (val, byteOffset) { 26682 if (byteOffset > 0x7fffffff) byteOffset = 0x7fffffff 26683 else if (byteOffset < -0x80000000) byteOffset = -0x80000000 26684 byteOffset >>= 0 26685 26686 if (this.length === 0) return -1 26687 if (byteOffset >= this.length) return -1 26688 26689 // Negative offsets start from the end of the buffer 26690 if (byteOffset < 0) byteOffset = Math.max(this.length + byteOffset, 0) 26691 26692 if (typeof val === 'string') { 26693 if (val.length === 0) return -1 // special case: looking for empty string always fails 26694 return String.prototype.indexOf.call(this, val, byteOffset) 26695 } 26696 if (Buffer.isBuffer(val)) { 26697 return arrayIndexOf(this, val, byteOffset) 26698 } 26699 if (typeof val === 'number') { 26700 if (Buffer.TYPED_ARRAY_SUPPORT && Uint8Array.prototype.indexOf === 'function') { 26701 return Uint8Array.prototype.indexOf.call(this, val, byteOffset) 26702 } 26703 return arrayIndexOf(this, [ val ], byteOffset) 26704 } 26705 26706 function arrayIndexOf (arr, val, byteOffset) { 26707 var foundIndex = -1 26708 for (var i = 0; byteOffset + i < arr.length; i++) { 26709 if (arr[byteOffset + i] === val[foundIndex === -1 ? 0 : i - foundIndex]) { 26710 if (foundIndex === -1) foundIndex = i 26711 if (i - foundIndex + 1 === val.length) return byteOffset + foundIndex 26712 } else { 26713 foundIndex = -1 26714 } 26715 } 26716 return -1 26717 } 26718 26719 throw new TypeError('val must be string, number or Buffer') 26720} 26721 26722// `get` is deprecated 26723Buffer.prototype.get = function get (offset) { 26724 console.log('.get() is deprecated. Access using array indexes instead.') 26725 return this.readUInt8(offset) 26726} 26727 26728// `set` is deprecated 26729Buffer.prototype.set = function set (v, offset) { 26730 console.log('.set() is deprecated. Access using array indexes instead.') 26731 return this.writeUInt8(v, offset) 26732} 26733 26734function hexWrite (buf, string, offset, length) { 26735 offset = Number(offset) || 0 26736 var remaining = buf.length - offset 26737 if (!length) { 26738 length = remaining 26739 } else { 26740 length = Number(length) 26741 if (length > remaining) { 26742 length = remaining 26743 } 26744 } 26745 26746 // must be an even number of digits 26747 var strLen = string.length 26748 if (strLen % 2 !== 0) throw new Error('Invalid hex string') 26749 26750 if (length > strLen / 2) { 26751 length = strLen / 2 26752 } 26753 for (var i = 0; i < length; i++) { 26754 var parsed = parseInt(string.substr(i * 2, 2), 16) 26755 if (isNaN(parsed)) throw new Error('Invalid hex string') 26756 buf[offset + i] = parsed 26757 } 26758 return i 26759} 26760 26761function utf8Write (buf, string, offset, length) { 26762 return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length) 26763} 26764 26765function asciiWrite (buf, string, offset, length) { 26766 return blitBuffer(asciiToBytes(string), buf, offset, length) 26767} 26768 26769function binaryWrite (buf, string, offset, length) { 26770 return asciiWrite(buf, string, offset, length) 26771} 26772 26773function base64Write (buf, string, offset, length) { 26774 return blitBuffer(base64ToBytes(string), buf, offset, length) 26775} 26776 26777function ucs2Write (buf, string, offset, length) { 26778 return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length) 26779} 26780 26781Buffer.prototype.write = function write (string, offset, length, encoding) { 26782 // Buffer#write(string) 26783 if (offset === undefined) { 26784 encoding = 'utf8' 26785 length = this.length 26786 offset = 0 26787 // Buffer#write(string, encoding) 26788 } else if (length === undefined && typeof offset === 'string') { 26789 encoding = offset 26790 length = this.length 26791 offset = 0 26792 // Buffer#write(string, offset[, length][, encoding]) 26793 } else if (isFinite(offset)) { 26794 offset = offset | 0 26795 if (isFinite(length)) { 26796 length = length | 0 26797 if (encoding === undefined) encoding = 'utf8' 26798 } else { 26799 encoding = length 26800 length = undefined 26801 } 26802 // legacy write(string, encoding, offset, length) - remove in v0.13 26803 } else { 26804 var swap = encoding 26805 encoding = offset 26806 offset = length | 0 26807 length = swap 26808 } 26809 26810 var remaining = this.length - offset 26811 if (length === undefined || length > remaining) length = remaining 26812 26813 if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) { 26814 throw new RangeError('attempt to write outside buffer bounds') 26815 } 26816 26817 if (!encoding) encoding = 'utf8' 26818 26819 var loweredCase = false 26820 for (;;) { 26821 switch (encoding) { 26822 case 'hex': 26823 return hexWrite(this, string, offset, length) 26824 26825 case 'utf8': 26826 case 'utf-8': 26827 return utf8Write(this, string, offset, length) 26828 26829 case 'ascii': 26830 return asciiWrite(this, string, offset, length) 26831 26832 case 'binary': 26833 return binaryWrite(this, string, offset, length) 26834 26835 case 'base64': 26836 // Warning: maxLength not taken into account in base64Write 26837 return base64Write(this, string, offset, length) 26838 26839 case 'ucs2': 26840 case 'ucs-2': 26841 case 'utf16le': 26842 case 'utf-16le': 26843 return ucs2Write(this, string, offset, length) 26844 26845 default: 26846 if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) 26847 encoding = ('' + encoding).toLowerCase() 26848 loweredCase = true 26849 } 26850 } 26851} 26852 26853Buffer.prototype.toJSON = function toJSON () { 26854 return { 26855 type: 'Buffer', 26856 data: Array.prototype.slice.call(this._arr || this, 0) 26857 } 26858} 26859 26860function base64Slice (buf, start, end) { 26861 if (start === 0 && end === buf.length) { 26862 return base64.fromByteArray(buf) 26863 } else { 26864 return base64.fromByteArray(buf.slice(start, end)) 26865 } 26866} 26867 26868function utf8Slice (buf, start, end) { 26869 end = Math.min(buf.length, end) 26870 var res = [] 26871 26872 var i = start 26873 while (i < end) { 26874 var firstByte = buf[i] 26875 var codePoint = null 26876 var bytesPerSequence = (firstByte > 0xEF) ? 4 26877 : (firstByte > 0xDF) ? 3 26878 : (firstByte > 0xBF) ? 2 26879 : 1 26880 26881 if (i + bytesPerSequence <= end) { 26882 var secondByte, thirdByte, fourthByte, tempCodePoint 26883 26884 switch (bytesPerSequence) { 26885 case 1: 26886 if (firstByte < 0x80) { 26887 codePoint = firstByte 26888 } 26889 break 26890 case 2: 26891 secondByte = buf[i + 1] 26892 if ((secondByte & 0xC0) === 0x80) { 26893 tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F) 26894 if (tempCodePoint > 0x7F) { 26895 codePoint = tempCodePoint 26896 } 26897 } 26898 break 26899 case 3: 26900 secondByte = buf[i + 1] 26901 thirdByte = buf[i + 2] 26902 if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) { 26903 tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F) 26904 if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) { 26905 codePoint = tempCodePoint 26906 } 26907 } 26908 break 26909 case 4: 26910 secondByte = buf[i + 1] 26911 thirdByte = buf[i + 2] 26912 fourthByte = buf[i + 3] 26913 if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) { 26914 tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F) 26915 if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) { 26916 codePoint = tempCodePoint 26917 } 26918 } 26919 } 26920 } 26921 26922 if (codePoint === null) { 26923 // we did not generate a valid codePoint so insert a 26924 // replacement char (U+FFFD) and advance only 1 byte 26925 codePoint = 0xFFFD 26926 bytesPerSequence = 1 26927 } else if (codePoint > 0xFFFF) { 26928 // encode to utf16 (surrogate pair dance) 26929 codePoint -= 0x10000 26930 res.push(codePoint >>>
vendor: 2,464 bytes, lines 26930-27045
26930 10 & 0x3FF | 0xD800) 26931 codePoint = 0xDC00 | codePoint & 0x3FF 26932 } 26933 26934 res.push(codePoint) 26935 i += bytesPerSequence 26936 } 26937 26938 return decodeCodePointsArray(res) 26939} 26940 26941// Based on http://stackoverflow.com/a/22747272/680742, the browser with 26942// the lowest limit is Chrome, with 0x10000 args. 26943// We go 1 magnitude less, for safety 26944var MAX_ARGUMENTS_LENGTH = 0x1000 26945 26946function decodeCodePointsArray (codePoints) { 26947 var len = codePoints.length 26948 if (len <= MAX_ARGUMENTS_LENGTH) { 26949 return String.fromCharCode.apply(String, codePoints) // avoid extra slice() 26950 } 26951 26952 // Decode in chunks to avoid "call stack size exceeded". 26953 var res = '' 26954 var i = 0 26955 while (i < len) { 26956 res += String.fromCharCode.apply( 26957 String, 26958 codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH) 26959 ) 26960 } 26961 return res 26962} 26963 26964function asciiSlice (buf, start, end) { 26965 var ret = '' 26966 end = Math.min(buf.length, end) 26967 26968 for (var i = start; i < end; i++) { 26969 ret += String.fromCharCode(buf[i] & 0x7F) 26970 } 26971 return ret 26972} 26973 26974function binarySlice (buf, start, end) { 26975 var ret = '' 26976 end = Math.min(buf.length, end) 26977 26978 for (var i = start; i < end; i++) { 26979 ret += String.fromCharCode(buf[i]) 26980 } 26981 return ret 26982} 26983 26984function hexSlice (buf, start, end) { 26985 var len = buf.length 26986 26987 if (!start || start < 0) start = 0 26988 if (!end || end < 0 || end > len) end = len 26989 26990 var out = '' 26991 for (var i = start; i < end; i++) { 26992 out += toHex(buf[i]) 26993 } 26994 return out 26995} 26996 26997function utf16leSlice (buf, start, end) { 26998 var bytes = buf.slice(start, end) 26999 var res = '' 27000 for (var i = 0; i < bytes.length; i += 2) { 27001 res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256) 27002 } 27003 return res 27004} 27005 27006Buffer.prototype.slice = function slice (start, end) { 27007 var len = this.length 27008 start = ~~start 27009 end = end === undefined ? len : ~~end 27010 27011 if (start < 0) { 27012 start += len 27013 if (start < 0) start = 0 27014 } else if (start > len) { 27015 start = len 27016 } 27017 27018 if (end < 0) { 27019 end += len 27020 if (end < 0) end = 0 27021 } else if (end > len) { 27022 end = len 27023 } 27024 27025 if (end < start) end = start 27026 27027 var newBuf 27028 if (Buffer.TYPED_ARRAY_SUPPORT) { 27029 newBuf = Buffer._augment(this.subarray(start, end)) 27030 } else { 27031 var sliceLen = end - start 27032 newBuf = new Buffer(sliceLen, undefined) 27033 for (var i = 0; i < sliceLen; i++) { 27034 newBuf[i] = this[i + start] 27035 } 27036 } 27037 27038 if (newBuf.length) newBuf.parent = this.parent || this 27039 27040 return newBuf 27041} 27042 27043/* 27044 * Need to make sure that buffer isn't trying to write out of bounds. 27045 */
vendor: 9,737 bytes, lines 27046-27374
27046function checkOffset (offset, ext, length) { 27047 if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint') 27048 if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length') 27049} 27050 27051Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) { 27052 offset = offset | 0 27053 byteLength = byteLength | 0 27054 if (!noAssert) checkOffset(offset, byteLength, this.length) 27055 27056 var val = this[offset] 27057 var mul = 1 27058 var i = 0 27059 while (++i < byteLength && (mul *= 0x100)) { 27060 val += this[offset + i] * mul 27061 } 27062 27063 return val 27064} 27065 27066Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) { 27067 offset = offset | 0 27068 byteLength = byteLength | 0 27069 if (!noAssert) { 27070 checkOffset(offset, byteLength, this.length) 27071 } 27072 27073 var val = this[offset + --byteLength] 27074 var mul = 1 27075 while (byteLength > 0 && (mul *= 0x100)) { 27076 val += this[offset + --byteLength] * mul 27077 } 27078 27079 return val 27080} 27081 27082Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) { 27083 if (!noAssert) checkOffset(offset, 1, this.length) 27084 return this[offset] 27085} 27086 27087Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) { 27088 if (!noAssert) checkOffset(offset, 2, this.length) 27089 return this[offset] | (this[offset + 1] << 8) 27090} 27091 27092Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) { 27093 if (!noAssert) checkOffset(offset, 2, this.length) 27094 return (this[offset] << 8) | this[offset + 1] 27095} 27096 27097Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) { 27098 if (!noAssert) checkOffset(offset, 4, this.length) 27099 27100 return ((this[offset]) | 27101 (this[offset + 1] << 8) | 27102 (this[offset + 2] << 16)) + 27103 (this[offset + 3] * 0x1000000) 27104} 27105 27106Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) { 27107 if (!noAssert) checkOffset(offset, 4, this.length) 27108 27109 return (this[offset] * 0x1000000) + 27110 ((this[offset + 1] << 16) | 27111 (this[offset + 2] << 8) | 27112 this[offset + 3]) 27113} 27114 27115Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) { 27116 offset = offset | 0 27117 byteLength = byteLength | 0 27118 if (!noAssert) checkOffset(offset, byteLength, this.length) 27119 27120 var val = this[offset] 27121 var mul = 1 27122 var i = 0 27123 while (++i < byteLength && (mul *= 0x100)) { 27124 val += this[offset + i] * mul 27125 } 27126 mul *= 0x80 27127 27128 if (val >= mul) val -= Math.pow(2, 8 * byteLength) 27129 27130 return val 27131} 27132 27133Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) { 27134 offset = offset | 0 27135 byteLength = byteLength | 0 27136 if (!noAssert) checkOffset(offset, byteLength, this.length) 27137 27138 var i = byteLength 27139 var mul = 1 27140 var val = this[offset + --i] 27141 while (i > 0 && (mul *= 0x100)) { 27142 val += this[offset + --i] * mul 27143 } 27144 mul *= 0x80 27145 27146 if (val >= mul) val -= Math.pow(2, 8 * byteLength) 27147 27148 return val 27149} 27150 27151Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) { 27152 if (!noAssert) checkOffset(offset, 1, this.length) 27153 if (!(this[offset] & 0x80)) return (this[offset]) 27154 return ((0xff - this[offset] + 1) * -1) 27155} 27156 27157Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) { 27158 if (!noAssert) checkOffset(offset, 2, this.length) 27159 var val = this[offset] | (this[offset + 1] << 8) 27160 return (val & 0x8000) ? val | 0xFFFF0000 : val 27161} 27162 27163Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) { 27164 if (!noAssert) checkOffset(offset, 2, this.length) 27165 var val = this[offset + 1] | (this[offset] << 8) 27166 return (val & 0x8000) ? val | 0xFFFF0000 : val 27167} 27168 27169Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) { 27170 if (!noAssert) checkOffset(offset, 4, this.length) 27171 27172 return (this[offset]) | 27173 (this[offset + 1] << 8) | 27174 (this[offset + 2] << 16) | 27175 (this[offset + 3] << 24) 27176} 27177 27178Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) { 27179 if (!noAssert) checkOffset(offset, 4, this.length) 27180 27181 return (this[offset] << 24) | 27182 (this[offset + 1] << 16) | 27183 (this[offset + 2] << 8) | 27184 (this[offset + 3]) 27185} 27186 27187Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) { 27188 if (!noAssert) checkOffset(offset, 4, this.length) 27189 return ieee754.read(this, offset, true, 23, 4) 27190} 27191 27192Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) { 27193 if (!noAssert) checkOffset(offset, 4, this.length) 27194 return ieee754.read(this, offset, false, 23, 4) 27195} 27196 27197Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) { 27198 if (!noAssert) checkOffset(offset, 8, this.length) 27199 return ieee754.read(this, offset, true, 52, 8) 27200} 27201 27202Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) { 27203 if (!noAssert) checkOffset(offset, 8, this.length) 27204 return ieee754.read(this, offset, false, 52, 8) 27205} 27206 27207function checkInt (buf, value, offset, ext, max, min) { 27208 if (!Buffer.isBuffer(buf)) throw new TypeError('buffer must be a Buffer instance') 27209 if (value > max || value < min) throw new RangeError('value is out of bounds') 27210 if (offset + ext > buf.length) throw new RangeError('index out of range') 27211} 27212 27213Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) { 27214 value = +value 27215 offset = offset | 0 27216 byteLength = byteLength | 0 27217 if (!noAssert) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0) 27218 27219 var mul = 1 27220 var i = 0 27221 this[offset] = value & 0xFF 27222 while (++i < byteLength && (mul *= 0x100)) { 27223 this[offset + i] = (value / mul) & 0xFF 27224 } 27225 27226 return offset + byteLength 27227} 27228 27229Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) { 27230 value = +value 27231 offset = offset | 0 27232 byteLength = byteLength | 0 27233 if (!noAssert) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0) 27234 27235 var i = byteLength - 1 27236 var mul = 1 27237 this[offset + i] = value & 0xFF 27238 while (--i >= 0 && (mul *= 0x100)) { 27239 this[offset + i] = (value / mul) & 0xFF 27240 } 27241 27242 return offset + byteLength 27243} 27244 27245Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) { 27246 value = +value 27247 offset = offset | 0 27248 if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0) 27249 if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) 27250 this[offset] = (value & 0xff) 27251 return offset + 1 27252} 27253 27254function objectWriteUInt16 (buf, value, offset, littleEndian) { 27255 if (value < 0) value = 0xffff + value + 1 27256 for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; i++) { 27257 buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>> 27258 (littleEndian ? i : 1 - i) * 8 27259 } 27260} 27261 27262Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) { 27263 value = +value 27264 offset = offset | 0 27265 if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) 27266 if (Buffer.TYPED_ARRAY_SUPPORT) { 27267 this[offset] = (value & 0xff) 27268 this[offset + 1] = (value >>> 8) 27269 } else { 27270 objectWriteUInt16(this, value, offset, true) 27271 } 27272 return offset + 2 27273} 27274 27275Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) { 27276 value = +value 27277 offset = offset | 0 27278 if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) 27279 if (Buffer.TYPED_ARRAY_SUPPORT) { 27280 this[offset] = (value >>> 8) 27281 this[offset + 1] = (value & 0xff) 27282 } else { 27283 objectWriteUInt16(this, value, offset, false) 27284 } 27285 return offset + 2 27286} 27287 27288function objectWriteUInt32 (buf, value, offset, littleEndian) { 27289 if (value < 0) value = 0xffffffff + value + 1 27290 for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; i++) { 27291 buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff 27292 } 27293} 27294 27295Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) { 27296 value = +value 27297 offset = offset | 0 27298 if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) 27299 if (Buffer.TYPED_ARRAY_SUPPORT) { 27300 this[offset + 3] = (value >>> 24) 27301 this[offset + 2] = (value >>> 16) 27302 this[offset + 1] = (value >>> 8) 27303 this[offset] = (value & 0xff) 27304 } else { 27305 objectWriteUInt32(this, value, offset, true) 27306 } 27307 return offset + 4 27308} 27309 27310Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) { 27311 value = +value 27312 offset = offset | 0 27313 if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) 27314 if (Buffer.TYPED_ARRAY_SUPPORT) { 27315 this[offset] = (value >>> 24) 27316 this[offset + 1] = (value >>> 16) 27317 this[offset + 2] = (value >>> 8) 27318 this[offset + 3] = (value & 0xff) 27319 } else { 27320 objectWriteUInt32(this, value, offset, false) 27321 } 27322 return offset + 4 27323} 27324 27325Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) { 27326 value = +value 27327 offset = offset | 0 27328 if (!noAssert) { 27329 var limit = Math.pow(2, 8 * byteLength - 1) 27330 27331 checkInt(this, value, offset, byteLength, limit - 1, -limit) 27332 } 27333 27334 var i = 0 27335 var mul = 1 27336 var sub = value < 0 ? 1 : 0 27337 this[offset] = value & 0xFF 27338 while (++i < byteLength && (mul *= 0x100)) { 27339 this[offset + i] = ((value / mul) >> 0) - sub & 0xFF 27340 } 27341 27342 return offset + byteLength 27343} 27344 27345Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) { 27346 value = +value 27347 offset = offset | 0 27348 if (!noAssert) { 27349 var limit = Math.pow(2, 8 * byteLength - 1) 27350 27351 checkInt(this, value, offset, byteLength, limit - 1, -limit) 27352 } 27353 27354 var i = byteLength - 1 27355 var mul = 1 27356 var sub = value < 0 ? 1 : 0 27357 this[offset + i] = value & 0xFF 27358 while (--i >= 0 && (mul *= 0x100)) { 27359 this[offset + i] = ((value / mul) >> 0) - sub & 0xFF 27360 } 27361 27362 return offset + byteLength 27363} 27364 27365Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { 27366 value = +value 27367 offset = offset | 0 27368 if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80) 27369 if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) 27370 if (value < 0) value = 0xff + value + 1 27371 this[offset] = (value & 0xff) 27372 return offset + 1 27373} 27374
vendor: 4,133 bytes, lines 27375-27498
27375Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { 27376 value = +value 27377 offset = offset | 0 27378 if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) 27379 if (Buffer.TYPED_ARRAY_SUPPORT) { 27380 this[offset] = (value & 0xff) 27381 this[offset + 1] = (value >>> 8) 27382 } else { 27383 objectWriteUInt16(this, value, offset, true) 27384 } 27385 return offset + 2 27386} 27387 27388Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { 27389 value = +value 27390 offset = offset | 0 27391 if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) 27392 if (Buffer.TYPED_ARRAY_SUPPORT) { 27393 this[offset] = (value >>> 8) 27394 this[offset + 1] = (value & 0xff) 27395 } else { 27396 objectWriteUInt16(this, value, offset, false) 27397 } 27398 return offset + 2 27399} 27400 27401Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { 27402 value = +value 27403 offset = offset | 0 27404 if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) 27405 if (Buffer.TYPED_ARRAY_SUPPORT) { 27406 this[offset] = (value & 0xff) 27407 this[offset + 1] = (value >>> 8) 27408 this[offset + 2] = (value >>> 16) 27409 this[offset + 3] = (value >>> 24) 27410 } else { 27411 objectWriteUInt32(this, value, offset, true) 27412 } 27413 return offset + 4 27414} 27415 27416Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { 27417 value = +value 27418 offset = offset | 0 27419 if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) 27420 if (value < 0) value = 0xffffffff + value + 1 27421 if (Buffer.TYPED_ARRAY_SUPPORT) { 27422 this[offset] = (value >>> 24) 27423 this[offset + 1] = (value >>> 16) 27424 this[offset + 2] = (value >>> 8) 27425 this[offset + 3] = (value & 0xff) 27426 } else { 27427 objectWriteUInt32(this, value, offset, false) 27428 } 27429 return offset + 4 27430} 27431 27432function checkIEEE754 (buf, value, offset, ext, max, min) { 27433 if (value > max || value < min) throw new RangeError('value is out of bounds') 27434 if (offset + ext > buf.length) throw new RangeError('index out of range') 27435 if (offset < 0) throw new RangeError('index out of range') 27436} 27437 27438function writeFloat (buf, value, offset, littleEndian, noAssert) { 27439 if (!noAssert) { 27440 checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38) 27441 } 27442 ieee754.write(buf, value, offset, littleEndian, 23, 4) 27443 return offset + 4 27444} 27445 27446Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) { 27447 return writeFloat(this, value, offset, true, noAssert) 27448} 27449 27450Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) { 27451 return writeFloat(this, value, offset, false, noAssert) 27452} 27453 27454function writeDouble (buf, value, offset, littleEndian, noAssert) { 27455 if (!noAssert) { 27456 checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308) 27457 } 27458 ieee754.write(buf, value, offset, littleEndian, 52, 8) 27459 return offset + 8 27460} 27461 27462Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) { 27463 return writeDouble(this, value, offset, true, noAssert) 27464} 27465 27466Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) { 27467 return writeDouble(this, value, offset, false, noAssert) 27468} 27469 27470// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) 27471Buffer.prototype.copy = function copy (target, targetStart, start, end) { 27472 if (!start) start = 0 27473 if (!end && end !== 0) end = this.length 27474 if (targetStart >= target.length) targetStart = target.length 27475 if (!targetStart) targetStart = 0 27476 if (end > 0 && end < start) end = start 27477 27478 // Copy 0 bytes; we're done 27479 if (end === start) return 0 27480 if (target.length === 0 || this.length === 0) return 0 27481 27482 // Fatal error conditions 27483 if (targetStart < 0) { 27484 throw new RangeError('targetStart out of bounds') 27485 } 27486 if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds') 27487 if (end < 0) throw new RangeError('sourceEnd out of bounds') 27488 27489 // Are we oob? 27490 if (end > this.length) end = this.length 27491 if (target.length - targetStart < end - start) { 27492 end = target.length - targetStart + start 27493 } 27494 27495 var len = end - start 27496 var i 27497 27498 if (this === target && start < targetStart && targetStart < end) {
27499 // descending copy from end 27500 for (i = len - 1; i >= 0; i--) { 27501 target[i + targetStart] = this[i + start] 27502 } 27503 } else if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) { 27504 // ascending copy from start 27505 for (i = 0; i < len; i++) { 27506 target[i + targetStart] = this[i + start] 27507 } 27508 } else { 27509 target._set(this.subarray(start, start + len), targetStart) 27510 } 27511 27512 return len 27513} 27514 27515// fill(value, start=0, end=buffer.length) 27516Buffer.prototype.fill = function fill (value, start, end) { 27517 if (!value) value = 0 27518 if (!start) start = 0 27519 if (!end) end = this.length 27520 27521 if (end < start) throw new RangeError('end < start') 27522 27523 // Fill 0 bytes; we're done 27524 if (end === start) return 27525 if (this.length === 0) return 27526 27527 if (start < 0 || start >= this.length) throw new RangeError('start out of bounds') 27528 if (end < 0 || end > this.length) throw new RangeError('end out of bounds') 27529 27530 var i 27531 if (typeof value === 'number') { 27532 for (i = start; i < end; i++) { 27533 this[i] = value 27534 } 27535 } else { 27536 var bytes = utf8ToBytes(value.toString()) 27537 var len = bytes.length 27538 for (i = start; i < end; i++) { 27539 this[i] = bytes[i % len] 27540 } 27541 } 27542 27543 return this 27544} 27545 27546/** 27547 * Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance. 27548 * Added in Node 0.12. Only available in browsers that support ArrayBuffer. 27549 */ 27550Buffer.prototype.toArrayBuffer = function toArrayBuffer () { 27551 if (typeof Uint8Array !== 'undefined') { 27552 if (Buffer.TYPED_ARRAY_SUPPORT) { 27553 return (new Buffer(this)).buffer 27554 } else { 27555 var buf = new Uint8Array(this.length) 27556 for (var i = 0, len = buf.length; i < len; i += 1) { 27557 buf[i] = this[i] 27558 } 27559 return buf.buffer 27560 } 27561 } else { 27562 throw new TypeError('Buffer.toArrayBuffer not supported in this browser') 27563 } 27564} 27565 27566// HELPER FUNCTIONS 27567// ================ 27568 27569var BP = Buffer.prototype 27570 27571/** 27572 * Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods 27573 */ 27574Buffer._augment = function _augment (arr) { 27575 arr.constructor = Buffer 27576 arr._isBuffer = true 27577 27578 // save reference to original Uint8Array set method before overwriting 27579 arr._set = arr.set 27580 27581 // deprecated 27582 arr.get = BP.get 27583 arr.set = BP.set 27584 27585 arr.write = BP.write 27586 arr.toString = BP.toString 27587 arr.toLocaleString = BP.toString 27588 arr.toJSON = BP.toJSON 27589 arr.equals = BP.equals 27590 arr.compare = BP.compare 27591 arr.indexOf = BP.indexOf 27592 arr.copy = BP.copy 27593 arr.slice = BP.slice 27594 arr.readUIntLE = BP.readUIntLE 27595 arr.readUIntBE = BP.readUIntBE 27596 arr.readUInt8 = BP.readUInt8 27597 arr.readUInt16LE = BP.readUInt16LE 27598 arr.readUInt16BE = BP.readUInt16BE 27599 arr.readUInt32LE = BP.readUInt32LE 27600 arr.readUInt32BE = BP.readUInt32BE 27601 arr.readIntLE = BP.readIntLE 27602 arr.readIntBE = BP.readIntBE 27603 arr.readInt8 = BP.readInt8 27604 arr.readInt16LE = BP.readInt16LE 27605 arr.readInt16BE = BP.readInt16BE 27606 arr.readInt32LE = BP.readInt32LE 27607 arr.readInt32BE = BP.readInt32BE 27608 arr.readFloatLE = BP.readFloatLE 27609 arr.readFloatBE = BP.readFloatBE 27610 arr.readDoubleLE = BP.readDoubleLE 27611 arr.readDoubleBE = BP.readDoubleBE 27612 arr.writeUInt8 = BP.writeUInt8 27613 arr.writeUIntLE = BP.writeUIntLE 27614 arr.writeUIntBE = BP.writeUIntBE 27615 arr.writeUInt16LE = BP.writeUInt16LE 27616 arr.writeUInt16BE = BP.writeUInt16BE 27617 arr.writeUInt32LE = BP.writeUInt32LE 27618 arr.writeUInt32BE = BP.writeUInt32BE 27619 arr.writeIntLE = BP.writeIntLE 27620 arr.writeIntBE = BP.writeIntBE 27621 arr.writeInt8 = BP.writeInt8 27622 arr.writeInt16LE = BP.writeInt16LE 27623 arr.writeInt16BE = BP.writeInt16BE 27624 arr.writeInt32LE = BP.writeInt32LE 27625 arr.writeInt32BE = BP.writeInt32BE 27626 arr.writeFloatLE = BP.writeFloatLE 27627 arr.writeFloatBE = BP.writeFloatBE 27628 arr.writeDoubleLE = BP.writeDoubleLE 27629 arr.writeDoubleBE = BP.writeDoubleBE 27630 arr.fill = BP.fill 27631 arr.inspect = BP.inspect 27632 arr.toArrayBuffer = BP.toArrayBuffer 27633 27634 return arr 27635} 27636 27637var INVALID_BASE64_RE = /[^+\/0-9A-Za-z-_]/g 27638 27639function base64clean (str) { 27640 // Node strips out invalid characters like \n and \t from the string, base64-js does not 27641 str = stringtrim(str).replace(INVALID_BASE64_RE, '') 27642 // Node converts strings with length < 2 to '' 27643 if (str.length < 2) return '' 27644 // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not 27645 while (str.length % 4 !== 0) { 27646 str = str + '=' 27647 } 27648 return str 27649} 27650 27651function stringtrim (str) { 27652 if (str.trim) return str.trim() 27653 return str.replace(/^\s+|\s+$/g, '') 27654} 27655 27656function toHex (n) { 27657 if (n < 16) return '0' + n.toString(16) 27658 return n.toString(16) 27659} 27660 27661function utf8ToBytes (string, units) { 27662 units = units || Infinity 27663 var codePoint 27664 var length = string.length 27665 var leadSurrogate = null 27666 var bytes = [] 27667 27668 for (var i = 0; i < length; i++) { 27669 codePoint = string.charCodeAt(i) 27670 27671 // is surrogate component 27672 if (codePoint > 0xD7FF && codePoint < 0xE000) { 27673 // last char was a lead 27674 if (!leadSurrogate) { 27675 // no lead yet 27676 if (codePoint > 0xDBFF) { 27677 // unexpected trail 27678 if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) 27679 continue 27680 } else if (i + 1 === length) { 27681 // unpaired lead 27682 if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) 27683 continue 27684 } 27685 27686 // valid lead 27687 leadSurrogate = codePoint 27688 27689 continue 27690 } 27691 27692 // 2 leads in a row 27693 if (codePoint < 0xDC00) { 27694 if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) 27695 leadSurrogate = codePoint 27696 continue 27697 } 27698 27699 // valid surrogate pair 27700 codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000 27701 } else if (leadSurrogate) { 27702 // valid bmp char, but last char was a lead 27703 if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) 27704 } 27705 27706 leadSurrogate = null 27707 27708 // encode utf8 27709 if (codePoint < 0x80) { 27710 if ((units -= 1) < 0) break 27711 bytes.push(codePoint) 27712 } else if (codePoint < 0x800) { 27713 if ((units -= 2) < 0) break 27714 bytes.push( 27715 codePoint >> 0x6 | 0xC0,
27716 codePoint & 0x3F | 0x80 27717 ) 27718 } else if (codePoint < 0x10000) { 27719 if ((units -= 3) < 0) break 27720 bytes.push( 27721 codePoint >> 0xC | 0xE0, 27722 codePoint >> 0x6 & 0x3F | 0x80, 27723 codePoint & 0x3F | 0x80 27724 ) 27725 } else if (codePoint < 0x110000) { 27726 if ((units -= 4) < 0) break 27727 bytes.push( 27728 codePoint >> 0x12 | 0xF0, 27729 codePoint >> 0xC & 0x3F | 0x80, 27730 codePoint >> 0x6 & 0x3F | 0x80, 27731 codePoint & 0x3F | 0x80 27732 ) 27733 } else { 27734 throw new Error('Invalid code point') 27735 } 27736 } 27737 27738 return bytes 27739} 27740 27741function asciiToBytes (str) { 27742 var byteArray = [] 27743 for (var i = 0; i < str.length; i++) { 27744 // Node's code seems to be doing this and not & 0x7F.. 27745 byteArray.push(str.charCodeAt(i) & 0xFF) 27746 } 27747 return byteArray 27748} 27749 27750function utf16leToBytes (str, units) { 27751 var c, hi, lo 27752 var byteArray = [] 27753 for (var i = 0; i < str.length; i++) { 27754 if ((units -= 2) < 0) break 27755 27756 c = str.charCodeAt(i) 27757 hi = c >> 8 27758 lo = c % 256 27759 byteArray.push(lo) 27760 byteArray.push(hi) 27761 } 27762 27763 return byteArray 27764} 27765 27766function base64ToBytes (str) { 27767 return base64.toByteArray(base64clean(str)) 27768} 27769 27770function blitBuffer (src, dst, offset, length) { 27771 for (var i = 0; i < length; i++) { 27772 if ((i + offset >= dst.length) || (i >= src.length)) break 27773 dst[i + offset] = src[i] 27774 } 27775 return i 27776} 27777 27778}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) 27779},{"base64-js":2,"ieee754":8,"isarray":9}],5:[function(_dereq_,module,exports){ 27780(function (process,global){ 27781/*! 27782 * @overview es6-promise - a tiny implementation of Promises/A+. 27783 * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald) 27784 * @license Licensed under MIT license 27785 * See https://raw.githubusercontent.com/stefanpenner/es6-promise/master/LICENSE 27786 * @version 4.1.1 27787 */ 27788 27789(function (global, factory) { 27790 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 27791 typeof define === 'function' && define.amd ? define(factory) : 27792 (global.ES6Promise = factory()); 27793}(this, (function () { 'use strict'; 27794 27795function objectOrFunction(x) { 27796 var type = typeof x; 27797 return x !== null && (type === 'object' || type === 'function'); 27798} 27799 27800function isFunction(x) { 27801 return typeof x === 'function'; 27802} 27803 27804var _isArray = undefined; 27805if (Array.isArray) { 27806 _isArray = Array.isArray; 27807} else { 27808 _isArray = function (x) { 27809 return Object.prototype.toString.call(x) === '[object Array]'; 27810 }; 27811} 27812 27813var isArray = _isArray; 27814 27815var len = 0; 27816var vertxNext = undefined; 27817var customSchedulerFn = undefined; 27818 27819var asap = function asap(callback, arg) { 27820 queue[len] = callback; 27821 queue[len + 1] = arg; 27822 len += 2; 27823 if (len === 2) { 27824 // If len is 2, that means that we need to schedule an async flush. 27825 // If additional callbacks are queued before the queue is flushed, they 27826 // will be processed by this flush that we are scheduling. 27827 if (customSchedulerFn) { 27828 customSchedulerFn(flush); 27829 } else { 27830 scheduleFlush(); 27831 } 27832 } 27833}; 27834 27835function setScheduler(scheduleFn) { 27836 customSchedulerFn = scheduleFn; 27837} 27838 27839function setAsap(asapFn) { 27840 asap = asapFn; 27841} 27842 27843var browserWindow = typeof window !== 'undefined' ? window : undefined; 27844var browserGlobal = browserWindow || {}; 27845var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver; 27846var isNode = typeof self === 'undefined' && typeof process !== 'undefined' && ({}).toString.call(process) === '[object process]'; 27847 27848// test for web worker but not in IE10 27849var isWorker = typeof Uint8ClampedArray !== 'undefined' && typeof importScripts !== 'undefined' && typeof MessageChannel !== 'undefined'; 27850 27851// node 27852function useNextTick() { 27853 // node version 0.10.x displays a deprecation warning when nextTick is used recursively 27854 // see https://github.com/cujojs/when/issues/410 for details 27855 return function () { 27856 return process.nextTick(flush); 27857 }; 27858} 27859 27860// vertx 27861function useVertxTimer() { 27862 if (typeof vertxNext !== 'undefined') { 27863 return function () { 27864 vertxNext(flush); 27865 }; 27866 } 27867 27868 return useSetTimeout(); 27869} 27870 27871function useMutationObserver() { 27872 var iterations = 0; 27873 var observer = new BrowserMutationObserver(flush); 27874 var node = document.createTextNode(''); 27875 observer.observe(node, { characterData: true }); 27876 27877 return function () { 27878 node.data = iterations = ++iterations % 2; 27879 }; 27880} 27881 27882// web worker 27883function useMessageChannel() { 27884 var channel = new MessageChannel(); 27885 channel.port1.onmessage = flush; 27886 return function () { 27887 return channel.port2.postMessage(0); 27888 }; 27889} 27890 27891function useSetTimeout() { 27892 // Store setTimeout reference so es6-promise will be unaffected by 27893 // other code modifying setTimeout (like sinon.useFakeTimers()) 27894 var globalSetTimeout = setTimeout; 27895 return function () { 27896 return globalSetTimeout(flush, 1); 27897 }; 27898} 27899 27900var queue = new Array(1000); 27901function flush() { 27902 for (var i = 0; i < len; i += 2) { 27903 var callback = queue[i]; 27904 var arg = queue[i + 1]; 27905 27906 callback(arg); 27907 27908 queue[i] = undefined; 27909 queue[i + 1] = undefined; 27910 } 27911 27912 len = 0; 27913} 27914 27915function attemptVertx() { 27916 try { 27917 var r = _dereq_; 27918 var vertx = r('vertx'); 27919 vertxNext = vertx.runOnLoop || vertx.runOnContext; 27920 return useVertxTimer(); 27921 } catch (e) { 27922 return useSetTimeout(); 27923 } 27924} 27925 27926var scheduleFlush = undefined; 27927// Decide what async method to use to triggering processing of queued callbacks: 27928if (isNode) { 27929 scheduleFlush = useNextTick(); 27930} else if (BrowserMutationObserver) { 27931 scheduleFlush = useMutationObserver(); 27932} else if (isWorker) {
27933 scheduleFlush = useMessageChannel(); 27934} else if (browserWindow === undefined && typeof _dereq_
vendor: 24,376 bytes, lines 27934-28936
27934 === 'function') { 27935 scheduleFlush = attemptVertx(); 27936} else { 27937 scheduleFlush = useSetTimeout(); 27938} 27939 27940function then(onFulfillment, onRejection) { 27941 var _arguments = arguments; 27942 27943 var parent = this; 27944 27945 var child = new this.constructor(noop); 27946 27947 if (child[PROMISE_ID] === undefined) { 27948 makePromise(child); 27949 } 27950 27951 var _state = parent._state; 27952 27953 if (_state) { 27954 (function () { 27955 var callback = _arguments[_state - 1]; 27956 asap(function () { 27957 return invokeCallback(_state, child, callback, parent._result); 27958 }); 27959 })(); 27960 } else { 27961 subscribe(parent, child, onFulfillment, onRejection); 27962 } 27963 27964 return child; 27965} 27966 27967/** 27968 `Promise.resolve` returns a promise that will become resolved with the 27969 passed `value`. It is shorthand for the following: 27970 27971 ```javascript 27972 let promise = new Promise(function(resolve, reject){ 27973 resolve(1); 27974 }); 27975 27976 promise.then(function(value){ 27977 // value === 1 27978 }); 27979 ``` 27980 27981 Instead of writing the above, your code now simply becomes the following: 27982 27983 ```javascript 27984 let promise = Promise.resolve(1); 27985 27986 promise.then(function(value){ 27987 // value === 1 27988 }); 27989 ``` 27990 27991 @method resolve 27992 @static 27993 @param {Any} value value that the returned promise will be resolved with 27994 Useful for tooling. 27995 @return {Promise} a promise that will become fulfilled with the given 27996 `value` 27997*/ 27998function resolve$1(object) { 27999 /*jshint validthis:true */ 28000 var Constructor = this; 28001 28002 if (object && typeof object === 'object' && object.constructor === Constructor) { 28003 return object; 28004 } 28005 28006 var promise = new Constructor(noop); 28007 resolve(promise, object); 28008 return promise; 28009} 28010 28011var PROMISE_ID = Math.random().toString(36).substring(16); 28012 28013function noop() {} 28014 28015var PENDING = void 0; 28016var FULFILLED = 1; 28017var REJECTED = 2; 28018 28019var GET_THEN_ERROR = new ErrorObject(); 28020 28021function selfFulfillment() { 28022 return new TypeError("You cannot resolve a promise with itself"); 28023} 28024 28025function cannotReturnOwn() { 28026 return new TypeError('A promises callback cannot return that same promise.'); 28027} 28028 28029function getThen(promise) { 28030 try { 28031 return promise.then; 28032 } catch (error) { 28033 GET_THEN_ERROR.error = error; 28034 return GET_THEN_ERROR; 28035 } 28036} 28037 28038function tryThen(then$$1, value, fulfillmentHandler, rejectionHandler) { 28039 try { 28040 then$$1.call(value, fulfillmentHandler, rejectionHandler); 28041 } catch (e) { 28042 return e; 28043 } 28044} 28045 28046function handleForeignThenable(promise, thenable, then$$1) { 28047 asap(function (promise) { 28048 var sealed = false; 28049 var error = tryThen(then$$1, thenable, function (value) { 28050 if (sealed) { 28051 return; 28052 } 28053 sealed = true; 28054 if (thenable !== value) { 28055 resolve(promise, value); 28056 } else { 28057 fulfill(promise, value); 28058 } 28059 }, function (reason) { 28060 if (sealed) { 28061 return; 28062 } 28063 sealed = true; 28064 28065 reject(promise, reason); 28066 }, 'Settle: ' + (promise._label || ' unknown promise')); 28067 28068 if (!sealed && error) { 28069 sealed = true; 28070 reject(promise, error); 28071 } 28072 }, promise); 28073} 28074 28075function handleOwnThenable(promise, thenable) { 28076 if (thenable._state === FULFILLED) { 28077 fulfill(promise, thenable._result); 28078 } else if (thenable._state === REJECTED) { 28079 reject(promise, thenable._result); 28080 } else { 28081 subscribe(thenable, undefined, function (value) { 28082 return resolve(promise, value); 28083 }, function (reason) { 28084 return reject(promise, reason); 28085 }); 28086 } 28087} 28088 28089function handleMaybeThenable(promise, maybeThenable, then$$1) { 28090 if (maybeThenable.constructor === promise.constructor && then$$1 === then && maybeThenable.constructor.resolve === resolve$1) { 28091 handleOwnThenable(promise, maybeThenable); 28092 } else { 28093 if (then$$1 === GET_THEN_ERROR) { 28094 reject(promise, GET_THEN_ERROR.error); 28095 GET_THEN_ERROR.error = null; 28096 } else if (then$$1 === undefined) { 28097 fulfill(promise, maybeThenable); 28098 } else if (isFunction(then$$1)) { 28099 handleForeignThenable(promise, maybeThenable, then$$1); 28100 } else { 28101 fulfill(promise, maybeThenable); 28102 } 28103 } 28104} 28105 28106function resolve(promise, value) { 28107 if (promise === value) { 28108 reject(promise, selfFulfillment()); 28109 } else if (objectOrFunction(value)) { 28110 handleMaybeThenable(promise, value, getThen(value)); 28111 } else { 28112 fulfill(promise, value); 28113 } 28114} 28115 28116function publishRejection(promise) { 28117 if (promise._onerror) { 28118 promise._onerror(promise._result); 28119 } 28120 28121 publish(promise); 28122} 28123 28124function fulfill(promise, value) { 28125 if (promise._state !== PENDING) { 28126 return; 28127 } 28128 28129 promise._result = value; 28130 promise._state = FULFILLED; 28131 28132 if (promise._subscribers.length !== 0) { 28133 asap(publish, promise); 28134 } 28135} 28136 28137function reject(promise, reason) { 28138 if (promise._state !== PENDING) { 28139 return; 28140 } 28141 promise._state = REJECTED; 28142 promise._result = reason; 28143 28144 asap(publishRejection, promise); 28145} 28146 28147function subscribe(parent, child, onFulfillment, onRejection) { 28148 var _subscribers = parent._subscribers; 28149 var length = _subscribers.length; 28150 28151 parent._onerror = null; 28152 28153 _subscribers[length] = child; 28154 _subscribers[length + FULFILLED] = onFulfillment; 28155 _subscribers[length + REJECTED] = onRejection; 28156 28157 if (length === 0 && parent._state) { 28158 asap(publish, parent); 28159 } 28160} 28161 28162function publish(promise) { 28163 var subscribers = promise._subscribers; 28164 var settled = promise._state; 28165 28166 if (subscribers.length === 0) { 28167 return; 28168 } 28169 28170 var child = undefined, 28171 callback = undefined, 28172 detail = promise._result; 28173 28174 for (var i = 0; i < subscribers.length; i += 3) { 28175 child = subscribers[i]; 28176 callback = subscribers[i + settled]; 28177 28178 if (child) { 28179 invokeCallback(settled, child, callback, detail); 28180 } else { 28181 callback(detail); 28182 } 28183 } 28184 28185 promise._subscribers.length = 0; 28186} 28187 28188function ErrorObject() { 28189 this.error = null; 28190} 28191 28192var TRY_CATCH_ERROR = new ErrorObject(); 28193 28194function tryCatch(callback, detail) { 28195 try { 28196 return callback(detail); 28197 } catch (e) { 28198 TRY_CATCH_ERROR.error = e; 28199 return TRY_CATCH_ERROR; 28200 } 28201} 28202 28203function invokeCallback(settled, promise, callback, detail) { 28204 var hasCallback = isFunction(callback), 28205 value = undefined, 28206 error = undefined, 28207 succeeded = undefined, 28208 failed = undefined; 28209 28210 if (hasCallback) { 28211 value = tryCatch(callback, detail); 28212 28213 if (value === TRY_CATCH_ERROR) { 28214 failed = true; 28215 error = value.error; 28216 value.error = null; 28217 } else { 28218 succeeded = true; 28219 } 28220 28221 if (promise === value) { 28222 reject(promise, cannotReturnOwn()); 28223 return; 28224 } 28225 } else { 28226 value = detail; 28227 succeeded = true; 28228 } 28229 28230 if (promise._state !== PENDING) { 28231 // noop 28232 } else if (hasCallback && succeeded) { 28233 resolve(promise, value); 28234 } else if (failed) { 28235 reject(promise, error); 28236 } else if (settled === FULFILLED) { 28237 fulfill(promise, value); 28238 } else if (settled === REJECTED) { 28239 reject(promise, value); 28240 } 28241} 28242 28243function initializePromise(promise, resolver) { 28244 try { 28245 resolver(function resolvePromise(value) { 28246 resolve(promise, value); 28247 }, function rejectPromise(reason) { 28248 reject(promise, reason); 28249 }); 28250 } catch (e) { 28251 reject(promise, e); 28252 } 28253} 28254 28255var id = 0; 28256function nextId() { 28257 return id++; 28258} 28259 28260function makePromise(promise) { 28261 promise[PROMISE_ID] = id++; 28262 promise._state = undefined; 28263 promise._result = undefined; 28264 promise._subscribers = []; 28265} 28266 28267function Enumerator$1(Constructor, input) { 28268 this._instanceConstructor = Constructor; 28269 this.promise = new Constructor(noop); 28270 28271 if (!this.promise[PROMISE_ID]) { 28272 makePromise(this.promise); 28273 } 28274 28275 if (isArray(input)) { 28276 this.length = input.length; 28277 this._remaining = input.length; 28278 28279 this._result = new Array(this.length); 28280 28281 if (this.length === 0) { 28282 fulfill(this.promise, this._result); 28283 } else { 28284 this.length = this.length || 0; 28285 this._enumerate(input); 28286 if (this._remaining === 0) { 28287 fulfill(this.promise, this._result); 28288 } 28289 } 28290 } else { 28291 reject(this.promise, validationError()); 28292 } 28293} 28294 28295function validationError() { 28296 return new Error('Array Methods must be provided an Array'); 28297} 28298 28299Enumerator$1.prototype._enumerate = function (input) { 28300 for (var i = 0; this._state === PENDING && i < input.length; i++) { 28301 this._eachEntry(input[i], i); 28302 } 28303}; 28304 28305Enumerator$1.prototype._eachEntry = function (entry, i) { 28306 var c = this._instanceConstructor; 28307 var resolve$$1 = c.resolve; 28308 28309 if (resolve$$1 === resolve$1) { 28310 var _then = getThen(entry); 28311 28312 if (_then === then && entry._state !== PENDING) { 28313 this._settledAt(entry._state, i, entry._result); 28314 } else if (typeof _then !== 'function') { 28315 this._remaining--; 28316 this._result[i] = entry; 28317 } else if (c === Promise$2) { 28318 var promise = new c(noop); 28319 handleMaybeThenable(promise, entry, _then); 28320 this._willSettleAt(promise, i); 28321 } else { 28322 this._willSettleAt(new c(function (resolve$$1) { 28323 return resolve$$1(entry); 28324 }), i); 28325 } 28326 } else { 28327 this._willSettleAt(resolve$$1(entry), i); 28328 } 28329}; 28330 28331Enumerator$1.prototype._settledAt = function (state, i, value) { 28332 var promise = this.promise; 28333 28334 if (promise._state === PENDING) { 28335 this._remaining--; 28336 28337 if (state === REJECTED) { 28338 reject(promise, value); 28339 } else { 28340 this._result[i] = value; 28341 } 28342 } 28343 28344 if (this._remaining === 0) { 28345 fulfill(promise, this._result); 28346 } 28347}; 28348 28349Enumerator$1.prototype._willSettleAt = function (promise, i) { 28350 var enumerator = this; 28351 28352 subscribe(promise, undefined, function (value) { 28353 return enumerator._settledAt(FULFILLED, i, value); 28354 }, function (reason) { 28355 return enumerator._settledAt(REJECTED, i, reason); 28356 }); 28357}; 28358 28359/** 28360 `Promise.all` accepts an array of promises, and returns a new promise which 28361 is fulfilled with an array of fulfillment values for the passed promises, or 28362 rejected with the reason of the first passed promise to be rejected. It casts all 28363 elements of the passed iterable to promises as it runs this algorithm. 28364 28365 Example: 28366 28367 ```javascript 28368 let promise1 = resolve(1); 28369 let promise2 = resolve(2); 28370 let promise3 = resolve(3); 28371 let promises = [ promise1, promise2, promise3 ]; 28372 28373 Promise.all(promises).then(function(array){ 28374 // The array here would be [ 1, 2, 3 ]; 28375 }); 28376 ``` 28377 28378 If any of the `promises` given to `all` are rejected, the first promise 28379 that is rejected will be given as an argument to the returned promises's 28380 rejection handler. For example: 28381 28382 Example: 28383 28384 ```javascript 28385 let promise1 = resolve(1); 28386 let promise2 = reject(new Error("2")); 28387 let promise3 = reject(new Error("3")); 28388 let promises = [ promise1, promise2, promise3 ]; 28389 28390 Promise.all(promises).then(function(array){ 28391 // Code here never runs because there are rejected promises! 28392 }, function(error) { 28393 // error.message === "2" 28394 }); 28395 ``` 28396 28397 @method all 28398 @static 28399 @param {Array} entries array of promises 28400 @param {String} label optional string for labeling the promise. 28401 Useful for tooling. 28402 @return {Promise} promise that is fulfilled when all `promises` have been 28403 fulfilled, or rejected if any of them become rejected. 28404 @static 28405*/ 28406function all$1(entries) { 28407 return new Enumerator$1(this, entries).promise; 28408} 28409 28410/** 28411 `Promise.race` returns a new promise which is settled in the same way as the 28412 first passed promise to settle. 28413 28414 Example: 28415 28416 ```javascript 28417 let promise1 = new Promise(function(resolve, reject){ 28418 setTimeout(function(){ 28419 resolve('promise 1'); 28420 }, 200); 28421 }); 28422 28423 let promise2 = new Promise(function(resolve, reject){ 28424 setTimeout(function(){ 28425 resolve('promise 2'); 28426 }, 100); 28427 }); 28428 28429 Promise.race([promise1, promise2]).then(function(result){ 28430 // result === 'promise 2' because it was resolved before promise1 28431 // was resolved. 28432 }); 28433 ``` 28434 28435 `Promise.race` is deterministic in that only the state of the first 28436 settled promise matters. For example, even if other promises given to the 28437 `promises` array argument are resolved, but the first settled promise has 28438 become rejected before the other promises became fulfilled, the returned 28439 promise will become rejected: 28440 28441 ```javascript 28442 let promise1 = new Promise(function(resolve, reject){ 28443 setTimeout(function(){ 28444 resolve('promise 1'); 28445 }, 200); 28446 }); 28447 28448 let promise2 = new Promise(function(resolve, reject){ 28449 setTimeout(function(){ 28450 reject(new Error('promise 2')); 28451 }, 100); 28452 }); 28453 28454 Promise.race([promise1, promise2]).then(function(result){ 28455 // Code here never runs 28456 }, function(reason){ 28457 // reason.message === 'promise 2' because promise 2 became rejected before 28458 // promise 1 became fulfilled 28459 }); 28460 ``` 28461 28462 An example real-world use case is implementing timeouts: 28463 28464 ```javascript 28465 Promise.race([ajax('foo.json'), timeout(5000)]) 28466 ``` 28467 28468 @method race 28469 @static 28470 @param {Array} promises array of promises to observe 28471 Useful for tooling. 28472 @return {Promise} a promise which settles in the same way as the first passed 28473 promise to settle. 28474*/ 28475function race$1(entries) { 28476 /*jshint validthis:true */ 28477 var Constructor = this; 28478 28479 if (!isArray(entries)) { 28480 return new Constructor(function (_, reject) { 28481 return reject(new TypeError('You must pass an array to race.')); 28482 }); 28483 } else { 28484 return new Constructor(function (resolve, reject) { 28485 var length = entries.length; 28486 for (var i = 0; i < length; i++) { 28487 Constructor.resolve(entries[i]).then(resolve, reject); 28488 } 28489 }); 28490 } 28491} 28492 28493/** 28494 `Promise.reject` returns a promise rejected with the passed `reason`. 28495 It is shorthand for the following: 28496 28497 ```javascript 28498 let promise = new Promise(function(resolve, reject){ 28499 reject(new Error('WHOOPS')); 28500 }); 28501 28502 promise.then(function(value){ 28503 // Code here doesn't run because the promise is rejected! 28504 }, function(reason){ 28505 // reason.message === 'WHOOPS' 28506 }); 28507 ``` 28508 28509 Instead of writing the above, your code now simply becomes the following: 28510 28511 ```javascript 28512 let promise = Promise.reject(new Error('WHOOPS')); 28513 28514 promise.then(function(value){ 28515 // Code here doesn't run because the promise is rejected! 28516 }, function(reason){ 28517 // reason.message === 'WHOOPS' 28518 }); 28519 ``` 28520 28521 @method reject 28522 @static 28523 @param {Any} reason value that the returned promise will be rejected with. 28524 Useful for tooling. 28525 @return {Promise} a promise rejected with the given `reason`. 28526*/ 28527function reject$1(reason) { 28528 /*jshint validthis:true */ 28529 var Constructor = this; 28530 var promise = new Constructor(noop); 28531 reject(promise, reason); 28532 return promise; 28533} 28534 28535function needsResolver() { 28536 throw new TypeError('You must pass a resolver function as the first argument to the promise constructor'); 28537} 28538 28539function needsNew() { 28540 throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function."); 28541} 28542 28543/** 28544 Promise objects represent the eventual result of an asynchronous operation. The 28545 primary way of interacting with a promise is through its `then` method, which 28546 registers callbacks to receive either a promise's eventual value or the reason 28547 why the promise cannot be fulfilled. 28548 28549 Terminology 28550 ----------- 28551 28552 - `promise` is an object or function with a `then` method whose behavior conforms to this specification. 28553 - `thenable` is an object or function that defines a `then` method. 28554 - `value` is any legal JavaScript value (including undefined, a thenable, or a promise). 28555 - `exception` is a value that is thrown using the throw statement. 28556 - `reason` is a value that indicates why a promise was rejected. 28557 - `settled` the final resting state of a promise, fulfilled or rejected. 28558 28559 A promise can be in one of three states: pending, fulfilled, or rejected. 28560 28561 Promises that are fulfilled have a fulfillment value and are in the fulfilled 28562 state. Promises that are rejected have a rejection reason and are in the 28563 rejected state. A fulfillment value is never a thenable. 28564 28565 Promises can also be said to *resolve* a value. If this value is also a 28566 promise, then the original promise's settled state will match the value's 28567 settled state. So a promise that *resolves* a promise that rejects will 28568 itself reject, and a promise that *resolves* a promise that fulfills will 28569 itself fulfill. 28570 28571 28572 Basic Usage: 28573 ------------ 28574 28575 ```js 28576 let promise = new Promise(function(resolve, reject) { 28577 // on success 28578 resolve(value); 28579 28580 // on failure 28581 reject(reason); 28582 }); 28583 28584 promise.then(function(value) { 28585 // on fulfillment 28586 }, function(reason) { 28587 // on rejection 28588 }); 28589 ``` 28590 28591 Advanced Usage: 28592 --------------- 28593 28594 Promises shine when abstracting away asynchronous interactions such as 28595 `XMLHttpRequest`s. 28596 28597 ```js 28598 function getJSON(url) { 28599 return new Promise(function(resolve, reject){ 28600 let xhr = new XMLHttpRequest(); 28601 28602 xhr.open('GET', url); 28603 xhr.onreadystatechange = handler; 28604 xhr.responseType = 'json'; 28605 xhr.setRequestHeader('Accept', 'application/json'); 28606 xhr.send(); 28607 28608 function handler() { 28609 if (this.readyState === this.DONE) { 28610 if (this.status === 200) { 28611 resolve(this.response); 28612 } else { 28613 reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']')); 28614 } 28615 } 28616 }; 28617 }); 28618 } 28619 28620 getJSON('/posts.json').then(function(json) { 28621 // on fulfillment 28622 }, function(reason) { 28623 // on rejection 28624 }); 28625 ``` 28626 28627 Unlike callbacks, promises are great composable primitives. 28628 28629 ```js 28630 Promise.all([ 28631 getJSON('/posts'), 28632 getJSON('/comments') 28633 ]).then(function(values){ 28634 values[0] // => postsJSON 28635 values[1] // => commentsJSON 28636 28637 return values; 28638 }); 28639 ``` 28640 28641 @class Promise 28642 @param {function} resolver 28643 Useful for tooling. 28644 @constructor 28645*/ 28646function Promise$2(resolver) { 28647 this[PROMISE_ID] = nextId(); 28648 this._result = this._state = undefined; 28649 this._subscribers = []; 28650 28651 if (noop !== resolver) { 28652 typeof resolver !== 'function' && needsResolver(); 28653 this instanceof Promise$2 ? initializePromise(this, resolver) : needsNew(); 28654 } 28655} 28656 28657Promise$2.all = all$1; 28658Promise$2.race = race$1; 28659Promise$2.resolve = resolve$1; 28660Promise$2.reject = reject$1; 28661Promise$2._setScheduler = setScheduler; 28662Promise$2._setAsap = setAsap; 28663Promise$2._asap = asap; 28664 28665Promise$2.prototype = { 28666 constructor: Promise$2, 28667 28668 /** 28669 The primary way of interacting with a promise is through its `then` method, 28670 which registers callbacks to receive either a promise's eventual value or the 28671 reason why the promise cannot be fulfilled. 28672 28673 ```js 28674 findUser().then(function(user){ 28675 // user is available 28676 }, function(reason){ 28677 // user is unavailable, and you are given the reason why 28678 }); 28679 ``` 28680 28681 Chaining 28682 -------- 28683 28684 The return value of `then` is itself a promise. This second, 'downstream' 28685 promise is resolved with the return value of the first promise's fulfillment 28686 or rejection handler, or rejected if the handler throws an exception. 28687 28688 ```js 28689 findUser().then(function (user) { 28690 return user.name; 28691 }, function (reason) { 28692 return 'default name'; 28693 }).then(function (userName) { 28694 // If `findUser` fulfilled, `userName` will be the user's name, otherwise it 28695 // will be `'default name'` 28696 }); 28697 28698 findUser().then(function (user) { 28699 throw new Error('Found user, but still unhappy'); 28700 }, function (reason) { 28701 throw new Error('`findUser` rejected and we're unhappy'); 28702 }).then(function (value) { 28703 // never reached 28704 }, function (reason) { 28705 // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'. 28706 // If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'. 28707 }); 28708 ``` 28709 If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream. 28710 28711 ```js 28712 findUser().then(function (user) { 28713 throw new PedagogicalException('Upstream error'); 28714 }).then(function (value) { 28715 // never reached 28716 }).then(function (value) { 28717 // never reached 28718 }, function (reason) { 28719 // The `PedgagocialException` is propagated all the way down to here 28720 }); 28721 ``` 28722 28723 Assimilation 28724 ------------ 28725 28726 Sometimes the value you want to propagate to a downstream promise can only be 28727 retrieved asynchronously. This can be achieved by returning a promise in the 28728 fulfillment or rejection handler. The downstream promise will then be pending 28729 until the returned promise is settled. This is called *assimilation*. 28730 28731 ```js 28732 findUser().then(function (user) { 28733 return findCommentsByAuthor(user); 28734 }).then(function (comments) { 28735 // The user's comments are now available 28736 }); 28737 ``` 28738 28739 If the assimliated promise rejects, then the downstream promise will also reject. 28740 28741 ```js 28742 findUser().then(function (user) { 28743 return findCommentsByAuthor(user); 28744 }).then(function (comments) { 28745 // If `findCommentsByAuthor` fulfills, we'll have the value here 28746 }, function (reason) { 28747 // If `findCommentsByAuthor` rejects, we'll have the reason here 28748 }); 28749 ``` 28750 28751 Simple Example 28752 -------------- 28753 28754 Synchronous Example 28755 28756 ```javascript 28757 let result; 28758 28759 try { 28760 result = findResult(); 28761 // success 28762 } catch(reason) { 28763 // failure 28764 } 28765 ``` 28766 28767 Errback Example 28768 28769 ```js 28770 findResult(function(result, err){ 28771 if (err) { 28772 // failure 28773 } else { 28774 // success 28775 } 28776 }); 28777 ``` 28778 28779 Promise Example; 28780 28781 ```javascript 28782 findResult().then(function(result){ 28783 // success 28784 }, function(reason){ 28785 // failure 28786 }); 28787 ``` 28788 28789 Advanced Example 28790 -------------- 28791 28792 Synchronous Example 28793 28794 ```javascript 28795 let author, books; 28796 28797 try { 28798 author = findAuthor(); 28799 books = findBooksByAuthor(author); 28800 // success 28801 } catch(reason) { 28802 // failure 28803 } 28804 ``` 28805 28806 Errback Example 28807 28808 ```js 28809 28810 function foundBooks(books) { 28811 28812 } 28813 28814 function failure(reason) { 28815 28816 } 28817 28818 findAuthor(function(author, err){ 28819 if (err) { 28820 failure(err); 28821 // failure 28822 } else { 28823 try { 28824 findBoooksByAuthor(author, function(books, err) { 28825 if (err) { 28826 failure(err); 28827 } else { 28828 try { 28829 foundBooks(books); 28830 } catch(reason) { 28831 failure(reason); 28832 } 28833 } 28834 }); 28835 } catch(error) { 28836 failure(err); 28837 } 28838 // success 28839 } 28840 }); 28841 ``` 28842 28843 Promise Example; 28844 28845 ```javascript 28846 findAuthor(). 28847 then(findBooksByAuthor). 28848 then(function(books){ 28849 // found books 28850 }).catch(function(reason){ 28851 // something went wrong 28852 }); 28853 ``` 28854 28855 @method then 28856 @param {Function} onFulfilled 28857 @param {Function} onRejected 28858 Useful for tooling. 28859 @return {Promise} 28860 */ 28861 then: then, 28862 28863 /** 28864 `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same 28865 as the catch block of a try/catch statement. 28866 28867 ```js 28868 function findAuthor(){ 28869 throw new Error('couldn't find that author'); 28870 } 28871 28872 // synchronous 28873 try { 28874 findAuthor(); 28875 } catch(reason) { 28876 // something went wrong 28877 } 28878 28879 // async with promises 28880 findAuthor().catch(function(reason){ 28881 // something went wrong 28882 }); 28883 ``` 28884 28885 @method catch 28886 @param {Function} onRejection 28887 Useful for tooling. 28888 @return {Promise} 28889 */ 28890 'catch': function _catch(onRejection) { 28891 return this.then(null, onRejection); 28892 } 28893}; 28894 28895/*global self*/ 28896function polyfill$1() { 28897 var local = undefined; 28898 28899 if (typeof global !== 'undefined') { 28900 local = global; 28901 } else if (typeof self !== 'undefined') { 28902 local = self; 28903 } else { 28904 try { 28905 local = Function('return this')(); 28906 } catch (e) { 28907 throw new Error('polyfill failed because global object is unavailable in this environment'); 28908 } 28909 } 28910 28911 var P = local.Promise; 28912 28913 if (P) { 28914 var promiseToString = null; 28915 try { 28916 promiseToString = Object.prototype.toString.call(P.resolve()); 28917 } catch (e) { 28918 // silently ignored 28919 } 28920 28921 if (promiseToString === '[object Promise]' && !P.cast) { 28922 return; 28923 } 28924 } 28925 28926 local.Promise = Promise$2; 28927} 28928 28929// Strange compat.. 28930Promise$2.polyfill = polyfill$1; 28931Promise$2.Promise = Promise$2; 28932 28933return Promise$2; 28934 28935}))); 28936
vendor: 2,252 bytes, lines 28937-29012
28937 28938 28939}).call(this,_dereq_('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) 28940},{"_process":11}],6:[function(_dereq_,module,exports){ 28941(function (global, factory) { 28942 if (typeof define === 'function' && define.amd) { 28943 define(['exports', 'module'], factory); 28944 } else if (typeof exports !== 'undefined' && typeof module !== 'undefined') { 28945 factory(exports, module); 28946 } else { 28947 var mod = { 28948 exports: {} 28949 }; 28950 factory(mod.exports, mod); 28951 global.fetchJsonp = mod.exports; 28952 } 28953})(this, function (exports, module) { 28954 'use strict'; 28955 28956 var defaultOptions = { 28957 timeout: 5000, 28958 jsonpCallback: 'callback', 28959 jsonpCallbackFunction: null 28960 }; 28961 28962 function generateCallbackFunction() { 28963 return 'jsonp_' + Date.now() + '_' + Math.ceil(Math.random() * 100000); 28964 } 28965 28966 function clearFunction(functionName) { 28967 // IE8 throws an exception when you try to delete a property on window 28968 // http://stackoverflow.com/a/1824228/751089 28969 try { 28970 delete window[functionName]; 28971 } catch (e) { 28972 window[functionName] = undefined; 28973 } 28974 } 28975 28976 function removeScript(scriptId) { 28977 var script = document.getElementById(scriptId); 28978 if (script) { 28979 document.getElementsByTagName('head')[0].removeChild(script); 28980 } 28981 } 28982 28983 function fetchJsonp(_url) { 28984 var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; 28985 28986 // to avoid param reassign 28987 var url = _url; 28988 var timeout = options.timeout || defaultOptions.timeout; 28989 var jsonpCallback = options.jsonpCallback || defaultOptions.jsonpCallback; 28990 28991 var timeoutId = undefined; 28992 28993 return new Promise(function (resolve, reject) { 28994 var callbackFunction = options.jsonpCallbackFunction || generateCallbackFunction(); 28995 var scriptId = jsonpCallback + '_' + callbackFunction; 28996 28997 window[callbackFunction] = function (response) { 28998 resolve({ 28999 ok: true, 29000 // keep consistent with fetch API 29001 json: function json() { 29002 return Promise.resolve(response); 29003 } 29004 }); 29005 29006 if (timeoutId) clearTimeout(timeoutId); 29007 29008 removeScript(scriptId); 29009 29010 clearFunction(callbackFunction); 29011 }; 29012
29013 // Check if the user set their own params, and if not add a ? to start a list of params 29014 url += url.indexOf('?') === -1 ? '?' : '&'; 29015 29016 var jsonpScript = document.createElement('script'); 29017 jsonpScript.setAttribute('src', '' + url + jsonpCallback + '=' + callbackFunction); 29018 if (options.charset) { 29019 jsonpScript.setAttribute('charset', options.charset); 29020 } 29021 jsonpScript.id = scriptId; 29022 document.getElementsByTagName('head')[0].appendChild(jsonpScript); 29023 29024 timeoutId = setTimeout(function () { 29025 reject(new Error('JSONP request to ' + _url + ' timed out')); 29026 29027 clearFunction(callbackFunction); 29028 removeScript(scriptId); 29029 window[callbackFunction] = function () { 29030 clearFunction(callbackFunction); 29031 }; 29032 }, timeout); 29033 29034 // Caught if got 404/500 29035 jsonpScript.onerror = function () { 29036 reject(new Error('JSONP request to ' + _url + ' failed')); 29037 29038 clearFunction(callbackFunction); 29039 removeScript(scriptId); 29040 if (timeoutId) clearTimeout(timeoutId); 29041 }; 29042 }); 29043 } 29044 29045 // export as global function 29046 /* 29047 let local; 29048 if (typeof global !== 'undefined') { 29049 local = global; 29050 } else if (typeof self !== 'undefined') { 29051 local = self; 29052 } else { 29053 try { 29054 local = Function('return this')(); 29055 } catch (e) { 29056 throw new Error('polyfill failed because global object is unavailable in this environment'); 29057 } 29058 } 29059 local.fetchJsonp = fetchJsonp; 29060 */ 29061 29062 module.exports = fetchJsonp; 29063}); 29064},{}],7:[function(_dereq_,module,exports){ 29065/* FileSaver.js 29066 * A saveAs() FileSaver implementation. 29067 * 1.3.2 29068 * 2016-06-16 18:25:19 29069 * 29070 * By Eli Grey, http://eligrey.com 29071 * License: MIT 29072 * See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md 29073 */ 29074 29075/*global self */ 29076/*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */ 29077 29078/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */ 29079 29080var saveAs = saveAs || (function(view) { 29081 "use strict"; 29082 // IE <10 is explicitly unsupported 29083 if (typeof view === "undefined" || typeof navigator !== "undefined" && /MSIE [1-9]\./.test(navigator.userAgent)) { 29084 return; 29085 } 29086 var 29087 doc = view.document 29088 // only get URL when necessary in case Blob.js hasn't overridden it yet 29089 , get_URL = function() { 29090 return view.URL || view.webkitURL || view; 29091 } 29092 , save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a") 29093 , can_use_save_link = "download" in save_link 29094 , click = function(node) { 29095 var event = new MouseEvent("click"); 29096 node.dispatchEvent(event); 29097 } 29098 , is_safari = /constructor/i.test(view.HTMLElement) || view.safari 29099 , is_chrome_ios =/CriOS\/[\d]+/.test(navigator.userAgent) 29100 , throw_outside = function(ex) { 29101 (view.setImmediate || view.setTimeout)(function() { 29102 throw ex; 29103 }, 0); 29104 } 29105 , force_saveable_type = "application/octet-stream" 29106 // the Blob API is fundamentally broken as there is no "downloadfinished" event to subscribe to 29107 , arbitrary_revoke_timeout = 1000 * 40 // in ms 29108 , revoke = function(file) { 29109 var revoker = function() { 29110 if (typeof file === "string") { // file is an object URL 29111 get_URL().revokeObjectURL(file); 29112 } else { // file is a File 29113 file.remove(); 29114 } 29115 }; 29116 setTimeout(revoker, arbitrary_revoke_timeout); 29117 } 29118 , dispatch = function(filesaver, event_types, event) { 29119 event_types = [].concat(event_types); 29120 var i = event_types.length; 29121 while (i--) { 29122 var listener = filesaver["on" + event_types[i]]; 29123 if (typeof listener === "function") { 29124 try { 29125 listener.call(filesaver, event || filesaver); 29126 } catch (ex) { 29127 throw_outside(ex); 29128 } 29129 } 29130 } 29131 } 29132 , auto_bom = function(blob) { 29133 // prepend BOM for UTF-8 XML and text/* types (including HTML) 29134 // note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF 29135 if (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) { 29136 return new Blob([String.fromCharCode(0xFEFF), blob], {type: blob.type}); 29137 } 29138 return blob; 29139 } 29140 , FileSaver = function(blob, name, no_auto_bom) { 29141 if (!no_auto_bom) { 29142 blob = auto_bom(blob); 29143 } 29144 // First try a.download, then web filesystem, then object URLs 29145 var 29146 filesaver = this 29147 , type = blob.type 29148 , force = type === force_saveable_type 29149 , object_url 29150 , dispatch_all = function() { 29151 dispatch(filesaver, "writestart progress write writeend".split(" ")); 29152 } 29153 // on any filesys errors revert to saving with object URLs 29154 , fs_error = function() { 29155 if ((is_chrome_ios || (force && is_safari)) && view.FileReader) { 29156 // Safari doesn't allow downloading of blob urls 29157 var reader = new FileReader(); 29158 reader.onloadend = function() { 29159 var url = is_chrome_ios ? reader.result : reader.result.replace(/^data:[^;]*;/, 'data:attachment/file;'); 29160 var popup = view.open(url, '_blank'); 29161 if(!popup) view.location.href = url; 29162 url=undefined; // release reference before dispatching 29163 filesaver.readyState = filesaver.DONE; 29164 dispatch_all(); 29165 };
29166 reader.readAsDataURL(blob); 29167 filesaver.readyState = filesaver.INIT; 29168 return; 29169 } 29170 // don't create more object URLs than needed 29171 if (!object_url) { 29172 object_url = get_URL().createObjectURL(blob); 29173 } 29174 if (force) { 29175 view.location.href = object_url; 29176 } else { 29177 var opened = view.open(object_url, "_blank"); 29178 if (!opened) { 29179 // Apple does not allow window.open, see https://developer.apple.com/library/safari/documentation/Tools/Conceptual/SafariExtensionGuide/WorkingwithWindowsandTabs/WorkingwithWindowsandTabs.html 29180 view.location.href = object_url; 29181 } 29182 } 29183 filesaver.readyState = filesaver.DONE; 29184 dispatch_all(); 29185 revoke(object_url); 29186 } 29187 ; 29188 filesaver.readyState = filesaver.INIT; 29189 29190 if (can_use_save_link) { 29191 object_url = get_URL().createObjectURL(blob); 29192 setTimeout(function() { 29193 save_link.href = object_url; 29194 save_link.download = name; 29195 click(save_link); 29196 dispatch_all(); 29197 revoke(object_url); 29198 filesaver.readyState = filesaver.DONE; 29199 }); 29200 return; 29201 } 29202 29203 fs_error(); 29204 } 29205 , FS_proto = FileSaver.prototype 29206 , saveAs = function(blob, name, no_auto_bom) { 29207 return new FileSaver(blob, name || blob.name || "download", no_auto_bom); 29208 } 29209 ; 29210 // IE 10+ (native saveAs) 29211 if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob) { 29212 return function(blob, name, no_auto_bom) { 29213 name = name || blob.name || "download"; 29214 29215 if (!no_auto_bom) { 29216 blob = auto_bom(blob); 29217 } 29218 return navigator.msSaveOrOpenBlob(blob, name); 29219 }; 29220 } 29221 29222 FS_proto.abort = function(){}; 29223 FS_proto.readyState = FS_proto.INIT = 0; 29224 FS_proto.WRITING = 1; 29225 FS_proto.DONE = 2; 29226 29227 FS_proto.error = 29228 FS_proto.onwritestart = 29229 FS_proto.onprogress = 29230 FS_proto.onwrite = 29231 FS_proto.onabort = 29232 FS_proto.onerror = 29233 FS_proto.onwriteend = 29234 null; 29235 29236 return saveAs; 29237}( 29238 typeof self !== "undefined" && self 29239 || typeof window !== "undefined" && window 29240 || this.content 29241)); 29242// `self` is undefined in Firefox for Android content script context 29243// while `this` is nsIContentFrameMessageManager 29244// with an attribute `content` that corresponds to the window 29245 29246if (typeof module !== "undefined" && module.exports) { 29247 module.exports.saveAs = saveAs; 29248} else if ((typeof define !== "undefined" && define !== null) && (define.amd !== null)) { 29249 define("FileSaver.js", function() { 29250 return saveAs; 29251 }); 29252} 29253 29254},{}],8:[function(_dereq_,module,exports){ 29255exports.read = function (buffer, offset, isLE, mLen, nBytes) { 29256 var e, m 29257 var eLen = nBytes * 8 - mLen - 1 29258 var eMax = (1 << eLen) - 1 29259 var eBias = eMax >> 1 29260 var nBits = -7 29261 var i = isLE ? (nBytes - 1) : 0 29262 var d = isLE ? -1 : 1 29263 var s = buffer[offset + i] 29264 29265 i += d 29266 29267 e = s & ((1 << (-nBits)) - 1) 29268 s >>= (-nBits) 29269 nBits += eLen 29270 for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {} 29271 29272 m = e & ((1 << (-nBits)) - 1) 29273 e >>= (-nBits) 29274 nBits += mLen 29275 for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {} 29276 29277 if (e === 0) { 29278 e = 1 - eBias 29279 } else if (e === eMax) { 29280 return m ? NaN : ((s ? -1 : 1) * Infinity) 29281 } else { 29282 m = m + Math.pow(2, mLen) 29283 e = e - eBias 29284 } 29285 return (s ? -1 : 1) * m * Math.pow(2, e - mLen) 29286} 29287 29288exports.write = function (buffer, value, offset, isLE, mLen, nBytes) { 29289 var e, m, c 29290 var eLen = nBytes * 8 - mLen - 1 29291 var eMax = (1 << eLen) - 1 29292 var eBias = eMax >> 1 29293 var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0) 29294 var i = isLE ? 0 : (nBytes - 1) 29295 var d = isLE ? 1 : -1 29296 var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0 29297 29298 value = Math.abs(value) 29299 29300 if (isNaN(value) || value === Infinity) { 29301 m = isNaN(value) ? 1 : 0 29302 e = eMax 29303 } else { 29304 e = Math.floor(Math.log(value) / Math.LN2) 29305 if (value * (c = Math.pow(2, -e)) < 1) { 29306 e-- 29307 c *= 2 29308 } 29309 if (e + eBias >= 1) { 29310 value += rt / c 29311 } else { 29312 value += rt * Math.pow(2, 1 - eBias) 29313 } 29314 if (value * c >= 2) { 29315 e++ 29316 c /= 2 29317 } 29318 29319 if (e + eBias >= eMax) { 29320 m = 0 29321 e = eMax 29322 } else if (e + eBias >= 1) { 29323 m = (value * c - 1) * Math.pow(2, mLen) 29324 e = e + eBias 29325 } else { 29326 m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen) 29327 e = 0 29328 } 29329 } 29330 29331 for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {} 29332 29333 e = (e << mLen) | m 29334 eLen += mLen 29335 for (; eLen > 0;
29335 buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {} 29336 29337 buffer[offset + i - d] |= s * 128 29338} 29339 29340},{}],9:[function(_dereq_,module,exports){ 29341var toString = {}.toString; 29342 29343module.exports = Array.isArray || function (arr) { 29344 return toString.call(arr) == '[object Array]'; 29345}; 29346 29347},{}],10:[function(_dereq_,module,exports){ 29348(function (Buffer){ 29349/** 29350 * https://opentype.js.org v0.7.3 | (c) Frederik De Bleser and other contributors | MIT License | Uses tiny-inflate by Devon Govett 29351 */ 29352 29353(function (global, factory) { 29354 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : 29355 typeof define === 'function' && define.amd ? define(['exports'], factory) : 29356 (factory((global.opentype = global.opentype || {}))); 29357}(this, (function (exports) { 'use strict'; 29358 29359var TINF_OK = 0; 29360var TINF_DATA_ERROR = -3; 29361 29362function Tree() { 29363 this.table = new Uint16Array(16); /* table of code length counts */ 29364 this.trans = new Uint16Array(288); /* code -> symbol translation table */ 29365} 29366 29367function Data(source, dest) { 29368 this.source = source; 29369 this.sourceIndex = 0; 29370 this.tag = 0; 29371 this.bitcount = 0; 29372 29373 this.dest = dest; 29374 this.destLen = 0; 29375 29376 this.ltree = new Tree(); /* dynamic length/symbol tree */ 29377 this.dtree = new Tree(); /* dynamic distance tree */ 29378} 29379 29380/* --------------------------------------------------- *
vendor: 7,409 bytes, lines 29381-29681
29381 * -- uninitialized global data (static structures) -- * 29382 * --------------------------------------------------- */ 29383 29384var sltree = new Tree(); 29385var sdtree = new Tree(); 29386 29387/* extra bits and base tables for length codes */ 29388var length_bits = new Uint8Array(30); 29389var length_base = new Uint16Array(30); 29390 29391/* extra bits and base tables for distance codes */ 29392var dist_bits = new Uint8Array(30); 29393var dist_base = new Uint16Array(30); 29394 29395/* special ordering of code length codes */ 29396var clcidx = new Uint8Array([ 29397 16, 17, 18, 0, 8, 7, 9, 6, 29398 10, 5, 11, 4, 12, 3, 13, 2, 29399 14, 1, 15 29400]); 29401 29402/* used by tinf_decode_trees, avoids allocations every call */ 29403var code_tree = new Tree(); 29404var lengths = new Uint8Array(288 + 32); 29405 29406/* ----------------------- * 29407 * -- utility functions -- * 29408 * ----------------------- */ 29409 29410/* build extra bits and base tables */ 29411function tinf_build_bits_base(bits, base, delta, first) { 29412 var i, sum; 29413 29414 /* build bits table */ 29415 for (i = 0; i < delta; ++i) { bits[i] = 0; } 29416 for (i = 0; i < 30 - delta; ++i) { bits[i + delta] = i / delta | 0; } 29417 29418 /* build base table */ 29419 for (sum = first, i = 0; i < 30; ++i) { 29420 base[i] = sum; 29421 sum += 1 << bits[i]; 29422 } 29423} 29424 29425/* build the fixed huffman trees */ 29426function tinf_build_fixed_trees(lt, dt) { 29427 var i; 29428 29429 /* build fixed length tree */ 29430 for (i = 0; i < 7; ++i) { lt.table[i] = 0; } 29431 29432 lt.table[7] = 24; 29433 lt.table[8] = 152; 29434 lt.table[9] = 112; 29435 29436 for (i = 0; i < 24; ++i) { lt.trans[i] = 256 + i; } 29437 for (i = 0; i < 144; ++i) { lt.trans[24 + i] = i; } 29438 for (i = 0; i < 8; ++i) { lt.trans[24 + 144 + i] = 280 + i; } 29439 for (i = 0; i < 112; ++i) { lt.trans[24 + 144 + 8 + i] = 144 + i; } 29440 29441 /* build fixed distance tree */ 29442 for (i = 0; i < 5; ++i) { dt.table[i] = 0; } 29443 29444 dt.table[5] = 32; 29445 29446 for (i = 0; i < 32; ++i) { dt.trans[i] = i; } 29447} 29448 29449/* given an array of code lengths, build a tree */ 29450var offs = new Uint16Array(16); 29451 29452function tinf_build_tree(t, lengths, off, num) { 29453 var i, sum; 29454 29455 /* clear code length count table */ 29456 for (i = 0; i < 16; ++i) { t.table[i] = 0; } 29457 29458 /* scan symbol lengths, and sum code length counts */ 29459 for (i = 0; i < num; ++i) { t.table[lengths[off + i]]++; } 29460 29461 t.table[0] = 0; 29462 29463 /* compute offset table for distribution sort */ 29464 for (sum = 0, i = 0; i < 16; ++i) { 29465 offs[i] = sum; 29466 sum += t.table[i]; 29467 } 29468 29469 /* create code->symbol translation table (symbols sorted by code) */ 29470 for (i = 0; i < num; ++i) { 29471 if (lengths[off + i]) { t.trans[offs[lengths[off + i]]++] = i; } 29472 } 29473} 29474 29475/* ---------------------- * 29476 * -- decode functions -- * 29477 * ---------------------- */ 29478 29479/* get one bit from source stream */ 29480function tinf_getbit(d) { 29481 /* check if tag is empty */ 29482 if (!d.bitcount--) { 29483 /* load next tag */ 29484 d.tag = d.source[d.sourceIndex++]; 29485 d.bitcount = 7; 29486 } 29487 29488 /* shift bit out of tag */ 29489 var bit = d.tag & 1; 29490 d.tag >>>= 1; 29491 29492 return bit; 29493} 29494 29495/* read a num bit value from a stream and add base */ 29496function tinf_read_bits(d, num, base) { 29497 if (!num) 29498 { return base; } 29499 29500 while (d.bitcount < 24) { 29501 d.tag |= d.source[d.sourceIndex++] << d.bitcount; 29502 d.bitcount += 8; 29503 } 29504 29505 var val = d.tag & (0xffff >>> (16 - num)); 29506 d.tag >>>= num; 29507 d.bitcount -= num; 29508 return val + base; 29509} 29510 29511/* given a data stream and a tree, decode a symbol */ 29512function tinf_decode_symbol(d, t) { 29513 while (d.bitcount < 24) { 29514 d.tag |= d.source[d.sourceIndex++] << d.bitcount; 29515 d.bitcount += 8; 29516 } 29517 29518 var sum = 0, cur = 0, len = 0; 29519 var tag = d.tag; 29520 29521 /* get more bits while code value is above sum */ 29522 do { 29523 cur = 2 * cur + (tag & 1); 29524 tag >>>= 1; 29525 ++len; 29526 29527 sum += t.table[len]; 29528 cur -= t.table[len]; 29529 } while (cur >= 0); 29530 29531 d.tag = tag; 29532 d.bitcount -= len; 29533 29534 return t.trans[sum + cur]; 29535} 29536 29537/* given a data stream, decode dynamic trees from it */ 29538function tinf_decode_trees(d, lt, dt) { 29539 var hlit, hdist, hclen; 29540 var i, num, length; 29541 29542 /* get 5 bits HLIT (257-286) */ 29543 hlit = tinf_read_bits(d, 5, 257); 29544 29545 /* get 5 bits HDIST (1-32) */ 29546 hdist = tinf_read_bits(d, 5, 1); 29547 29548 /* get 4 bits HCLEN (4-19) */ 29549 hclen = tinf_read_bits(d, 4, 4); 29550 29551 for (i = 0; i < 19; ++i) { lengths[i] = 0; } 29552 29553 /* read code lengths for code length alphabet */ 29554 for (i = 0; i < hclen; ++i) { 29555 /* get 3 bits code length (0-7) */ 29556 var clen = tinf_read_bits(d, 3, 0); 29557 lengths[clcidx[i]] = clen; 29558 } 29559 29560 /* build code length tree */ 29561 tinf_build_tree(code_tree, lengths, 0, 19); 29562 29563 /* decode code lengths for the dynamic trees */ 29564 for (num = 0; num < hlit + hdist;) { 29565 var sym = tinf_decode_symbol(d, code_tree); 29566 29567 switch (sym) { 29568 case 16: 29569 /* copy previous code length 3-6 times (read 2 bits) */ 29570 var prev = lengths[num - 1]; 29571 for (length = tinf_read_bits(d, 2, 3); length; --length) { 29572 lengths[num++] = prev; 29573 } 29574 break; 29575 case 17: 29576 /* repeat code length 0 for 3-10 times (read 3 bits) */ 29577 for (length = tinf_read_bits(d, 3, 3); length; --length) { 29578 lengths[num++] = 0; 29579 } 29580 break; 29581 case 18: 29582 /* repeat code length 0 for 11-138 times (read 7 bits) */ 29583 for (length = tinf_read_bits(d, 7, 11); length; --length) { 29584 lengths[num++] = 0; 29585 } 29586 break; 29587 default: 29588 /* values 0-15 represent the actual code lengths */ 29589 lengths[num++] = sym; 29590 break; 29591 } 29592 } 29593 29594 /* build dynamic trees */ 29595 tinf_build_tree(lt, lengths, 0, hlit); 29596 tinf_build_tree(dt, lengths, hlit, hdist); 29597} 29598 29599/* ----------------------------- * 29600 * -- block inflate functions -- * 29601 * ----------------------------- */ 29602 29603/* given a stream and two trees, inflate a block of data */ 29604function tinf_inflate_block_data(d, lt, dt) { 29605 while (1) { 29606 var sym = tinf_decode_symbol(d, lt); 29607 29608 /* check for end of block */ 29609 if (sym === 256) { 29610 return TINF_OK; 29611 } 29612 29613 if (sym < 256) { 29614 d.dest[d.destLen++] = sym; 29615 } else { 29616 var length, dist, offs; 29617 var i; 29618 29619 sym -= 257; 29620 29621 /* possibly get more bits from length code */ 29622 length = tinf_read_bits(d, length_bits[sym], length_base[sym]); 29623 29624 dist = tinf_decode_symbol(d, dt); 29625 29626 /* possibly get more bits from distance code */ 29627 offs = d.destLen - tinf_read_bits(d, dist_bits[dist], dist_base[dist]); 29628 29629 /* copy match */ 29630 for (i = offs; i < offs + length; ++i) { 29631 d.dest[d.destLen++] = d.dest[i]; 29632 } 29633 } 29634 } 29635} 29636 29637/* inflate an uncompressed block of data */ 29638function tinf_inflate_uncompressed_block(d) { 29639 var length, invlength; 29640 var i; 29641 29642 /* unread from bitbuffer */ 29643 while (d.bitcount > 8) { 29644 d.sourceIndex--; 29645 d.bitcount -= 8; 29646 } 29647 29648 /* get length */ 29649 length = d.source[d.sourceIndex + 1]; 29650 length = 256 * length + d.source[d.sourceIndex]; 29651 29652 /* get one's complement of length */ 29653 invlength = d.source[d.sourceIndex + 3]; 29654 invlength = 256 * invlength + d.source[d.sourceIndex + 2]; 29655 29656 /* check length */ 29657 if (length !== (~invlength & 0x0000ffff)) 29658 { return TINF_DATA_ERROR; } 29659 29660 d.sourceIndex += 4; 29661 29662 /* copy block */ 29663 for (i = length; i; --i) 29664 { d.dest[d.destLen++] = d.source[d.sourceIndex++]; } 29665 29666 /* make sure we start next block on a byte boundary */ 29667 d.bitcount = 0; 29668 29669 return TINF_OK; 29670} 29671 29672/* inflate stream from source to dest */ 29673function tinf_uncompress(source, dest) { 29674 var d = new Data(source, dest); 29675 var bfinal, btype, res; 29676 29677 do { 29678 /* read final block flag */ 29679 bfinal = tinf_getbit(d); 29680 29681 /* read block type (2 bits) */
29682 btype = tinf_read_bits(d, 2, 0); 29683 29684 /* decompress block */ 29685 switch (btype) { 29686 case 0: 29687 /* decompress uncompressed block */ 29688 res = tinf_inflate_uncompressed_block(d); 29689 break; 29690 case 1: 29691 /* decompress block with fixed huffman trees */ 29692 res = tinf_inflate_block_data(d, sltree, sdtree); 29693 break; 29694 case 2: 29695 /* decompress block with dynamic huffman trees */ 29696 tinf_decode_trees(d, d.ltree, d.dtree); 29697 res = tinf_inflate_block_data(d, d.ltree, d.dtree); 29698 break; 29699 default: 29700 res = TINF_DATA_ERROR; 29701 } 29702 29703 if (res !== TINF_OK) 29704 { throw new Error('Data error'); } 29705 29706 } while (!bfinal); 29707 29708 if (d.destLen < d.dest.length) { 29709 if (typeof d.dest.slice === 'function') 29710 { return d.dest.slice(0, d.destLen); } 29711 else 29712 { return d.dest.subarray(0, d.destLen); } 29713 } 29714 29715 return d.dest; 29716} 29717 29718/* -------------------- * 29719 * -- initialization -- * 29720 * -------------------- */ 29721 29722/* build fixed huffman trees */ 29723tinf_build_fixed_trees(sltree, sdtree); 29724 29725/* build extra bits and base tables */ 29726tinf_build_bits_base(length_bits, length_base, 4, 3); 29727tinf_build_bits_base(dist_bits, dist_base, 2, 1); 29728 29729/* fix a special case */ 29730length_bits[28] = 0; 29731length_base[28] = 258; 29732 29733var index = tinf_uncompress; 29734 29735// The Bounding Box object 29736 29737function derive(v0, v1, v2, v3, t) { 29738 return Math.pow(1 - t, 3) * v0 + 29739 3 * Math.pow(1 - t, 2) * t * v1 + 29740 3 * (1 - t) * Math.pow(t, 2) * v2 + 29741 Math.pow(t, 3) * v3; 29742} 29743/** 29744 * A bounding box is an enclosing box that describes the smallest measure within which all the points lie. 29745 * It is used to calculate the bounding box of a glyph or text path. 29746 * 29747 * On initialization, x1/y1/x2/y2 will be NaN. Check if the bounding box is empty using `isEmpty()`. 29748 * 29749 * @exports opentype.BoundingBox 29750 * @class 29751 * @constructor 29752 */ 29753function BoundingBox() { 29754 this.x1 = Number.NaN; 29755 this.y1 = Number.NaN; 29756 this.x2 = Number.NaN; 29757 this.y2 = Number.NaN; 29758} 29759 29760/** 29761 * Returns true if the bounding box is empty, that is, no points have been added to the box yet. 29762 */ 29763BoundingBox.prototype.isEmpty = function() { 29764 return isNaN(this.x1) || isNaN(this.y1) || isNaN(this.x2) || isNaN(this.y2); 29765}; 29766 29767/** 29768 * Add the point to the bounding box. 29769 * The x1/y1/x2/y2 coordinates of the bounding box will now encompass the given point. 29770 * @param {number} x - The X coordinate of the point. 29771 * @param {number} y - The Y coordinate of the point. 29772 */ 29773BoundingBox.prototype.addPoint = function(x, y) { 29774 if (typeof x === 'number') { 29775 if (isNaN(this.x1) || isNaN(this.x2)) { 29776 this.x1 = x; 29777 this.x2 = x; 29778 } 29779 if (x < this.x1) { 29780 this.x1 = x; 29781 } 29782 if (x > this.x2) { 29783 this.x2 = x; 29784 } 29785 } 29786 if (typeof y === 'number') { 29787 if (isNaN(this.y1) || isNaN(this.y2)) { 29788 this.y1 = y; 29789 this.y2 = y; 29790 } 29791 if (y < this.y1) { 29792 this.y1 = y; 29793 } 29794 if (y > this.y2) { 29795 this.y2 = y; 29796 } 29797 } 29798}; 29799 29800/** 29801 * Add a X coordinate to the bounding box. 29802 * This extends the bounding box to include the X coordinate. 29803 * This function is used internally inside of addBezier. 29804 * @param {number} x - The X coordinate of the point. 29805 */ 29806BoundingBox.prototype.addX = function(x) { 29807 this.addPoint(x, null); 29808}; 29809 29810/** 29811 * Add a Y coordinate to the bounding box. 29812 * This extends the bounding box to include the Y coordinate. 29813 * This function is used internally inside of addBezier. 29814 * @param {number} y - The Y coordinate of the point. 29815 */ 29816BoundingBox.prototype.addY = function(y) { 29817 this.addPoint(null, y); 29818}; 29819 29820/** 29821 * Add a Bézier curve to the bounding box. 29822 * This extends the bounding box to include the entire Bézier. 29823 * @param {number} x0 - The starting X coordinate. 29824 * @param {number} y0 - The starting Y coordinate. 29825 * @param {number} x1 - The X coordinate of the first control point. 29826 * @param {number} y1 - The Y coordinate of the first control point. 29827 * @param {number} x2 - The X coordinate of the second control point. 29828 * @param {number} y2 - The Y coordinate of the second control point. 29829 * @param {number} x - The ending X coordinate. 29830 * @param {number} y - The ending Y coordinate. 29831 */ 29832BoundingBox.prototype.addBezier = function(x0, y0, x1, y1, x2, y2, x, y) { 29833 var this$1 = this; 29834 29835 // This code is based on http://nishiohirokazu.blogspot.com/2009/06/how-to-calculate-bezier-curves-bounding.html 29836 // and https://github.com/icons8/svg-path-bounding-box 29837 29838 var p0 = [x0, y0]; 29839 var p1 = [x1, y1]; 29840 var p2 = [x2, y2]; 29841 var p3 = [x, y]; 29842 29843 this.addPoint(x0, y0); 29844 this.addPoint(x, y); 29845 29846 for (var i = 0; i <= 1; i++) { 29847 var b = 6 * p0[i] - 12 * p1[i] + 6 * p2[i]; 29848 var a = -3 * p0[i] + 9 * p1[i] - 9 * p2[i] + 3 * p3[i]; 29849 var c = 3 * p1[i] - 3 * p0[i]; 29850 29851 if (a === 0) { 29852 if (b === 0) { continue; } 29853 var t = -c / b; 29854 if (0 < t && t < 1) { 29855 if (i === 0) { this$1.addX(derive(p0[i], p1[i], p2[i], p3[
29855i], t)); } 29856 if (i === 1) { this$1.addY(derive(p0[i], p1[i], p2[i], p3[i], t)); } 29857 } 29858 continue; 29859 } 29860 29861 var b2ac = Math.pow(b, 2) - 4 * c * a; 29862 if (b2ac < 0) { continue; } 29863 var t1 = (-b + Math.sqrt(b2ac)) / (2 * a); 29864 if (0 < t1 && t1 < 1) { 29865 if (i === 0) { this$1.addX(derive(p0[i], p1[i], p2[i], p3[i], t1)); } 29866 if (i === 1) { this$1.addY(derive(p0[i], p1[i], p2[i], p3[i], t1)); } 29867 } 29868 var t2 = (-b - Math.sqrt(b2ac)) / (2 * a); 29869 if (0 < t2 && t2 < 1) { 29870 if (i === 0) { this$1.addX(derive(p0[i], p1[i], p2[i], p3[i], t2)); } 29871 if (i === 1) { this$1.addY(derive(p0[i], p1[i], p2[i], p3[i], t2)); } 29872 } 29873 } 29874}; 29875 29876/** 29877 * Add a quadratic curve to the bounding box. 29878 * This extends the bounding box to include the entire quadratic curve. 29879 * @param {number} x0 - The starting X coordinate. 29880 * @param {number} y0 - The starting Y coordinate. 29881 * @param {number} x1 - The X coordinate of the control point. 29882 * @param {number} y1 - The Y coordinate of the control point. 29883 * @param {number} x - The ending X coordinate. 29884 * @param {number} y - The ending Y coordinate. 29885 */ 29886BoundingBox.prototype.addQuad = function(x0, y0, x1, y1, x, y) { 29887 var cp1x = x0 + 2 / 3 * (x1 - x0); 29888 var cp1y = y0 + 2 / 3 * (y1 - y0); 29889 var cp2x = cp1x + 1 / 3 * (x - x0); 29890 var cp2y = cp1y + 1 / 3 * (y - y0); 29891 this.addBezier(x0, y0, cp1x, cp1y, cp2x, cp2y, x, y); 29892}; 29893 29894// Geometric objects 29895 29896/** 29897 * A bézier path containing a set of path commands similar to a SVG path. 29898 * Paths can be drawn on a context using `draw`. 29899 * @exports opentype.Path 29900 * @class 29901 * @constructor 29902 */ 29903function Path() { 29904 this.commands = []; 29905 this.fill = 'black'; 29906 this.stroke = null; 29907 this.strokeWidth = 1; 29908} 29909 29910/** 29911 * @param {number} x 29912 * @param {number} y 29913 */ 29914Path.prototype.moveTo = function(x, y) { 29915 this.commands.push({ 29916 type: 'M', 29917 x: x, 29918 y: y 29919 }); 29920}; 29921 29922/** 29923 * @param {number} x 29924 * @param {number} y 29925 */ 29926Path.prototype.lineTo = function(x, y) { 29927 this.commands.push({ 29928 type: 'L', 29929 x: x, 29930 y: y 29931 }); 29932}; 29933 29934/** 29935 * Draws cubic curve 29936 * @function 29937 * curveTo 29938 * @memberof opentype.Path.prototype 29939 * @param {number} x1 - x of control 1 29940 * @param {number} y1 - y of control 1 29941 * @param {number} x2 - x of control 2 29942 * @param {number} y2 - y of control 2 29943 * @param {number} x - x of path point 29944 * @param {number} y - y of path point 29945 */ 29946 29947/** 29948 * Draws cubic curve 29949 * @function 29950 * bezierCurveTo 29951 * @memberof opentype.Path.prototype 29952 * @param {number} x1 - x of control 1 29953 * @param {number} y1 - y of control 1 29954 * @param {number} x2 - x of control 2 29955 * @param {number} y2 - y of control 2 29956 * @param {number} x - x of path point 29957 * @param {number} y - y of path point 29958 * @see curveTo 29959 */ 29960Path.prototype.curveTo = Path.prototype.bezierCurveTo = function(x1, y1, x2, y2, x, y) { 29961 this.commands.push({ 29962 type: 'C', 29963 x1: x1, 29964 y1: y1, 29965 x2: x2, 29966 y2: y2, 29967 x: x, 29968 y: y 29969 }); 29970}; 29971 29972/** 29973 * Draws quadratic curve 29974 * @function 29975 * quadraticCurveTo 29976 * @memberof opentype.Path.prototype 29977 * @param {number} x1 - x of control 29978 * @param {number} y1 - y of control 29979 * @param {number} x - x of path point 29980 * @param {number} y - y of path point 29981 */ 29982 29983/** 29984 * Draws quadratic curve 29985 * @function 29986 * quadTo 29987 * @memberof opentype.Path.prototype 29988 * @param {number} x1 - x of control 29989 * @param {number} y1 - y of control 29990 * @param {number} x - x of path point 29991 * @param {number} y - y of path point 29992 */ 29993Path.prototype.quadTo = Path.prototype.quadraticCurveTo = function(x1, y1, x, y) { 29994 this.commands.push({ 29995 type: 'Q', 29996 x1: x1, 29997 y1: y1, 29998 x: x, 29999 y: y 30000 }); 30001}; 30002 30003/** 30004 * Closes the path 30005 * @function closePath 30006 * @memberof opentype.Path.prototype 30007 */ 30008 30009/** 30010 * Close the path 30011 * @function close 30012 * @memberof opentype.Path.prototype 30013 */ 30014Path.prototype.close = Path.prototype.closePath = function() { 30015 this.commands.push({ 30016 type: 'Z' 30017 }); 30018}; 30019 30020/** 30021 * Add the given path or list of commands to the commands of this path. 30022 * @param {Array} pathOrCommands - another opentype.Path, an opentype.BoundingBox, or an array of commands. 30023 */ 30024Path.prototype.extend = function(pathOrCommands) { 30025 if (pathOrCommands.commands) { 30026 pathOrCommands = pathOrCommands.commands; 30027 } else if (pathOrCommands instanceof BoundingBox) { 30028 var box = pathOrCommands; 30029 this.moveTo(box.x1, box.y1); 30030 this.lineTo(box.x2, box.y1); 30031 this.lineTo(box.x2, box.y2); 30032 this.lineTo(box.x1, box.y2); 30033 this.close(); 30034 return; 30035 } 30036 30037 Array.prototype.push.apply(this.commands, pathOrCommands); 30038}; 30039 30040/** 30041 * Calculate the bounding box of the path.
30042 * @returns {opentype.BoundingBox} 30043 */ 30044Path.prototype.getBoundingBox = function() { 30045 var this$1 = this; 30046 30047 var box = new BoundingBox(); 30048 30049 var startX = 0; 30050 var startY = 0; 30051 var prevX = 0; 30052 var prevY = 0; 30053 for (var i = 0; i < this.commands.length; i++) { 30054 var cmd = this$1.commands[i]; 30055 switch (cmd.type) { 30056 case 'M': 30057 box.addPoint(cmd.x, cmd.y); 30058 startX = prevX = cmd.x; 30059 startY = prevY = cmd.y; 30060 break; 30061 case 'L': 30062 box.addPoint(cmd.x, cmd.y); 30063 prevX = cmd.x; 30064 prevY = cmd.y; 30065 break; 30066 case 'Q': 30067 box.addQuad(prevX, prevY, cmd.x1, cmd.y1, cmd.x, cmd.y); 30068 prevX = cmd.x; 30069 prevY = cmd.y; 30070 break; 30071 case 'C': 30072 box.addBezier(prevX, prevY, cmd.x1, cmd.y1, cmd.x2, cmd.y2, cmd.x, cmd.y); 30073 prevX = cmd.x; 30074 prevY = cmd.y; 30075 break; 30076 case 'Z': 30077 prevX = startX; 30078 prevY = startY; 30079 break; 30080 default: 30081 throw new Error('Unexpected path command ' + cmd.type); 30082 } 30083 } 30084 if (box.isEmpty()) { 30085 box.addPoint(0, 0); 30086 } 30087 return box; 30088}; 30089 30090/** 30091 * Draw the path to a 2D context. 30092 * @param {CanvasRenderingContext2D} ctx - A 2D drawing context. 30093 */ 30094Path.prototype.draw = function(ctx) { 30095 var this$1 = this; 30096 30097 ctx.beginPath(); 30098 for (var i = 0; i < this.commands.length; i += 1) { 30099 var cmd = this$1.commands[i]; 30100 if (cmd.type === 'M') { 30101 ctx.moveTo(cmd.x, cmd.y); 30102 } else if (cmd.type === 'L') { 30103 ctx.lineTo(cmd.x, cmd.y); 30104 } else if (cmd.type === 'C') { 30105 ctx.bezierCurveTo(cmd.x1, cmd.y1, cmd.x2, cmd.y2, cmd.x, cmd.y); 30106 } else if (cmd.type === 'Q') { 30107 ctx.quadraticCurveTo(cmd.x1, cmd.y1, cmd.x, cmd.y); 30108 } else if (cmd.type === 'Z') { 30109 ctx.closePath(); 30110 } 30111 } 30112 30113 if (this.fill) { 30114 ctx.fillStyle = this.fill; 30115 ctx.fill(); 30116 } 30117 30118 if (this.stroke) { 30119 ctx.strokeStyle = this.stroke; 30120 ctx.lineWidth = this.strokeWidth; 30121 ctx.stroke(); 30122 } 30123}; 30124 30125/** 30126 * Convert the Path to a string of path data instructions 30127 * See http://www.w3.org/TR/SVG/paths.html#PathData 30128 * @param {number} [decimalPlaces=2] - The amount of decimal places for floating-point values 30129 * @return {string} 30130 */ 30131Path.prototype.toPathData = function(decimalPlaces) { 30132 var this$1 = this; 30133 30134 decimalPlaces = decimalPlaces !== undefined ? decimalPlaces : 2; 30135 30136 function floatToString(v) { 30137 if (Math.round(v) === v) { 30138 return '' + Math.round(v); 30139 } else { 30140 return v.toFixed(decimalPlaces); 30141 } 30142 } 30143 30144 function packValues() { 30145 var arguments$1 = arguments; 30146 30147 var s = ''; 30148 for (var i = 0; i < arguments.length; i += 1) { 30149 var v = arguments$1[i]; 30150 if (v >= 0 && i > 0) { 30151 s += ' '; 30152 } 30153 30154 s += floatToString(v); 30155 } 30156 30157 return s; 30158 } 30159 30160 var d = ''; 30161 for (var i = 0; i < this.commands.length; i += 1) { 30162 var cmd = this$1.commands[i]; 30163 if (cmd.type === 'M') { 30164 d += 'M' + packValues(cmd.x, cmd.y); 30165 } else if (cmd.type === 'L') { 30166 d += 'L' + packValues(cmd.x, cmd.y); 30167 } else if (cmd.type === 'C') { 30168 d += 'C' + packValues(cmd.x1, cmd.y1, cmd.x2, cmd.y2, cmd.x, cmd.y); 30169 } else if (cmd.type === 'Q') { 30170 d += 'Q' + packValues(cmd.x1, cmd.y1, cmd.x, cmd.y); 30171 } else if (cmd.type === 'Z') { 30172 d += 'Z'; 30173 } 30174 } 30175 30176 return d; 30177}; 30178 30179/** 30180 * Convert the path to an SVG <path> element, as a string. 30181 * @param {number} [decimalPlaces=2] - The amount of decimal places for floating-point values 30182 * @return {string} 30183 */ 30184Path.prototype.toSVG = function(decimalPlaces) { 30185 var svg = '<path d="'; 30186 svg += this.toPathData(decimalPlaces); 30187 svg += '"'; 30188 if (this.fill && this.fill !== 'black') { 30189 if (this.fill === null) { 30190 svg += ' fill="none"'; 30191 } else { 30192 svg += ' fill="' + this.fill + '"'; 30193 } 30194 } 30195 30196 if (this.stroke) { 30197 svg += ' stroke="' + this.stroke + '" stroke-width="' + this.strokeWidth + '"'; 30198 } 30199 30200 svg += '/>'; 30201 return svg; 30202}; 30203 30204/** 30205 * Convert the path to a DOM element. 30206 * @param {number} [decimalPlaces=2] - The amount of decimal places for floating-point values 30207 * @return {SVGPathElement} 30208 */ 30209Path.prototype.toDOMElement = function(decimalPlaces) { 30210 var temporaryPath = this.toPathData(decimalPlaces); 30211 var newPath = document.createElementNS('http://www.w3.org/2000/svg', 'path'); 30212 30213 newPath.setAttribute('d', temporaryPath); 30214 30215 return newPath; 30216}; 30217 30218// Run-time checking of preconditions. 30219 30220function fail(message) { 30221 throw new Error(message); 30222} 30223 30224// Precondition function that checks if the given predicate is true. 30225// If not, it will throw an error. 30226function argument(predicate, message) { 30227 if (!predicate) { 30228 fail(message); 30229 } 30230} 30231 30232var check = { fail: fail, argument: argument, assert: argument }; 30233 30234// Data types used in the OpenType font file. 30235// All OpenType fonts use Motorola-style byte ordering (Big Endian) 30236 30237var LIMIT16 = 32768; // The limit at which a 16-bit number switches signs == 2^15 30238var LIMIT32 = 2147483648; // The limit at which a 32-bit number switches signs == 2 ^ 31 30239 30240/** 30241 * @exports opentype.decode 30242 * @class 30243 */ 30244var decode = {}; 30245/** 30246 * @exports opentype.encode 30247 * @class 30248 */ 30249var encode = {}; 30250/** 30251 * @exports opentype.sizeOf 30252 * @class 30253 */ 30254var sizeOf = {}; 30255 30256// Return a function that always returns the same value. 30257function constant(v) { 30258 return function() { 30259 return v; 30260 }; 30261} 30262 30263// OpenType data types ////////////////////////////////////////////////////// 30264 30265/** 30266 * Convert an 8-bit unsigned integer to a list of 1 byte. 30267 * @param {number} 30268 * @returns {Array} 30269 */ 30270encode.BYTE = function(v) { 30271 check.argument(v >= 0 && v <= 255, 'Byte value should be between 0 and 255.'); 30272 return [v]; 30273}; 30274/** 30275 * @constant 30276 * @type {number} 30277 */ 30278sizeOf.BYTE = constant(1); 30279 30280/** 30281 * Convert a 8-bit signed integer to a list of 1 byte. 30282 * @param {string} 30283 * @returns {Array} 30284 */ 30285encode.CHAR = function(v) { 30286 return [v.charCodeAt(0)]; 30287}; 30288 30289/** 30290 * @constant 30291 * @type {number} 30292 */ 30293sizeOf.CHAR = constant(1); 30294 30295/**
30296 * Convert an ASCII string to a list of bytes. 30297 * @param {string} 30298 * @returns {Array} 30299 */ 30300encode.CHARARRAY = function(v) { 30301 var b = []; 30302 for (var i = 0; i < v.length; i += 1) { 30303 b[i] = v.charCodeAt(i); 30304 } 30305 30306 return b; 30307}; 30308 30309/** 30310 * @param {Array} 30311 * @returns {number} 30312 */ 30313sizeOf.CHARARRAY = function(v) { 30314 return v.length; 30315}; 30316 30317/** 30318 * Convert a 16-bit unsigned integer to a list of 2 bytes. 30319 * @param {number} 30320 * @returns {Array} 30321 */ 30322encode.USHORT = function(v) { 30323 return [(v >> 8) & 0xFF, v & 0xFF]; 30324}; 30325 30326/** 30327 * @constant 30328 * @type {number} 30329 */ 30330sizeOf.USHORT = constant(2); 30331 30332/** 30333 * Convert a 16-bit signed integer to a list of 2 bytes. 30334 * @param {number} 30335 * @returns {Array} 30336 */ 30337encode.SHORT = function(v) { 30338 // Two's complement 30339 if (v >= LIMIT16) { 30340 v = -(2 * LIMIT16 - v); 30341 } 30342 30343 return [(v >> 8) & 0xFF, v & 0xFF]; 30344}; 30345 30346/** 30347 * @constant 30348 * @type {number} 30349 */ 30350sizeOf.SHORT = constant(2); 30351 30352/** 30353 * Convert a 24-bit unsigned integer to a list of 3 bytes. 30354 * @param {number} 30355 * @returns {Array} 30356 */ 30357encode.UINT24 = function(v) { 30358 return [(v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF]; 30359}; 30360 30361/** 30362 * @constant 30363 * @type {number} 30364 */ 30365sizeOf.UINT24 = constant(3); 30366 30367/** 30368 * Convert a 32-bit unsigned integer to a list of 4 bytes. 30369 * @param {number} 30370 * @returns {Array} 30371 */ 30372encode.ULONG = function(v) { 30373 return [(v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF]; 30374}; 30375 30376/** 30377 * @constant 30378 * @type {number} 30379 */ 30380sizeOf.ULONG = constant(4); 30381 30382/** 30383 * Convert a 32-bit unsigned integer to a list of 4 bytes. 30384 * @param {number} 30385 * @returns {Array} 30386 */ 30387encode.LONG = function(v) { 30388 // Two's complement 30389 if (v >= LIMIT32) { 30390 v = -(2 * LIMIT32 - v); 30391 } 30392 30393 return [(v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF]; 30394}; 30395 30396/** 30397 * @constant 30398 * @type {number} 30399 */ 30400sizeOf.LONG = constant(4); 30401 30402encode.FIXED = encode.ULONG; 30403sizeOf.FIXED = sizeOf.ULONG; 30404 30405encode.FWORD = encode.SHORT; 30406sizeOf.FWORD = sizeOf.SHORT; 30407 30408encode.UFWORD = encode.USHORT; 30409sizeOf.UFWORD = sizeOf.USHORT; 30410 30411/** 30412 * Convert a 32-bit Apple Mac timestamp integer to a list of 8 bytes, 64-bit timestamp. 30413 * @param {number} 30414 * @returns {Array} 30415 */ 30416encode.LONGDATETIME = function(v) { 30417 return [0, 0, 0, 0, (v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF]; 30418}; 30419 30420/** 30421 * @constant 30422 * @type {number} 30423 */ 30424sizeOf.LONGDATETIME = constant(8); 30425 30426/** 30427 * Convert a 4-char tag to a list of 4 bytes. 30428 * @param {string} 30429 * @returns {Array} 30430 */ 30431encode.TAG = function(v) { 30432 check.argument(v.length === 4, 'Tag should be exactly 4 ASCII characters.'); 30433 return [v.charCodeAt(0), 30434 v.charCodeAt(1), 30435 v.charCodeAt(2), 30436 v.charCodeAt(3)]; 30437}; 30438 30439/** 30440 * @constant 30441 * @type {number} 30442 */ 30443sizeOf.TAG = constant(4); 30444 30445// CFF data types /////////////////////////////////////////////////////////// 30446 30447encode.Card8 = encode.BYTE; 30448sizeOf.Card8 = sizeOf.BYTE; 30449 30450encode.Card16 = encode.USHORT; 30451sizeOf.Card16 = sizeOf.USHORT; 30452 30453encode.OffSize = encode.BYTE; 30454sizeOf.OffSize = sizeOf.BYTE; 30455 30456encode.SID = encode.USHORT; 30457sizeOf.SID = sizeOf.USHORT; 30458 30459// Convert a numeric operand or charstring number to a variable-size list of bytes. 30460/** 30461 * Convert a numeric operand or charstring number to a variable-size list of bytes. 30462 * @param {number} 30463 * @returns {Array} 30464 */ 30465encode.NUMBER = function(v) { 30466 if (v >= -107 && v <= 107) { 30467 return [v + 139]; 30468 } else if (v >= 108 && v <= 1131) { 30469 v = v - 108; 30470 return [(v >> 8) + 247, v & 0xFF]; 30471 } else if (v >= -1131 && v <= -108) { 30472 v = -v - 108; 30473 return [(v >> 8) + 251, v & 0xFF]; 30474 } else if (v >= -32768 && v <= 32767) { 30475 return encode.NUMBER16(v); 30476 } else { 30477 return encode.NUMBER32(v); 30478 } 30479}; 30480 30481/** 30482 * @param {number} 30483 * @returns {number} 30484 */ 30485sizeOf.NUMBER = function(v) { 30486 return encode.NUMBER(v).length; 30487}; 30488 30489/** 30490 * Convert a signed number between -32768 and +32767 to a three-byte value. 30491 * This ensures we always use three bytes, but is not the most compact format. 30492 * @param {number} 30493 * @returns {Array} 30494 */ 30495encode.NUMBER16 = function(v) { 30496 return [28, (v >> 8) & 0xFF, v & 0xFF]; 30497}; 30498 30499/** 30500 * @constant 30501 * @type {number} 30502 */ 30503sizeOf.NUMBER16 = constant(3); 30504 30505/** 30506 * Convert a signed number between -(2^31) and +(2^31-1) to a five-byte value. 30507 * This is useful if you want to be sure you always use four bytes, 30508 * at the expense of wasting a few bytes for smaller numbers. 30509 * @param {number} 30510 * @returns {Array} 30511 */ 30512encode.NUMBER32 = function(v) { 30513 return [29, (v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF]; 30514}; 30515 30516/** 30517 * @constant 30518 * @type {number} 30519 */ 30520sizeOf.NUMBER32 = constant(5); 30521 30522/** 30523 * @param {number} 30524 * @returns {Array} 30525 */ 30526encode.REAL = function(v) { 30527 var value = v.toString(); 30528 30529 // Some numbers use an epsilon to encode the value. (e.g. JavaScript will store 0.0000001 as 1e-7) 30530 // This code converts it back to a number without the epsilon. 30531 var m = /\.(\d*?)(?:9{5,20}|0{5,20})\d{0,2}(?:e(.+)|$)/.exec(value); 30532 if (m) { 30533 var epsilon = parseFloat('1e' + ((m[2] ? +m[2] : 0) + m[1].length)); 30534 value = (Math.round(v * epsilon) / epsilon).toString(); 30535 } 30536 30537 var nibbles = ''; 30538 for (var i = 0, ii = value.length; i < ii; i += 1) { 30539 var c = value[i]; 30540 if (c === 'e') { 30541 nibbles += value[++i] === '-' ? 'c' : 'b'; 30542 } else if (c === '.') { 30543 nibbles += 'a'; 30544 } else if (c === '-') { 30545 nibbles += 'e'; 30546 } else { 30547 nibbles += c; 30548 } 30549 } 30550 30551 nibbles += (nibbles.length & 1) ? 'f' : 'ff'; 30552 var out = [30]; 30553 for (var i$1 = 0, ii$1 = nibbles.length; i$1 < ii$1; i$1 += 2) { 30554 out.push(parseInt(nibbles.substr(i$1, 2), 16)); 30555 } 30556 30557 return out; 30558}; 30559 30560/** 30561 * @param {number} 30562 * @returns {number} 30563 */ 30564sizeOf.REAL = function(v) { 30565 return encode.REAL(v).length; 30566}; 30567 30568encode.NAME = encode.CHARARRAY; 30569sizeOf.NAME = sizeOf.CHARARRAY; 30570 30571encode.STRING = encode.CHARARRAY; 30572sizeOf.STRING = sizeOf.CHARARRAY; 30573 30574/** 30575 * @param {DataView} data 30576 * @param {number} offset 30577 * @param {number} numBytes 30578 * @returns {string} 30579 */ 30580decode.UTF8 = function(data, offset, numBytes) { 30581 var codePoints = []; 30582 var numChars = numBytes; 30583 for (var j = 0; j < numChars; j++, offset += 1) { 30584 codePoints[j] = data.getUint8(offset); 30585 } 30586 30587 return String.fromCharCode.apply(null, codePoints); 30588}; 30589 30590/** 30591 * @param {DataView} data 30592 * @param {number} offset 30593 * @param {number} numBytes 30594 * @returns {string} 30595 */ 30596decode.UTF16 = function(data, offset, numBytes) { 30597 var codePoints = []; 30598 var numChars = numBytes / 2; 30599 for (var j = 0; j < numChars; j++, offset += 2) { 30600 codePoints[j] = data.getUint16(offset); 30601 } 30602 30603 return String.fromCharCode.apply(null, codePoints); 30604}; 30605 30606/** 30607 * Convert a JavaScript string to UTF16-BE. 30608 * @param {string} 30609 * @returns {Array} 30610 */ 30611encode.UTF16 = function(v) { 30612 var b = []; 30613 for (var i = 0; i < v.length; i += 1) { 30614 var codepoint = v.charCodeAt(i); 30615 b[b.length] = (codepoint >> 8) & 0xFF; 30616 b[b.length] = codepoint & 0xFF; 30617 } 30618 30619 return b; 30620}; 30621 30622/** 30623 * @param {string} 30624 * @returns {number} 30625 */ 30626sizeOf.UTF16 = function(v) { 30627 return v.length * 2; 30628}; 30629 30630// Data for converting old eight-bit Macintosh encodings to Unicode. 30631// This representation is optimized for decoding; encoding is slower 30632// and needs more memory. The assumption is that all opentype.js users 30633// want to open fonts, but saving a font will be comparatively rare 30634// so it can be more expensive. Keyed by IANA character set name. 30635// 30636// Python script for generating these strings: 30637// 30638// s = u''.join([chr(c).decode('mac_greek') for c in range(128, 256)]) 30639// print(s.encode('utf-8')) 30640/** 30641 * @private 30642 */ 30643var eightBitMacEncodings = { 30644 'x-mac-croatian': // Python: 'mac_croatian' 30645 'Ãà ÃÃÃÃÃáà âäãåçéèêëÃìîïñóòôöõúùûüâ °¢£§â¢Â¶Ã®Šâ¢Â´Â¨â ŽÃâ±â¤â¥âµâââÅ¡â«ÂªÂºÎ©Å¾Ã¸' + 30646 '¿¡¬âÆâÄ«Äâ¦Â ÃÃÃÅÅÄâââââ÷â©ââ¬â¹âºÃ»â·âââ°ÃÄÃÄÃÃÃÃÃÃÃÄÃÃÃÃıË˯ÏÃË¸ÃæË', 30647 'x-mac-cyrillic': // Python: 'mac_cyrillic' 30648 'ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐРСТУФХЦЧШЩЪЫЬÐЮЯâ °Ò£§â¢Â¶Ð®©â¢ÐÑâ ÐÑâ±â¤â¥ÑµÒÐÐÑÐÑÐÑÐÑ' + 30649 'ÑР¬âÆââ«»â¦Â ÐÑÐÑÑââââââ÷âÐÑÐÑâÐÑÑабвгдежзийклмнопÑÑÑÑÑÑ ÑÑÑÑÑÑÑÑÑ', 30650 'x-mac-gaelic': // http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/GAELIC.TXT 30651 'Ãà ÃÃÃÃÃáà âäãåçéèêëÃìîïñóòôöõúùûüâ °¢£§â¢Â¶Ã®©â¢Â´Â¨â ÃÃá¸Â±â¤â¥á¸ÄÄá¸á¸á¸á¸Ä Ä¡á¹Ã¦Ã¸' + 30652 'á¹á¹á¹É¼ÆÅ¿á¹ «»â¦Â ÃÃÃÅÅââââââṡáºÃ¿Å¸á¹ªâ¬â¹âºÅ¶Å·á¹«Â·á»²á»³âÃÃÃÃÃÃÃÃÃÃÃâ£ÃÃÃÃıÃýŴŵáºáº áºáºáºáº', 30653 'x-mac-greek': // Python: 'mac_greek' 30654 'ù²Ã³ÃÃΠà âäΨçéèêë£â¢Ã®Ã¯â¢Â½â°Ã´Ã¶Â¦â¬Ã¹Ã»Ã¼â ÎÎÎÎÎΠî©ΣΪ§â °·Î±â¤â¥Â¥ÎÎÎÎÎÎÎΦΫΨΩ' + 30655 'άάÎΡâΤ«»â¦Â ΥΧÎÎÅââââââ÷ÎÎÎÎÎήίÏÎÏαβÏδεÏγηιξκλμνοÏÏÏÏÏθÏÏÏÏ Î¶ÏÏÎΰ\u00AD', 30656 'x-mac-icelandic': // Python: 'mac_iceland' 30657 'Ãà ÃÃÃÃÃáà âäãåçéèêëÃìîïñóòôöõúùûü𢣧â¢Â¶Ã®©â¢Â´Â¨â ÃÃâ±â¤â¥Â¥ÂµâââÏâ«ÂªÂºÎ©Ã¦Ã¸' + 30658 '¿¡¬âÆââ«»â¦Â ÃÃÃÅÅââââââ÷âÿŸââ¬ÃðÃþý·âââ°ÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃıË˯ËË˸ËËË', 30659 'x-mac-inuit': // http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/INUIT.TXT 30660 'ááá áááá±á²á³á´á¸á¹áááááááá¦áá®á¯á°á²á³ááááááá°á¡á¥á¦â¢Â¶á§Â®Â©â¢á¨áªá«á»áááá áááá¯á°á±á²á´áµá ááá' + 30661 'ááááªá¨á©áªá«áâ¦Â á®á¾áááââââââáááááááááááá¿áááááá áááááááá±á²á³á´áµá¶áá á¡á¢á£á¤á¥á¦á¼ÅÅ', 30662 'x-mac-ce': // Python: 'mac_latin2' 30663 'ÃÄÄÃÄÃÃÃ¡Ä ÄäÄÄÄ鏟ÄÃÄÄÄÄóÄôöõúÄÄüâ °Ä£§â¢Â¶Ã®©â¢Ä¨â ģĮįĪâ¤â¥Ä«Ä¶ââÅĻļĽľĹĺŠ' + 30664 'ÅŬâÅÅâ«»â¦Â ÅÅÃÅÅââââââ÷âÅÅÅÅâ¹âºÅÅÅÅ ââÅ¡ÅÅÃŤťÃŽžŪÃÃūŮÃůŰűŲųÃýķŻÅżĢË', 30665 macintosh: // Python: 'mac_roman' 30666 'Ãà ÃÃÃÃÃáà âäãåçéèêëÃìîïñóòôöõúùûüâ °¢£§â¢Â¶Ã®©â¢Â´Â¨â ÃÃâ±â¤â¥Â¥ÂµâââÏâ«ÂªÂºÎ©Ã¦Ã¸' + 30667 '¿¡¬âÆââ«»â¦Â ÃÃÃÅÅââââââ÷âÿŸââ¬â¹âºï¬ï¬â¡Â·âââ°ÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃıË˯ËË˸ËËË', 30668 'x-mac-romanian': // Python: 'mac_romanian' 30669 'Ãà ÃÃÃÃÃáà âäãåçéèêëÃìîïñóòôöõúùûüâ °¢£§â¢Â¶Ã®©â¢Â´Â¨â ÄÈâ±â¤â¥Â¥ÂµâââÏâ«ÂªÂºÎ©ÄÈ' + 30670 '¿¡¬âÆââ«»â¦Â ÃÃÃÅÅââââââ÷âÿŸââ¬â¹âºÈÈâ¡Â·âââ°ÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃıË˯ËË˸ËËË', 30671 'x-mac-turkish': // Python: 'mac_turkish' 30672 'Ãà ÃÃÃÃÃáà âäãåçéèêëÃìîïñóòôöõúùûüâ °¢£§â¢Â¶Ã®©â¢Â´Â¨â ÃÃâ±â¤â¥Â¥ÂµâââÏâ«ÂªÂºÎ©Ã¦Ã¸' + 30673 '¿¡¬âÆââ«»â¦Â ÃÃÃÅÅââââââ÷âÿŸÄÄİıÅÅâ¡Â·âââ°ÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃï¢ Ë˯ËË˸ËËË' 30674}; 30675 30676/** 30677 * Decodes an old-style Macintosh string. Returns either a Unicode JavaScript 30678 * string, or 'undefined' if the encoding is unsupported. For example, we do 30679 * not support Chinese, Japanese or Korean because these would need large 30680 * mapping tables. 30681 * @param {DataView} dataView 30682 * @param {number} offset 30683 * @param {number} dataLength 30684 * @param {string} encoding 30685 * @returns {string} 30686 */ 30687decode.MACSTRING = function(dataView, offset, dataLength, encoding) { 30688 var table = eightBitMacEncodings[encoding]; 30689 if (table === undefined) { 30690 return undefined; 30691 } 30692 30693 var result = ''; 30694 for (var i = 0; i < dataLength; i++) { 30695 var c = dataView.getUint8(offset + i); 30696 // In all eight-bit Mac encodings, the characters 0x00..0x7F are 30697 // mapped to U+0000..U+007F; we only need to look up the others. 30698 if (c <= 0x7F) { 30699 result += String.fromCharCode(c); 30700 } else { 30701 result += table[c & 0x7F]; 30702 } 30703 } 30704 30705 return result; 30706}; 30707 30708// Helper function for encode.MACSTRING. Returns a dictionary for mapping 30709// Unicode character codes to their 8-bit MacOS equivalent. This table 30710// is not exactly a super cheap data structure, but we do not care because 30711// encoding Macintosh strings is only rarely needed in typical applications. 30712var macEncodingTableCache = typeof WeakMap === 'function' && new WeakMap(); 30713var macEncodingCacheKeys; 30714var getMacEncodingTable = function (encoding) { 30715 // Since we use encoding as a cache key for WeakMap, it has to be 30716 // a String object and not a literal. And at least on NodeJS 2.10.1, 30717 // WeakMap requires that the same String instance is passed for cache hits. 30718 if (!macEncodingCacheKeys) { 30719 macEncodingCacheKeys = {}; 30720 for (var e in eightBitMacEncodings) { 30721 /*jshint -W053 */ // Suppress "Do not use String as a constructor." 30722 macEncodingCacheKeys[e] = new String(e); 30723 } 30724 } 30725 30726 var cacheKey = macEncodingCacheKeys[encoding]; 30727 if (cacheKey === undefined) { 30728 return undefined; 30729 } 30730 30731 // We can't do "if (cache.has(key)) {return cache.get(key)}" here: 30732 // since garbage collection may run at any time, it could also kick in 30733 // between the calls to cache.has() and cache.get(). In that case, 30734 // we would return 'undefined' even though we do support the encoding. 30735 if (macEncodingTableCache) { 30736 var cachedTable = macEncodingTableCache.get(cacheKey); 30737 if (cachedTable !== undefined) { 30738 return cachedTable; 30739 } 30740 } 30741 30742 var decodingTable = eightBitMacEncodings[encoding]; 30743 if (decodingTable === undefined) { 30744 return undefined; 30745 } 30746 30747 var encodingTable = {}; 30748 for (var i = 0; i < decodingTable.length; i++) { 30749 encodingTable[decodingTable.charCodeAt(i)] = i + 0x80; 30750 } 30751 30752 if (macEncodingTableCache) { 30753 macEncodingTableCache.set(cacheKey, encodingTable); 30754 } 30755 30756 return encodingTable; 30757}; 30758 30759/** 30760 * Encodes an old-style Macintosh string. Returns a byte array upon success. 30761 * If the requested encoding is unsupported, or if the input string contains 30762 * a character that cannot be expressed in the encoding, the function returns 30763 * 'undefined'. 30764 * @param {string} str 30765 * @param {string} encoding 30766 * @returns {Array} 30767 */ 30768encode.MACSTRING = function(str, encoding) { 30769 var table = getMacEncodingTable(encoding); 30770 if (table === undefined) { 30771 return undefined; 30772 } 30773 30774 var result = []; 30775 for (var i = 0; i < str.length; i++) { 30776 var c = str.charCodeAt(i); 30777 30778 // In all eight-bit Mac encodings, the characters 0x00..0x7F are 30779 // mapped to U+0000..U+007F; we only need to look up the others. 30780 if (c >= 0x80) { 30781 c = table[c]; 30782 if (c === undefined) { 30783 // str contains a Unicode character that cannot be encoded 30784 // in the requested encoding. 30785 return undefined; 30786 } 30787 } 30788 result[i] = c; 30789 // result.push(c); 30790 } 30791 30792 return result; 30793}; 30794 30795/** 30796 * @param {string} str 30797 * @param {string} encoding 30798 * @returns {number} 30799 */ 30800sizeOf.MACSTRING = function(str, encoding) { 30801 var b = encode.MACSTRING(str, encoding); 30802 if (b !== undefined) { 30803 return b.length; 30804 } else { 30805 return 0; 30806 } 30807}; 30808 30809// Helper for encode.VARDELTAS 30810function isByteEncodable(value) { 30811 return value >= -128 && value <= 127; 30812} 30813 30814// Helper for encode.VARDELTAS 30815function encodeVarDeltaRunAsZeroes(deltas, pos, result) { 30816 var runLength = 0; 30817 var numDeltas = deltas.length; 30818 while (pos < numDeltas && runLength < 64 && deltas[pos] === 0) { 30819 ++pos; 30820 ++runLength; 30821 } 30822 result.push(0x80 | (runLength - 1)); 30823 return pos; 30824} 30825 30826// Helper for encode.VARDELTAS 30827function encodeVarDeltaRunAsBytes(deltas, offset, result) { 30828 var runLength = 0; 30829 var numDeltas = deltas.length; 30830 var pos = offset; 30831 while (pos < numDeltas && runLength < 64) { 30832 var value = deltas[pos]; 30833 if (!isByteEncodable(value)) { 30834 break; 30835
30835 } 30836 30837 // Within a byte-encoded run of deltas, a single zero is best 30838 // stored literally as 0x00 value. However, if we have two or 30839 // more zeroes in a sequence, it is better to start a new run. 30840 // Fore example, the sequence of deltas [15, 15, 0, 15, 15] 30841 // becomes 6 bytes (04 0F 0F 00 0F 0F) when storing the zero 30842 // within the current run, but 7 bytes (01 0F 0F 80 01 0F 0F) 30843 // when starting a new run. 30844 if (value === 0 && pos + 1 < numDeltas && deltas[pos + 1] === 0) { 30845 break; 30846 } 30847 30848 ++pos; 30849 ++runLength; 30850 } 30851 result.push(runLength - 1); 30852 for (var i = offset; i < pos; ++i) { 30853 result.push((deltas[i] + 256) & 0xff); 30854 } 30855 return pos; 30856} 30857 30858// Helper for encode.VARDELTAS 30859function encodeVarDeltaRunAsWords(deltas, offset, result) { 30860 var runLength = 0; 30861 var numDeltas = deltas.length; 30862 var pos = offset; 30863 while (pos < numDeltas && runLength < 64) { 30864 var value = deltas[pos]; 30865 30866 // Within a word-encoded run of deltas, it is easiest to start 30867 // a new run (with a different encoding) whenever we encounter 30868 // a zero value. For example, the sequence [0x6666, 0, 0x7777] 30869 // needs 7 bytes when storing the zero inside the current run 30870 // (42 66 66 00 00 77 77), and equally 7 bytes when starting a 30871 // new run (40 66 66 80 40 77 77). 30872 if (value === 0) { 30873 break; 30874 } 30875 30876 // Within a word-encoded run of deltas, a single value in the 30877 // range (-128..127) should be encoded within the current run 30878 // because it is more compact. For example, the sequence 30879 // [0x6666, 2, 0x7777] becomes 7 bytes when storing the value 30880 // literally (42 66 66 00 02 77 77), but 8 bytes when starting 30881 // a new run (40 66 66 00 02 40 77 77). 30882 if (isByteEncodable(value) && pos + 1 < numDeltas && isByteEncodable(deltas[pos + 1])) { 30883 break; 30884 } 30885 30886 ++pos; 30887 ++runLength; 30888 } 30889 result.push(0x40 | (runLength - 1)); 30890 for (var i = offset; i < pos; ++i) { 30891 var val = deltas[i]; 30892 result.push(((val + 0x10000) >> 8) & 0xff, (val + 0x100) & 0xff); 30893 } 30894 return pos; 30895} 30896 30897/** 30898 * Encode a list of variation adjustment deltas. 30899 * 30900 * Variation adjustment deltas are used in âgvarâ and âcvarâ tables. 30901 * They indicate how points (in âgvarâ) or values (in âcvarâ) get adjusted 30902 * when generating instances of variation fonts. 30903 * 30904 * @see https://www.microsoft.com/typography/otspec/gvar.htm 30905 * @see https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6gvar.html 30906 * @param {Array} 30907 * @return {Array} 30908 */ 30909encode.VARDELTAS = function(deltas) { 30910 var pos = 0; 30911 var result = []; 30912 while (pos < deltas.length) { 30913 var value = deltas[pos]; 30914 if (value === 0) { 30915 pos = encodeVarDeltaRunAsZeroes(deltas, pos, result); 30916 } else if (value >= -128 && value <= 127) { 30917 pos = encodeVarDeltaRunAsBytes(deltas, pos, result); 30918 } else { 30919 pos = encodeVarDeltaRunAsWords(deltas, pos, result); 30920 } 30921 } 30922 return result; 30923}; 30924 30925// Convert a list of values to a CFF INDEX structure. 30926// The values should be objects containing name / type / value. 30927/** 30928 * @param {Array} l 30929 * @returns {Array} 30930 */ 30931encode.INDEX = function(l) { 30932 //var offset, offsets, offsetEncoder, encodedOffsets, encodedOffset, data, 30933 // i, v; 30934 // Because we have to know which data type to use to encode the offsets, 30935 // we have to go through the values twice: once to encode the data and 30936 // calculate the offsets, then again to encode the offsets using the fitting data type. 30937 var offset = 1; // First offset is always 1. 30938 var offsets = [offset]; 30939 var data = []; 30940 for (var i = 0; i < l.length; i += 1) { 30941 var v = encode.OBJECT(l[i]); 30942 Array.prototype.push.apply(data, v); 30943 offset += v.length; 30944 offsets.push(offset); 30945 } 30946 30947 if (data.length === 0) { 30948 return [0, 0]; 30949 } 30950 30951 var encodedOffsets = []; 30952 var offSize = (1 + Math.floor(Math.log(offset) / Math.log(2)) / 8) | 0; 30953 var offsetEncoder = [undefined, encode.BYTE, encode.USHORT, encode.UINT24, encode.ULONG][offSize]; 30954 for (var i$1 = 0; i$1 < offsets.length; i$1 += 1) { 30955 var encodedOffset = offsetEncoder(offsets[i$1]); 30956 Array.prototype.push.apply(encodedOffsets, encodedOffset); 30957 } 30958 30959 return Array.prototype.concat(encode.Card16(l.length), 30960 encode.OffSize(offSize), 30961 encodedOffsets, 30962 data); 30963}; 30964 30965/** 30966 * @param {Array} 30967 * @returns {number} 30968 */ 30969sizeOf.INDEX = function(v) { 30970 return encode.INDEX(v).length; 30971}; 30972 30973/** 30974 * Convert an object to a CFF DICT structure. 30975 * The keys should be numeric. 30976 * The values should be objects containing name / type / value. 30977 * @param {Object} m 30978 * @returns {Array} 30979 */ 30980encode.DICT = function(m) { 30981 var d = []; 30982 var keys = Object.keys(m); 30983 var length = keys.length; 30984 30985 for (var i = 0; i < length; i += 1) { 30986 // Object.keys() return string keys, but our keys are always numeric. 30987 var k = parseInt(keys[i], 0); 30988 var v = m[k]; 30989 // Value comes before the key. 30990 d = d.concat(encode.OPERAND(v.value, v.type)); 30991 d = d.concat(encode.OPERATOR(k)); 30992 } 30993 30994 return d; 30995}; 30996 30997/** 30998 * @param {Object} 30999 * @returns {number} 31000 */ 31001sizeOf.DICT = function(m) { 31002 return encode.DICT(m).length; 31003}; 31004 31005/** 31006 * @param {number} 31007 * @returns {Array} 31008 */ 31009encode.OPERATOR = function(v) { 31010 if (v < 1200) { 31011 return [v]; 31012 } else { 31013 return [12, v - 1200]; 31014 } 31015}; 31016 31017/** 31018 * @param {Array} v 31019 * @param {string} 31020 * @returns {Array} 31021 */ 31022encode.OPERAND = function(v, type) { 31023 var d = []; 31024 if (Array.isArray(type)) { 31025 for (var i = 0; i < type.length; i += 1) { 31026 check.argument(v.length === type.length, 'Not enough arguments given for type' + type); 31027 d = d.concat(encode.OPERAND(v[i], type[i])); 31028 } 31029 } else { 31030 if (type === 'SID') { 31031 d = d.concat(encode.NUMBER(v)); 31032 } else if (type === 'offset') { 31033 // We make it easy for ourselves and always encode offsets as 31034 // 4 bytes. This makes offset calculation for the top dict easier. 31035 d = d.concat(encode.NUMBER32(v)); 31036 } else if (type === 'number') { 31037 d = d.concat(encode.NUMBER(v)); 31038 } else if (type === 'real') { 31039 d = d.concat(encode.REAL(v)); 31040 } else { 31041 throw new Error('Unknown operand type ' + type); 31042 // FIXME Add support for booleans 31043 } 31044 } 31045 31046 return d; 31047}; 31048 31049encode.OP = encode.BYTE; 31050sizeOf.OP = sizeOf.BYTE; 31051 31052// memoize charstring encoding using WeakMap if available 31053var wmm = typeof WeakMap === 'function' && new WeakMap(); 31054 31055/** 31056 * Convert a list of CharString operations to bytes. 31057 * @param {Array} 31058 * @returns {Array} 31059 */ 31060encode.CHARSTRING = function(ops) { 31061 // See encode.MACSTRING for why we don't do "if (wmm && wmm.has(ops))". 31062 if (wmm) { 31063 var cachedValue = wmm.get(ops); 31064 if (cachedValue !== undefined) { 31065 return cachedValue; 31066 } 31067 } 31068 31069 var d = []; 31070 var length = ops.length; 31071 31072 for (var i = 0; i < length; i += 1) { 31073 var op = ops[i]; 31074 d = d.concat(encode[op.type](op.value)); 31075 } 31076 31077 if (wmm) { 31078 wmm.set(ops, d); 31079 } 31080 31081 return d; 31082}; 31083 31084/** 31085 * @param {Array} 31086 * @returns {number} 31087 */ 31088sizeOf.CHARSTRING = function(ops) { 31089 return encode.CHARSTRING(ops).length; 31090}; 31091 31092// Utility functions //////////////////////////////////////////////////////// 31093 31094/**
31095 * Convert an object containing name / type / value to bytes. 31096 * @param {Object} 31097 * @returns {Array} 31098 */ 31099encode.OBJECT = function(v) { 31100 var encodingFunction = encode[v.type]; 31101 check.argument(encodingFunction !== undefined, 'No encoding function for type ' + v.type); 31102 return encodingFunction(v.value); 31103}; 31104 31105/** 31106 * @param {Object} 31107 * @returns {number} 31108 */ 31109sizeOf.OBJECT = function(v) { 31110 var sizeOfFunction = sizeOf[v.type]; 31111 check.argument(sizeOfFunction !== undefined, 'No sizeOf function for type ' + v.type); 31112 return sizeOfFunction(v.value); 31113}; 31114 31115/** 31116 * Convert a table object to bytes. 31117 * A table contains a list of fields containing the metadata (name, type and default value). 31118 * The table itself has the field values set as attributes. 31119 * @param {opentype.Table} 31120 * @returns {Array} 31121 */ 31122encode.TABLE = function(table) { 31123 var d = []; 31124 var length = table.fields.length; 31125 var subtables = []; 31126 var subtableOffsets = []; 31127 31128 for (var i = 0; i < length; i += 1) { 31129 var field = table.fields[i]; 31130 var encodingFunction = encode[field.type]; 31131 check.argument(encodingFunction !== undefined, 'No encoding function for field type ' + field.type + ' (' + field.name + ')'); 31132 var value = table[field.name]; 31133 if (value === undefined) { 31134 value = field.value; 31135 } 31136 31137 var bytes = encodingFunction(value); 31138 31139 if (field.type === 'TABLE') { 31140 subtableOffsets.push(d.length); 31141 d = d.concat([0, 0]); 31142 subtables.push(bytes); 31143 } else { 31144 d = d.concat(bytes); 31145 } 31146 } 31147 31148 for (var i$1 = 0; i$1 < subtables.length; i$1 += 1) { 31149 var o = subtableOffsets[i$1]; 31150 var offset = d.length; 31151 check.argument(offset < 65536, 'Table ' + table.tableName + ' too big.'); 31152 d[o] = offset >> 8; 31153 d[o + 1] = offset & 0xff; 31154 d = d.concat(subtables[i$1]); 31155 } 31156 31157 return d; 31158}; 31159 31160/** 31161 * @param {opentype.Table} 31162 * @returns {number} 31163 */ 31164sizeOf.TABLE = function(table) { 31165 var numBytes = 0; 31166 var length = table.fields.length; 31167 31168 for (var i = 0; i < length; i += 1) { 31169 var field = table.fields[i]; 31170 var sizeOfFunction = sizeOf[field.type]; 31171 check.argument(sizeOfFunction !== undefined, 'No sizeOf function for field type ' + field.type + ' (' + field.name + ')'); 31172 var value = table[field.name]; 31173 if (value === undefined) { 31174 value = field.value; 31175 } 31176 31177 numBytes += sizeOfFunction(value); 31178 31179 // Subtables take 2 more bytes for offsets. 31180 if (field.type === 'TABLE') { 31181 numBytes += 2; 31182 } 31183 } 31184 31185 return numBytes; 31186}; 31187 31188encode.RECORD = encode.TABLE; 31189sizeOf.RECORD = sizeOf.TABLE; 31190 31191// Merge in a list of bytes. 31192encode.LITERAL = function(v) { 31193 return v; 31194}; 31195 31196sizeOf.LITERAL = function(v) { 31197 return v.length; 31198}; 31199 31200// Table metadata 31201 31202/** 31203 * @exports opentype.Table 31204 * @class 31205 * @param {string} tableName 31206 * @param {Array} fields 31207 * @param {Object} options 31208 * @constructor 31209 */ 31210function Table(tableName, fields, options) { 31211 var this$1 = this; 31212 31213 for (var i = 0; i < fields.length; i += 1) { 31214 var field = fields[i]; 31215 this$1[field.name] = field.value; 31216 } 31217 31218 this.tableName = tableName; 31219 this.fields = fields; 31220 if (options) { 31221 var optionKeys = Object.keys(options); 31222 for (var i$1 = 0; i$1 < optionKeys.length; i$1 += 1) { 31223 var k = optionKeys[i$1]; 31224 var v = options[k]; 31225 if (this$1[k] !== undefined) { 31226 this$1[k] = v; 31227 } 31228 } 31229 } 31230} 31231 31232/** 31233 * Encodes the table and returns an array of bytes 31234 * @return {Array} 31235 */ 31236Table.prototype.encode = function() { 31237 return encode.TABLE(this); 31238}; 31239 31240/** 31241 * Get the size of the table. 31242 * @return {number} 31243 */ 31244Table.prototype.sizeOf = function() { 31245 return sizeOf.TABLE(this); 31246}; 31247 31248/** 31249 * @private 31250 */ 31251function ushortList(itemName, list, count) { 31252 if (count === undefined) { 31253 count = list.length; 31254 } 31255 var fields = new Array(list.length + 1); 31256 fields[0] = {name: itemName + 'Count', type: 'USHORT', value: count}; 31257 for (var i = 0; i < list.length; i++) { 31258 fields[i + 1] = {name: itemName + i, type: 'USHORT', value: list[i]}; 31259 } 31260 return fields; 31261} 31262 31263/** 31264 * @private 31265 */ 31266function tableList(itemName, records, itemCallback) { 31267 var count = records.length; 31268 var fields = new Array(count + 1); 31269 fields[0] = {name: itemName + 'Count', type: 'USHORT', value: count}; 31270 for (var i = 0; i < count; i++) { 31271 fields[i + 1] = {name: itemName + i, type: 'TABLE', value: itemCallback(records[i], i)}; 31272 } 31273 return fields; 31274} 31275 31276/** 31277 * @private 31278 */ 31279function recordList(itemName, records, itemCallback) { 31280 var count = records.length; 31281 var fields = []; 31282 fields[0] = {name: itemName + 'Count', type: 'USHORT', value: count}; 31283 for (var i = 0; i < count; i++) { 31284 fields = fields.concat(itemCallback(records[i], i)); 31285 } 31286 return fields; 31287} 31288 31289// Common Layout Tables 31290 31291/** 31292 * @exports opentype.Coverage 31293 * @class 31294 * @param {opentype.Table} 31295 * @constructor 31296 * @extends opentype.Table 31297 */ 31298function Coverage(coverageTable) { 31299 if (coverageTable.format === 1) { 31300 Table.call(this, 'coverageTable', 31301 [{name: 'coverageFormat', type: 'USHORT', value: 1}] 31302 .concat(ushortList('glyph', coverageTable.glyphs)) 31303 ); 31304 } else { 31305 check.assert(false, 'Can\'t create coverage table format 2 yet.'); 31306 } 31307} 31308Coverage.prototype = Object.create(Table.prototype); 31309Coverage.prototype.constructor = Coverage; 31310 31311function ScriptList(scriptListTable) { 31312 Table.call(this, 'scriptListTable', 31313 recordList('scriptRecord', scriptListTable, function(scriptRecord, i) { 31314 var script = scriptRecord.script; 31315 var defaultLangSys = script.defaultLangSys; 31316 check.assert(!!defaultLangSys, 'Unable to write GSUB: script ' + scriptRecord.tag + ' has no default language system.'); 31317 return [ 31318 {name: 'scriptTag' + i, type: 'TAG', value: scriptRecord.tag}, 31319 {name: 'script' + i, type: 'TABLE', value: new Table('scriptTable', [ 31320 {name: 'defaultLangSys', type: 'TABLE', value: new Table('defaultLangSys', [ 31321 {name: 'lookupOrder', type: 'USHORT', value: 0}, 31322 {name: 'reqFeatureIndex', type: 'USHORT', value: defaultLangSys.reqFeatureIndex}] 31323 .concat(ushortList('featureIndex', defaultLangSys.featureIndexes)))} 31324 ].concat(recordList('langSys', script.langSysRecords, function(langSysRecord, i) { 31325 var langSys = langSysRecord.langSys; 31326 return [ 31327 {name: 'langSysTag' + i, type: 'TAG', value: langSysRecord.tag}, 31328 {name: 'langSys' + i, type: 'TABLE', value: new Table('langSys', [ 31329 {name: 'lookupOrder', type: 'USHORT', value: 0}, 31330 {name: 'reqFeatureIndex', type: 'USHORT', value: langSys.reqFeatureIndex} 31331 ].concat(ushortList('featureIndex', langSys.featureIndexes)))} 31332 ]; 31333 })))} 31334 ]; 31335 }) 31336 ); 31337} 31338ScriptList.prototype = Object.create(Table.prototype); 31339ScriptList.prototype.constructor = ScriptList; 31340 31341/** 31342 * @exports opentype.FeatureList 31343 * @class 31344 * @param {opentype.Table} 31345 * @constructor 31346 * @extends opentype.Table 31347 */ 31348function FeatureList(featureListTable) { 31349 Table.call(this, 'featureListTable', 31350 recordList('featureRecord', featureListTable, function(featureRecord, i) { 31351 var feature = featureRecord.feature; 31352 return [ 31353 {name: 'featureTag' + i, type: 'TAG', value: featureRecord.tag}, 31354 {name: 'feature' + i, type: 'TABLE', value: new Table('featureTable', [
31355 {name: 'featureParams', type: 'USHORT', value: feature.featureParams} ].concat(ushortList('lookupListIndex', feature.lookupListIndexes)))} 31356 ]; 31357 }) 31358 ); 31359} 31360FeatureList.prototype = Object.create(Table.prototype); 31361FeatureList.prototype.constructor = FeatureList; 31362 31363/** 31364 * @exports opentype.LookupList 31365 * @class 31366 * @param {opentype.Table} 31367 * @param {Object} 31368 * @constructor 31369 * @extends opentype.Table 31370 */ 31371function LookupList(lookupListTable, subtableMakers) { 31372 Table.call(this, 'lookupListTable', tableList('lookup', lookupListTable, function(lookupTable) { 31373 var subtableCallback = subtableMakers[lookupTable.lookupType]; 31374 check.assert(!!subtableCallback, 'Unable to write GSUB lookup type ' + lookupTable.lookupType + ' tables.'); 31375 return new Table('lookupTable', [ 31376 {name: 'lookupType', type: 'USHORT', value: lookupTable.lookupType}, 31377 {name: 'lookupFlag', type: 'USHORT', value: lookupTable.lookupFlag} 31378 ].concat(tableList('subtable', lookupTable.subtables, subtableCallback))); 31379 })); 31380} 31381LookupList.prototype = Object.create(Table.prototype); 31382LookupList.prototype.constructor = LookupList; 31383 31384// Record = same as Table, but inlined (a Table has an offset and its data is further in the stream) 31385// Don't use offsets inside Records (probable bug), only in Tables. 31386var table = { 31387 Table: Table, 31388 Record: Table, 31389 Coverage: Coverage, 31390 ScriptList: ScriptList, 31391 FeatureList: FeatureList, 31392 LookupList: LookupList, 31393 ushortList: ushortList, 31394 tableList: tableList, 31395 recordList: recordList, 31396}; 31397 31398// Parsing utility functions 31399 31400// Retrieve an unsigned byte from the DataView. 31401function getByte(dataView, offset) { 31402 return dataView.getUint8(offset); 31403} 31404 31405// Retrieve an unsigned 16-bit short from the DataView. 31406// The value is stored in big endian. 31407function getUShort(dataView, offset) { 31408 return dataView.getUint16(offset, false); 31409} 31410 31411// Retrieve a signed 16-bit short from the DataView. 31412// The value is stored in big endian. 31413function getShort(dataView, offset) { 31414 return dataView.getInt16(offset, false); 31415} 31416 31417// Retrieve an unsigned 32-bit long from the DataView. 31418// The value is stored in big endian. 31419function getULong(dataView, offset) { 31420 return dataView.getUint32(offset, false); 31421} 31422 31423// Retrieve a 32-bit signed fixed-point number (16.16) from the DataView. 31424// The value is stored in big endian. 31425function getFixed(dataView, offset) { 31426 var decimal = dataView.getInt16(offset, false); 31427 var fraction = dataView.getUint16(offset + 2, false); 31428 return decimal + fraction / 65535; 31429} 31430 31431// Retrieve a 4-character tag from the DataView. 31432// Tags are used to identify tables. 31433function getTag(dataView, offset) { 31434 var tag = ''; 31435 for (var i = offset; i < offset + 4; i += 1) { 31436 tag += String.fromCharCode(dataView.getInt8(i)); 31437 } 31438 31439 return tag; 31440} 31441 31442// Retrieve an offset from the DataView. 31443// Offsets are 1 to 4 bytes in length, depending on the offSize argument. 31444function getOffset(dataView, offset, offSize) { 31445 var v = 0; 31446 for (var i = 0; i < offSize; i += 1) { 31447 v <<= 8; 31448 v += dataView.getUint8(offset + i); 31449 } 31450 31451 return v; 31452} 31453 31454// Retrieve a number of bytes from start offset to the end offset from the DataView. 31455function getBytes(dataView, startOffset, endOffset) { 31456 var bytes = []; 31457 for (var i = startOffset; i < endOffset; i += 1) { 31458 bytes.push(dataView.getUint8(i)); 31459 } 31460 31461 return bytes; 31462} 31463 31464// Convert the list of bytes to a string. 31465function bytesToString(bytes) { 31466 var s = ''; 31467 for (var i = 0; i < bytes.length; i += 1) { 31468 s += String.fromCharCode(bytes[i]); 31469 } 31470 31471 return s; 31472} 31473 31474var typeOffsets = { 31475 byte: 1, 31476 uShort: 2, 31477 short: 2, 31478 uLong: 4, 31479 fixed: 4, 31480 longDateTime: 8, 31481 tag: 4 31482}; 31483 31484// A stateful parser that changes the offset whenever a value is retrieved. 31485// The data is a DataView. 31486function Parser(data, offset) { 31487 this.data = data; 31488 this.offset = offset; 31489 this.relativeOffset = 0; 31490} 31491 31492Parser.prototype.parseByte = function() { 31493 var v = this.data.getUint8(this.offset + this.relativeOffset); 31494 this.relativeOffset += 1; 31495 return v; 31496}; 31497 31498Parser.prototype.parseChar = function() { 31499 var v = this.data.getInt8(this.offset + this.relativeOffset); 31500 this.relativeOffset += 1; 31501 return v; 31502}; 31503 31504Parser.prototype.parseCard8 = Parser.prototype.parseByte; 31505 31506Parser.prototype.parseUShort = function() { 31507 var v = this.data.getUint16(this.offset + this.relativeOffset); 31508 this.relativeOffset += 2; 31509 return v; 31510}; 31511 31512Parser.prototype.parseCard16 = Parser.prototype.parseUShort; 31513Parser.prototype.parseSID = Parser.prototype.parseUShort; 31514Parser.prototype.parseOffset16 = Parser.prototype.parseUShort; 31515 31516Parser.prototype.parseShort = function() { 31517 var v = this.data.getInt16(this.offset + this.relativeOffset); 31518 this.relativeOffset += 2; 31519 return v; 31520}; 31521 31522Parser.prototype.parseF2Dot14 = function() { 31523 var v = this.data.getInt16(this.offset + this.relativeOffset) / 16384; 31524 this.relativeOffset += 2; 31525 return v; 31526}; 31527 31528Parser.prototype.parseULong = function() { 31529 var v = getULong(this.data, this.offset + this.relativeOffset); 31530 this.relativeOffset += 4; 31531 return v; 31532}; 31533 31534Parser.prototype.parseFixed = function() { 31535 var v = getFixed(this.data, this.offset + this.relativeOffset); 31536 this.relativeOffset += 4; 31537 return v; 31538}; 31539 31540Parser.prototype.parseString = function(length) { 31541 var dataView = this.data; 31542 var offset = this.offset + this.relativeOffset; 31543 var string = ''; 31544 this.relativeOffset += length; 31545 for (var i = 0; i < length; i++) {
31546 string += String.fromCharCode(dataView.getUint8(offset + i)); 31547 } 31548 31549 return string; 31550}; 31551 31552Parser.prototype.parseTag = function() { 31553 return this.parseString(4); 31554}; 31555 31556// LONGDATETIME is a 64-bit integer. 31557// JavaScript and unix timestamps traditionally use 32 bits, so we 31558// only take the last 32 bits. 31559// + Since until 2038 those bits will be filled by zeros we can ignore them. 31560Parser.prototype.parseLongDateTime = function() { 31561 var v = getULong(this.data, this.offset + this.relativeOffset + 4); 31562 // Subtract seconds between 01/01/1904 and 01/01/1970 31563 // to convert Apple Mac timestamp to Standard Unix timestamp 31564 v -= 2082844800; 31565 this.relativeOffset += 8; 31566 return v; 31567}; 31568 31569Parser.prototype.parseVersion = function() { 31570 var major = getUShort(this.data, this.offset + this.relativeOffset); 31571 31572 // How to interpret the minor version is very vague in the spec. 0x5000 is 5, 0x1000 is 1 31573 // This returns the correct number if minor = 0xN000 where N is 0-9 31574 var minor = getUShort(this.data, this.offset + this.relativeOffset + 2); 31575 this.relativeOffset += 4;
31576 return major + minor / 0x1000 / 10; 31577}; 31578 31579Parser.prototype.skip = function(type, amount) { 31580 if (amount === undefined) { 31581 amount = 1; 31582 } 31583 31584 this.relativeOffset += typeOffsets[type] * amount; 31585}; 31586 31587///// Parsing lists and records /////////////////////////////// 31588 31589// Parse a list of 16 bit unsigned integers. The length of the list can be read on the stream 31590// or provided as an argument. 31591Parser.prototype.parseOffset16List = 31592Parser.prototype.parseUShortList = function(count) { 31593 if (count === undefined) { count = this.parseUShort(); } 31594 var offsets = new Array(count); 31595 var dataView = this.data; 31596 var offset = this.offset + this.relativeOffset; 31597 for (var i = 0; i < count; i++) { 31598 offsets[i] = dataView.getUint16(offset); 31599 offset += 2; 31600 } 31601 31602 this.relativeOffset += count * 2; 31603 return offsets; 31604}; 31605 31606// Parses a list of 16 bit signed integers. 31607Parser.prototype.parseShortList = function(count) { 31608 var list = new Array(count); 31609 var dataView = this.data; 31610 var offset = this.offset + this.relativeOffset; 31611 for (var i = 0; i < count; i++) { 31612 list[i] = dataView.getInt16(offset); 31613 offset += 2; 31614 } 31615 31616 this.relativeOffset += count * 2; 31617 return list; 31618}; 31619 31620// Parses a list of bytes. 31621Parser.prototype.parseByteList = function(count) { 31622 var list = new Array(count); 31623 var dataView = this.data; 31624 var offset = this.offset + this.relativeOffset; 31625 for (var i = 0; i < count; i++) { 31626 list[i] = dataView.getUint8(offset++); 31627 } 31628 31629 this.relativeOffset += count; 31630 return list; 31631}; 31632 31633/** 31634 * Parse a list of items. 31635 * Record count is optional, if omitted it is read from the stream. 31636 * itemCallback is one of the Parser methods. 31637 */ 31638Parser.prototype.parseList = function(count, itemCallback) { 31639 var this$1 = this; 31640 31641 if (!itemCallback) { 31642 itemCallback = count; 31643 count = this.parseUShort(); 31644 } 31645 var list = new Array(count); 31646 for (var i = 0; i < count; i++) { 31647 list[i] = itemCallback.call(this$1); 31648 } 31649 return list; 31650}; 31651 31652/** 31653 * Parse a list of records. 31654 * Record count is optional, if omitted it is read from the stream. 31655 * Example of recordDescription: { sequenceIndex: Parser.uShort, lookupListIndex: Parser.uShort } 31656 */ 31657Parser.prototype.parseRecordList = function(count, recordDescription) { 31658 var this$1 = this; 31659 31660 // If the count argument is absent, read it in the stream. 31661 if (!recordDescription) { 31662 recordDescription = count; 31663 count = this.parseUShort(); 31664 } 31665 var records = new Array(count); 31666 var fields = Object.keys(recordDescription); 31667 for (var i = 0; i < count; i++) { 31668 var rec = {}; 31669 for (var j = 0; j < fields.length; j++) { 31670 var fieldName = fields[j]; 31671 var fieldType = recordDescription[fieldName]; 31672 rec[fieldName] = fieldType.call(this$1); 31673 } 31674 records[i] = rec; 31675 } 31676 return records; 31677}; 31678 31679// Parse a data structure into an object 31680// Example of description: { sequenceIndex: Parser.uShort, lookupListIndex: Parser.uShort } 31681Parser.prototype.parseStruct = function(description) { 31682 var this$1 = this; 31683 31684 if (typeof description === 'function') { 31685 return description.call(this); 31686 } else { 31687 var fields = Object.keys(description); 31688 var struct = {}; 31689 for (var j = 0; j < fields.length; j++) { 31690 var fieldName = fields[j]; 31691 var fieldType = description[fieldName]; 31692 struct[fieldName] = fieldType.call(this$1); 31693 } 31694 return struct; 31695 } 31696}; 31697 31698Parser.prototype.parsePointer = function(description) { 31699 var structOffset = this.parseOffset16(); 31700 if (structOffset > 0) { // NULL offset => return undefined 31701 return new Parser(this.data, this.offset + structOffset).parseStruct(description); 31702 } 31703 return undefined; 31704}; 31705 31706/** 31707 * Parse a list of offsets to lists of 16-bit integers, 31708 * or a list of offsets to lists of offsets to any kind of items. 31709 * If itemCallback is not provided, a list of list of UShort is assumed. 31710 * If provided, itemCallback is called on each item and must parse the item. 31711 * See examples in tables/gsub.js 31712 */ 31713Parser.prototype.parseListOfLists = function(itemCallback) { 31714 var this$1 = this; 31715 31716 var offsets = this.parseOffset16List(); 31717 var count = offsets.length; 31718 var relativeOffset = this.relativeOffset; 31719 var list = new Array(count); 31720 for (var i = 0; i < count; i++) { 31721 var start = offsets[i]; 31722 if (start === 0) { // NULL offset 31723 list[i] = undefined; // Add i as owned property to list. Convenient with assert. 31724 continue; 31725 } 31726 this$1.relativeOffset = start; 31727 if (itemCallback) { 31728 var subOffsets = this$1.parseOffset16List(); 31729 var subList = new Array(subOffsets.length); 31730 for (var j = 0; j < subOffsets.length; j++) { 31731 this$1.relativeOffset = start + subOffsets[j]; 31732 subList[j] = itemCallback.call(this$1); 31733 } 31734 list[i] = subList; 31735 } else { 31736 list[i] = this$1.parseUShortList(); 31737 } 31738 } 31739 this.relativeOffset = relativeOffset; 31740 return list; 31741}; 31742
vendor: 4,374 bytes, lines 31743-31873
31743///// Complex tables parsing ////////////////////////////////// 31744 31745// Parse a coverage table in a GSUB, GPOS or GDEF table. 31746// https://www.microsoft.com/typography/OTSPEC/chapter2.htm 31747// parser.offset must point to the start of the table containing the coverage. 31748Parser.prototype.parseCoverage = function() { 31749 var this$1 = this; 31750 31751 var startOffset = this.offset + this.relativeOffset; 31752 var format = this.parseUShort(); 31753 var count = this.parseUShort(); 31754 if (format === 1) { 31755 return { 31756 format: 1, 31757 glyphs: this.parseUShortList(count) 31758 }; 31759 } else if (format === 2) { 31760 var ranges = new Array(count); 31761 for (var i = 0; i < count; i++) { 31762 ranges[i] = { 31763 start: this$1.parseUShort(), 31764 end: this$1.parseUShort(), 31765 index: this$1.parseUShort() 31766 }; 31767 } 31768 return { 31769 format: 2, 31770 ranges: ranges 31771 }; 31772 } 31773 throw new Error('0x' + startOffset.toString(16) + ': Coverage format must be 1 or 2.'); 31774}; 31775 31776// Parse a Class Definition Table in a GSUB, GPOS or GDEF table. 31777// https://www.microsoft.com/typography/OTSPEC/chapter2.htm 31778Parser.prototype.parseClassDef = function() { 31779 var startOffset = this.offset + this.relativeOffset; 31780 var format = this.parseUShort(); 31781 if (format === 1) { 31782 return { 31783 format: 1, 31784 startGlyph: this.parseUShort(), 31785 classes: this.parseUShortList() 31786 }; 31787 } else if (format === 2) { 31788 return { 31789 format: 2, 31790 ranges: this.parseRecordList({ 31791 start: Parser.uShort, 31792 end: Parser.uShort, 31793 classId: Parser.uShort 31794 }) 31795 }; 31796 } 31797 throw new Error('0x' + startOffset.toString(16) + ': ClassDef format must be 1 or 2.'); 31798}; 31799 31800///// Static methods /////////////////////////////////// 31801// These convenience methods can be used as callbacks and should be called with "this" context set to a Parser instance. 31802 31803Parser.list = function(count, itemCallback) { 31804 return function() { 31805 return this.parseList(count, itemCallback); 31806 }; 31807}; 31808 31809Parser.recordList = function(count, recordDescription) { 31810 return function() { 31811 return this.parseRecordList(count, recordDescription); 31812 }; 31813}; 31814 31815Parser.pointer = function(description) { 31816 return function() { 31817 return this.parsePointer(description); 31818 }; 31819}; 31820 31821Parser.tag = Parser.prototype.parseTag; 31822Parser.byte = Parser.prototype.parseByte; 31823Parser.uShort = Parser.offset16 = Parser.prototype.parseUShort; 31824Parser.uShortList = Parser.prototype.parseUShortList; 31825Parser.struct = Parser.prototype.parseStruct; 31826Parser.coverage = Parser.prototype.parseCoverage; 31827Parser.classDef = Parser.prototype.parseClassDef; 31828 31829///// Script, Feature, Lookup lists /////////////////////////////////////////////// 31830// https://www.microsoft.com/typography/OTSPEC/chapter2.htm 31831 31832var langSysTable = { 31833 reserved: Parser.uShort, 31834 reqFeatureIndex: Parser.uShort, 31835 featureIndexes: Parser.uShortList 31836}; 31837 31838Parser.prototype.parseScriptList = function() { 31839 return this.parsePointer(Parser.recordList({ 31840 tag: Parser.tag, 31841 script: Parser.pointer({ 31842 defaultLangSys: Parser.pointer(langSysTable), 31843 langSysRecords: Parser.recordList({ 31844 tag: Parser.tag, 31845 langSys: Parser.pointer(langSysTable) 31846 }) 31847 }) 31848 })); 31849}; 31850 31851Parser.prototype.parseFeatureList = function() { 31852 return this.parsePointer(Parser.recordList({ 31853 tag: Parser.tag, 31854 feature: Parser.pointer({ 31855 featureParams: Parser.offset16, 31856 lookupListIndexes: Parser.uShortList 31857 }) 31858 })); 31859}; 31860 31861Parser.prototype.parseLookupList = function(lookupTableParsers) { 31862 return this.parsePointer(Parser.list(Parser.pointer(function() { 31863 var lookupType = this.parseUShort(); 31864 check.argument(1 <= lookupType && lookupType <= 8, 'GSUB lookup type ' + lookupType + ' unknown.'); 31865 var lookupFlag = this.parseUShort(); 31866 var useMarkFilteringSet = lookupFlag & 0x10; 31867 return { 31868 lookupType: lookupType, 31869 lookupFlag: lookupFlag, 31870 subtables: this.parseList(Parser.pointer(lookupTableParsers[lookupType])), 31871 markFilteringSet: useMarkFilteringSet ? this.parseUShort() : undefined 31872 }; 31873 }
31873))); 31874}; 31875 31876var parse = { 31877 getByte: getByte, 31878 getCard8: getByte, 31879 getUShort: getUShort, 31880 getCard16: getUShort, 31881 getShort: getShort, 31882 getULong: getULong, 31883 getFixed: getFixed, 31884 getTag: getTag, 31885 getOffset: getOffset, 31886 getBytes: getBytes, 31887 bytesToString: bytesToString, 31888 Parser: Parser, 31889}; 31890 31891// The `cmap` table stores the mappings from characters to glyphs. 31892// https://www.microsoft.com/typography/OTSPEC/cmap.htm 31893 31894function parseCmapTableFormat12(cmap, p) { 31895 //Skip reserved. 31896 p.parseUShort(); 31897 31898 // Length in bytes of the sub-tables. 31899 cmap.length = p.parseULong(); 31900 cmap.language = p.parseULong(); 31901 31902 var groupCount; 31903 cmap.groupCount = groupCount = p.parseULong(); 31904 cmap.glyphIndexMap = {}; 31905 31906 for (var i = 0; i < groupCount; i += 1) { 31907 var startCharCode = p.parseULong(); 31908 var endCharCode = p.parseULong(); 31909 var startGlyphId = p.parseULong(); 31910 31911 for (var c = startCharCode; c <= endCharCode; c += 1) { 31912 cmap.glyphIndexMap[c] = startGlyphId; 31913 startGlyphId++; 31914 } 31915 } 31916} 31917 31918function parseCmapTableFormat4(cmap, p, data, start, offset) { 31919 // Length in bytes of the sub-tables. 31920 cmap.length = p.parseUShort(); 31921 cmap.language = p.parseUShort(); 31922 31923 // segCount is stored x 2. 31924 var segCount; 31925 cmap.segCount = segCount = p.parseUShort() >> 1; 31926 31927 // Skip searchRange, entrySelector, rangeShift. 31928 p.skip('uShort', 3); 31929 31930 // The "unrolled" mapping from character codes to glyph indices. 31931 cmap.glyphIndexMap = {}; 31932 var endCountParser = new parse.Parser(data, start + offset + 14); 31933 var startCountParser = new parse.Parser(data, start + offset + 16 + segCount * 2); 31934 var idDeltaParser = new parse.Parser(data, start + offset + 16 + segCount * 4); 31935 var idRangeOffsetParser = new parse.Parser(data, start + offset + 16 + segCount * 6); 31936 var glyphIndexOffset = start + offset + 16 + segCount * 8; 31937 for (var i = 0; i < segCount - 1; i += 1) { 31938 var glyphIndex = (void 0); 31939 var endCount = endCountParser.parseUShort(); 31940 var startCount = startCountParser.parseUShort(); 31941 var idDelta = idDeltaParser.parseShort(); 31942 var idRangeOffset = idRangeOffsetParser.parseUShort(); 31943 for (var c = startCount; c <= endCount; c += 1) { 31944 if (idRangeOffset !== 0) { 31945 // The idRangeOffset is relative to the current position in the idRangeOffset array. 31946 // Take the current offset in the idRangeOffset array. 31947 glyphIndexOffset = (idRangeOffsetParser.offset + idRangeOffsetParser.relativeOffset - 2); 31948 31949 // Add the value of the idRangeOffset, which will move us into the glyphIndex array. 31950 glyphIndexOffset += idRangeOffset; 31951 31952 // Then add the character index of the current segment, multiplied by 2 for USHORTs. 31953 glyphIndexOffset += (c - startCount) * 2; 31954 glyphIndex = parse.getUShort(data, glyphIndexOffset); 31955 if (glyphIndex !== 0) { 31956 glyphIndex = (glyphIndex + idDelta) & 0xFFFF; 31957 } 31958 } else { 31959 glyphIndex = (c + idDelta) & 0xFFFF; 31960 } 31961 31962 cmap.glyphIndexMap[c] = glyphIndex; 31963 } 31964 } 31965} 31966 31967// Parse the `cmap` table. This table stores the mappings from characters to glyphs. 31968// There are many available formats, but we only support the Windows format 4 and 12. 31969// This function returns a `CmapEncoding` object or null if no supported format could be found. 31970function parseCmapTable(data, start) { 31971 var cmap = {}; 31972 cmap.version = parse.getUShort(data, start); 31973 check.argument(cmap.version === 0, 'cmap table version should be 0.'); 31974 31975 // The cmap table can contain many sub-tables, each with their own format. 31976 // We're only interested in a "platform 3" table. This is a Windows format. 31977 cmap.numTables = parse.getUShort(data, start + 2); 31978 var offset = -1; 31979 for (var i = cmap.numTables - 1; i >= 0; i -= 1) { 31980 var platformId = parse.getUShort(data, start + 4 + (i * 8)); 31981 var encodingId = parse.getUShort(data, start + 4 + (i * 8) + 2); 31982 if (platformId === 3 && (encodingId === 0 || encodingId === 1 || encodingId === 10)) { 31983 offset = parse.getULong(data, start + 4 + (i * 8) + 4); 31984 break; 31985 } 31986 } 31987 31988 if (offset === -1) { 31989 // There is no cmap table in the font that we support. 31990 throw new Error('No valid cmap sub-tables found.'); 31991 } 31992 31993 var p = new parse.Parser(data, start + offset); 31994 cmap.format = p.parseUShort(); 31995 31996 if (cmap.format === 12) { 31997 parseCmapTableFormat12(cmap, p); 31998 } else if (cmap.format === 4) { 31999 parseCmapTableFormat4(cmap, p, data, start, offset); 32000 } else { 32001 throw new Error('Only format 4 and 12 cmap tables are supported (found format ' + cmap.format + ').'); 32002 } 32003 32004 return cmap; 32005} 32006 32007function addSegment(t, code, glyphIndex) { 32008 t.segments.push({ 32009 end: code, 32010 start: code, 32011 delta: -(code - glyphIndex), 32012 offset: 0 32013 }); 32014} 32015 32016function addTerminatorSegment(t) { 32017 t.segments.push({ 32018 end: 0xFFFF, 32019 start: 0xFFFF, 32020 delta: 1, 32021 offset: 0 32022 }); 32023} 32024 32025function makeCmapTable(glyphs) { 32026 var t = new table.Table('cmap', [ 32027 {name: 'version', type: 'USHORT', value: 0}, 32028 {name: 'numTables', type: 'USHORT', value: 1}, 32029 {name: 'platformID', type: 'USHORT', value: 3}, 32030 {name: 'encodingID', type: 'USHORT', value: 1}, 32031 {name: 'offset', type: 'ULONG', value: 12}, 32032 {name: 'format', type: 'USHORT', value: 4}, 32033 {name: 'length', type: 'USHORT', value: 0}, 32034 {name: 'language', type: 'USHORT', value: 0}, 32035 {name: 'segCountX2', type: 'USHORT', value: 0},
32036 {name: 'searchRange', type: 'USHORT', value: 0}, 32037 {name: 'entrySelector', type: 'USHORT', value: 0}, 32038 {name: 'rangeShift', type: 'USHORT', value: 0} 32039 ]); 32040 32041 t.segments = []; 32042 for (var i = 0; i < glyphs.length; i += 1) { 32043 var glyph = glyphs.get(i); 32044 for (var j = 0; j < glyph.unicodes.length; j += 1) { 32045 addSegment(t, glyph.unicodes[j], i); 32046 } 32047 32048 t.segments = t.segments.sort(function(a, b) { 32049 return a.start - b.start; 32050 }); 32051 } 32052 32053 addTerminatorSegment(t); 32054 32055 var segCount; 32056 segCount = t.segments.length; 32057 t.segCountX2 = segCount * 2; 32058 t.searchRange = Math.pow(2, Math.floor(Math.log(segCount) / Math.log(2))) * 2; 32059 t.entrySelector = Math.log(t.searchRange / 2) / Math.log(2); 32060 t.rangeShift = t.segCountX2 - t.searchRange; 32061 32062 // Set up parallel segment arrays. 32063 var endCounts = []; 32064 var startCounts = []; 32065 var idDeltas = []; 32066 var idRangeOffsets = []; 32067 var glyphIds = []; 32068 32069 for (var i$1 = 0; i$1 < segCount; i$1 += 1) { 32070 var segment = t.segments[i$1]; 32071 endCounts = endCounts.concat({name: 'end_' + i$1, type: 'USHORT', value: segment.end}); 32072 startCounts = startCounts.concat({name: 'start_' + i$1, type: 'USHORT', value: segment.start}); 32073 idDeltas = idDeltas.concat({name: 'idDelta_' + i$1, type: 'SHORT', value: segment.delta}); 32074 idRangeOffsets = idRangeOffsets.concat({name: 'idRangeOffset_' + i$1, type: 'USHORT', value: segment.offset}); 32075 if (segment.glyphId !== undefined) { 32076 glyphIds = glyphIds.concat({name: 'glyph_' + i$1, type: 'USHORT', value: segment.glyphId}); 32077 } 32078 } 32079 32080 t.fields = t.fields.concat(endCounts); 32081 t.fields.push({name: 'reservedPad', type: 'USHORT', value: 0}); 32082 t.fields = t.fields.concat(startCounts); 32083 t.fields = t.fields.concat(idDeltas); 32084 t.fields = t.fields.concat(idRangeOffsets); 32085 t.fields = t.fields.concat(glyphIds); 32086 32087 t.length = 14 + // Subtable header 32088 endCounts.length * 2 + 32089 2 + // reservedPad 32090 startCounts.length * 2 + 32091 idDeltas.length * 2 + 32092 idRangeOffsets.length * 2 + 32093 glyphIds.length * 2; 32094 32095 return t; 32096} 32097 32098var cmap = { parse: parseCmapTable, make: makeCmapTable }; 32099 32100// Glyph encoding 32101 32102var cffStandardStrings = [ 32103 '.notdef', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', 'ampersand', 'quoteright', 32104 'parenleft', 'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 32105 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less', 'equal', 'greater', 32106 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 32107 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore', 32108 'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 32109 'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', 'exclamdown', 'cent', 'sterling', 32110 'fraction', 'yen', 'florin', 'section', 'currency', 'quotesingle', 'quotedblleft', 'guillemotleft', 32111 'guilsinglleft', 'guilsinglright', 'fi', 'fl', 'endash', 'dagger', 'daggerdbl', 'periodcentered', 'paragraph', 32112 'bullet', 'quotesinglbase', 'quotedblbase', 'quotedblright', 'guillemotright', 'ellipsis', 'perthousand', 32113 'questiondown', 'grave', 'acute', 'circumflex', 'tilde', 'macron', 'breve', 'dotaccent', 'dieresis', 'ring', 32114 'cedilla', 'hungarumlaut', 'ogonek', 'caron', 'emdash', 'AE', 'ordfeminine', 'Lslash', 'Oslash', 'OE', 32115 'ordmasculine', 'ae', 'dotlessi', 'lslash', 'oslash', 'oe', 'germandbls', 'onesuperior', 'logicalnot', 'mu', 32116 'trademark', 'Eth', 'onehalf', 'plusminus', 'Thorn', 'onequarter', 'divide', 'brokenbar', 'degree', 'thorn', 32117 'threequarters', 'twosuperior', 'registered', 'minus', 'eth', 'multiply', 'threesuperior', 'copyright', 32118 'Aacute', 'Acircumflex', 'Adieresis', 'Agrave', 'Aring', 'Atilde', 'Ccedilla', 'Eacute', 'Ecircumflex', 32119 'Edieresis', 'Egrave', 'Iacute', 'Icircumflex', 'Idieresis', 'Igrave', 'Ntilde', 'Oacute', 'Ocircumflex', 32120 'Odieresis', 'Ograve', 'Otilde', 'Scaron', 'Uacute', 'Ucircumflex', 'Udieresis', 'Ugrave', 'Yacute', 32121 'Ydieresis', 'Zcaron', 'aacute', 'acircumflex', 'adieresis', 'agrave', 'aring', 'atilde', 'ccedilla', 'eacute', 32122 'ecircumflex', 'edieresis', 'egrave', 'iacute', 'icircumflex', 'idieresis', 'igrave', 'ntilde', 'oacute', 32123 'ocircumflex', 'odieresis', 'ograve', 'otilde', 'scaron', 'uacute', 'ucircumflex', 'udieresis', 'ugrave', 32124 'yacute', 'ydieresis', 'zcaron', 'exclamsmall', 'Hungarumlautsmall', 'dollaroldstyle', 'dollarsuperior', 32125 'ampersandsmall', 'Acutesmall', 'parenleftsuperior', 'parenrightsuperior', '266 ff', 'onedotenleader', 32126 'zerooldstyle', 'oneoldstyle', 'twooldstyle', 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle', 'sixoldstyle', 32127 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'commasuperior', 'threequartersemdash', 'periodsuperior', 32128 'questionsmall', 'asuperior', 'bsuperior', 'centsuperior', 'dsuperior', 'esuperior', 'isuperior', 'lsuperior', 32129 'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior', 'tsuperior', 'ff', 'ffi', 'ffl', 32130 'parenleftinferior', 'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall', 'Asmall', 32131 'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall', 32132 'Msmall', 'Nsmall', 'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall', 32133 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah', 'Tildesmall', 'exclamdownsmall', 32134 'centoldstyle', 'Lslashsmall', 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall', 'Brevesmall', 'Caronsmall', 32135 'Dotaccentsmall', 'Macronsmall', 'figuredash', 'hypheninferior', 'Ogoneksmall', 'Ringsmall', 'Cedillasmall', 32136 'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths', 'seveneighths', 'onethird', 'twothirds', 32137 'zerosuperior', 'foursuperior', 'fivesuperior', 'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior', 32138 'zeroinferior', 'oneinferior', 'twoinferior', 'threeinferior', 'fourinferior', 'fiveinferior', 'sixinferior', 32139 'seveninferior', 'eightinferior', 'nineinferior', 'centinferior', 'dollarinferior', 'periodinferior', 32140 'commainferior', 'Agravesmall', 'Aacutesmall', 'Acircumflexsmall', 'Atildesmall', 'Adieresissmall', 32141 'Aringsmall', 'AEsmall', 'Ccedillasmall', 'Egravesmall', 'Eacutesmall', 'Ecircumflexsmall', 'Edieresissmall', 32142 'Igravesmall', 'Iacutesmall', 'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall', 'Ogravesmall', 32143 'Oacutesmall', 'Ocircumflexsmall', 'Otildesmall', 'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall', 32144 'Uacutesmall', 'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall', 'Ydieresissmall', '001.000', 32145 '001.001', '001.002', '001.003', 'Black', 'Bold', 'Book', 'Light', 'Medium', 'Regular', 'Roman', 'Semibold']; 32146 32147var cffStandardEncoding = [ 32148 '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 32149 '', '', '', '', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', 'ampersand', 'quoteright', 32150 'parenleft', 'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 32151 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less', 'equal', 'greater', 32152 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 32153 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore', 32154 'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 32155 'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', '', '', '', '', '', '', '', '', 32156 '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 32157 'exclamdown', 'cent', 'sterling', 'fraction', 'yen', 'florin', 'section', 'currency', 'quotesingle', 32158 'quotedblleft', 'guillemotleft', 'guilsinglleft', 'guilsinglright', 'fi', 'fl', '', 'endash', 'dagger',
32159 'daggerdbl', 'periodcentered', '', 'paragraph', 'bullet', 'quotesinglbase', 'quotedblbase', 'quotedblright', 32160 'guillemotright', 'ellipsis', 'perthousand', '', 'questiondown', '', 'grave', 'acute', 'circumflex', 'tilde', 32161 'macron', 'breve', 'dotaccent', 'dieresis', '', 'ring', 'cedilla', '', 'hungarumlaut', 'ogonek', 'caron', 32162 'emdash', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'AE', '', 'ordfeminine', '', '', '', 32163 '', 'Lslash', 'Oslash', 'OE', 'ordmasculine', '', '', '', '', '', 'ae', '', '', '', 'dotlessi', '', '', 32164 'lslash', 'oslash', 'oe', 'germandbls']; 32165 32166var cffExpertEncoding = [ 32167 '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 32168 '', '', '', '', 'space', 'exclamsmall', 'Hungarumlautsmall', '', 'dollaroldstyle', 'dollarsuperior', 32169 'ampersandsmall', 'Acutesmall', 'parenleftsuperior', 'parenrightsuperior', 'twodotenleader', 'onedotenleader', 32170 'comma', 'hyphen', 'period', 'fraction', 'zerooldstyle', 'oneoldstyle', 'twooldstyle', 'threeoldstyle', 32171 'fouroldstyle', 'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'colon', 32172 'semicolon', 'commasuperior', 'threequartersemdash', 'periodsuperior', 'questionsmall', '', 'asuperior', 32173 'bsuperior', 'centsuperior', 'dsuperior', 'esuperior', '', '', 'isuperior', '', '', 'lsuperior', 'msuperior', 32174 'nsuperior', 'osuperior', '', '', 'rsuperior', 'ssuperior', 'tsuperior', '', 'ff', 'fi', 'fl', 'ffi', 'ffl', 32175 'parenleftinferior', '', 'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall', 'Asmall', 32176 'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall', 32177 'Msmall', 'Nsmall', 'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall', 32178 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah', 'Tildesmall', '', '', '', '', '', '', '', 32179 '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 32180 'exclamdownsmall', 'centoldstyle', 'Lslashsmall', '', '', 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall', 32181 'Brevesmall', 'Caronsmall', '', 'Dotaccentsmall', '', '', 'Macronsmall', '', '', 'figuredash', 'hypheninferior', 32182 '', '', 'Ogoneksmall', 'Ringsmall', 'Cedillasmall', '', '', '', 'onequarter', 'onehalf', 'threequarters', 32183 'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths', 'seveneighths', 'onethird', 'twothirds', '', 32184 '', 'zerosuperior', 'onesuperior', 'twosuperior', 'threesuperior', 'foursuperior', 'fivesuperior', 32185 'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior', 'zeroinferior', 'oneinferior', 'twoinferior', 32186 'threeinferior', 'fourinferior', 'fiveinferior', 'sixinferior', 'seveninferior', 'eightinferior', 32187 'nineinferior', 'centinferior', 'dollarinferior', 'periodinferior', 'commainferior', 'Agravesmall', 32188 'Aacutesmall', 'Acircumflexsmall', 'Atildesmall', 'Adieresissmall', 'Aringsmall', 'AEsmall', 'Ccedillasmall', 32189 'Egravesmall', 'Eacutesmall', 'Ecircumflexsmall', 'Edieresissmall', 'Igravesmall', 'Iacutesmall', 32190 'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall', 'Ogravesmall', 'Oacutesmall', 32191 'Ocircumflexsmall', 'Otildesmall', 'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall', 'Uacutesmall', 32192 'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall', 'Ydieresissmall']; 32193 32194var standardNames = [ 32195 '.notdef', '.null', 'nonmarkingreturn', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', 32196 'ampersand', 'quotesingle', 'parenleft', 'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', 32197 'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less', 32198 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 32199 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', 32200 'asciicircum', 'underscore', 'grave', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 32201 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', 32202 'Adieresis', 'Aring', 'Ccedilla', 'Eacute', 'Ntilde', 'Odieresis', 'Udieresis', 'aacute', 'agrave', 32203 'acircumflex', 'adieresis', 'atilde', 'aring', 'ccedilla', 'eacute', 'egrave', 'ecircumflex', 'edieresis', 32204 'iacute', 'igrave', 'icircumflex', 'idieresis', 'ntilde', 'oacute', 'ograve', 'ocircumflex', 'odieresis', 32205 'otilde', 'uacute', 'ugrave', 'ucircumflex', 'udieresis', 'dagger', 'degree', 'cent', 'sterling', 'section', 32206 'bullet', 'paragraph', 'germandbls', 'registered', 'copyright', 'trademark', 'acute', 'dieresis', 'notequal', 32207 'AE', 'Oslash', 'infinity', 'plusminus', 'lessequal', 'greaterequal', 'yen', 'mu', 'partialdiff', 'summation', 32208 'product', 'pi', 'integral', 'ordfeminine', 'ordmasculine', 'Omega', 'ae', 'oslash', 'questiondown', 32209 'exclamdown', 'logicalnot', 'radical', 'florin', 'approxequal', 'Delta', 'guillemotleft', 'guillemotright', 32210 'ellipsis', 'nonbreakingspace', 'Agrave', 'Atilde', 'Otilde', 'OE', 'oe', 'endash', 'emdash', 'quotedblleft', 32211 'quotedblright', 'quoteleft', 'quoteright', 'divide', 'lozenge', 'ydieresis', 'Ydieresis', 'fraction', 32212 'currency', 'guilsinglleft', 'guilsinglright', 'fi', 'fl', 'daggerdbl', 'periodce
32212ntered', 'quotesinglbase', 32213 'quotedblbase', 'perthousand', 'Acircumflex', 'Ecircumflex', 'Aacute', 'Edieresis', 'Egrave', 'Iacute', 32214 'Icircumflex', 'Idieresis', 'Igrave', 'Oacute', 'Ocircumflex', 'apple', 'Ograve', 'Uacute', 'Ucircumflex', 32215 'Ugrave', 'dotlessi', 'circumflex', 'tilde', 'macron', 'breve', 'dotaccent', 'ring', 'cedilla', 'hungarumlaut', 32216 'ogonek', 'caron', 'Lslash', 'lslash', 'Scaron', 'scaron', 'Zcaron', 'zcaron', 'brokenbar', 'Eth', 'eth', 32217 'Yacute', 'yacute', 'Thorn', 'thorn', 'minus', 'multiply', 'onesuperior', 'twosuperior', 'threesuperior', 32218 'onehalf', 'onequarter', 'threequarters', 'franc', 'Gbreve', 'gbreve', 'Idotaccent', 'Scedilla', 'scedilla', 32219 'Cacute', 'cacute', 'Ccaron', 'ccaron', 'dcroat']; 32220 32221/** 32222 * This is the encoding used for fonts created from scratch. 32223 * It loops through all glyphs and finds the appropriate unicode value. 32224 * Since it's linear time, other encodings will be faster. 32225 * @exports opentype.DefaultEncoding 32226 * @class 32227 * @constructor 32228 * @param {opentype.Font} 32229 */ 32230function DefaultEncoding(font) { 32231 this.font = font; 32232} 32233 32234DefaultEncoding.prototype.charToGlyphIndex = function(c) { 32235 var code = c.charCodeAt(0); 32236 var glyphs = this.font.glyphs; 32237 if (glyphs) { 32238 for (var i = 0; i < glyphs.length; i += 1) { 32239 var glyph = glyphs.get(i); 32240 for (var j = 0; j < glyph.unicodes.length; j += 1) { 32241 if (glyph.unicodes[j] === code) { 32242 return i; 32243 } 32244 } 32245 } 32246 } 32247 return null; 32248}; 32249 32250/** 32251 * @exports opentype.CmapEncoding 32252 * @class 32253 * @constructor 32254 * @param {Object} cmap - a object with the cmap encoded data 32255 */ 32256function CmapEncoding(cmap) { 32257 this.cmap = cmap; 32258} 32259 32260/** 32261 * @param {string} c - the character 32262 * @return {number} The glyph index. 32263 */ 32264CmapEncoding.prototype.charToGlyphIndex = function(c) { 32265 return this.cmap.glyphIndexMap[c.charCodeAt(0)] || 0; 32266}; 32267 32268/** 32269 * @exports opentype.CffEncoding 32270 * @class 32271 * @constructor 32272 * @param {string} encoding - The encoding 32273 * @param {Array} charset - The character set. 32274 */ 32275function CffEncoding(encoding, charset) { 32276 this.encoding = encoding; 32277 this.charset = charset; 32278} 32279 32280/** 32281 * @param {string} s - The character 32282 * @return {number} The index. 32283 */ 32284CffEncoding.prototype.charToGlyphIndex = function(s) { 32285 var code = s.charCodeAt(0); 32286 var charName = this.encoding[code]; 32287 return this.charset.indexOf(charName); 32288}; 32289 32290/** 32291 * @exports opentype.GlyphNames 32292 * @class 32293 * @constructor 32294 * @param {Object} post 32295 */ 32296function GlyphNames(post) { 32297 var this$1 = this; 32298 32299 switch (post.version) { 32300 case 1: 32301 this.names = standardNames.slice(); 32302 break; 32303 case 2: 32304 this.names = new Array(post.numberOfGlyphs); 32305 for (var i = 0; i < post.numberOfGlyphs; i++) { 32306 if (post.glyphNameIndex[i] < standardNames.length) { 32307 this$1.names[i] = standardNames[post.glyphNameIndex[i]]; 32308 } else { 32309 this$1.names[i] = post.names[post.glyphNameIndex[i] - standardNames.length]; 32310 } 32311 } 32312 32313 break; 32314 case 2.5: 32315 this.names = new Array(post.numberOfGlyphs); 32316 for (var i$1 = 0; i$1 < post.numberOfGlyphs; i$1++) { 32317 this$1.names[i$1] = standardNames[i$1 + post.glyphNameIndex[i$1]]; 32318 } 32319 32320 break; 32321 case 3: 32322 this.names = []; 32323 break; 32324 default: 32325 this.names = []; 32326 break; 32327 } 32328} 32329 32330/** 32331 * Gets the index of a glyph by name. 32332 * @param {string} name - The glyph name 32333 * @return {number} The index 32334 */ 32335GlyphNames.prototype.nameToGlyphIndex = function(name) { 32336 return this.names.indexOf(name); 32337}; 32338 32339/** 32340 * @param {number} gid 32341 * @return {string} 32342 */ 32343GlyphNames.prototype.glyphIndexToName = function(gid) { 32344 return this.names[gid]; 32345}; 32346 32347/** 32348 * @alias opentype.addGlyphNames 32349 * @param {opentype.Font} 32350 */ 32351function addGlyphNames(font) { 32352 var glyph; 32353 var glyphIndexMap = font.tables.cmap.glyphIndexMap; 32354 var charCodes = Object.keys(glyphIndexMap); 32355 32356 for (var i = 0; i < charCodes.length; i += 1) { 32357 var c = charCodes[i]; 32358 var glyphIndex = glyphIndexMap[c]; 32359 glyph = font.glyphs.get(glyphIndex); 32360 glyph.addUnicode(parseInt(c)); 32361 } 32362 32363 for (var i$1 = 0; i$1 < font.glyphs.length; i$1 += 1) {
vendor: 11,569 bytes, lines 32364-32696
32364 glyph = font.glyphs.get(i$1); 32365 if (font.cffEncoding) { 32366 if (font.isCIDFont) { 32367 glyph.name = 'gid' + i$1; 32368 } else { 32369 glyph.name = font.cffEncoding.charset[i$1]; 32370 } 32371 } else if (font.glyphNames.names) { 32372 glyph.name = font.glyphNames.glyphIndexToName(i$1); 32373 } 32374 } 32375} 32376 32377// Drawing utility functions. 32378 32379// Draw a line on the given context from point `x1,y1` to point `x2,y2`. 32380function line(ctx, x1, y1, x2, y2) { 32381 ctx.beginPath(); 32382 ctx.moveTo(x1, y1); 32383 ctx.lineTo(x2, y2); 32384 ctx.stroke(); 32385} 32386 32387var draw = { line: line }; 32388 32389// The `glyf` table describes the glyphs in TrueType outline format. 32390// http://www.microsoft.com/typography/otspec/glyf.htm 32391 32392// Parse the coordinate data for a glyph. 32393function parseGlyphCoordinate(p, flag, previousValue, shortVectorBitMask, sameBitMask) { 32394 var v; 32395 if ((flag & shortVectorBitMask) > 0) { 32396 // The coordinate is 1 byte long. 32397 v = p.parseByte(); 32398 // The `same` bit is re-used for short values to signify the sign of the value. 32399 if ((flag & sameBitMask) === 0) { 32400 v = -v; 32401 } 32402 32403 v = previousValue + v; 32404 } else { 32405 // The coordinate is 2 bytes long. 32406 // If the `same` bit is set, the coordinate is the same as the previous coordinate. 32407 if ((flag & sameBitMask) > 0) { 32408 v = previousValue; 32409 } else { 32410 // Parse the coordinate as a signed 16-bit delta value. 32411 v = previousValue + p.parseShort(); 32412 } 32413 } 32414 32415 return v; 32416} 32417 32418// Parse a TrueType glyph. 32419function parseGlyph(glyph, data, start) { 32420 var p = new parse.Parser(data, start); 32421 glyph.numberOfContours = p.parseShort(); 32422 glyph._xMin = p.parseShort(); 32423 glyph._yMin = p.parseShort(); 32424 glyph._xMax = p.parseShort(); 32425 glyph._yMax = p.parseShort(); 32426 var flags; 32427 var flag; 32428 32429 if (glyph.numberOfContours > 0) { 32430 // This glyph is not a composite. 32431 var endPointIndices = glyph.endPointIndices = []; 32432 for (var i = 0; i < glyph.numberOfContours; i += 1) { 32433 endPointIndices.push(p.parseUShort()); 32434 } 32435 32436 glyph.instructionLength = p.parseUShort(); 32437 glyph.instructions = []; 32438 for (var i$1 = 0; i$1 < glyph.instructionLength; i$1 += 1) { 32439 glyph.instructions.push(p.parseByte()); 32440 } 32441 32442 var numberOfCoordinates = endPointIndices[endPointIndices.length - 1] + 1; 32443 flags = []; 32444 for (var i$2 = 0; i$2 < numberOfCoordinates; i$2 += 1) { 32445 flag = p.parseByte(); 32446 flags.push(flag); 32447 // If bit 3 is set, we repeat this flag n times, where n is the next byte. 32448 if ((flag & 8) > 0) { 32449 var repeatCount = p.parseByte(); 32450 for (var j = 0; j < repeatCount; j += 1) { 32451 flags.push(flag); 32452 i$2 += 1; 32453 } 32454 } 32455 } 32456 32457 check.argument(flags.length === numberOfCoordinates, 'Bad flags.'); 32458 32459 if (endPointIndices.length > 0) { 32460 var points = []; 32461 var point; 32462 // X/Y coordinates are relative to the previous point, except for the first point which is relative to 0,0. 32463 if (numberOfCoordinates > 0) { 32464 for (var i$3 = 0; i$3 < numberOfCoordinates; i$3 += 1) { 32465 flag = flags[i$3]; 32466 point = {}; 32467 point.onCurve = !!(flag & 1); 32468 point.lastPointOfContour = endPointIndices.indexOf(i$3) >= 0; 32469 points.push(point); 32470 } 32471 32472 var px = 0; 32473 for (var i$4 = 0; i$4 < numberOfCoordinates; i$4 += 1) { 32474 flag = flags[i$4]; 32475 point = points[i$4]; 32476 point.x = parseGlyphCoordinate(p, flag, px, 2, 16); 32477 px = point.x; 32478 } 32479 32480 var py = 0; 32481 for (var i$5 = 0; i$5 < numberOfCoordinates; i$5 += 1) { 32482 flag = flags[i$5]; 32483 point = points[i$5]; 32484 point.y = parseGlyphCoordinate(p, flag, py, 4, 32); 32485 py = point.y; 32486 } 32487 } 32488 32489 glyph.points = points; 32490 } else { 32491 glyph.points = []; 32492 } 32493 } else if (glyph.numberOfContours === 0) { 32494 glyph.points = []; 32495 } else { 32496 glyph.isComposite = true; 32497 glyph.points = []; 32498 glyph.components = []; 32499 var moreComponents = true; 32500 while (moreComponents) { 32501 flags = p.parseUShort(); 32502 var component = { 32503 glyphIndex: p.parseUShort(), 32504 xScale: 1, 32505 scale01: 0, 32506 scale10: 0, 32507 yScale: 1, 32508 dx: 0, 32509 dy: 0 32510 }; 32511 if ((flags & 1) > 0) { 32512 // The arguments are words 32513 if ((flags & 2) > 0) { 32514 // values are offset 32515 component.dx = p.parseShort(); 32516 component.dy = p.parseShort(); 32517 } else { 32518 // values are matched points 32519 component.matchedPoints = [p.parseUShort(), p.parseUShort()]; 32520 } 32521 32522 } else { 32523 // The arguments are bytes 32524 if ((flags & 2) > 0) { 32525 // values are offset 32526 component.dx = p.parseChar(); 32527 component.dy = p.parseChar(); 32528 } else { 32529 // values are matched points 32530 component.matchedPoints = [p.parseByte(), p.parseByte()]; 32531 } 32532 } 32533 32534 if ((flags & 8) > 0) { 32535 // We have a scale 32536 component.xScale = component.yScale = p.parseF2Dot14(); 32537 } else if ((flags & 64) > 0) { 32538 // We have an X / Y scale 32539 component.xScale = p.parseF2Dot14(); 32540 component.yScale = p.parseF2Dot14(); 32541 } else if ((flags & 128) > 0) { 32542 // We have a 2x2 transformation 32543 component.xScale = p.parseF2Dot14(); 32544 component.scale01 = p.parseF2Dot14(); 32545 component.scale10 = p.parseF2Dot14(); 32546 component.yScale = p.parseF2Dot14(); 32547 } 32548 32549 glyph.components.push(component); 32550 moreComponents = !!(flags & 32); 32551 } 32552 if (flags & 0x100) { 32553 // We have instructions 32554 glyph.instructionLength = p.parseUShort(); 32555 glyph.instructions = []; 32556 for (var i$6 = 0; i$6 < glyph.instructionLength; i$6 += 1) { 32557 glyph.instructions.push(p.parseByte()); 32558 } 32559 } 32560 } 32561} 32562 32563// Transform an array of points and return a new array. 32564function transformPoints(points, transform) { 32565 var newPoints = []; 32566 for (var i = 0; i < points.length; i += 1) { 32567 var pt = points[i]; 32568 var newPt = { 32569 x: transform.xScale * pt.x + transform.scale01 * pt.y + transform.dx, 32570 y: transform.scale10 * pt.x + transform.yScale * pt.y + transform.dy, 32571 onCurve: pt.onCurve, 32572 lastPointOfContour: pt.lastPointOfContour 32573 }; 32574 newPoints.push(newPt); 32575 } 32576 32577 return newPoints; 32578} 32579 32580function getContours(points) { 32581 var contours = []; 32582 var currentContour = []; 32583 for (var i = 0; i < points.length; i += 1) { 32584 var pt = points[i]; 32585 currentContour.push(pt); 32586 if (pt.lastPointOfContour) { 32587 contours.push(currentContour); 32588 currentContour = []; 32589 } 32590 } 32591 32592 check.argument(currentContour.length === 0, 'There are still points left in the current contour.'); 32593 return contours; 32594} 32595 32596// Convert the TrueType glyph outline to a Path. 32597function getPath(points) { 32598 var p = new Path(); 32599 if (!points) { 32600 return p; 32601 } 32602 32603 var contours = getContours(points); 32604 32605 for (var contourIndex = 0; contourIndex < contours.length; ++contourIndex) { 32606 var contour = contours[contourIndex]; 32607 32608 var prev = null; 32609 var curr = contour[contour.length - 1]; 32610 var next = contour[0]; 32611 32612 if (curr.onCurve) { 32613 p.moveTo(curr.x, curr.y); 32614 } else { 32615 if (next.onCurve) { 32616 p.moveTo(next.x, next.y); 32617 } else { 32618 // If both first and last points are off-curve, start at their middle. 32619 var start = {x: (curr.x + next.x) * 0.5, y: (curr.y + next.y) * 0.5}; 32620 p.moveTo(start.x, start.y); 32621 } 32622 } 32623 32624 for (var i = 0; i < contour.length; ++i) { 32625 prev = curr; 32626 curr = next; 32627 next = contour[(i + 1) % contour.length]; 32628 32629 if (curr.onCurve) { 32630 // This is a straight line. 32631 p.lineTo(curr.x, curr.y); 32632 } else { 32633 var prev2 = prev; 32634 var next2 = next; 32635 32636 if (!prev.onCurve) { 32637 prev2 = { x: (curr.x + prev.x) * 0.5, y: (curr.y + prev.y) * 0.5 }; 32638 p.lineTo(prev2.x, prev2.y); 32639 } 32640 32641 if (!next.onCurve) { 32642 next2 = { x: (curr.x + next.x) * 0.5, y: (curr.y + next.y) * 0.5 }; 32643 } 32644 32645 p.lineTo(prev2.x, prev2.y); 32646 p.quadraticCurveTo(curr.x, curr.y, next2.x, next2.y); 32647 } 32648 } 32649 32650 p.closePath(); 32651 } 32652 return p; 32653} 32654 32655function buildPath(glyphs, glyph) { 32656 if (glyph.isComposite) { 32657 for (var j = 0; j < glyph.components.length; j += 1) { 32658 var component = glyph.components[j]; 32659 var componentGlyph = glyphs.get(component.glyphIndex); 32660 // Force the ttfGlyphLoader to parse the glyph. 32661 componentGlyph.getPath(); 32662 if (componentGlyph.points) { 32663 var transformedPoints = (void 0); 32664 if (component.matchedPoints === undefined) { 32665 // component positioned by offset 32666 transformedPoints = transformPoints(componentGlyph.points, component); 32667 } else { 32668 // component positioned by matched points 32669 if ((component.matchedPoints[0] > glyph.points.length - 1) || 32670 (component.matchedPoints[1] > componentGlyph.points.length - 1)) { 32671 throw Error('Matched points out of range in ' + glyph.name); 32672 } 32673 var firstPt = glyph.points[component.matchedPoints[0]]; 32674 var secondPt = componentGlyph.points[component.matchedPoints[1]]; 32675 var transform = { 32676 xScale: component.xScale, scale01: component.scale01, 32677 scale10: component.scale10, yScale: component.yScale, 32678 dx: 0, dy: 0 32679 }; 32680 secondPt = transformPoints([secondPt], transform)[0]; 32681 transform.dx = firstPt.x - secondPt.x; 32682 transform.dy = firstPt.y - secondPt.y; 32683 transformedPoints = transformPoints(componentGlyph.points, transform); 32684 } 32685 glyph.points = glyph.points.concat(transformedPoints); 32686 } 32687 } 32688 } 32689 32690 return getPath(glyph.points); 32691} 32692 32693// Parse all the glyphs according to the offsets from the `loca` table. 32694function parseGlyfTable(data, start, loca, font) { 32695 var glyphs = new glyphset.GlyphSet(font); 32696
32697 // The last element of the loca table is invalid. 32698 for (var i = 0; i < loca.length - 1; i += 1) { 32699 var offset = loca[i]; 32700 var nextOffset = loca[i + 1]; 32701 if (offset !== nextOffset) { 32702 glyphs.push(i, glyphset.ttfGlyphLoader(font, i, parseGlyph, data, start + offset, buildPath)); 32703 } else { 32704 glyphs.push(i, glyphset.glyphLoader(font, i)); 32705 } 32706 } 32707 32708 return glyphs; 32709} 32710 32711var glyf = { getPath: getPath, parse: parseGlyfTable }; 32712 32713// The Glyph object 32714 32715function getPathDefinition(glyph, path) { 32716 var _path = path || {commands: []}; 32717 return { 32718 configurable: true, 32719 32720 get: function() { 32721 if (typeof _path === 'function') { 32722 _path = _path(); 32723 } 32724 32725 return _path; 32726 }, 32727 32728 set: function(p) { 32729 _path = p; 32730 } 32731 }; 32732} 32733/** 32734 * @typedef GlyphOptions 32735 * @type Object 32736 * @property {string} [name] - The glyph name 32737 * @property {number} [unicode] 32738 * @property {Array} [unicodes] 32739 * @property {number} [xMin] 32740 * @property {number} [yMin] 32741 * @property {number} [xMax] 32742 * @property {number} [yMax] 32743 * @property {number} [advanceWidth] 32744 */ 32745 32746// A Glyph is an individual mark that often corresponds to a character. 32747// Some glyphs, such as ligatures, are a combination of many characters. 32748// Glyphs are the basic building blocks of a font. 32749// 32750// The `Glyph` class contains utility methods for drawing the path and its points. 32751/** 32752 * @exports opentype.Glyph 32753 * @class 32754 * @param {GlyphOptions} 32755 * @constructor 32756 */ 32757function Glyph(options) { 32758 // By putting all the code on a prototype function (which is only declared once) 32759 // we reduce the memory requirements for larger fonts by some 2% 32760 this.bindConstructorValues(options); 32761} 32762 32763/** 32764 * @param {GlyphOptions} 32765 */ 32766Glyph.prototype.bindConstructorValues = function(options) { 32767 this.index = options.index || 0; 32768 32769 // These three values cannot be deferred for memory optimization: 32770 this.name = options.name || null; 32771 this.unicode = options.unicode || undefined; 32772 this.unicodes = options.unicodes || options.unicode !== undefined ? [options.unicode] : []; 32773 32774 // But by binding these values only when necessary, we reduce can 32775 // the memory requirements by almost 3% for larger fonts. 32776 if (options.xMin) { 32777 this.xMin = options.xMin; 32778 } 32779 32780 if (options.yMin) { 32781 this.yMin = options.yMin; 32782 } 32783 32784 if (options.xMax) { 32785 this.xMax = options.xMax; 32786 } 32787 32788 if (options.yMax) { 32789 this.yMax = options.yMax; 32790 } 32791 32792 if (options.advanceWidth) { 32793 this.advanceWidth = options.advanceWidth; 32794 } 32795 32796 // The path for a glyph is the most memory intensive, and is bound as a value 32797 // with a getter/setter to ensure we actually do path parsing only once the 32798 // path is actually needed by anything. 32799 Object.defineProperty(this, 'path', getPathDefinition(this, options.path)); 32800}; 32801 32802/** 32803 * @param {number} 32804 */ 32805Glyph.prototype.addUnicode = function(unicode) { 32806 if (this.unicodes.length === 0) { 32807 this.unicode = unicode; 32808 } 32809 32810 this.unicodes.push(unicode); 32811}; 32812 32813/** 32814 * Calculate the minimum bounding box for this glyph. 32815 * @return {opentype.BoundingBox} 32816 */ 32817Glyph.prototype.getBoundingBox = function() { 32818 return this.path.getBoundingBox(); 32819}; 32820 32821/** 32822 * Convert the glyph to a Path we can draw on a drawing context. 32823 * @param {number} [x=0] - Horizontal position of the beginning of the text. 32824 * @param {number} [y=0] - Vertical position of the *baseline* of the text. 32825 * @param {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. 32826 * @param {Object=} options - xScale, yScale to stretch the glyph. 32827 * @param {opentype.Font} if hinting is to be used, the font 32828 * @return {opentype.Path} 32829 */ 32830Glyph.prototype.getPath = function(x, y, fontSize, options, font) { 32831 x = x !== undefined ? x : 0; 32832 y = y !== undefined ? y : 0; 32833 fontSize = fontSize !== undefined ? fontSize : 72; 32834 var commands; 32835 var hPoints; 32836 if (!options) { options = { }; } 32837 var xScale = options.xScale; 32838 var yScale = options.yScale; 32839 32840 if (options.hinting && font && font.hinting) { 32841 // in case of hinting, the hinting engine takes care 32842 // of scaling the points (not the path) before hinting. 32843 hPoints = this.path && font.hinting.exec(this, fontSize); 32844 // in case the hinting engine failed hPoints is undefined 32845 // and thus reverts to plain rending 32846 } 32847 32848 if (hPoints) { 32849 commands = glyf.getPath(hPoints).commands; 32850 x = Math.round(x); 32851 y = Math.round(y); 32852 // TODO in case of hinting xyScaling is not yet supported 32853 xScale = yScale = 1; 32854 } else { 32855 commands = this.path.commands; 32856 var scale = 1 / this.path.unitsPerEm * fontSize; 32857 if (xScale === undefined) { xScale = scale; } 32858 if (yScale === undefined) { yScale = scale; } 32859 } 32860 32861 var p = new Path(); 32862 for (var i = 0; i < commands.length; i += 1) { 32863 var cmd = commands[i]; 32864 if (cmd.type === 'M') { 32865 p.moveTo(x + (cmd.x * xScale), y + (-cmd.y * yScale)); 32866 } else if (cmd.type === 'L') { 32867 p.lineTo(x + (cmd.x * xScale), y + (-cmd.y * yScale)); 32868 } else if (cmd.type === 'Q') { 32869 p.quadraticCurveTo(x + (cmd.x1 * xScale), y + (-cmd.y1 * yScale), 32870 x + (cmd.x * xScale), y + (-cmd.y * yScale)); 32871 } else if (cmd.type === 'C') { 32872 p.curveTo(x + (cmd.x1 * xScale), y + (-cmd.y1 * yScale), 32873 x + (cmd.x2 * xScale), y + (-cmd.y2 * yScale), 32874 x + (cmd.x * xScale), y + (-cmd.y * yScale)); 32875 } else if (cmd.type === 'Z') { 32876 p.closePath(); 32877 } 32878 } 32879 32880 return p; 32881}; 32882 32883/** 32884 * Split the glyph into contours. 32885 * This function is here for backwards compatibility, and to 32886 * provide raw access to the TrueType glyph outlines. 32887 * @return {Array} 32888 */ 32889Glyph.prototype.getContours = function() { 32890 var this$1 = this; 32891 32892 if (this.points === undefined) { 32893 return []; 32894 } 32895 32896 var contours = []; 32897 var currentContour = []; 32898 for (var i = 0; i < this.points.length; i += 1) { 32899 var pt = this$1.points[i]; 32900 currentContour.push(pt); 32901 if (pt.lastPointOfContour) { 32902 contours.push(currentContour); 32903 currentContour = []; 32904 } 32905 } 32906 32907 check.argument(currentContour.length === 0, 'There are still points left in the current contour.'); 32908 return contours; 32909}; 32910 32911/**
32912 * Calculate the xMin/yMin/xMax/yMax/lsb/rsb for a Glyph. 32913 * @return {Object} 32914 */ 32915Glyph.prototype.getMetrics = function() { 32916 var commands = this.path.commands; 32917 var xCoords = []; 32918 var yCoords = []; 32919 for (var i = 0; i < commands.length; i += 1) { 32920 var cmd = commands[i]; 32921 if (cmd.type !== 'Z') { 32922 xCoords.push(cmd.x); 32923 yCoords.push(cmd.y); 32924 } 32925 32926 if (cmd.type === 'Q' || cmd.type === 'C') { 32927 xCoords.push(cmd.x1); 32928 yCoords.push(cmd.y1); 32929 } 32930 32931 if (cmd.type === 'C') { 32932 xCoords.push(cmd.x2); 32933 yCoords.push(cmd.y2); 32934 } 32935 } 32936 32937 var metrics = { 32938 xMin: Math.min.apply(null, xCoords), 32939 yMin: Math.min.apply(null, yCoords), 32940 xMax: Math.max.apply(null, xCoords), 32941 yMax: Math.max.apply(null, yCoords), 32942 leftSideBearing: this.leftSideBearing 32943 }; 32944 32945 if (!isFinite(metrics.xMin)) { 32946 metrics.xMin = 0; 32947 } 32948 32949 if (!isFinite(metrics.xMax)) { 32950 metrics.xMax = this.advanceWidth; 32951 } 32952 32953 if (!isFinite(metrics.yMin)) { 32954 metrics.yMin = 0; 32955 } 32956 32957 if (!isFinite(metrics.yMax)) { 32958 metrics.yMax = 0; 32959 } 32960 32961 metrics.rightSideBearing = this.advanceWidth - metrics.leftSideBearing - (metrics.xMax - metrics.xMin); 32962 return metrics; 32963}; 32964 32965/** 32966 * Draw the glyph on the given context. 32967 * @param {CanvasRenderingContext2D} ctx - A 2D drawing context, like Canvas. 32968 * @param {number} [x=0] - Horizontal position of the beginning of the text. 32969 * @param {number} [y=0] - Vertical position of the *baseline* of the text. 32970 * @param {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. 32971 * @param {Object=} options - xScale, yScale to stretch the glyph. 32972 */ 32973Glyph.prototype.draw = function(ctx, x, y, fontSize, options) { 32974 this.getPath(x, y, fontSize, options).draw(ctx); 32975}; 32976 32977/** 32978 * Draw the points of the glyph. 32979 * On-curve points will be drawn in blue, off-curve points will be drawn in red. 32980 * @param {CanvasRenderingContext2D} ctx - A 2D drawing context, like Canvas. 32981 * @param {number} [x=0] - Horizontal position of the beginning of the text. 32982 * @param {number} [y=0] - Vertical position of the *baseline* of the text. 32983 * @param {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. 32984 */ 32985Glyph.prototype.drawPoints = function(ctx, x, y, fontSize) { 32986 function drawCircles(l, x, y, scale) { 32987 var PI_SQ = Math.PI * 2; 32988 ctx.beginPath(); 32989 for (var j = 0; j < l.length; j += 1) { 32990 ctx.moveTo(x + (l[j].x * scale), y + (l[j].y * scale)); 32991 ctx.arc(x + (l[j].x * scale), y + (l[j].y * scale), 2, 0, PI_SQ, false); 32992 } 32993 32994 ctx.closePath(); 32995 ctx.fill(); 32996 } 32997 32998 x = x !== undefined ? x : 0; 32999 y = y !== undefined ? y : 0; 33000 fontSize = fontSize !== undefined ? fontSize : 24; 33001 var scale = 1 / this.path.unitsPerEm * fontSize; 33002 33003 var blueCircles = []; 33004 var redCircles = []; 33005 var path = this.path; 33006 for (var i = 0; i < path.commands.length; i += 1) { 33007 var cmd = path.commands[i]; 33008 if (cmd.x !== undefined) { 33009 blueCircles.push({x: cmd.x, y: -cmd.y}); 33010 } 33011 33012 if (cmd.x1 !== undefined) { 33013 redCircles.push({x: cmd.x1, y: -cmd.y1}); 33014 } 33015 33016 if (cmd.x2 !== undefined) { 33017 redCircles.push({x: cmd.x2, y: -cmd.y2}); 33018 } 33019 } 33020 33021 ctx.fillStyle = 'blue'; 33022 drawCircles(blueCircles, x, y, scale); 33023 ctx.fillStyle = 'red'; 33024 drawCircles(redCircles, x, y, scale); 33025}; 33026 33027/** 33028 * Draw lines indicating important font measurements. 33029 * Black lines indicate the origin of the coordinate system (point 0,0). 33030 * Blue lines indicate the glyph bounding box. 33031 * Green line indicates the advance width of the glyph. 33032 * @param {CanvasRenderingContext2D} ctx - A 2D drawing context, like Canvas. 33033 * @param {number} [x=0] - Horizontal position of the beginning of the text. 33034 * @param {number} [y=0] - Vertical position of the *baseline* of the text. 33035 * @param {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. 33036 */ 33037Glyph.prototype.drawMetrics = function(ctx, x, y, fontSize) { 33038 var scale; 33039 x = x !== undefined ? x : 0; 33040 y = y !== undefined ? y : 0; 33041 fontSize = fontSize !== undefined ? fontSize : 24; 33042 scale = 1 / this.path.unitsPerEm * fontSize; 33043 ctx.lineWidth = 1; 33044 33045 // Draw the origin 33046 ctx.strokeStyle = 'black'; 33047 draw.line(ctx, x, -10000, x, 10000); 33048 draw.line(ctx, -10000, y, 10000, y); 33049 33050 // This code is here due to memory optimization: by not using 33051 // defaults in the constructor, we save a notable amount of memory. 33052 var xMin = this.xMin || 0; 33053 var yMin = this.yMin || 0; 33054 var xMax = this.xMax || 0; 33055 var yMax = this.yMax || 0; 33056 var advanceWidth = this.advanceWidth || 0; 33057 33058 // Draw the glyph box 33059 ctx.strokeStyle = 'blue'; 33060 draw.line(ctx, x + (xMin * scale), -10000, x + (xMin * scale), 10000); 33061 draw.line(ctx, x + (xMax * scale), -10000, x + (xMax * scale), 10000); 33062 draw.line(ctx, -10000, y + (-yMin * scale), 10000, y + (-yMin * scale)); 33063 draw.line(ctx, -10000, y + (-yMax * scale), 10000, y + (-yMax * scale)); 33064 33065 // Draw the advance width 33066 ctx.strokeStyle = 'green'; 33067 draw.line(ctx, x + (advanceWidth * scale), -10000, x + (advanceWidth * scale), 10000); 33068}; 33069 33070// The GlyphSet object 33071 33072// Define a property on the glyph that depends on the path being loaded.
33073function defineDependentProperty(glyph, externalName, internalName) { 33074 Object.defineProperty(glyph, externalName, { 33075 get: function() { 33076 // Request the path property to make sure the path is loaded. 33077 glyph.path; // jshint ignore:line 33078 return glyph[internalName]; 33079 }, 33080 set: function(newValue) { 33081 glyph[internalName] = newValue; 33082 }, 33083 enumerable: true, 33084 configurable: true 33085 }); 33086} 33087 33088/** 33089 * A GlyphSet represents all glyphs available in the font, but modelled using 33090 * a deferred glyph loader, for retrieving glyphs only once they are absolutely 33091 * necessary, to keep the memory footprint down. 33092 * @exports opentype.GlyphSet 33093 * @class 33094 * @param {opentype.Font} 33095 * @param {Array} 33096 */ 33097function GlyphSet(font, glyphs) { 33098 var this$1 = this; 33099 33100 this.font = font; 33101 this.glyphs = {}; 33102 if (Array.isArray(glyphs)) { 33103 for (var i = 0; i < glyphs.length; i++) { 33104 this$1.glyphs[i] = glyphs[i]; 33105 } 33106 } 33107 33108 this.length = (glyphs && glyphs.length) || 0; 33109} 33110 33111/** 33112 * @param {number} index 33113 * @return {opentype.Glyph} 33114 */ 33115GlyphSet.prototype.get = function(index) { 33116 if (typeof this.glyphs[index] === 'function') { 33117 this.glyphs[index] = this.glyphs[index](); 33118 } 33119 33120 return this.glyphs[index]; 33121}; 33122 33123/** 33124 * @param {number} index 33125 * @param {Object} 33126 */ 33127GlyphSet.prototype.push = function(index, loader) { 33128 this.glyphs[index] = loader; 33129 this.length++; 33130}; 33131 33132/** 33133 * @alias opentype.glyphLoader 33134 * @param {opentype.Font} font 33135 * @param {number} index 33136 * @return {opentype.Glyph} 33137 */ 33138function glyphLoader(font, index) { 33139 return new Glyph({index: index, font: font}); 33140} 33141 33142/** 33143 * Generate a stub glyph that can be filled with all metadata *except* 33144 * the "points" and "path" properties, which must be loaded only once 33145 * the glyph's path is actually requested for text shaping. 33146 * @alias opentype.ttfGlyphLoader 33147 * @param {opentype.Font} font 33148 * @param {number} index 33149 * @param {Function} parseGlyph 33150 * @param {Object} data 33151 * @param {number} position 33152 * @param {Function} buildPath 33153 * @return {opentype.Glyph} 33154 */ 33155function ttfGlyphLoader(font, index, parseGlyph, data, position, buildPath) { 33156 return function() { 33157 var glyph = new Glyph({index: index, font: font}); 33158 33159 glyph.path = function() { 33160 parseGlyph(glyph, data, position); 33161 var path = buildPath(font.glyphs, glyph); 33162 path.unitsPerEm = font.unitsPerEm; 33163 return path; 33164 }; 33165 33166 defineDependentProperty(glyph, 'xMin', '_xMin'); 33167 defineDependentProperty(glyph, 'xMax', '_xMax'); 33168 defineDependentProperty(glyph, 'yMin', '_yMin'); 33169 defineDependentProperty(glyph, 'yMax', '_yMax'); 33170 33171 return glyph; 33172 }; 33173} 33174/** 33175 * @alias opentype.cffGlyphLoader 33176 * @param {opentype.Font} font 33177 * @param {number} index 33178 * @param {Function} parseCFFCharstring 33179 * @param {string} charstring 33180 * @return {opentype.Glyph} 33181 */ 33182function cffGlyphLoader(font, index, parseCFFCharstring, charstring) { 33183 return function() { 33184 var glyph = new Glyph({index: index, font: font}); 33185 33186 glyph.path = function() { 33187 var path = parseCFFCharstring(font, glyph, charstring); 33188 path.unitsPerEm = font.unitsPerEm; 33189 return path; 33190 }; 33191 33192 return glyph; 33193 }; 33194} 33195 33196var glyphset = { GlyphSet: GlyphSet, glyphLoader: glyphLoader, ttfGlyphLoader: ttfGlyphLoader, cffGlyphLoader: cffGlyphLoader }; 33197 33198// The `CFF` table contains the glyph outlines in PostScript format. 33199// https://www.microsoft.com/typography/OTSPEC/cff.htm 33200// http://download.microsoft.com/download/8/0/1/801a191c-029d-4af3-9642-555f6fe514ee/cff.pdf 33201// http://download.microsoft.com/download/8/0/1/801a191c-029d-4af3-9642-555f6fe514ee/type2.pdf 33202 33203// Custom equals function that can also check lists. 33204function equals(a, b) { 33205 if (a === b) { 33206 return true; 33207 } else if (Array.isArray(a) && Array.isArray(b)) { 33208 if (a.length !== b.length) { 33209 return false; 33210 } 33211 33212 for (var i = 0; i < a.length; i += 1) { 33213 if (!equals(a[i], b[i])) { 33214 return false;
vendor: 33,020 bytes, lines 33215-34113
33215 } 33216 } 33217 33218 return true; 33219 } else { 33220 return false; 33221 } 33222} 33223 33224// Subroutines are encoded using the negative half of the number space. 33225// See type 2 chapter 4.7 "Subroutine operators". 33226function calcCFFSubroutineBias(subrs) { 33227 var bias; 33228 if (subrs.length < 1240) { 33229 bias = 107; 33230 } else if (subrs.length < 33900) { 33231 bias = 1131; 33232 } else { 33233 bias = 32768; 33234 } 33235 33236 return bias; 33237} 33238 33239// Parse a `CFF` INDEX array. 33240// An index array consists of a list of offsets, then a list of objects at those offsets. 33241function parseCFFIndex(data, start, conversionFn) { 33242 var offsets = []; 33243 var objects = []; 33244 var count = parse.getCard16(data, start); 33245 var objectOffset; 33246 var endOffset; 33247 if (count !== 0) { 33248 var offsetSize = parse.getByte(data, start + 2); 33249 objectOffset = start + ((count + 1) * offsetSize) + 2; 33250 var pos = start + 3; 33251 for (var i = 0; i < count + 1; i += 1) { 33252 offsets.push(parse.getOffset(data, pos, offsetSize)); 33253 pos += offsetSize; 33254 } 33255 33256 // The total size of the index array is 4 header bytes + the value of the last offset. 33257 endOffset = objectOffset + offsets[count]; 33258 } else { 33259 endOffset = start + 2; 33260 } 33261 33262 for (var i$1 = 0; i$1 < offsets.length - 1; i$1 += 1) { 33263 var value = parse.getBytes(data, objectOffset + offsets[i$1], objectOffset + offsets[i$1 + 1]); 33264 if (conversionFn) { 33265 value = conversionFn(value); 33266 } 33267 33268 objects.push(value); 33269 } 33270 33271 return {objects: objects, startOffset: start, endOffset: endOffset}; 33272} 33273 33274// Parse a `CFF` DICT real value. 33275function parseFloatOperand(parser) { 33276 var s = ''; 33277 var eof = 15; 33278 var lookup = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', 'E', 'E-', null, '-']; 33279 while (true) { 33280 var b = parser.parseByte(); 33281 var n1 = b >> 4; 33282 var n2 = b & 15; 33283 33284 if (n1 === eof) { 33285 break; 33286 } 33287 33288 s += lookup[n1]; 33289 33290 if (n2 === eof) { 33291 break; 33292 } 33293 33294 s += lookup[n2]; 33295 } 33296 33297 return parseFloat(s); 33298} 33299 33300// Parse a `CFF` DICT operand. 33301function parseOperand(parser, b0) { 33302 var b1; 33303 var b2; 33304 var b3; 33305 var b4; 33306 if (b0 === 28) { 33307 b1 = parser.parseByte(); 33308 b2 = parser.parseByte(); 33309 return b1 << 8 | b2; 33310 } 33311 33312 if (b0 === 29) { 33313 b1 = parser.parseByte(); 33314 b2 = parser.parseByte(); 33315 b3 = parser.parseByte(); 33316 b4 = parser.parseByte(); 33317 return b1 << 24 | b2 << 16 | b3 << 8 | b4; 33318 } 33319 33320 if (b0 === 30) { 33321 return parseFloatOperand(parser); 33322 } 33323 33324 if (b0 >= 32 && b0 <= 246) { 33325 return b0 - 139; 33326 } 33327 33328 if (b0 >= 247 && b0 <= 250) { 33329 b1 = parser.parseByte(); 33330 return (b0 - 247) * 256 + b1 + 108; 33331 } 33332 33333 if (b0 >= 251 && b0 <= 254) { 33334 b1 = parser.parseByte(); 33335 return -(b0 - 251) * 256 - b1 - 108; 33336 } 33337 33338 throw new Error('Invalid b0 ' + b0); 33339} 33340 33341// Convert the entries returned by `parseDict` to a proper dictionary. 33342// If a value is a list of one, it is unpacked. 33343function entriesToObject(entries) { 33344 var o = {}; 33345 for (var i = 0; i < entries.length; i += 1) { 33346 var key = entries[i][0]; 33347 var values = entries[i][1]; 33348 var value = (void 0); 33349 if (values.length === 1) { 33350 value = values[0]; 33351 } else { 33352 value = values; 33353 } 33354 33355 if (o.hasOwnProperty(key) && !isNaN(o[key])) { 33356 throw new Error('Object ' + o + ' already has key ' + key); 33357 } 33358 33359 o[key] = value; 33360 } 33361 33362 return o; 33363} 33364 33365// Parse a `CFF` DICT object. 33366// A dictionary contains key-value pairs in a compact tokenized format. 33367function parseCFFDict(data, start, size) { 33368 start = start !== undefined ? start : 0; 33369 var parser = new parse.Parser(data, start); 33370 var entries = []; 33371 var operands = []; 33372 size = size !== undefined ? size : data.length; 33373 33374 while (parser.relativeOffset < size) { 33375 var op = parser.parseByte(); 33376 33377 // The first byte for each dict item distinguishes between operator (key) and operand (value). 33378 // Values <= 21 are operators. 33379 if (op <= 21) { 33380 // Two-byte operators have an initial escape byte of 12. 33381 if (op === 12) { 33382 op = 1200 + parser.parseByte(); 33383 } 33384 33385 entries.push([op, operands]); 33386 operands = []; 33387 } else { 33388 // Since the operands (values) come before the operators (keys), we store all operands in a list 33389 // until we encounter an operator. 33390 operands.push(parseOperand(parser, op)); 33391 } 33392 } 33393 33394 return entriesToObject(entries); 33395} 33396 33397// Given a String Index (SID), return the value of the string. 33398// Strings below index 392 are standard CFF strings and are not encoded in the font. 33399function getCFFString(strings, index) { 33400 if (index <= 390) { 33401 index = cffStandardStrings[index]; 33402 } else { 33403 index = strings[index - 391]; 33404 } 33405 33406 return index; 33407} 33408 33409// Interpret a dictionary and return a new dictionary with readable keys and values for missing entries. 33410// This function takes `meta` which is a list of objects containing `operand`, `name` and `default`. 33411function interpretDict(dict, meta, strings) { 33412 var newDict = {}; 33413 var value; 33414 33415 // Because we also want to include missing values, we start out from the meta list 33416 // and lookup values in the dict. 33417 for (var i = 0; i < meta.length; i += 1) { 33418 var m = meta[i]; 33419 33420 if (Array.isArray(m.type)) { 33421 var values = []; 33422 values.length = m.type.length; 33423 for (var j = 0; j < m.type.length; j++) { 33424 value = dict[m.op] !== undefined ? dict[m.op][j] : undefined; 33425 if (value === undefined) { 33426 value = m.value !== undefined && m.value[j] !== undefined ? m.value[j] : null; 33427 } 33428 if (m.type[j] === 'SID') { 33429 value = getCFFString(strings, value); 33430 } 33431 values[j] = value; 33432 } 33433 newDict[m.name] = values; 33434 } else { 33435 value = dict[m.op]; 33436 if (value === undefined) { 33437 value = m.value !== undefined ? m.value : null; 33438 } 33439 33440 if (m.type === 'SID') { 33441 value = getCFFString(strings, value); 33442 } 33443 newDict[m.name] = value; 33444 } 33445 } 33446 33447 return newDict; 33448} 33449 33450// Parse the CFF header. 33451function parseCFFHeader(data, start) { 33452 var header = {}; 33453 header.formatMajor = parse.getCard8(data, start); 33454 header.formatMinor = parse.getCard8(data, start + 1); 33455 header.size = parse.getCard8(data, start + 2); 33456 header.offsetSize = parse.getCard8(data, start + 3); 33457 header.startOffset = start; 33458 header.endOffset = start + 4; 33459 return header; 33460} 33461 33462var TOP_DICT_META = [ 33463 {name: 'version', op: 0, type: 'SID'}, 33464 {name: 'notice', op: 1, type: 'SID'}, 33465 {name: 'copyright', op: 1200, type: 'SID'}, 33466 {name: 'fullName', op: 2, type: 'SID'}, 33467 {name: 'familyName', op: 3, type: 'SID'}, 33468 {name: 'weight', op: 4, type: 'SID'}, 33469 {name: 'isFixedPitch', op: 1201, type: 'number', value: 0}, 33470 {name: 'italicAngle', op: 1202, type: 'number', value: 0}, 33471 {name: 'underlinePosition', op: 1203, type: 'number', value: -100}, 33472 {name: 'underlineThickness', op: 1204, type: 'number', value: 50}, 33473 {name: 'paintType', op: 1205, type: 'number', value: 0}, 33474 {name: 'charstringType', op: 1206, type: 'number', value: 2}, 33475 { 33476 name: 'fontMatrix', 33477 op: 1207, 33478 type: ['real', 'real', 'real', 'real', 'real', 'real'], 33479 value: [0.001, 0, 0, 0.001, 0, 0] 33480 }, 33481 {name: 'uniqueId', op: 13, type: 'number'}, 33482 {name: 'fontBBox', op: 5, type: ['number', 'number', 'number', 'number'], value: [0, 0, 0, 0]}, 33483 {name: 'strokeWidth', op: 1208, type: 'number', value: 0}, 33484 {name: 'xuid', op: 14, type: [], value: null}, 33485 {name: 'charset', op: 15, type: 'offset', value: 0}, 33486 {name: 'encoding', op: 16, type: 'offset', value: 0}, 33487 {name: 'charStrings', op: 17, type: 'offset', value: 0}, 33488 {name: 'private', op: 18, type: ['number', 'offset'], value: [0, 0]}, 33489 {name: 'ros', op: 1230, type: ['SID', 'SID', 'number']}, 33490 {name: 'cidFontVersion', op: 1231, type: 'number', value: 0}, 33491 {name: 'cidFontRevision', op: 1232, type: 'number', value: 0}, 33492 {name: 'cidFontType', op: 1233, type: 'number', value: 0}, 33493 {name: 'cidCount', op: 1234, type: 'number', value: 8720}, 33494 {name: 'uidBase', op: 1235, type: 'number'}, 33495 {name: 'fdArray', op: 1236, type: 'offset'}, 33496 {name: 'fdSelect', op: 1237, type: 'offset'}, 33497 {name: 'fontName', op: 1238, type: 'SID'} 33498]; 33499 33500var PRIVATE_DICT_META = [ 33501 {name: 'subrs', op: 19, type: 'offset', value: 0}, 33502 {name: 'defaultWidthX', op: 20, type: 'number', value: 0}, 33503 {name: 'nominalWidthX', op: 21, type: 'number', value: 0} 33504]; 33505 33506// Parse the CFF top dictionary. A CFF table can contain multiple fonts, each with their own top dictionary. 33507// The top dictionary contains the essential metadata for the font, together with the private dictionary. 33508function parseCFFTopDict(data, strings) { 33509 var dict = parseCFFDict(data, 0, data.byteLength); 33510 return interpretDict(dict, TOP_DICT_META, strings); 33511} 33512 33513// Parse the CFF private dictionary. We don't fully parse out all the values, only the ones we need. 33514function parseCFFPrivateDict(data, start, size, strings) { 33515 var dict = parseCFFDict(data, start, size); 33516 return interpretDict(dict, PRIVATE_DICT_META, strings); 33517} 33518 33519// Returns a list of "Top DICT"s found using an INDEX list. 33520// Used to read both the usual high-level Top DICTs and also the FDArray 33521// discovered inside CID-keyed fonts. When a Top DICT has a reference to 33522// a Private DICT that is read and saved into the Top DICT. 33523// 33524// In addition to the expected/optional values as outlined in TOP_DICT_META 33525// the following values might be saved into the Top DICT. 33526// 33527// _subrs [] array of local CFF subroutines from Private DICT 33528// _subrsBias bias value computed from number of subroutines 33529// (see calcCFFSubroutineBias() and parseCFFCharstring()) 33530// _defaultWidthX default widths for CFF characters 33531// _nominalWidthX bias added to width embedded within glyph description 33532// 33533// _privateDict saved copy of parsed Private DICT from Top DICT 33534function gatherCFFTopDicts(data, start, cffIndex, strings) { 33535 var topDictArray = []; 33536 for (var iTopDict = 0; iTopDict < cffIndex.length; iTopDict += 1) { 33537 var topDictData = new DataView(new Uint8Array(cffIndex[iTopDict]).buffer); 33538 var topDict = parseCFFTopDict(topDictData, strings); 33539 topDict._subrs = []; 33540 topDict._subrsBias = 0; 33541 var privateSize = topDict.private[0]; 33542 var privateOffset = topDict.private[1]; 33543 if (privateSize !== 0 && privateOffset !== 0) { 33544 var privateDict = parseCFFPrivateDict(data, privateOffset + start, privateSize, strings); 33545 topDict._defaultWidthX = privateDict.defaultWidthX; 33546 topDict._nominalWidthX = privateDict.nominalWidthX; 33547 if (privateDict.subrs !== 0) { 33548 var subrOffset = privateOffset + privateDict.subrs; 33549 var subrIndex = parseCFFIndex(data, subrOffset + start); 33550 topDict._subrs = subrIndex.objects; 33551 topDict._subrsBias = calcCFFSubroutineBias(topDict._subrs); 33552 } 33553 topDict._privateDict = privateDict; 33554 } 33555 topDictArray.push(topDict); 33556 } 33557 return topDictArray; 33558} 33559 33560// Parse the CFF charset table, which contains internal names for all the glyphs. 33561// This function will return a list of glyph names. 33562// See Adobe TN #5176 chapter 13, "Charsets". 33563function parseCFFCharset(data, start, nGlyphs, strings) { 33564 var sid; 33565 var count; 33566 var parser = new parse.Parser(data, start); 33567 33568 // The .notdef glyph is not included, so subtract 1. 33569 nGlyphs -= 1; 33570 var charset = ['.notdef']; 33571 33572 var format = parser.parseCard8(); 33573 if (format === 0) { 33574 for (var i = 0; i < nGlyphs; i += 1) { 33575 sid = parser.parseSID(); 33576 charset.push(getCFFString(strings, sid)); 33577 } 33578 } else if (format === 1) { 33579 while (charset.length <= nGlyphs) { 33580 sid = parser.parseSID(); 33581 count = parser.parseCard8(); 33582 for (var i$1 = 0; i$1 <= count; i$1 += 1) { 33583 charset.push(getCFFString(strings, sid)); 33584 sid += 1; 33585 } 33586 } 33587 } else if (format === 2) { 33588 while (charset.length <= nGlyphs) { 33589 sid = parser.parseSID(); 33590 count = parser.parseCard16(); 33591 for (var i$2 = 0; i$2 <= count; i$2 += 1) { 33592 charset.push(getCFFString(strings, sid)); 33593 sid += 1; 33594 } 33595 } 33596 } else { 33597 throw new Error('Unknown charset format ' + format); 33598 } 33599 33600 return charset; 33601} 33602 33603// Parse the CFF encoding data. Only one encoding can be specified per font. 33604// See Adobe TN #5176 chapter 12, "Encodings". 33605function parseCFFEncoding(data, start, charset) { 33606 var code; 33607 var enc = {}; 33608 var parser = new parse.Parser(data, start); 33609 var format = parser.parseCard8(); 33610 if (format === 0) { 33611 var nCodes = parser.parseCard8(); 33612 for (var i = 0; i < nCodes; i += 1) { 33613 code = parser.parseCard8(); 33614 enc[code] = i; 33615 } 33616 } else if (format === 1) { 33617 var nRanges = parser.parseCard8(); 33618 code = 1; 33619 for (var i$1 = 0; i$1 < nRanges; i$1 += 1) { 33620 var first = parser.parseCard8(); 33621 var nLeft = parser.parseCard8(); 33622 for (var j = first; j <= first + nLeft; j += 1) { 33623 enc[j] = code; 33624 code += 1; 33625 } 33626 } 33627 } else { 33628 throw new Error('Unknown encoding format ' + format); 33629 } 33630 33631 return new CffEncoding(enc, charset); 33632} 33633 33634// Take in charstring code and return a Glyph object. 33635// The encoding is described in the Type 2 Charstring Format 33636// https://www.microsoft.com/typography/OTSPEC/charstr2.htm 33637function parseCFFCharstring(font, glyph, code) { 33638 var c1x; 33639 var c1y; 33640 var c2x; 33641 var c2y; 33642 var p = new Path(); 33643 var stack = []; 33644 var nStems = 0; 33645 var haveWidth = false; 33646 var open = false; 33647 var x = 0; 33648 var y = 0; 33649 var subrs; 33650 var subrsBias; 33651 var defaultWidthX; 33652 var nominalWidthX; 33653 if (font.isCIDFont) { 33654 var fdIndex = font.tables.cff.topDict._fdSelect[glyph.index]; 33655 var fdDict = font.tables.cff.topDict._fdArray[fdIndex]; 33656 subrs = fdDict._subrs; 33657 subrsBias = fdDict._subrsBias; 33658 defaultWidthX = fdDict._defaultWidthX; 33659 nominalWidthX = fdDict._nominalWidthX; 33660 } else { 33661 subrs = font.tables.cff.topDict._subrs; 33662 subrsBias = font.tables.cff.topDict._subrsBias; 33663 defaultWidthX = font.tables.cff.topDict._defaultWidthX; 33664 nominalWidthX = font.tables.cff.topDict._nominalWidthX; 33665 } 33666 var width = defaultWidthX; 33667 33668 function newContour(x, y) { 33669 if (open) { 33670 p.closePath(); 33671 } 33672 33673 p.moveTo(x, y); 33674 open = true; 33675 } 33676 33677 function parseStems() { 33678 var hasWidthArg; 33679 33680 // The number of stem operators on the stack is always even. 33681 // If the value is uneven, that means a width is specified. 33682 hasWidthArg = stack.length % 2 !== 0; 33683 if (hasWidthArg && !haveWidth) { 33684 width = stack.shift() + nominalWidthX; 33685 } 33686 33687 nStems += stack.length >> 1; 33688 stack.length = 0; 33689 haveWidth = true; 33690 } 33691 33692 function parse$$1(code) { 33693 var b1; 33694 var b2; 33695 var b3; 33696 var b4; 33697 var codeIndex; 33698 var subrCode; 33699 var jpx; 33700 var jpy; 33701 var c3x; 33702 var c3y; 33703 var c4x; 33704 var c4y; 33705 33706 var i = 0; 33707 while (i < code.length) { 33708 var v = code[i]; 33709 i += 1; 33710 switch (v) { 33711 case 1: // hstem 33712 parseStems(); 33713 break; 33714 case 3: // vstem 33715 parseStems(); 33716 break; 33717 case 4: // vmoveto 33718 if (stack.length > 1 && !haveWidth) { 33719 width = stack.shift() + nominalWidthX; 33720 haveWidth = true; 33721 } 33722 33723 y += stack.pop(); 33724 newContour(x, y); 33725 break; 33726 case 5: // rlineto 33727 while (stack.length > 0) { 33728 x += stack.shift(); 33729 y += stack.shift(); 33730 p.lineTo(x, y); 33731 } 33732 33733 break; 33734 case 6: // hlineto 33735 while (stack.length > 0) { 33736 x += stack.shift(); 33737 p.lineTo(x, y); 33738 if (stack.length === 0) { 33739 break; 33740 } 33741 33742 y += stack.shift(); 33743 p.lineTo(x, y); 33744 } 33745 33746 break; 33747 case 7: // vlineto 33748 while (stack.length > 0) { 33749 y += stack.shift(); 33750 p.lineTo(x, y); 33751 if (stack.length === 0) { 33752 break; 33753 } 33754 33755 x += stack.shift(); 33756 p.lineTo(x, y); 33757 } 33758 33759 break; 33760 case 8: // rrcurveto 33761 while (stack.length > 0) { 33762 c1x = x + stack.shift(); 33763 c1y = y + stack.shift(); 33764 c2x = c1x + stack.shift(); 33765 c2y = c1y + stack.shift(); 33766 x = c2x + stack.shift(); 33767 y = c2y + stack.shift(); 33768 p.curveTo(c1x, c1y, c2x, c2y, x, y); 33769 } 33770 33771 break; 33772 case 10: // callsubr 33773 codeIndex = stack.pop() + subrsBias; 33774 subrCode = subrs[codeIndex]; 33775 if (subrCode) { 33776 parse$$1(subrCode); 33777 } 33778 33779 break; 33780 case 11: // return 33781 return; 33782 case 12: // flex operators 33783 v = code[i]; 33784 i += 1; 33785 switch (v) { 33786 case 35: // flex 33787 // |- dx1 dy1 dx2 dy2 dx3 dy3 dx4 dy4 dx5 dy5 dx6 dy6 fd flex (12 35) |- 33788 c1x = x + stack.shift(); // dx1 33789 c1y = y + stack.shift(); // dy1 33790 c2x = c1x + stack.shift(); // dx2 33791 c2y = c1y + stack.shift(); // dy2 33792 jpx = c2x + stack.shift(); // dx3 33793 jpy = c2y + stack.shift(); // dy3 33794 c3x = jpx + stack.shift(); // dx4 33795 c3y = jpy + stack.shift(); // dy4 33796 c4x = c3x + stack.shift(); // dx5 33797 c4y = c3y + stack.shift(); // dy5 33798 x = c4x + stack.shift(); // dx6 33799 y = c4y + stack.shift(); // dy6 33800 stack.shift(); // flex depth 33801 p.curveTo(c1x, c1y, c2x, c2y, jpx, jpy); 33802 p.curveTo(c3x, c3y, c4x, c4y, x, y); 33803 break; 33804 case 34: // hflex 33805 // |- dx1 dx2 dy2 dx3 dx4 dx5 dx6 hflex (12 34) |- 33806 c1x = x + stack.shift(); // dx1 33807 c1y = y; // dy1 33808 c2x = c1x + stack.shift(); // dx2 33809 c2y = c1y + stack.shift(); // dy2 33810 jpx = c2x + stack.shift(); // dx3 33811 jpy = c2y; // dy3 33812 c3x = jpx + stack.shift(); // dx4 33813 c3y = c2y; // dy4 33814 c4x = c3x + stack.shift(); // dx5 33815 c4y = y; // dy5 33816 x = c4x + stack.shift(); // dx6 33817 p.curveTo(c1x, c1y, c2x, c2y, jpx, jpy); 33818 p.curveTo(c3x, c3y, c4x, c4y, x, y); 33819 break; 33820 case 36: // hflex1 33821 // |- dx1 dy1 dx2 dy2 dx3 dx4 dx5 dy5 dx6 hflex1 (12 36) |- 33822 c1x = x + stack.shift(); // dx1 33823 c1y = y + stack.shift(); // dy1 33824 c2x = c1x + stack.shift(); // dx2 33825 c2y = c1y + stack.shift(); // dy2 33826 jpx = c2x + stack.shift(); // dx3 33827 jpy = c2y; // dy3 33828 c3x = jpx + stack.shift(); // dx4 33829 c3y = c2y; // dy4 33830 c4x = c3x + stack.shift(); // dx5 33831 c4y = c3y + stack.shift(); // dy5 33832 x = c4x + stack.shift(); // dx6 33833 p.curveTo(c1x, c1y, c2x, c2y, jpx, jpy); 33834 p.curveTo(c3x, c3y, c4x, c4y, x, y); 33835 break; 33836 case 37: // flex1 33837 // |- dx1 dy1 dx2 dy2 dx3 dy3 dx4 dy4 dx5 dy5 d6 flex1 (12 37) |- 33838 c1x = x + stack.shift(); // dx1 33839 c1y = y + stack.shift(); // dy1 33840 c2x = c1x + stack.shift(); // dx2 33841 c2y = c1y + stack.shift(); // dy2 33842 jpx = c2x + stack.shift(); // dx3 33843 jpy = c2y + stack.shift(); // dy3 33844 c3x = jpx + stack.shift(); // dx4 33845 c3y = jpy + stack.shift(); // dy4 33846 c4x = c3x + stack.shift(); // dx5 33847 c4y = c3y + stack.shift(); // dy5 33848 if (Math.abs(c4x - x) > Math.abs(c4y - y)) { 33849 x = c4x + stack.shift(); 33850 } else { 33851 y = c4y + stack.shift(); 33852 } 33853 33854 p.curveTo(c1x, c1y, c2x, c2y, jpx, jpy); 33855 p.curveTo(c3x, c3y, c4x, c4y, x, y); 33856 break; 33857 default: 33858 console.log('Glyph ' + glyph.index + ': unknown operator ' + 1200 + v); 33859 stack.length = 0; 33860 } 33861 break; 33862 case 14: // endchar 33863 if (stack.length > 0 && !haveWidth) { 33864 width = stack.shift() + nominalWidthX; 33865 haveWidth = true; 33866 } 33867 33868 if (open) { 33869 p.closePath(); 33870 open = false; 33871 } 33872 33873 break; 33874 case 18: // hstemhm 33875 parseStems(); 33876 break; 33877 case 19: // hintmask 33878 case 20: // cntrmask 33879 parseStems(); 33880 i += (nStems + 7) >> 3; 33881 break; 33882 case 21: // rmoveto 33883 if (stack.length > 2 && !haveWidth) { 33884 width = stack.shift() + nominalWidthX; 33885 haveWidth = true; 33886 } 33887 33888 y += stack.pop(); 33889 x += stack.pop(); 33890 newContour(x, y); 33891 break; 33892 case 22: // hmoveto 33893 if (stack.length > 1 && !haveWidth) { 33894 width = stack.shift() + nominalWidthX; 33895 haveWidth = true; 33896 } 33897 33898 x += stack.pop(); 33899 newContour(x, y); 33900 break; 33901 case 23: // vstemhm 33902 parseStems(); 33903 break; 33904 case 24: // rcurveline 33905 while (stack.length > 2) { 33906 c1x = x + stack.shift(); 33907 c1y = y + stack.shift(); 33908 c2x = c1x + stack.shift(); 33909 c2y = c1y + stack.shift(); 33910 x = c2x + stack.shift(); 33911 y = c2y + stack.shift(); 33912 p.curveTo(c1x, c1y, c2x, c2y, x, y); 33913 } 33914 33915 x += stack.shift(); 33916 y += stack.shift(); 33917 p.lineTo(x, y); 33918 break; 33919 case 25: // rlinecurve 33920 while (stack.length > 6) { 33921 x += stack.shift(); 33922 y += stack.shift(); 33923 p.lineTo(x, y); 33924 } 33925 33926 c1x = x + stack.shift(); 33927 c1y = y + stack.shift(); 33928 c2x = c1x + stack.shift(); 33929 c2y = c1y + stack.shift(); 33930 x = c2x + stack.shift(); 33931 y = c2y + stack.shift(); 33932 p.curveTo(c1x, c1y, c2x, c2y, x, y); 33933 break; 33934 case 26: // vvcurveto 33935 if (stack.length % 2) { 33936 x += stack.shift(); 33937 } 33938 33939 while (stack.length > 0) { 33940 c1x = x; 33941 c1y = y + stack.shift(); 33942 c2x = c1x + stack.shift(); 33943 c2y = c1y + stack.shift(); 33944 x = c2x; 33945 y = c2y + stack.shift(); 33946 p.curveTo(c1x, c1y, c2x, c2y, x, y); 33947 } 33948 33949 break; 33950 case 27: // hhcurveto 33951 if (stack.length % 2) { 33952 y += stack.shift(); 33953 } 33954 33955 while (stack.length > 0) { 33956 c1x = x + stack.shift(); 33957 c1y = y; 33958 c2x = c1x + stack.shift(); 33959 c2y = c1y + stack.shift(); 33960 x = c2x + stack.shift(); 33961 y = c2y; 33962 p.curveTo(c1x, c1y, c2x, c2y, x, y); 33963 } 33964 33965 break; 33966 case 28: // shortint 33967 b1 = code[i]; 33968 b2 = code[i + 1]; 33969 stack.push(((b1 << 24) | (b2 << 16)) >> 16); 33970 i += 2; 33971 break; 33972 case 29: // callgsubr 33973 codeIndex = stack.pop() + font.gsubrsBias; 33974 subrCode = font.gsubrs[codeIndex]; 33975 if (subrCode) { 33976 parse$$1(subrCode); 33977 } 33978 33979 break; 33980 case 30: // vhcurveto 33981 while (stack.length > 0) { 33982 c1x = x; 33983 c1y = y + stack.shift(); 33984 c2x = c1x + stack.shift(); 33985 c2y = c1y + stack.shift(); 33986 x = c2x + stack.shift(); 33987 y = c2y + (stack.length === 1 ? stack.shift() : 0); 33988 p.curveTo(c1x, c1y, c2x, c2y, x, y); 33989 if (stack.length === 0) { 33990 break; 33991 } 33992 33993 c1x = x + stack.shift(); 33994 c1y = y; 33995 c2x = c1x + stack.shift(); 33996 c2y = c1y + stack.shift(); 33997 y = c2y + stack.shift(); 33998 x = c2x + (stack.length === 1 ? stack.shift() : 0); 33999 p.curveTo(c1x, c1y, c2x, c2y, x, y); 34000 } 34001 34002 break; 34003 case 31: // hvcurveto 34004 while (stack.length > 0) { 34005 c1x = x + stack.shift(); 34006 c1y = y; 34007 c2x = c1x + stack.shift(); 34008 c2y = c1y + stack.shift(); 34009 y = c2y + stack.shift(); 34010 x = c2x + (stack.length === 1 ? stack.shift() : 0); 34011 p.curveTo(c1x, c1y, c2x, c2y, x, y); 34012 if (stack.length === 0) { 34013 break; 34014 } 34015 34016 c1x = x; 34017 c1y = y + stack.shift(); 34018 c2x = c1x + stack.shift(); 34019 c2y = c1y + stack.shift(); 34020 x = c2x + stack.shift(); 34021 y = c2y + (stack.length === 1 ? stack.shift() : 0); 34022 p.curveTo(c1x, c1y, c2x, c2y, x, y); 34023 } 34024 34025 break; 34026 default: 34027 if (v < 32) { 34028 console.log('Glyph ' + glyph.index + ': unknown operator ' + v); 34029 } else if (v < 247) { 34030 stack.push(v - 139); 34031 } else if (v < 251) { 34032 b1 = code[i]; 34033 i += 1; 34034 stack.push((v - 247) * 256 + b1 + 108); 34035 } else if (v < 255) { 34036 b1 = code[i]; 34037 i += 1; 34038 stack.push(-(v - 251) * 256 - b1 - 108); 34039 } else { 34040 b1 = code[i]; 34041 b2 = code[i + 1]; 34042 b3 = code[i + 2]; 34043 b4 = code[i + 3]; 34044 i += 4; 34045 stack.push(((b1 << 24) | (b2 << 16) | (b3 << 8) | b4) / 65536); 34046 } 34047 } 34048 } 34049 } 34050 34051 parse$$1(code); 34052 34053 glyph.advanceWidth = width; 34054 return p; 34055} 34056 34057function parseCFFFDSelect(data, start, nGlyphs, fdArrayCount) { 34058 var fdSelect = []; 34059 var fdIndex; 34060 var parser = new parse.Parser(data, start); 34061 var format = parser.parseCard8(); 34062 if (format === 0) { 34063 // Simple list of nGlyphs elements 34064 for (var iGid = 0; iGid < nGlyphs; iGid++) { 34065 fdIndex = parser.parseCard8(); 34066 if (fdIndex >= fdArrayCount) { 34067 throw new Error('CFF table CID Font FDSelect has bad FD index value ' + fdIndex + ' (FD count ' + fdArrayCount + ')'); 34068 } 34069 fdSelect.push(fdIndex); 34070 } 34071 } else if (format === 3) { 34072 // Ranges 34073 var nRanges = parser.parseCard16(); 34074 var first = parser.parseCard16(); 34075 if (first !== 0) { 34076 throw new Error('CFF Table CID Font FDSelect format 3 range has bad initial GID ' + first); 34077 } 34078 var next; 34079 for (var iRange = 0; iRange < nRanges; iRange++) { 34080 fdIndex = parser.parseCard8(); 34081 next = parser.parseCard16(); 34082 if (fdIndex >= fdArrayCount) { 34083 throw new Error('CFF table CID Font FDSelect has bad FD index value ' + fdIndex + ' (FD count ' + fdArrayCount + ')'); 34084 } 34085 if (next > nGlyphs) { 34086 throw new Error('CFF Table CID Font FDSelect format 3 range has bad GID ' + next); 34087 } 34088 for (; first < next; first++) { 34089 fdSelect.push(fdIndex); 34090 } 34091 first = next; 34092 } 34093 if (next !== nGlyphs) { 34094 throw new Error('CFF Table CID Font FDSelect format 3 range has bad final GID ' + next); 34095 } 34096 } else { 34097 throw new Error('CFF Table CID Font FDSelect table has unsupported format ' + format); 34098 } 34099 return fdSelect; 34100} 34101 34102// Parse the `CFF` table, which contains the glyph outlines in PostScript format. 34103function parseCFFTable(data, start, font) { 34104 font.tables.cff = {}; 34105 var header = parseCFFHeader(data, start); 34106 var nameIndex = parseCFFIndex(data, header.endOffset, parse.bytesToString); 34107 var topDictIndex = parseCFFIndex(data, nameIndex.endOffset); 34108 var stringIndex = parseCFFIndex(data, topDictIndex.endOffset, parse.bytesToString); 34109 var globalSubrIndex = parseCFFIndex(data, stringIndex.endOffset); 34110 font.gsubrs = globalSubrIndex.objects; 34111 font.gsubrsBias = calcCFFSubroutineBias(font.gsubrs); 34112 34113 var topDictArray = gatherCFFTopDicts(data, start, topDictIndex.objects, str
34113ingIndex.objects); 34114 if (topDictArray.length !== 1) { 34115 throw new Error('CFF table has too many fonts in \'FontSet\' - count of fonts NameIndex.length = ' + topDictArray.length); 34116 } 34117 34118 var topDict = topDictArray[0]; 34119 font.tables.cff.topDict = topDict; 34120 34121 if (topDict._privateDict) { 34122 font.defaultWidthX = topDict._privateDict.defaultWidthX; 34123 font.nominalWidthX = topDict._privateDict.nominalWidthX; 34124 } 34125 34126 if (topDict.ros[0] !== undefined && topDict.ros[1] !== undefined) { 34127 font.isCIDFont = true; 34128 } 34129 34130 if (font.isCIDFont) { 34131 var fdArrayOffset = topDict.fdArray; 34132 var fdSelectOffset = topDict.fdSelect; 34133 if (fdArrayOffset === 0 || fdSelectOffset === 0) { 34134 throw new Error('Font is marked as a CID font, but FDArray and/or FDSelect information is missing'); 34135 } 34136 fdArrayOffset += start; 34137 var fdArrayIndex = parseCFFIndex(data, fdArrayOffset); 34138 var fdArray = gatherCFFTopDicts(data, start, fdArrayIndex.objects, stringIndex.objects); 34139 topDict._fdArray = fdArray; 34140 fdSelectOffset += start; 34141 topDict._fdSelect = parseCFFFDSelect(data, fdSelectOffset, font.numGlyphs, fdArray.length); 34142 } 34143 34144 var privateDictOffset = start + topDict.private[1]; 34145 var privateDict = parseCFFPrivateDict(data, privateDictOffset, topDict.private[0], stringIndex.objects); 34146 font.defaultWidthX = privateDict.defaultWidthX; 34147 font.nominalWidthX = privateDict.nominalWidthX; 34148 34149 if (privateDict.subrs !== 0) { 34150 var subrOffset = privateDictOffset + privateDict.subrs; 34151 var subrIndex = parseCFFIndex(data, subrOffset); 34152 font.subrs = subrIndex.objects; 34153 font.subrsBias = calcCFFSubroutineBias(font.subrs); 34154 } else { 34155 font.subrs = []; 34156 font.subrsBias = 0; 34157 } 34158 34159 // Offsets in the top dict are relative to the beginning of the CFF data, so add the CFF start offset. 34160 var charStringsIndex = parseCFFIndex(data, start + topDict.charStrings); 34161 font.nGlyphs = charStringsIndex.objects.length; 34162 34163 var charset = parseCFFCharset(data, start + topDict.charset, font.nGlyphs, stringIndex.objects); 34164 if (topDict.encoding === 0) { // Standard encoding 34165 font.cffEncoding = new CffEncoding(cffStandardEncoding, charset); 34166 } else if (topDict.encoding === 1) { // Expert encoding 34167 font.cffEncoding = new CffEncoding(cffExpertEncoding, charset); 34168 } else { 34169 font.cffEncoding = parseCFFEncoding(data, start + topDict.encoding, charset); 34170 } 34171 34172 // Prefer the CMAP encoding to the CFF encoding. 34173 font.encoding = font.encoding || font.cffEncoding; 34174 34175 font.glyphs = new glyphset.GlyphSet(font); 34176 for (var i = 0; i < font.nGlyphs; i += 1) { 34177 var charString = charStringsIndex.objects[i]; 34178 font.glyphs.push(i, glyphset.cffGlyphLoader(font, i, parseCFFCharstring, charString)); 34179 } 34180} 34181 34182// Convert a string to a String ID (SID). 34183// The list of strings is modified in place. 34184function encodeString(s, strings) { 34185 var sid; 34186 34187 // Is the string in the CFF standard strings? 34188 var i = cffStandardStrings.indexOf(s); 34189 if (i >= 0) { 34190 sid = i; 34191 } 34192 34193 // Is the string already in the string index? 34194 i = strings.indexOf(s); 34195 if (i >= 0) { 34196 sid = i + cffStandardStrings.length; 34197 } else { 34198 sid = cffStandardStrings.length + strings.length; 34199 strings.push(s); 34200 } 34201 34202 return sid; 34203} 34204 34205function makeHeader() { 34206 return new table.Record('Header', [ 34207 {name: 'major', type: 'Card8', value: 1}, 34208 {name: 'minor', type: 'Card8', value: 0}, 34209 {name: 'hdrSize', type: 'Card8', value: 4}, 34210 {name: 'major', type: 'Card8', value: 1} 34211 ]); 34212} 34213 34214function makeNameIndex(fontNames) { 34215 var t = new table.Record('Name INDEX', [ 34216 {name: 'names', type: 'INDEX', value: []} 34217 ]); 34218 t.names = []; 34219 for (var i = 0; i < fontNames.length; i += 1) { 34220 t.names.push({name: 'name_' + i, type: 'NAME', value: fontNames[i]}); 34221 } 34222 34223 return t; 34224} 34225 34226// Given a dictionary's metadata, create a DICT structure. 34227function makeDict(meta, attrs, strings) { 34228 var m = {}; 34229 for (var i = 0; i < meta.length; i += 1) { 34230 var entry = meta[i]; 34231 var value = attrs[entry.name]; 34232 if (value !== undefined && !equals(value, entry.value)) { 34233 if (entry.type === 'SID') { 34234 value = encodeString(value, strings); 34235 } 34236 34237 m[entry.op] = {name: entry.name, type: entry.type, value: value}; 34238 } 34239 } 34240 34241 return m; 34242} 34243 34244// The Top DICT houses the global font attributes. 34245function makeTopDict(attrs, strings) { 34246 var t = new table.Record('Top DICT', [ 34247 {name: 'dict', type: 'DICT', value: {}} 34248 ]); 34249 t.dict = makeDict(TOP_DICT_META, attrs, strings); 34250 return t; 34251} 34252 34253function makeTopDictIndex(topDict) { 34254 var t = new table.Record('Top DICT INDEX', [ 34255 {name: 'topDicts', type: 'INDEX', value: []} 34256 ]); 34257 t.topDicts = [{name: 'topDict_0', type: 'TABLE', value: topDict}]; 34258 return t; 34259} 34260 34261function makeStringIndex(strings) { 34262 var t = new table.Record('String INDEX', [ 34263 {name: 'strings', type: 'INDEX', value: []} 34264 ]); 34265 t.strings = []; 34266 for (var i = 0; i < strings.length; i += 1) { 34267 t.strings.push({name: 'string_' + i, type: 'STRING', value: strings[i]}); 34268 } 34269 34270 return t; 34271} 34272 34273function makeGlobalSubrIndex() { 34274 // Currently we don't use subroutines. 34275 return new table.Record('Global Subr INDEX', [ 34276 {name: 'subrs', type: 'INDEX', value: []} 34277 ]); 34278} 34279
34280function makeCharsets(glyphNames, strings) { 34281 var t = new table.Record('Charsets', [ 34282 {name: 'format', type: 'Card8', value: 0} 34283 ]); 34284 for (var i = 0; i < glyphNames.length; i += 1) { 34285 var glyphName = glyphNames[i]; 34286 var glyphSID = encodeString(glyphName, strings); 34287 t.fields.push({name: 'glyph_' + i, type: 'SID', value: glyphSID}); 34288 } 34289 34290 return t; 34291} 34292 34293function glyphToOps(glyph) { 34294 var ops = []; 34295 var path = glyph.path; 34296 ops.push({name: 'width', type: 'NUMBER', value: glyph.advanceWidth}); 34297 var x = 0; 34298 var y = 0; 34299 for (var i = 0; i < path.commands.length; i += 1) { 34300 var dx = (void 0); 34301 var dy = (void 0); 34302 var cmd = path.commands[i]; 34303 if (cmd.type === 'Q') { 34304 // CFF only supports bézier curves, so convert the quad to a bézier. 34305 var _13 = 1 / 3; 34306 var _23 = 2 / 3; 34307 34308 // We're going to create a new command so we don't change the original path. 34309 cmd = { 34310 type: 'C', 34311 x: cmd.x, 34312 y: cmd.y, 34313 x1: _13 * x + _23 * cmd.x1, 34314 y1: _13 * y + _23 * cmd.y1, 34315 x2: _13 * cmd.x + _23 * cmd.x1, 34316 y2: _13 * cmd.y + _23 * cmd.y1 34317 }; 34318 } 34319 34320 if (cmd.type === 'M') { 34321 dx = Math.round(cmd.x - x); 34322 dy = Math.round(cmd.y - y); 34323 ops.push({name: 'dx', type: 'NUMBER', value: dx}); 34324 ops.push({name: 'dy', type: 'NUMBER', value: dy}); 34325 ops.push({name: 'rmoveto', type: 'OP', value: 21}); 34326 x = Math.round(cmd.x); 34327 y = Math.round(cmd.y); 34328 } else if (cmd.type === 'L') { 34329 dx = Math.round(cmd.x - x); 34330 dy = Math.round(cmd.y - y); 34331 ops.push({name: 'dx', type: 'NUMBER', value: dx}); 34332 ops.push({name: 'dy', type: 'NUMBER', value: dy}); 34333 ops.push({name: 'rlineto', type: 'OP', value: 5}); 34334 x = Math.round(cmd.x); 34335 y = Math.round(cmd.y); 34336 } else if (cmd.type === 'C') { 34337 var dx1 = Math.round(cmd.x1 - x); 34338 var dy1 = Math.round(cmd.y1 - y); 34339 var dx2 = Math.round(cmd.x2 - cmd.x1); 34340 var dy2 = Math.round(cmd.y2 - cmd.y1); 34341 dx = Math.round(cmd.x - cmd.x2); 34342 dy = Math.round(cmd.y - cmd.y2); 34343 ops.push({name: 'dx1', type: 'NUMBER', value: dx1}); 34344 ops.push({name: 'dy1', type: 'NUMBER', value: dy1}); 34345 ops.push({name: 'dx2', type: 'NUMBER', value: dx2}); 34346 ops.push({name: 'dy2', type: 'NUMBER', value: dy2}); 34347 ops.push({name: 'dx', type: 'NUMBER', value: dx}); 34348 ops.push({name: 'dy', type: 'NUMBER', value: dy}); 34349 ops.push({name: 'rrcurveto', type: 'OP', value: 8}); 34350 x = Math.round(cmd.x); 34351 y = Math.round(cmd.y); 34352 } 34353 34354 // Contours are closed automatically. 34355 } 34356 34357 ops.push({name: 'endchar', type: 'OP', value: 14}); 34358 return ops; 34359} 34360 34361function makeCharStringsIndex(glyphs) { 34362 var t = new table.Record('CharStrings INDEX', [ 34363 {name: 'charStrings', type: 'INDEX', value: []} 34364 ]); 34365 34366 for (var i = 0; i < glyphs.length; i += 1) { 34367 var glyph = glyphs.get(i); 34368 var ops = glyphToOps(glyph); 34369 t.charStrings.push({name: glyph.name, type: 'CHARSTRING', value: ops}); 34370 } 34371 34372 return t; 34373} 34374 34375function makePrivateDict(attrs, strings) { 34376 var t = new table.Record('Private DICT', [ 34377 {name: 'dict', type: 'DICT', value: {}} 34378 ]); 34379 t.dict = makeDict(PRIVATE_DICT_META, attrs, strings); 34380 return t; 34381} 34382 34383function makeCFFTable(glyphs, options) { 34384 var t = new table.Table('CFF ', [ 34385 {name: 'header', type: 'RECORD'}, 34386 {name: 'nameIndex', type: 'RECORD'}, 34387 {name: 'topDictIndex', type: 'RECORD'}, 34388 {name: 'stringIndex', type: 'RECORD'}, 34389 {name: 'globalSubrIndex', type: 'RECORD'}, 34390 {name: 'charsets', type: 'RECORD'}, 34391 {name: 'charStringsIndex', type: 'RECORD'}, 34392 {name: 'privateDict', type: 'RECORD'} 34393 ]); 34394 34395 var fontScale = 1 / options.unitsPerEm; 34396 // We use non-zero values for the offsets so that the DICT encodes them. 34397 // This is important because the size of the Top DICT plays a role in offset calculation, 34398 // and the size shouldn't change after we've written correct offsets. 34399 var attrs = { 34400 version: options.version, 34401 fullName: options.fullName, 34402 familyName: options.familyName, 34403 weight: options.weightName, 34404 fontBBox: options.fontBBox || [0, 0, 0, 0], 34405 fontMatrix: [fontScale, 0, 0, fontScale, 0, 0], 34406 charset: 999, 34407 encoding: 0, 34408 charStrings: 999, 34409 private: [0, 999] 34410 }; 34411 34412 var privateAttrs = {}; 34413 34414 var glyphNames = []; 34415 var glyph; 34416 34417 // Skip first glyph (.notdef) 34418 for (var i = 1; i < glyphs.length; i += 1) { 34419 glyph = glyphs.get(i); 34420 glyphNames.push(glyph.name); 34421 } 34422 34423 var strings = []; 34424 34425 t.header = makeHeader(); 34426 t.nameIndex = makeNameIndex([options.postScriptName]); 34427 var topDict = makeTopDict(attrs, strings); 34428 t.topDictIndex = makeTopDictIndex(topDict); 34429 t.globalSubrIndex = makeGlobalSubrIndex();
34430 t.charsets = makeCharsets(glyphNames, strings); 34431 t.charStringsIndex = makeCharStringsIndex(glyphs); 34432 t.privateDict = makePrivateDict(privateAttrs, strings); 34433 34434 // Needs to come at the end, to encode all custom strings used in the font. 34435 t.stringIndex = makeStringIndex(strings); 34436 34437 var startOffset = t.header.sizeOf() + 34438 t.nameIndex.sizeOf() + 34439 t.topDictIndex.sizeOf() + 34440 t.stringIndex.sizeOf() + 34441 t.globalSubrIndex.sizeOf(); 34442 attrs.charset = startOffset; 34443 34444 // We use the CFF standard encoding; proper encoding will be handled in cmap. 34445 attrs.encoding = 0; 34446 attrs.charStrings = attrs.charset + t.charsets.sizeOf(); 34447 attrs.private[1] = attrs.charStrings + t.charStringsIndex.sizeOf(); 34448 34449 // Recreate the Top DICT INDEX with the correct offsets. 34450 topDict = makeTopDict(attrs, strings); 34451 t.topDictIndex = makeTopDictIndex(topDict); 34452 34453 return t; 34454} 34455 34456var cff = { parse: parseCFFTable, make: makeCFFTable }; 34457 34458// The `head` table contains global information about the font. 34459// https://www.microsoft.com/typography/OTSPEC/head.htm 34460 34461// Parse the header `head` table 34462function parseHeadTable(data, start) { 34463 var head = {}; 34464 var p = new parse.Parser(data, start); 34465 head.version = p.parseVersion(); 34466 head.fontRevision = Math.round(p.parseFixed() * 1000) / 1000; 34467 head.checkSumAdjustment = p.parseULong(); 34468 head.magicNumber = p.parseULong(); 34469 check.argument(head.magicNumber === 0x5F0F3CF5, 'Font header has wrong magic number.'); 34470 head.flags = p.parseUShort(); 34471 head.unitsPerEm = p.parseUShort(); 34472 head.created = p.parseLongDateTime(); 34473 head.modified = p.parseLongDateTime(); 34474 head.xMin = p.parseShort(); 34475 head.yMin = p.parseShort(); 34476 head.xMax = p.parseShort(); 34477 head.yMax = p.parseShort(); 34478 head.macStyle = p.parseUShort(); 34479 head.lowestRecPPEM = p.parseUShort(); 34480 head.fontDirectionHint = p.parseShort(); 34481 head.indexToLocFormat = p.parseShort(); 34482 head.glyphDataFormat = p.parseShort(); 34483 return head; 34484} 34485 34486function makeHeadTable(options) { 34487 // Apple Mac timestamp epoch is 01/01/1904 not 01/01/1970 34488 var timestamp = Math.round(new Date().getTime() / 1000) + 2082844800; 34489 var createdTimestamp = timestamp; 34490 34491 if (options.createdTimestamp) { 34492 createdTimestamp = options.createdTimestamp + 2082844800; 34493 } 34494 34495 return new table.Table('head', [ 34496 {name: 'version', type: 'FIXED', value: 0x00010000}, 34497 {name: 'fontRevision', type: 'FIXED', value: 0x00010000}, 34498 {name: 'checkSumAdjustment', type: 'ULONG', value: 0}, 34499 {name: 'magicNumber', type: 'ULONG', value: 0x5F0F3CF5}, 34500 {name: 'flags', type: 'USHORT', value: 0}, 34501 {name: 'unitsPerEm', type: 'USHORT', value: 1000}, 34502 {name: 'created', type: 'LONGDATETIME', value: createdTimestamp}, 34503 {name: 'modified', type: 'LONGDATETIME', value: timestamp}, 34504 {name: 'xMin', type: 'SHORT', value: 0}, 34505 {name: 'yMin', type: 'SHORT', value: 0}, 34506 {name: 'xMax', type: 'SHORT', value: 0}, 34507 {name: 'yMax', type: 'SHORT', value: 0}, 34508 {name: 'macStyle', type: 'USHORT', value: 0}, 34509 {name: 'lowestRecPPEM', type: 'USHORT', value: 0}, 34510 {name: 'fontDirectionHint', type: 'SHORT', value: 2}, 34511 {name: 'indexToLocFormat', type: 'SHORT', value: 0}, 34512 {name: 'glyphDataFormat', type: 'SHORT', value: 0} 34513 ], options); 34514} 34515 34516var head = { parse: parseHeadTable, make: makeHeadTable }; 34517 34518// The `hhea` table contains information for horizontal layout. 34519// https://www.microsoft.com/typography/OTSPEC/hhea.htm 34520 34521// Parse the horizontal header `hhea` table 34522function parseHheaTable(data, start) { 34523 var hhea = {}; 34524 var p = new parse.Parser(data, start); 34525 hhea.version = p.parseVersion(); 34526 hhea.ascender = p.parseShort(); 34527 hhea.descender = p.parseShort(); 34528 hhea.lineGap = p.parseShort(); 34529 hhea.advanceWidthMax = p.parseUShort(); 34530 hhea.minLeftSideBearing = p.parseShort(); 34531 hhea.minRightSideBearing = p.parseShort(); 34532 hhea.xMaxExtent = p.parseShort(); 34533 hhea.caretSlopeRise = p.parseShort(); 34534 hhea.caretSlopeRun = p.parseShort();
34535 hhea.caretOffset = p.parseShort(); 34536 p.relativeOffset += 8; 34537 hhea.metricDataFormat = p.parseShort(); 34538 hhea.numberOfHMetrics = p.parseUShort(); 34539 return hhea; 34540} 34541 34542function makeHheaTable(options) { 34543 return new table.Table('hhea', [ 34544 {name: 'version', type: 'FIXED', value: 0x00010000}, 34545 {name: 'ascender', type: 'FWORD', value: 0}, 34546 {name: 'descender', type: 'FWORD', value: 0}, 34547 {name: 'lineGap', type: 'FWORD', value: 0}, 34548 {name: 'advanceWidthMax', type: 'UFWORD', value: 0}, 34549 {name: 'minLeftSideBearing', type: 'FWORD', value: 0}, 34550 {name: 'minRightSideBearing', type: 'FWORD', value: 0}, 34551 {name: 'xMaxExtent', type: 'FWORD', value: 0}, 34552 {name: 'caretSlopeRise', type: 'SHORT', value: 1}, 34553 {name: 'caretSlopeRun', type: 'SHORT', value: 0}, 34554 {name: 'caretOffset', type: 'SHORT', value: 0}, 34555 {name: 'reserved1', type: 'SHORT', value: 0}, 34556 {name: 'reserved2', type: 'SHORT', value: 0}, 34557 {name: 'reserved3', type: 'SHORT', value: 0}, 34558 {name: 'reserved4', type: 'SHORT', value: 0}, 34559 {name: 'metricDataFormat', type: 'SHORT', value: 0}, 34560 {name: 'numberOfHMetrics', type: 'USHORT', value: 0} 34561 ], options); 34562} 34563 34564var hhea = { parse: parseHheaTable, make: makeHheaTable }; 34565 34566// The `hmtx` table contains the horizontal metrics for all glyphs. 34567// https://www.microsoft.com/typography/OTSPEC/hmtx.htm 34568 34569// Parse the `hmtx` table, which contains the horizontal metrics for all glyphs. 34570// This function augments the glyph array, adding the advanceWidth and leftSideBearing to each glyph. 34571function parseHmtxTable(data, start, numMetrics, numGlyphs, glyphs) { 34572 var advanceWidth; 34573 var leftSideBearing; 34574 var p = new parse.Parser(data, start); 34575 for (var i = 0; i < numGlyphs; i += 1) { 34576 // If the font is monospaced, only one entry is needed. This last entry applies to all subsequent glyphs. 34577 if (i < numMetrics) { 34578 advanceWidth = p.parseUShort(); 34579 leftSideBearing = p.parseShort(); 34580 } 34581 34582 var glyph = glyphs.get(i); 34583 glyph.advanceWidth = advanceWidth; 34584 glyph.leftSideBearing = leftSideBearing; 34585 } 34586} 34587 34588function makeHmtxTable(glyphs) { 34589 var t = new table.Table('hmtx', []); 34590 for (var i = 0; i < glyphs.length; i += 1) { 34591 var glyph = glyphs.get(i); 34592 var advanceWidth = glyph.advanceWidth || 0; 34593 var leftSideBearing = glyph.leftSideBearing || 0; 34594 t.fields.push({name: 'advanceWidth_' + i, type: 'USHORT', value: advanceWidth}); 34595 t.fields.push({name: 'leftSideBearing_' + i, type: 'SHORT', value: leftSideBearing}); 34596 } 34597 34598 return t; 34599} 34600 34601var hmtx = { parse: parseHmtxTable, make: makeHmtxTable }; 34602 34603// The `ltag` table stores IETF BCP-47 language tags. It allows supporting 34604// languages for which TrueType does not assign a numeric code. 34605// https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6ltag.html 34606// http://www.w3.org/International/articles/language-tags/ 34607// http://www.iana.org/assignments/language-subtag-registry/language-subtag-registry 34608 34609function makeLtagTable(tags) { 34610 var result = new table.Table('ltag', [ 34611 {name: 'version', type: 'ULONG', value: 1}, 34612 {name: 'flags', type: 'ULONG', value: 0}, 34613 {name: 'numTags', type: 'ULONG', value: tags.length} 34614 ]); 34615 34616 var stringPool = ''; 34617 var stringPoolOffset = 12 + tags.length * 4; 34618 for (var i = 0; i < tags.length; ++i) { 34619 var pos = stringPool.indexOf(tags[i]); 34620 if (pos < 0) { 34621 pos = stringPool.length; 34622 stringPool += tags[i]; 34623 } 34624 34625 result.fields.push({name: 'offset ' + i, type: 'USHORT', value: stringPoolOffset + pos}); 34626 result.fields.push({name: 'length ' + i, type: 'USHORT', value: tags[i].length}); 34627 } 34628 34629 result.fields.push({name: 'stringPool', type: 'CHARARRAY', value: stringPool}); 34630 return result; 34631} 34632 34633function parseLtagTable(data, start) { 34634 var p = new parse.Parser(data, start); 34635 var tableVersion = p.parseULong(); 34636 check.argument(tableVersion === 1, 'Unsupported ltag table version.'); 34637 // The 'ltag' specification does not define any flags; skip the field. 34638 p.skip('uLong', 1); 34639 var numTags = p.parseULong(); 34640 34641 var tags = []; 34642 for (var i = 0; i < numTags; i++) { 34643 var tag = ''; 34644 var offset = start + p.parseUShort(); 34645 var length = p.parseUShort(); 34646 for (var j = offset; j < offset + length; ++j) { 34647 tag += String.fromCharCode(data.getInt8(j)); 34648 } 34649 34650 tags.push(tag); 34651 } 34652 34653 return tags; 34654} 34655 34656var ltag = { make: makeLtagTable, parse: parseLtagTable }; 34657 34658// The `maxp` table establishes the memory requirements for the font. 34659// We need it just to get the number of glyphs in the font. 34660// https://www.microsoft.com/typography/OTSPEC/maxp.htm 34661 34662// Parse the maximum profile `maxp` table. 34663function parseMaxpTable(data, start) { 34664 var maxp = {}; 34665 var p = new parse.Parser(data, start); 34666 maxp.version = p.parseVersion(); 34667 maxp.numGlyphs = p.parseUShort(); 34668 if (maxp.version === 1.0) { 34669 maxp.maxPoints = p.parseUShort(); 34670 maxp.maxContours = p.parseUShort(); 34671 maxp.maxCompositePoints = p.parseUShort(); 34672 maxp.maxCompositeContours = p.parseUShort(); 34673 maxp.maxZones = p.parseUShort(); 34674 maxp.maxTwilightPoints = p.parseUShort(); 34675 maxp.maxStorage = p.parseUShort(); 34676 maxp.maxFunctionDefs = p.parseUShort(); 34677 maxp.maxInstructionDefs = p.parseUShort(); 34678 maxp.maxStackElements = p.parseUShort();
34679 maxp.maxSizeOfInstructions = p.parseUShort(); 34680 maxp.maxComponentElements = p.parseUShort(); 34681 maxp.maxComponentDepth = p.parseUShort(); 34682 } 34683 34684 return maxp; 34685} 34686 34687function makeMaxpTable(numGlyphs) { 34688 return new table.Table('maxp', [ 34689 {name: 'version', type: 'FIXED', value: 0x00005000}, 34690 {name: 'numGlyphs', type: 'USHORT', value: numGlyphs} 34691 ]); 34692} 34693 34694var maxp = { parse: parseMaxpTable, make: makeMaxpTable }; 34695 34696// The `name` naming table. 34697// https://www.microsoft.com/typography/OTSPEC/name.htm 34698 34699// NameIDs for the name table. 34700var nameTableNames = [ 34701 'copyright', // 0 34702 'fontFamily', // 1 34703 'fontSubfamily', // 2 34704 'uniqueID', // 3 34705 'fullName', // 4 34706 'version', // 5 34707 'postScriptName', // 6 34708 'trademark', // 7 34709 'manufacturer', // 8 34710 'designer', // 9 34711 'description', // 10 34712 'manufacturerURL', // 11 34713 'designerURL', // 12 34714 'license', // 13 34715 'licenseURL', // 14 34716 'reserved', // 15 34717 'preferredFamily', // 16 34718 'preferredSubfamily', // 17 34719 'compatibleFullName', // 18 34720 'sampleText', // 19 34721 'postScriptFindFontName', // 20 34722 'wwsFamily', // 21 34723 'wwsSubfamily' // 22 34724]; 34725 34726var macLanguages = { 34727 0: 'en', 34728 1: 'fr', 34729 2: 'de', 34730 3: 'it', 34731 4: 'nl', 34732 5: 'sv', 34733 6: 'es', 34734 7: 'da', 34735 8: 'pt', 34736 9: 'no', 34737 10: 'he', 34738 11: 'ja', 34739 12: 'ar', 34740 13: 'fi', 34741 14: 'el', 34742 15: 'is', 34743 16: 'mt', 34744 17: 'tr', 34745 18: 'hr', 34746 19: 'zh-Hant', 34747 20: 'ur', 34748 21: 'hi', 34749 22: 'th', 34750 23: 'ko', 34751 24: 'lt', 34752 25: 'pl', 34753 26: 'hu', 34754 27: 'es', 34755 28: 'lv', 34756 29: 'se', 34757 30: 'fo', 34758 31: 'fa', 34759 32: 'ru', 34760 33: 'zh', 34761 34: 'nl-BE', 34762 35: 'ga', 34763 36: 'sq', 34764 37: 'ro', 34765 38: 'cz', 34766 39: 'sk', 34767 40: 'si', 34768 41: 'yi', 34769 42: 'sr', 34770 43: 'mk', 34771 44: 'bg', 34772 45: 'uk', 34773 46: 'be', 34774 47: 'uz', 34775 48: 'kk', 34776 49: 'az-Cyrl', 34777 50: 'az-Arab', 34778 51: 'hy', 34779 52: 'ka', 34780 53: 'mo', 34781 54: 'ky', 34782 55: 'tg', 34783 56: 'tk', 34784 57: 'mn-CN', 34785 58: 'mn', 34786 59: 'ps', 34787 60: 'ks', 34788 61: 'ku', 34789 62: 'sd', 34790 63: 'bo', 34791 64: 'ne', 34792 65: 'sa', 34793 66: 'mr', 34794 67: 'bn', 34795 68: 'as', 34796 69: 'gu', 34797 70: 'pa', 34798 71: 'or', 34799 72: 'ml', 34800 73: 'kn', 34801 74: 'ta', 34802 75: 'te', 34803 76: 'si', 34804 77: 'my', 34805 78: 'km', 34806 79: 'lo', 34807 80: 'vi', 34808 81: 'id', 34809 82: 'tl', 34810 83: 'ms', 34811 84: 'ms-Arab', 34812 85: 'am', 34813 86: 'ti', 34814 87: 'om', 34815 88: 'so', 34816 89: 'sw', 34817 90: 'rw', 34818 91: 'rn', 34819 92: 'ny', 34820 93: 'mg', 34821 94: 'eo', 34822 128: 'cy', 34823 129: 'eu', 34824 130: 'ca', 34825 131: 'la', 34826 132: 'qu', 34827 133: 'gn', 34828 134: 'ay', 34829 135: 'tt', 34830 136: 'ug', 34831 137: 'dz', 34832 138: 'jv', 34833 139: 'su', 34834 140: 'gl', 34835 141: 'af', 34836 142: 'br', 34837 143: 'iu', 34838 144: 'gd', 34839 145: 'gv', 34840 146: 'ga', 34841 147: 'to', 34842 148: 'el-polyton', 34843 149: 'kl', 34844 150: 'az', 34845 151: 'nn' 34846}; 34847 34848// MacOS language ID â MacOS script ID 34849// 34850// Note that the script ID is not sufficient to determine what encoding 34851// to use in TrueType files. For some languages, MacOS used a modification 34852// of a mainstream script. For example, an Icelandic name would be stored 34853// with smRoman in the TrueType naming table, but the actual encoding 34854// is a special Icelandic version of the normal Macintosh Roman encoding. 34855// As another example, Inuktitut uses an 8-bit encoding for Canadian Aboriginal 34856// Syllables but MacOS had run out of available script codes, so this was 34857// done as a (pretty radical) "modification" of Ethiopic. 34858// 34859// http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/Readme.txt 34860var macLanguageToScript = { 34861 0: 0, // langEnglish â smRoman 34862 1: 0, // langFrench â smRoman 34863 2: 0, // langGerman â smRoman 34864 3: 0, // langItalian â smRoman 34865 4: 0, // langDutch â smRoman 34866 5: 0, // langSwedish â smRoman 34867 6: 0, // langSpanish â smRoman 34868 7: 0, // langDanish â smRoman 34869 8: 0, // langPortuguese â smRoman 34870 9: 0, // langNorwegian â smRoman 34871 10: 5, // langHebrew â smHebrew 34872 11: 1, // langJapanese â smJapanese 34873 12: 4, // langArabic â smArabic 34874 13: 0, // langFinnish â smRoman 34875 14: 6, // langGreek â smGreek 34876 15: 0, // langIcelandic â smRoman (modified) 34877 16: 0, // langMaltese â smRoman 34878 17: 0, // langTurkish â smRoman (modified) 34879 18: 0, // langCroatian â smRoman (modified) 34880 19: 2, // langTradChinese â smTradChinese 34881 20: 4, // langUrdu â smArabic 34882 21: 9, // langHindi â smDevanagari
34883 22: 21, // langThai â smThai 34884 23: 3, // langKorean â smKorean 34885 24: 29, // langLithuanian â smCentralEuroRoman 34886 25: 29, // langPolish â smCentralEuroRoman 34887 26: 29, // langHungarian â smCentralEuroRoman 34888 27: 29, // langEstonian â smCentralEuroRoman 34889 28: 29, // langLatvian â smCentralEuroRoman 34890 29: 0, // langSami â smRoman 34891 30: 0, // langFaroese â smRoman (modified) 34892 31: 4, // langFarsi â smArabic (modified) 34893 32: 7, // langRussian â smCyrillic 34894 33: 25, // langSimpChinese â smSimpChinese 34895 34: 0, // langFlemish â smRoman 34896 35: 0, // langIrishGaelic â smRoman (modified) 34897 36: 0, // langAlbanian â smRoman 34898 37: 0, // langRomanian â smRoman (modified) 34899 38: 29, // langCzech â smCentralEuroRoman 34900 39: 29, // langSlovak â smCentralEuroRoman 34901 40: 0, // langSlovenian â smRoman (modified) 34902 41: 5, // langYiddish â smHebrew 34903 42: 7, // langSerbian â smCyrillic 34904 43: 7, // langMacedonian â smCyrillic 34905 44: 7, // langBulgarian â smCyrillic 34906 45: 7, // langUkrainian â smCyrillic (modified) 34907 46: 7, // langByelorussian â smCyrillic 34908 47: 7, // langUzbek â smCyrillic 34909 48: 7, // langKazakh â smCyrillic 34910 49: 7, // langAzerbaijani â smCyrillic 34911 50: 4, // langAzerbaijanAr â smArabic 34912 51: 24, // langArmenian â smArmenian 34913 52: 23, // langGeorgian â smGeorgian 34914 53: 7, // langMoldavian â smCyrillic 34915 54: 7, // langKirghiz â smCyrillic 34916 55: 7, // langTajiki â smCyrillic 34917 56: 7, // langTurkmen â smCyrillic 34918 57: 27, // langMongolian â smMongolian 34919 58: 7, // langMongolianCyr â smCyrillic 34920 59: 4, // langPashto â smArabic 34921 60: 4, // langKurdish â smArabic 34922 61: 4, // langKashmiri â smArabic 34923 62: 4, // langSindhi â smArabic 34924 63: 26, // langTibetan â smTibetan 34925 64: 9, // langNepali â smDevanagari 34926 65: 9, // langSanskrit â smDevanagari 34927 66: 9, // langMarathi â smDevanagari 34928 67: 13, // langBengali â smBengali 34929 68: 13, // langAssamese â smBengali 34930 69: 11, // langGujarati â smGujarati 34931 70: 10, // langPunjabi â smGurmukhi 34932 71: 12, // langOriya â smOriya 34933 72: 17, // langMalayalam â smMalayalam 34934 73: 16, // langKannada â smKannada 34935 74: 14, // langTamil â smTamil 34936 75: 15, // langTelugu â smTelugu 34937 76: 18, // langSinhalese â smSinhalese 34938 77: 19, // langBurmese â smBurmese 34939 78: 20, // langKhmer â smKhmer 34940 79: 22, // langLao â smLao 34941 80: 30, // langVietnamese â smVietnamese 34942 81: 0, // langIndonesian â smRoman 34943 82: 0, // langTagalog â smRoman 34944 83: 0, // langMalayRoman â smRoman 34945 84: 4, // langMalayArabic â smArabic 34946 85: 28, // langAmharic â smEthiopic 34947 86: 28, // langTigrinya â smEthiopic 34948 87: 28, // langOromo â smEthiopic 34949 88: 0, // langSomali â smRoman 34950 89: 0, // langSwahili â smRoman 34951 90: 0, // langKinyarwanda â smRoman 34952 91: 0, // langRundi â smRoman 34953 92: 0, // langNyanja â smRoman 34954 93: 0, // langMalagasy â smRoman 34955 94: 0, // langEsperanto â smRoman 34956 128: 0, // langWelsh â smRoman (modified) 34957 129: 0, // langBasque â smRoman 34958 130: 0, // langCatalan â smRoman 34959 131: 0, // langLatin â smRoman 34960 132: 0, // langQuechua â smRoman 34961 133: 0, // langGuarani â smRoman 34962 134: 0, // langAymara â smRoman 34963 135: 7, // langTatar â smCyrillic 34964 136: 4, // langUighur â smArabic 34965 137: 26, // langDzongkha â smTibetan 34966 138: 0, // langJavaneseRom â smRoman 34967 139: 0, // langSundaneseRom â smRoman 34968 140: 0, // langGalician â smRoman 34969 141: 0, // langAfrikaans â smRoman 34970 142: 0, // langBreton â smRoman (modified) 34971 143: 28, // langInuktitut â smEthiopic (modified) 34972 144: 0, // langScottishGaelic â smRoman (modified) 34973 145: 0, // langManxGaelic â smRoman (modified) 34974 146: 0, // langIrishGaelicScript â smRoman (modified) 34975 147: 0, // langTongan â smRoman 34976 148: 6, // langGreekAncient â smRoman 34977 149: 0, // langGreenlandic â smRoman 34978 150: 0, // langAzerbaijanRoman â smRoman 34979 151: 0 // langNynorsk â smRoman 34980}; 34981 34982// While Microsoft indicates a region/country for all its language 34983// IDs, we omit the region code if it's equal to the "most likely 34984// region subtag" according to Unicode CLDR. For scripts, we omit 34985// the subtag if it is equal to the Suppress-Script entry in the 34986// IANA language subtag registry for IETF BCP 47. 34987// 34988// For example, Microsoft states that its language code 0x041A is 34989// Croatian in Croatia. We transform this to the BCP 47 language code 'hr' 34990// and not 'hr-HR' because Croatia is the default country for Croatian, 34991// according to Unicode CLDR. As another example, Microsoft states 34992// that 0x101A is Croatian (Latin) in Bosnia-Herzegovina. We transform 34993// this to 'hr-BA' and not 'hr-Latn-BA' because Latin is the default script 34994// for the Croatian language, according to IANA. 34995//
34996// http://www.unicode.org/cldr/charts/latest/supplemental/likely_subtags.html 34997// http://www.iana.org/assignments/language-subtag-registry/language-subtag-registry 34998var windowsLanguages = { 34999 0x0436: 'af', 35000 0x041C: 'sq', 35001 0x0484: 'gsw', 35002 0x045E: 'am', 35003 0x1401: 'ar-DZ', 35004 0x3C01: 'ar-BH', 35005 0x0C01: 'ar', 35006 0x0801: 'ar-IQ', 35007 0x2C01: 'ar-JO', 35008 0x3401: 'ar-KW', 35009 0x3001: 'ar-LB', 35010 0x1001: 'ar-LY', 35011 0x1801: 'ary', 35012 0x2001: 'ar-OM', 35013 0x4001: 'ar-QA', 35014 0x0401: 'ar-SA', 35015 0x2801: 'ar-SY', 35016 0x1C01: 'aeb', 35017 0x3801: 'ar-AE', 35018 0x2401: 'ar-YE', 35019 0x042B: 'hy', 35020 0x044D: 'as', 35021 0x082C: 'az-Cyrl', 35022 0x042C: 'az', 35023 0x046D: 'ba', 35024 0x042D: 'eu', 35025 0x0423: 'be', 35026 0x0845: 'bn', 35027 0x0445: 'bn-IN', 35028 0x201A: 'bs-Cyrl', 35029 0x141A: 'bs', 35030 0x047E: 'br', 35031 0x0402: 'bg', 35032 0x0403: 'ca', 35033 0x0C04: 'zh-HK', 35034 0x1404: 'zh-MO', 35035 0x0804: 'zh', 35036 0x1004: 'zh-SG', 35037 0x0404: 'zh-TW', 35038 0x0483: 'co', 35039 0x041A: 'hr', 35040 0x101A: 'hr-BA', 35041 0x0405: 'cs', 35042 0x0406: 'da', 35043 0x048C: 'prs', 35044 0x0465: 'dv', 35045 0x0813: 'nl-BE', 35046 0x0413: 'nl', 35047 0x0C09: 'en-AU', 35048 0x2809: 'en-BZ', 35049 0x1009: 'en-CA', 35050 0x2409: 'en-029', 35051 0x4009: 'en-IN', 35052 0x1809: 'en-IE', 35053 0x2009: 'en-JM', 35054 0x4409: 'en-MY', 35055 0x1409: 'en-NZ', 35056 0x3409: 'en-PH', 35057 0x4809: 'en-SG', 35058 0x1C09: 'en-ZA', 35059 0x2C09: 'en-TT', 35060 0x0809: 'en-GB', 35061 0x0409: 'en', 35062 0x3009: 'en-ZW', 35063 0x0425: 'et', 35064 0x0438: 'fo', 35065 0x0464: 'fil', 35066 0x040B: 'fi', 35067 0x080C: 'fr-BE', 35068 0x0C0C: 'fr-CA', 35069 0x040C: 'fr', 35070 0x140C: 'fr-LU', 35071 0x180C: 'fr-MC', 35072 0x100C: 'fr-CH', 35073 0x0462: 'fy', 35074 0x0456: 'gl', 35075 0x0437: 'ka', 35076 0x0C07: 'de-AT', 35077 0x0407: 'de', 35078 0x1407: 'de-LI', 35079 0x1007: 'de-LU', 35080 0x0807: 'de-CH', 35081 0x0408: 'el', 35082 0x046F: 'kl', 35083 0x0447: 'gu', 35084 0x0468: 'ha', 35085 0x040D: 'he', 35086 0x0439: 'hi', 35087 0x040E: 'hu', 35088 0x040F: 'is', 35089 0x0470: 'ig', 35090 0x0421: 'id', 35091 0x045D: 'iu', 35092 0x085D: 'iu-Latn', 35093 0x083C: 'ga', 35094 0x0434: 'xh', 35095 0x0435: 'zu', 35096 0x0410: 'it', 35097 0x0810: 'it-CH', 35098 0x0411: 'ja', 35099 0x044B: 'kn', 35100 0x043F: 'kk',
35101 0x0453: 'km', 35102 0x0486: 'quc', 35103 0x0487: 'rw', 35104 0x0441: 'sw', 35105 0x0457: 'kok', 35106 0x0412: 'ko', 35107 0x0440: 'ky', 35108 0x0454: 'lo', 35109 0x0426: 'lv', 35110 0x0427: 'lt', 35111 0x082E: 'dsb', 35112 0x046E: 'lb', 35113 0x042F: 'mk', 35114 0x083E: 'ms-BN', 35115 0x043E: 'ms', 35116 0x044C: 'ml', 35117 0x043A: 'mt', 35118 0x0481: 'mi', 35119 0x047A: 'arn', 35120 0x044E: 'mr', 35121 0x047C: 'moh', 35122 0x0450: 'mn', 35123 0x0850: 'mn-CN', 35124 0x0461: 'ne', 35125 0x0414: 'nb', 35126 0x0814: 'nn', 35127 0x0482: 'oc', 35128 0x0448: 'or', 35129 0x0463: 'ps', 35130 0x0415: 'pl', 35131 0x0416: 'pt', 35132 0x0816: 'pt-PT', 35133 0x0446: 'pa', 35134 0x046B: 'qu-BO', 35135 0x086B: 'qu-EC', 35136 0x0C6B: 'qu', 35137 0x0418: 'ro', 35138 0x0417: 'rm', 35139 0x0419: 'ru', 35140 0x243B: 'smn', 35141 0x103B: 'smj-NO', 35142 0x143B: 'smj', 35143 0x0C3B: 'se-FI', 35144 0x043B: 'se', 35145 0x083B: 'se-SE', 35146 0x203B: 'sms', 35147 0x183B: 'sma-NO', 35148 0x1C3B: 'sms', 35149 0x044F: 'sa', 35150 0x1C1A: 'sr-Cyrl-BA', 35151 0x0C1A: 'sr', 35152 0x181A: 'sr-Latn-BA', 35153 0x081A: 'sr-Latn', 35154 0x046C: 'nso', 35155 0x0432: 'tn', 35156 0x045B: 'si', 35157 0x041B: 'sk', 35158 0x0424: 'sl', 35159 0x2C0A: 'es-AR', 35160 0x400A: 'es-BO', 35161 0x340A: 'es-CL', 35162 0x240A: 'es-CO', 35163 0x140A: 'es-CR', 35164 0x1C0A: 'es-DO', 35165 0x300A: 'es-EC', 35166 0x440A: 'es-SV', 35167 0x100A: 'es-GT', 35168 0x480A: 'es-HN', 35169 0x080A: 'es-MX', 35170 0x4C0A: 'es-NI', 35171 0x180A: 'es-PA', 35172 0x3C0A: 'es-PY', 35173 0x280A: 'es-PE', 35174 0x500A: 'es-PR', 35175 35176 // Microsoft has defined two different language codes for 35177 // âSpanish with modern sortingâ and âSpanish with traditional 35178 // sortingâ. This makes sense for collation APIs, and it would be 35179 // possible to express this in BCP 47 language tags via Unicode 35180 // extensions (eg., es-u-co-trad is Spanish with traditional 35181 // sorting). However, for storing names in fonts, the distinction 35182 // does not make sense, so we give âesâ in both cases. 35183 0x0C0A: 'es', 35184 0x040A: 'es', 35185 35186 0x540A: 'es-US', 35187 0x380A: 'es-UY', 35188 0x200A: 'es-VE', 35189 0x081D: 'sv-FI', 35190 0x041D: 'sv', 35191 0x045A: 'syr', 35192 0x0428: 'tg', 35193 0x085F: 'tzm', 35194 0x0449: 'ta', 35195 0x0444: 'tt', 35196 0x044A: 'te', 35197 0x041E: 'th', 35198 0x0451: 'bo', 35199 0x041F: 'tr', 35200 0x0442: 'tk', 35201 0x0480: 'ug', 35202 0x0422: 'uk', 35203 0x042E: 'hsb', 35204 0x0420: 'ur', 35205 0x0843: 'uz-Cyrl', 35206 0x0443: 'uz', 35207 0x042A: 'vi', 35208 0x0452: 'cy', 35209 0x0488: 'wo', 35210 0x0485: 'sah', 35211 0x0478: 'ii', 35212 0x046A: 'yo' 35213}; 35214 35215// Returns a IETF BCP 47 language code, for example 'zh-Hant' 35216// for 'Chinese in the traditional script'. 35217function getLanguageCode(platformID, languageID, ltag) { 35218 switch (platformID) { 35219 case 0: // Unicode 35220 if (languageID === 0xFFFF) { 35221 return 'und'; 35222 } else if (ltag) { 35223 return ltag[languageID]; 35224 } 35225 35226 break; 35227 35228 case 1: // Macintosh 35229 return macLanguages[languageID]; 35230 35231 case 3: // Windows 35232 return windowsLanguages[languageID]; 35233 } 35234 35235 return undefined; 35236} 35237 35238var utf16 = 'utf-16'; 35239 35240// MacOS script ID â encoding. This table stores the default case, 35241// which can be overridden by macLanguageEncodings. 35242var macScriptEncodings = { 35243 0: 'macintosh', // smRoman 35244 1: 'x-mac-japanese', // smJapanese 35245 2: 'x-mac-chinesetrad', // smTradChinese 35246 3: 'x-mac-korean', // smKorean 35247 6: 'x-mac-greek', // smGreek 35248 7: 'x-mac-cyrillic', // smCyrillic 35249 9: 'x-mac-devanagai', // smDevanagari 35250 10: 'x-mac-gurmukhi', // smGurmukhi 35251 11: 'x-mac-gujarati', // smGujarati 35252 12: 'x-mac-oriya', // smOriya 35253 13: 'x-mac-bengali', // smBengali 35254 14: 'x-mac-tamil', // smTamil 35255 15: 'x-mac-telugu', // smTelugu 35256 16: 'x-mac-kannada', // smKannada 35257 17: 'x-mac-malayalam', // smMalayalam 35258 18: 'x-mac-sinhalese', // smSinhalese 35259 19: 'x-mac-burmese', // smBurmese 35260 20: 'x-mac-khmer', // smKhmer 35261 21: 'x-mac-thai', // smThai 35262 22: 'x-mac-lao', // smLao 35263 23: 'x-mac-georgian', // smGeorgian 35264 24: 'x-mac-armenian', // smArmenian 35265 25: 'x-mac-chinesesimp', // smSimpChinese 35266 26: 'x-mac-tibetan', // smTibetan 35267 27: 'x-mac-mongolian', // smMongolian 35268 28: 'x-mac-ethiopic', // smEthiopic 35269 29: 'x-mac-ce', // smCentralEuroRoman 35270 30: 'x-mac-vietnamese', // smVietnamese 35271 31: 'x-mac-extarabic' // smExtArabic 35272}; 35273 35274// MacOS language ID â encoding. This table stores the exceptional 35275// cases, which override macScriptEncodings. For writing MacOS naming 35276// tables, we need to emit a MacOS script ID. Therefore, we cannot 35277// merge macScriptEncodings into macLanguageEncodings. 35278// 35279// http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/Readme.txt 35280var macLanguageEncodings = { 35281 15: 'x-mac-icelandic', // langIcelandic 35282 17: 'x-mac-turkish', // langTurkish 35283 18: 'x-mac-croatian', // langCroatian 35284 24: 'x-mac-ce', // langLithuanian 35285 25: 'x-mac-ce', // langPolish 35286 26: 'x-mac-ce', // langHungarian 35287 27: 'x-mac-ce', // langEstonian 35288 28: 'x-mac-ce', // langLatvian 35289 30: 'x-mac-icelandic', // langFaroese 35290 37: 'x-mac-romanian', // langRomanian 35291 38: 'x-mac-ce', // langCzech 35292 39: 'x-mac-ce', // langSlovak 35293 40: 'x-mac-ce', // langSlovenian 35294 143: 'x-mac-inuit', // langInuktitut 35295 146: 'x-mac-gaelic' // langIrishGaelicScript 35296}; 35297 35298function getEncoding(platformID, encodingID, languageID) { 35299 switch (platformID) { 35300 case 0: // Unicode 35301 return utf16; 35302 35303 case 1: // Apple Macintosh 35304 return macLanguageEncodings[languageID] || macScriptEncodings[encodingID]; 35305 35306 case 3: // Microsoft Windows 35307 if (encodingID === 1 || encodingID === 10) { 35308 return utf16; 35309 } 35310 35311 break; 35312 } 35313 35314 return undefined; 35315} 35316 35317// Parse the naming `name` table. 35318// FIXME: Format 1 additional fields are not supported yet. 35319// ltag is the content of the `ltag' table, such as ['en', 'zh-Hans', 'de-CH-1904']. 35320function parseNameTable(data, start, ltag) { 35321 var name = {}; 35322 var p = new parse.Parser(data, start); 35323 var format = p.parseUShort(); 35324 var count = p.parseUShort(); 35325 var stringOffset = p.offset + p.parseUShort(); 35326 for (var i = 0; i < count; i++) { 35327 var platformID = p.parseUShort(); 35328 var encodingID = p.parseUShort(); 35329 var languageID = p.parseUShort(); 35330 var nameID = p.parseUShort(); 35331 var property = nameTableNames[nameID] || nameID; 35332 var byteLength = p.parseUShort(); 35333 var offset = p.parseUShort(); 35334 var language = getLanguageCode(platformID, languageID, ltag); 35335 var encoding = getEncoding(platformID, encodingID, languageID); 35336 if (encoding !== undefined && language !== undefined) { 35337 var text = (void 0); 35338 if (encoding === utf16) { 35339 text = decode.UTF16(data, stringOffset + offset, byteLength); 35340 } else { 35341 text = decode.MACSTRING(data, stringOffset + offset, byteLength, encoding); 35342 } 35343 35344 if (text) { 35345 var translations = name[property]; 35346 if (translations === undefined) { 35347 translations = name[property] = {}; 35348 } 35349 35350 translations[language] = text; 35351 } 35352 } 35353 } 35354 35355 var langTagCount = 0; 35356 if (format === 1) { 35357 // FIXME: Also handle Microsoft's 'name' table 1. 35358 langTagCount = p.parseUShort(); 35359 } 35360 35361 return name; 35362} 35363 35364// {23: 'foo'} â {'foo': 23} 35365// ['bar', 'baz'] â {'bar': 0, 'baz': 1} 35366function reverseDict(dict) { 35367 var result = {}; 35368 for (var key in dict) { 35369 result[dict[key]] = parseInt(key); 35370 } 35371 35372 return result; 35373} 35374 35375function makeNameRecord(platformID, encodingID, languageID, nameID, length, offset) { 35376 return new table.Record('NameRecord', [ 35377 {name: 'platformID', type: 'USHORT', value: platformID}, 35378 {name: 'encodingID', type: 'USHORT', value: encodingID}, 35379 {name: 'languageID', type: 'USHORT', value: languageID}, 35380 {name: 'nameID', type: 'USHORT', value: nameID}, 35381 {name: 'length', type: 'USHORT', value: length}, 35382 {name: 'offset', type: 'USHORT', value: offset} 35383 ]); 35384} 35385 35386// Finds the position of needle in haystack, or -1 if not there. 35387// Like String.indexOf(), but for arrays. 35388function findSubArray(needle, haystack) { 35389 var needleLength = needle.length; 35390 var limit = haystack.length - needleLength + 1; 35391 35392 loop: 35393 for (var pos = 0; pos < limit; pos++) { 35394 for (; pos < limit; pos++) { 35395 for (var k = 0; k < needleLength; k++) { 35396 if (haystack[pos + k] !== needle[k]) { 35397 continue loop; 35398 } 35399 } 35400 35401 return pos; 35402 } 35403 } 35404 35405 return -1; 35406} 35407 35408function addStringToPool(s, pool) { 35409 var offset = findSubArray(s, pool); 35410 if (offset < 0) { 35411 offset = pool.length; 35412 var i = 0; 35413 var len = s.length; 35414 for (; i < len; ++i) { 35415 pool.push(s[i]); 35416 } 35417 35418 } 35419 35420 return offset; 35421} 35422 35423function makeNameTable(names, ltag) { 35424 var nameID; 35425 var nameIDs = []; 35426 35427 var namesWithNumericKeys = {}; 35428 var nameTableIds = reverseDict(nameTableNames); 35429 for (var key in names) {
35430 var id = nameTableIds[key]; 35431 if (id === undefined) { 35432 id = key; 35433 } 35434 35435 nameID = parseInt(id); 35436 35437 if (isNaN(nameID)) { 35438 throw new Error('Name table entry "' + key + '" does not exist, see nameTableNames for complete list.'); 35439 } 35440 35441 namesWithNumericKeys[nameID] = names[key]; 35442 nameIDs.push(nameID); 35443 } 35444 35445 var macLanguageIds = reverseDict(macLanguages); 35446 var windowsLanguageIds = reverseDict(windowsLanguages); 35447 35448 var nameRecords = []; 35449 var stringPool = []; 35450 35451 for (var i = 0; i < nameIDs.length; i++) { 35452 nameID = nameIDs[i]; 35453 var translations = namesWithNumericKeys[nameID]; 35454 for (var lang in translations) { 35455 var text = translations[lang]; 35456 35457 // For MacOS, we try to emit the name in the form that was introduced 35458 // in the initial version of the TrueType spec (in the late 1980s). 35459 // However, this can fail for various reasons: the requested BCP 47 35460 // language code might not have an old-style Mac equivalent; 35461 // we might not have a codec for the needed character encoding; 35462 // or the name might contain characters that cannot be expressed 35463 // in the old-style Macintosh encoding. In case of failure, we emit 35464 // the name in a more modern fashion (Unicode encoding with BCP 47 35465 // language tags) that is recognized by MacOS 10.5, released in 2009. 35466 // If fonts were only read by operating systems, we could simply 35467 // emit all names in the modern form; this would be much easier. 35468 // However, there are many applications and libraries that read 35469 // 'name' tables directly, and these will usually only recognize 35470 // the ancient form (silently skipping the unrecognized names). 35471 var macPlatform = 1; // Macintosh 35472 var macLanguage = macLanguageIds[lang]; 35473 var macScript = macLanguageToScript[macLanguage]; 35474 var macEncoding = getEncoding(macPlatform, macScript, macLanguage); 35475 var macName = encode.MACSTRING(text, macEncoding); 35476 if (macName === undefined) { 35477 macPlatform = 0; // Unicode 35478 macLanguage = ltag.indexOf(lang); 35479 if (macLanguage < 0) { 35480 macLanguage = ltag.length; 35481 ltag.push(lang); 35482 } 35483 35484 macScript = 4; // Unicode 2.0 and later 35485 macName = encode.UTF16(text); 35486 } 35487 35488 var macNameOffset = addStringToPool(macName, stringPool); 35489 nameRecords.push(makeNameRecord(macPlatform, macScript, macLanguage, 35490 nameID, macName.length, macNameOffset)); 35491 35492 var winLanguage = windowsLanguageIds[lang]; 35493 if (winLanguage !== undefined) { 35494 var winName = encode.UTF16(text); 35495 var winNameOffset = addStringToPool(winName, stringPool); 35496 nameRecords.push(makeNameRecord(3, 1, winLanguage, 35497 nameID, winName.length, winNameOffset)); 35498 } 35499 } 35500 } 35501 35502 nameRecords.sort(function(a, b) { 35503 return ((a.platformID - b.platformID) || 35504 (a.encodingID - b.encodingID) || 35505 (a.languageID - b.languageID) || 35506 (a.nameID - b.nameID)); 35507 }); 35508 35509 var t = new table.Table('name', [ 35510 {name: 'format', type: 'USHORT', value: 0}, 35511 {name: 'count', type: 'USHORT', value: nameRecords.length}, 35512 {name: 'stringOffset', type: 'USHORT', value: 6 + nameRecords.length * 12} 35513 ]); 35514 35515 for (var r = 0; r < nameRecords.length; r++) { 35516 t.fields.push({name: 'record_' + r, type: 'RECORD', value: nameRecords[r]}); 35517 } 35518 35519 t.fields.push({name: 'strings', type: 'LITERAL', value: stringPool}); 35520 return t; 35521} 35522 35523var _name = { parse: parseNameTable, make: makeNameTable }; 35524 35525// The `OS/2` table contains metrics required in OpenType fonts. 35526// https://www.microsoft.com/typography/OTSPEC/os2.htm 35527 35528var unicodeRanges = [ 35529 {begin: 0x0000, end: 0x007F}, // Basic Latin 35530 {begin: 0x0080, end: 0x00FF}, // Latin-1 Supplement 35531 {begin: 0x0100, end: 0x017F}, // Latin Extended-A 35532 {begin: 0x0180, end: 0x024F}, // Latin Extended-B 35533 {begin: 0x0250, end: 0x02AF}, // IPA Extensions 35534 {begin: 0x02B0, end: 0x02FF}, // Spacing Modifier Letters 35535 {begin: 0x0300, end: 0x036F}, // Combining Diacritical Marks 35536 {begin: 0x0370, end: 0x03FF}, // Greek and Coptic 35537 {begin: 0x2C80, end: 0x2CFF}, // Coptic 35538 {begin: 0x0400, end: 0x04FF}, // Cyrillic 35539 {begin: 0x0530, end: 0x058F}, // Armenian 35540 {begin: 0x0590, end: 0x05FF}, // Hebrew 35541 {begin: 0xA500, end: 0xA63F}, // Vai 35542 {begin: 0x0600, end: 0x06FF}, // Arabic 35543 {begin: 0x07C0, end: 0x07FF}, // NKo 35544 {begin: 0x0900, end: 0x097F}, // Devanagari 35545 {begin: 0x0980, end: 0x09FF}, // Bengali 35546 {begin: 0x0A00, end: 0x0A7F}, // Gurmukhi 35547 {begin: 0x0A80, end: 0x0AFF}, // Gujarati 35548 {begin: 0x0B00, end: 0x0B7F}, // Oriya 35549 {begin: 0x0B80, end: 0x0BFF}, // Tamil 35550 {begin: 0x0C00, end: 0x0C7F}, // Telugu 35551 {begin: 0x0C80, end: 0x0CFF}, // Kannada 35552 {begin: 0x0D00, end: 0x0D7F}, // Malayalam 35553 {begin: 0x0E00, end: 0x0E7F}, // Thai 35554 {begin: 0x0E80, end: 0x0EFF}, // Lao 35555 {begin: 0x10A0, end: 0x10FF}, // Georgian 35556 {begin: 0x1B00, end: 0x1B7F}, // Balinese 35557 {begin: 0x1100, end: 0x11FF}, // Hangul Jamo 35558 {begin: 0x1E00, end: 0x1EFF}, // Latin Extended Additional 35559 {begin: 0x1F00, end: 0x1FFF}, // Greek Extended 35560 {begin: 0x2000, end: 0x206F}, // General Punctuation 35561 {begin: 0x2070, end: 0x209F}, // Superscripts And Subscripts 35562 {begin: 0x20A0, end: 0x20CF}, // Currency Symbol 35563 {begin: 0x20D0, end: 0x20FF}, // Combining Diacritical Marks For Symbols 35564 {begin: 0x2100, end: 0x214F}, // Letterlike Symbols 35565 {begin: 0x2150, end: 0x218F}, // Number Forms 35566 {begin: 0x2190, end: 0x21FF}, // Arrows 35567 {begin: 0x2200, end: 0x22FF}, // Mathematical Operators 35568 {begin: 0x2300, end: 0x23FF}, // Miscellaneous Technical 35569 {begin: 0x2400, end: 0x243F}, // Control Pictures 35570 {begin: 0x2440, end: 0x245F}, // Optical Character Recognition 35571 {begin: 0x2460, end: 0x24FF}, // Enclosed Alphanumerics 35572 {begin: 0x2500, end: 0x257F}, // Box Drawing 35573 {begin: 0x2580, end: 0x259F}, // Block Elements 35574 {begin: 0x25A0, end: 0x25FF}, // Geometric Shapes 35575 {begin: 0x2600, end: 0x26FF}, // Miscellaneous Symbols 35576 {begin: 0x2700, end: 0x27BF}, // Dingbats 35577 {begin: 0x3000, end: 0x303F}
35577, // CJK Symbols And Punctuation 35578 {begin: 0x3040, end: 0x309F}, // Hiragana 35579 {begin: 0x30A0, end: 0x30FF}, // Katakana 35580 {begin: 0x3100, end: 0x312F}, // Bopomofo 35581 {begin: 0x3130, end: 0x318F}, // Hangul Compatibility Jamo 35582 {begin: 0xA840, end: 0xA87F}, // Phags-pa 35583 {begin: 0x3200, end: 0x32FF}, // Enclosed CJK Letters And Months 35584 {begin: 0x3300, end: 0x33FF}, // CJK Compatibility 35585 {begin: 0xAC00, end: 0xD7AF}, // Hangul Syllables 35586 {begin: 0xD800, end: 0xDFFF}, // Non-Plane 0 * 35587 {begin: 0x10900, end: 0x1091F}, // Phoenicia 35588 {begin: 0x4E00, end: 0x9FFF}, // CJK Unified Ideographs 35589 {begin: 0xE000, end: 0xF8FF}, // Private Use Area (plane 0) 35590 {begin: 0x31C0, end: 0x31EF}, // CJK Strokes 35591 {begin: 0xFB00, end: 0xFB4F}, // Alphabetic Presentation Forms 35592 {begin: 0xFB50, end: 0xFDFF}, // Arabic Presentation Forms-A 35593 {begin: 0xFE20, end: 0xFE2F}, // Combining Half Marks 35594 {begin: 0xFE10, end: 0xFE1F}, // Vertical Forms 35595 {begin: 0xFE50, end: 0xFE6F}, // Small Form Variants 35596 {begin: 0xFE70, end: 0xFEFF}, // Arabic Presentation Forms-B 35597 {begin: 0xFF00, end: 0xFFEF}, // Halfwidth And Fullwidth Forms 35598 {begin: 0xFFF0, end: 0xFFFF}, // Specials 35599 {begin: 0x0F00, end: 0x0FFF}, // Tibetan 35600 {begin: 0x0700, end: 0x074F}, // Syriac 35601 {begin: 0x0780, end: 0x07BF}, // Thaana 35602 {begin: 0x0D80, end: 0x0DFF}, // Sinhala 35603 {begin: 0x1000, end: 0x109F}, // Myanmar 35604 {begin: 0x1200, end: 0x137F}, // Ethiopic 35605 {begin: 0x13A0, end: 0x13FF}, // Cherokee 35606 {begin: 0x1400, end: 0x167F}, // Unified Canadian Aboriginal Syllabics 35607 {begin: 0x1680, end: 0x169F}, // Ogham 35608 {begin: 0x16A0, end: 0x16FF}, // Runic 35609 {begin: 0x1780, end: 0x17FF}, // Khmer 35610 {begin: 0x1800, end: 0x18AF}, // Mongolian 35611 {begin: 0x2800, end: 0x28FF}, // Braille Patterns 35612 {begin: 0xA000, end: 0xA48F}, // Yi Syllables 35613 {begin: 0x1700, end: 0x171F}, // Tagalog 35614 {begin: 0x10300, end: 0x1032F}, // Old Italic 35615 {begin: 0x10330, end: 0x1034F}, // Gothic 35616 {begin: 0x10400, end: 0x1044F}, // Deseret 35617 {begin: 0x1D000, end: 0x1D0FF}, // Byzantine Musical Symbols 35618 {begin: 0x1D400, end: 0x1D7FF}, // Mathematical Alphanumeric Symbols 35619 {begin: 0xFF000, end: 0xFFFFD}, // Private Use (plane 15) 35620 {begin: 0xFE00, end: 0xFE0F}, // Variation Selectors 35621 {begin: 0xE0000, end: 0xE007F}, // Tags 35622 {begin: 0x1900, end: 0x194F}, // Limbu 35623 {begin: 0x1950, end: 0x197F}, // Tai Le 35624 {begin: 0x1980, end: 0x19DF}, // New Tai Lue 35625 {begin: 0x1A00, end: 0x1A1F}, // Buginese 35626 {begin: 0x2C00, end: 0x2C5F}, // Glagolitic 35627 {begin: 0x2D30, end: 0x2D7F}, // Tifinagh 35628 {begin: 0x4DC0, end: 0x4DFF}, // Yijing Hexagram Symbols 35629 {begin: 0xA800, end: 0xA82F}, // Syloti Nagri 35630 {begin: 0x10000, end: 0x1007F}, // Linear B Syllabary 35631 {begin: 0x10140, end: 0x1018F}, // Ancient Greek Numbers 35632 {begin: 0x10380, end: 0x1039F}, // Ugaritic 35633 {begin: 0x103A0, end: 0x103DF}, // Old Persian 35634 {begin: 0x10450, end: 0x1047F}, // Shavian 35635 {begin: 0x10480, end: 0x104AF}, // Osmanya 35636 {begin: 0x10800, end: 0x1083F}, // Cypriot Syllabary 35637 {begin: 0x10A00, end: 0x10A5F}, // Kharoshthi 35638 {begin: 0x1D300, end: 0x1D35F}, // Tai Xuan Jing Symbols 35639 {begin: 0x12000, end: 0x123FF}, // Cuneiform 35640 {begin: 0x1D360, end: 0x1D37F}, // Counting Rod Numerals 35641 {begin: 0x1B80, end: 0x1BBF}, // Sundanese 35642 {begin: 0x1C00, end: 0x1C4F}, // Lepcha 35643 {begin: 0x1C50, end: 0x1C7F}, // Ol Chiki 35644 {begin: 0xA880, end: 0xA8DF}, // Saurashtra 35645 {begin: 0xA900, end: 0xA92F}, // Kayah Li 35646 {begin: 0xA930, end: 0xA95F}, // Rejang 35647 {begin: 0xAA00, end: 0xAA5F}, // Cham 35648 {begin: 0x10190, end: 0x101CF}, // Ancient Symbols 35649 {begin: 0x101D0, end: 0x101FF}, // Phaistos Disc 35650 {begin: 0x102A0, end: 0x102DF}, // Carian 35651 {begin: 0x1F030, end: 0x1F09F} // Domino Tiles 35652]; 35653 35654function getUnicodeRange(unicode) { 35655 for (var i = 0; i < unicodeRanges.length; i += 1) { 35656 var range = unicodeRanges[i]; 35657 if (unicode >= range.begin && unicode < range.end) { 35658 return i; 35659 } 35660 } 35661 35662 return -1; 35663} 35664 35665// Parse the OS/2 and Windows metrics `OS/2` table 35666function parseOS2Table(data, start) { 35667 var os2 = {}; 35668 var p = new parse.Parser(data, start); 35669 os2.version = p.parseUShort(); 35670 os2.xAvgCharWidth = p.parseShort(); 35671 os2.usWeightClass = p.parseUShort(); 35672 os2.usWidthClass = p.parseUShort(); 35673 os2.fsType = p.parseUShort(); 35674 os2.ySubscriptXSize = p.parseShort(); 35675 os2.ySubscriptYSize = p.parseShort(); 35676 os2.ySubscriptXOffset = p.parseShort(); 35677 os2.ySubscriptYOffset = p.parseShort(); 35678 os2.ySuperscriptXSize = p.parseShort(); 35679 os2.ySuperscriptYSize = p.parseShort(); 35680 os2.ySuperscriptXOffset = p.parseShort(); 35681 os2.ySuperscriptYOffset = p.parseShort(); 35682 os2.yStrikeoutSize = p.parseShort(); 35683 os2.yStrikeoutPosition = p.parseShort(); 35684 os2.sFamilyClass = p.parseShort(); 35685 os2.panose = []; 35686 for (var i = 0; i < 10; i++) { 35687 os2.panose[i] = p.parseByte(); 35688 } 35689 35690 os2.ulUnicodeRange1 = p.parseULong(); 35691 os2.ulUnicodeRange2 = p.parseULong(); 35692 os2.ulUnicodeRange3 = p.parseULong(); 35693 os2.ulUnicodeRange4 = p.parseULong(); 35694 os2.achVendID = String.fromCharCode(p.parseByte(), p.parseByte(), p.parseByte(), p.parseByte()); 35695 os2.fsSelection = p.parseUShort(); 35696 os2.usFirstCharIndex = p.parseUShort(); 35697 os2.usLastCharIndex = p.parseUShort(); 35698 os2.sTypoAscender = p.parseShort(); 35699 os2.sTypoDescender = p.parseShort(); 35700 os2.sTypoLineGap = p.parseShort(); 35701 os2.usWinAscent = p.parseUShort(); 35702 os2.usWinDescent = p.parseUShort();
35703 if (os2.version >= 1) { 35704 os2.ulCodePageRange1 = p.parseULong(); 35705 os2.ulCodePageRange2 = p.parseULong(); 35706 } 35707 35708 if (os2.version >= 2) { 35709 os2.sxHeight = p.parseShort(); 35710 os2.sCapHeight = p.parseShort(); 35711 os2.usDefaultChar = p.parseUShort(); 35712 os2.usBreakChar = p.parseUShort(); 35713 os2.usMaxContent = p.parseUShort(); 35714 } 35715 35716 return os2; 35717} 35718 35719function makeOS2Table(options) { 35720 return new table.Table('OS/2', [ 35721 {name: 'version', type: 'USHORT', value: 0x0003}, 35722 {name: 'xAvgCharWidth', type: 'SHORT', value: 0}, 35723 {name: 'usWeightClass', type: 'USHORT', value: 0}, 35724 {name: 'usWidthClass', type: 'USHORT', value: 0}, 35725 {name: 'fsType', type: 'USHORT', value: 0}, 35726 {name: 'ySubscriptXSize', type: 'SHORT', value: 650}, 35727 {name: 'ySubscriptYSize', type: 'SHORT', value: 699}, 35728 {name: 'ySubscriptXOffset', type: 'SHORT', value: 0}, 35729 {name: 'ySubscriptYOffset', type: 'SHORT', value: 140}, 35730 {name: 'ySuperscriptXSize', type: 'SHORT', value: 650}, 35731 {name: 'ySuperscriptYSize', type: 'SHORT', value: 699}, 35732 {name: 'ySuperscriptXOffset', type: 'SHORT', value: 0}, 35733 {name: 'ySuperscriptYOffset', type: 'SHORT', value: 479}, 35734 {name: 'yStrikeoutSize', type: 'SHORT', value: 49}, 35735 {name: 'yStrikeoutPosition', type: 'SHORT', value: 258}, 35736 {name: 'sFamilyClass', type: 'SHORT', value: 0}, 35737 {name: 'bFamilyType', type: 'BYTE', value: 0}, 35738 {name: 'bSerifStyle', type: 'BYTE', value: 0}, 35739 {name: 'bWeight', type: 'BYTE', value: 0}, 35740 {name: 'bProportion', type: 'BYTE', value: 0}, 35741 {name: 'bContrast', type: 'BYTE', value: 0}, 35742 {name: 'bStrokeVariation', type: 'BYTE', value: 0}, 35743 {name: 'bArmStyle', type: 'BYTE', value: 0}, 35744 {name: 'bLetterform', type: 'BYTE', value: 0}, 35745 {name: 'bMidline', type: 'BYTE', value: 0}, 35746 {name: 'bXHeight', type: 'BYTE', value: 0}, 35747 {name: 'ulUnicodeRange1', type: 'ULONG', value: 0}, 35748 {name: 'ulUnicodeRange2', type: 'ULONG', value: 0}, 35749 {name: 'ulUnicodeRange3', type: 'ULONG', value: 0}, 35750 {name: 'ulUnicodeRange4', type: 'ULONG', value: 0}, 35751 {name: 'achVendID', type: 'CHARARRAY', value: 'XXXX'}, 35752 {name: 'fsSelection', type: 'USHORT', value: 0}, 35753 {name: 'usFirstCharIndex', type: 'USHORT', value: 0}, 35754 {name: 'usLastCharIndex', type: 'USHORT', value: 0}, 35755 {name: 'sTypoAscender', type: 'SHORT', value: 0}, 35756 {name: 'sTypoDescender', type: 'SHORT', value: 0}, 35757 {name: 'sTypoLineGap', type: 'SHORT', value: 0}, 35758 {name: 'usWinAscent', type: 'USHORT', value: 0}, 35759 {name: 'usWinDescent', type: 'USHORT', value: 0}, 35760 {name: 'ulCodePageRange1', type: 'ULONG', value: 0}, 35761 {name: 'ulCodePageRange2', type: 'ULONG', value: 0}, 35762 {name: 'sxHeight', type: 'SHORT', value: 0}, 35763 {name: 'sCapHeight', type: 'SHORT', value: 0}, 35764 {name: 'usDefaultChar', type: 'USHORT', value: 0},
vendor: 9,333 bytes, lines 35765-36007
35765 {name: 'usBreakChar', type: 'USHORT', value: 0}, 35766 {name: 'usMaxContext', type: 'USHORT', value: 0} 35767 ], options); 35768} 35769 35770var os2 = { parse: parseOS2Table, make: makeOS2Table, unicodeRanges: unicodeRanges, getUnicodeRange: getUnicodeRange }; 35771 35772// The `post` table stores additional PostScript information, such as glyph names. 35773// https://www.microsoft.com/typography/OTSPEC/post.htm 35774 35775// Parse the PostScript `post` table 35776function parsePostTable(data, start) { 35777 var post = {}; 35778 var p = new parse.Parser(data, start); 35779 post.version = p.parseVersion(); 35780 post.italicAngle = p.parseFixed(); 35781 post.underlinePosition = p.parseShort(); 35782 post.underlineThickness = p.parseShort(); 35783 post.isFixedPitch = p.parseULong(); 35784 post.minMemType42 = p.parseULong(); 35785 post.maxMemType42 = p.parseULong(); 35786 post.minMemType1 = p.parseULong(); 35787 post.maxMemType1 = p.parseULong(); 35788 switch (post.version) { 35789 case 1: 35790 post.names = standardNames.slice(); 35791 break; 35792 case 2: 35793 post.numberOfGlyphs = p.parseUShort(); 35794 post.glyphNameIndex = new Array(post.numberOfGlyphs); 35795 for (var i = 0; i < post.numberOfGlyphs; i++) { 35796 post.glyphNameIndex[i] = p.parseUShort(); 35797 } 35798 35799 post.names = []; 35800 for (var i$1 = 0; i$1 < post.numberOfGlyphs; i$1++) { 35801 if (post.glyphNameIndex[i$1] >= standardNames.length) { 35802 var nameLength = p.parseChar(); 35803 post.names.push(p.parseString(nameLength)); 35804 } 35805 } 35806 35807 break; 35808 case 2.5: 35809 post.numberOfGlyphs = p.parseUShort(); 35810 post.offset = new Array(post.numberOfGlyphs); 35811 for (var i$2 = 0; i$2 < post.numberOfGlyphs; i$2++) { 35812 post.offset[i$2] = p.parseChar(); 35813 } 35814 35815 break; 35816 } 35817 return post; 35818} 35819 35820function makePostTable() { 35821 return new table.Table('post', [ 35822 {name: 'version', type: 'FIXED', value: 0x00030000}, 35823 {name: 'italicAngle', type: 'FIXED', value: 0}, 35824 {name: 'underlinePosition', type: 'FWORD', value: 0}, 35825 {name: 'underlineThickness', type: 'FWORD', value: 0}, 35826 {name: 'isFixedPitch', type: 'ULONG', value: 0}, 35827 {name: 'minMemType42', type: 'ULONG', value: 0}, 35828 {name: 'maxMemType42', type: 'ULONG', value: 0}, 35829 {name: 'minMemType1', type: 'ULONG', value: 0}, 35830 {name: 'maxMemType1', type: 'ULONG', value: 0} 35831 ]); 35832} 35833 35834var post = { parse: parsePostTable, make: makePostTable }; 35835 35836// The `GSUB` table contains ligatures, among other things. 35837// https://www.microsoft.com/typography/OTSPEC/gsub.htm 35838 35839var subtableParsers = new Array(9); // subtableParsers[0] is unused 35840 35841// https://www.microsoft.com/typography/OTSPEC/GSUB.htm#SS 35842subtableParsers[1] = function parseLookup1() { 35843 var start = this.offset + this.relativeOffset; 35844 var substFormat = this.parseUShort(); 35845 if (substFormat === 1) { 35846 return { 35847 substFormat: 1, 35848 coverage: this.parsePointer(Parser.coverage), 35849 deltaGlyphId: this.parseUShort() 35850 }; 35851 } else if (substFormat === 2) { 35852 return { 35853 substFormat: 2, 35854 coverage: this.parsePointer(Parser.coverage), 35855 substitute: this.parseOffset16List() 35856 }; 35857 } 35858 check.assert(false, '0x' + start.toString(16) + ': lookup type 1 format must be 1 or 2.'); 35859}; 35860 35861// https://www.microsoft.com/typography/OTSPEC/GSUB.htm#MS 35862subtableParsers[2] = function parseLookup2() { 35863 var substFormat = this.parseUShort(); 35864 check.argument(substFormat === 1, 'GSUB Multiple Substitution Subtable identifier-format must be 1'); 35865 return { 35866 substFormat: substFormat, 35867 coverage: this.parsePointer(Parser.coverage), 35868 sequences: this.parseListOfLists() 35869 }; 35870}; 35871 35872// https://www.microsoft.com/typography/OTSPEC/GSUB.htm#AS 35873subtableParsers[3] = function parseLookup3() { 35874 var substFormat = this.parseUShort(); 35875 check.argument(substFormat === 1, 'GSUB Alternate Substitution Subtable identifier-format must be 1'); 35876 return { 35877 substFormat: substFormat, 35878 coverage: this.parsePointer(Parser.coverage), 35879 alternateSets: this.parseListOfLists() 35880 }; 35881}; 35882 35883// https://www.microsoft.com/typography/OTSPEC/GSUB.htm#LS 35884subtableParsers[4] = function parseLookup4() { 35885 var substFormat = this.parseUShort(); 35886 check.argument(substFormat === 1, 'GSUB ligature table identifier-format must be 1'); 35887 return { 35888 substFormat: substFormat, 35889 coverage: this.parsePointer(Parser.coverage), 35890 ligatureSets: this.parseListOfLists(function() { 35891 return { 35892 ligGlyph: this.parseUShort(), 35893 components: this.parseUShortList(this.parseUShort() - 1) 35894 }; 35895 }) 35896 }; 35897}; 35898 35899var lookupRecordDesc = { 35900 sequenceIndex: Parser.uShort, 35901 lookupListIndex: Parser.uShort 35902}; 35903 35904// https://www.microsoft.com/typography/OTSPEC/GSUB.htm#CSF 35905subtableParsers[5] = function parseLookup5() { 35906 var start = this.offset + this.relativeOffset; 35907 var substFormat = this.parseUShort(); 35908 35909 if (substFormat === 1) { 35910 return { 35911 substFormat: substFormat, 35912 coverage: this.parsePointer(Parser.coverage), 35913 ruleSets: this.parseListOfLists(function() { 35914 var glyphCount = this.parseUShort(); 35915 var substCount = this.parseUShort(); 35916 return { 35917 input: this.parseUShortList(glyphCount - 1), 35918 lookupRecords: this.parseRecordList(substCount, lookupRecordDesc) 35919 }; 35920 }) 35921 }; 35922 } else if (substFormat === 2) { 35923 return { 35924 substFormat: substFormat, 35925 coverage: this.parsePointer(Parser.coverage), 35926 classDef: this.parsePointer(Parser.classDef), 35927 classSets: this.parseListOfLists(function() { 35928 var glyphCount = this.parseUShort(); 35929 var substCount = this.parseUShort(); 35930 return { 35931 classes: this.parseUShortList(glyphCount - 1), 35932 lookupRecords: this.parseRecordList(substCount, lookupRecordDesc) 35933 }; 35934 }) 35935 }; 35936 } else if (substFormat === 3) { 35937 var glyphCount = this.parseUShort(); 35938 var substCount = this.parseUShort(); 35939 return { 35940 substFormat: substFormat, 35941 coverages: this.parseList(glyphCount, Parser.pointer(Parser.coverage)), 35942 lookupRecords: this.parseRecordList(substCount, lookupRecordDesc) 35943 }; 35944 } 35945 check.assert(false, '0x' + start.toString(16) + ': lookup type 5 format must be 1, 2 or 3.'); 35946}; 35947 35948// https://www.microsoft.com/typography/OTSPEC/GSUB.htm#CC 35949subtableParsers[6] = function parseLookup6() { 35950 var start = this.offset + this.relativeOffset; 35951 var substFormat = this.parseUShort(); 35952 if (substFormat === 1) { 35953 return { 35954 substFormat: 1, 35955 coverage: this.parsePointer(Parser.coverage), 35956 chainRuleSets: this.parseListOfLists(function() { 35957 return { 35958 backtrack: this.parseUShortList(), 35959 input: this.parseUShortList(this.parseShort() - 1), 35960 lookahead: this.parseUShortList(), 35961 lookupRecords: this.parseRecordList(lookupRecordDesc) 35962 }; 35963 }) 35964 }; 35965 } else if (substFormat === 2) { 35966 return { 35967 substFormat: 2, 35968 coverage: this.parsePointer(Parser.coverage), 35969 backtrackClassDef: this.parsePointer(Parser.classDef), 35970 inputClassDef: this.parsePointer(Parser.classDef), 35971 lookaheadClassDef: this.parsePointer(Parser.classDef), 35972 chainClassSet: this.parseListOfLists(function() { 35973 return { 35974 backtrack: this.parseUShortList(), 35975 input: this.parseUShortList(this.parseShort() - 1), 35976 lookahead: this.parseUShortList(), 35977 lookupRecords: this.parseRecordList(lookupRecordDesc) 35978 }; 35979 }) 35980 }; 35981 } else if (substFormat === 3) { 35982 return { 35983 substFormat: 3, 35984 backtrackCoverage: this.parseList(Parser.pointer(Parser.coverage)), 35985 inputCoverage: this.parseList(Parser.pointer(Parser.coverage)), 35986 lookaheadCoverage: this.parseList(Parser.pointer(Parser.coverage)), 35987 lookupRecords: this.parseRecordList(lookupRecordDesc) 35988 }; 35989 } 35990 check.assert(false, '0x' + start.toString(16) + ': lookup type 6 format must be 1, 2 or 3.'); 35991}; 35992 35993// https://www.microsoft.com/typography/OTSPEC/GSUB.htm#ES 35994subtableParsers[7] = function parseLookup7() { 35995 // Extension Substitution subtable 35996 var substFormat = this.parseUShort(); 35997 check.argument(substFormat === 1, 'GSUB Extension Substitution subtable identifier-format must be 1'); 35998 var extensionLookupType = this.parseUShort(); 35999 var extensionParser = new Parser(this.data, this.offset + this.parseULong()); 36000 return { 36001 substFormat: 1, 36002 lookupType: extensionLookupType, 36003 extension: subtableParsers[extensionLookupType].call(extensionParser) 36004 }; 36005}; 36006 36007// https://www.microsoft.com/typography/OTSPEC/GSUB.htm#RCCS
36008subtableParsers[8] = function parseLookup8() { 36009 var substFormat = this.parseUShort(); 36010 check.argument(substFormat === 1, 'GSUB Reverse Chaining Contextual Single Substitution Subtable identifier-format must be 1'); 36011 return { 36012 substFormat: substFormat, 36013 coverage: this.parsePointer(Parser.coverage), 36014 backtrackCoverage: this.parseList(Parser.pointer(Parser.coverage)), 36015 lookaheadCoverage: this.parseList(Parser.pointer(Parser.coverage)), 36016 substitutes: this.parseUShortList() 36017 }; 36018}; 36019 36020// https://www.microsoft.com/typography/OTSPEC/gsub.htm 36021function parseGsubTable(data, start) { 36022 start = start || 0; 36023 var p = new Parser(data, start); 36024 var tableVersion = p.parseVersion(); 36025 check.argument(tableVersion === 1, 'Unsupported GSUB table version.'); 36026 return { 36027 version: tableVersion, 36028 scripts: p.parseScriptList(), 36029 features: p.parseFeatureList(), 36030 lookups: p.parseLookupList(subtableParsers) 36031 }; 36032} 36033 36034// GSUB Writing ////////////////////////////////////////////// 36035var subtableMakers = new Array(9); 36036 36037subtableMakers[1] = function makeLookup1(subtable) { 36038 if (subtable.substFormat === 1) { 36039 return new table.Table('substitutionTable', [ 36040 {name: 'substFormat', type: 'USHORT', value: 1}, 36041 {name: 'coverage', type: 'TABLE', value: new table.Coverage(subtable.coverage)}, 36042 {name: 'deltaGlyphID', type: 'USHORT', value: subtable.deltaGlyphId} 36043 ]); 36044 } else { 36045 return new table.Table('substitutionTable', [ 36046 {name: 'substFormat', type: 'USHORT', value: 2}, 36047 {name: 'coverage', type: 'TABLE', value: new table.Coverage(subtable.coverage)} 36048 ].concat(table.ushortList('substitute', subtable.substitute))); 36049 } 36050 check.fail('Lookup type 1 substFormat must be 1 or 2.'); 36051}; 36052 36053subtableMakers[3] = function makeLookup3(subtable) { 36054 check.assert(subtable.substFormat === 1, 'Lookup type 3 substFormat must be 1.'); 36055 return new table.Table('substitutionTable', [ 36056 {name: 'substFormat', type: 'USHORT', value: 1}, 36057 {name: 'coverage', type: 'TABLE', value: new table.Coverage(subtable.coverage)} 36058 ].concat(table.tableList('altSet', subtable.alternateSets, function(alternateSet) { 36059 return new table.Table('alternateSetTable', table.ushortList('alternate', alternateSet)); 36060 }))); 36061}; 36062 36063subtableMakers[4] = function makeLookup4(subtable) { 36064 check.assert(subtable.substFormat === 1, 'Lookup type 4 substFormat must be 1.'); 36065 return new table.Table('substitutionTable', [ 36066 {name: 'substFormat', type: 'USHORT', value: 1}, 36067 {name: 'coverage', type: 'TABLE', value: new table.Coverage(subtable.coverage)} 36068 ].concat(table.tableList('ligSet', subtable.ligatureSets, function(ligatureSet) { 36069 return new table.Table('ligatureSetTable', table.tableList('ligature', ligatureSet, function(ligature) { 36070 return new table.Table('ligatureTable', 36071 [{name: 'ligGlyph', type: 'USHORT', value: ligature.ligGlyph}] 36072 .concat(table.ushortList('component', ligature.components, ligature.components.length + 1)) 36073 ); 36074 })); 36075 }))); 36076}; 36077 36078function makeGsubTable(gsub) { 36079 return new table.Table('GSUB', [ 36080 {name: 'version', type: 'ULONG', value: 0x10000}, 36081 {name: 'scripts', type: 'TABLE', value: new table.ScriptList(gsub.scripts)}, 36082 {name: 'features', type: 'TABLE', value: new table.FeatureList(gsub.features)}, 36083 {name: 'lookups', type: 'TABLE', value: new table.LookupList(gsub.lookups, subtableMakers)} 36084 ]); 36085} 36086 36087var gsub = { parse: parseGsubTable, make: makeGsubTable }; 36088 36089// The `GPOS` table contains kerning pairs, among other things. 36090// https://www.microsoft.com/typography/OTSPEC/gpos.htm 36091 36092// Parse the metadata `meta` table. 36093// https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6meta.html 36094function parseMetaTable(data, start) { 36095 var p = new parse.Parser(data, start); 36096 var tableVersion = p.parseULong(); 36097 check.argument(tableVersion === 1, 'Unsupported META table version.'); 36098 p.parseULong(); // flags - currently unused and set to 0 36099 p.parseULong(); // tableOffset 36100 var numDataMaps = p.parseULong(); 36101 36102 var tags = {}; 36103 for (var i = 0; i < numDataMaps; i++) { 36104 var tag = p.parseTag(); 36105 var dataOffset = p.parseULong(); 36106 var dataLength = p.parseULong(); 36107 var text = decode.UTF8(data, start + dataOffset, dataLength); 36108
36109 tags[tag] = text; 36110 } 36111 return tags; 36112} 36113 36114function makeMetaTable(tags) { 36115 var numTags = Object.keys(tags).length; 36116 var stringPool = ''; 36117 var stringPoolOffset = 16 + numTags * 12; 36118 36119 var result = new table.Table('meta', [ 36120 {name: 'version', type: 'ULONG', value: 1}, 36121 {name: 'flags', type: 'ULONG', value: 0}, 36122 {name: 'offset', type: 'ULONG', value: stringPoolOffset}, 36123 {name: 'numTags', type: 'ULONG', value: numTags} 36124 ]); 36125 36126 for (var tag in tags) { 36127 var pos = stringPool.length; 36128 stringPool += tags[tag]; 36129 36130 result.fields.push({name: 'tag ' + tag, type: 'TAG', value: tag}); 36131 result.fields.push({name: 'offset ' + tag, type: 'ULONG', value: stringPoolOffset + pos}); 36132 result.fields.push({name: 'length ' + tag, type: 'ULONG', value: tags[tag].length}); 36133 } 36134 36135 result.fields.push({name: 'stringPool', type: 'CHARARRAY', value: stringPool}); 36136 36137 return result; 36138} 36139 36140var meta = { parse: parseMetaTable, make: makeMetaTable }; 36141 36142// The `sfnt` wrapper provides organization for the tables in the font. 36143// It is the top-level data structure in a font. 36144// https://www.microsoft.com/typography/OTSPEC/otff.htm 36145// Recommendations for creating OpenType Fonts: 36146// http://www.microsoft.com/typography/otspec140/recom.htm 36147 36148function log2(v) { 36149 return Math.log(v) / Math.log(2) | 0; 36150} 36151 36152function computeCheckSum(bytes) { 36153 while (bytes.length % 4 !== 0) { 36154 bytes.push(0); 36155 } 36156 36157 var sum = 0; 36158 for (var i = 0; i < bytes.length; i += 4) { 36159 sum += (bytes[i] << 24) + 36160 (bytes[i + 1] << 16) + 36161 (bytes[i + 2] << 8) + 36162 (bytes[i + 3]); 36163 } 36164 36165 sum %= Math.pow(2, 32); 36166 return sum; 36167} 36168 36169function makeTableRecord(tag, checkSum, offset, length) { 36170 return new table.Record('Table Record', [ 36171 {name: 'tag', type: 'TAG', value: tag !== undefined ? tag : ''}, 36172 {name: 'checkSum', type: 'ULONG', value: checkSum !== undefined ? checkSum : 0}, 36173 {name: 'offset', type: 'ULONG', value: offset !== undefined ? offset : 0}, 36174 {name: 'length', type: 'ULONG', value: length !== undefined ? length : 0} 36175 ]); 36176} 36177 36178function makeSfntTable(tables) { 36179 var sfnt = new table.Table('sfnt', [ 36180 {name: 'version', type: 'TAG', value: 'OTTO'}, 36181 {name: 'numTables', type: 'USHORT', value: 0}, 36182 {name: 'searchRange', type: 'USHORT', value: 0}, 36183 {name: 'entrySelector', type: 'USHORT', value: 0}, 36184 {name: 'rangeShift', type: 'USHORT', value: 0} 36185 ]); 36186 sfnt.tables = tables; 36187 sfnt.numTables = tables.length; 36188 var highestPowerOf2 = Math.pow(2, log2(sfnt.numTables)); 36189 sfnt.searchRange = 16 * highestPowerOf2; 36190 sfnt.entrySelector = log2(highestPowerOf2); 36191 sfnt.rangeShift = sfnt.numTables * 16 - sfnt.searchRange; 36192 36193 var recordFields = []; 36194 var tableFields = []; 36195 36196 var offset = sfnt.sizeOf() + (makeTableRecord().sizeOf() * sfnt.numTables); 36197 while (offset % 4 !== 0) { 36198 offset += 1; 36199 tableFields.push({name: 'padding', type: 'BYTE', value: 0}); 36200 } 36201 36202 for (var i = 0; i < tables.length; i += 1) { 36203 var t = tables[i]; 36204 check.argument(t.tableName.length === 4, 'Table name' + t.tableName + ' is invalid.'); 36205 var tableLength = t.sizeOf(); 36206 var tableRecord = makeTableRecord(t.tableName, computeCheckSum(t.encode()), offset, tableLength); 36207 recordFields.push({name: tableRecord.tag + ' Table Record', type: 'RECORD', value: tableRecord}); 36208 tableFields.push({name: t.tableName + ' table', type: 'RECORD', value: t}); 36209 offset += tableLength; 36210 check.argument(!isNaN(offset), 'Something went wrong calculating the offset.'); 36211 while (offset % 4 !== 0) { 36212 offset += 1; 36213 tableFields.push({name: 'padding', type: 'BYTE', value: 0}); 36214 } 36215 } 36216 36217 // Table records need to be sorted alphabetically. 36218 recordFields.sort(function(r1, r2) { 36219 if (r1.value.tag > r2.value.tag) { 36220 return 1; 36221 } else { 36222 return -1; 36223 } 36224 }); 36225 36226 sfnt.fields = sfnt.fields.concat(recordFields); 36227 sfnt.fields = sfnt.fields.concat(tableFields); 36228 return sfnt; 36229} 36230 36231// Get the metrics for a character. If the string has more than one character 36232// this function returns metrics for the first available character. 36233// You can provide optional fallback metrics if no characters are available. 36234function metricsForChar(font, chars, notFoundMetrics) { 36235 for (var i = 0; i < chars.length; i += 1) { 36236 var glyphIndex = font.charToGlyphIndex(chars[i]); 36237 if (glyphIndex > 0) { 36238 var glyph = font.glyphs.get(glyphIndex); 36239 return glyph.getMetrics(); 36240 } 36241 } 36242 36243 return notFoundMetrics; 36244} 36245 36246function average(vs) { 36247 var sum = 0; 36248 for (var i = 0; i < vs.length; i += 1) { 36249 sum += vs[i]; 36250 } 36251 36252 return sum / vs.length; 36253} 36254 36255// Convert the font object to a SFNT data structure. 36256// This structure contains all the necessary tables and metadata to create a binary OTF file. 36257function fontToSfntTable(font) {
36258 var xMins = []; 36259 var yMins = []; 36260 var xMaxs = []; 36261 var yMaxs = []; 36262 var advanceWidths = []; 36263 var leftSideBearings = []; 36264 var rightSideBearings = []; 36265 var firstCharIndex; 36266 var lastCharIndex = 0; 36267 var ulUnicodeRange1 = 0; 36268 var ulUnicodeRange2 = 0; 36269 var ulUnicodeRange3 = 0; 36270 var ulUnicodeRange4 = 0; 36271 36272 for (var i = 0; i < font.glyphs.length; i += 1) { 36273 var glyph = font.glyphs.get(i); 36274 var unicode = glyph.unicode | 0; 36275 36276 if (isNaN(glyph.advanceWidth)) { 36277 throw new Error('Glyph ' + glyph.name + ' (' + i + '): advanceWidth is not a number.'); 36278 } 36279 36280 if (firstCharIndex > unicode || firstCharIndex === undefined) { 36281 // ignore .notdef char 36282 if (unicode > 0) { 36283 firstCharIndex = unicode; 36284 } 36285 } 36286 36287 if (lastCharIndex < unicode) { 36288 lastCharIndex = unicode; 36289 } 36290 36291 var position = os2.getUnicodeRange(unicode); 36292 if (position < 32) { 36293 ulUnicodeRange1 |= 1 << position; 36294 } else if (position < 64) { 36295 ulUnicodeRange2 |= 1 << position - 32; 36296 } else if (position < 96) { 36297 ulUnicodeRange3 |= 1 << position - 64; 36298 } else if (position < 123) { 36299 ulUnicodeRange4 |= 1 << position - 96; 36300 } else { 36301 throw new Error('Unicode ranges bits > 123 are reserved for internal usage'); 36302 } 36303 // Skip non-important characters. 36304 if (glyph.name === '.notdef') { continue; } 36305 var metrics = glyph.getMetrics(); 36306 xMins.push(metrics.xMin); 36307 yMins.push(metrics.yMin); 36308 xMaxs.push(metrics.xMax); 36309 yMaxs.push(metrics.yMax); 36310 leftSideBearings.push(metrics.leftSideBearing); 36311 rightSideBearings.push(metrics.rightSideBearing); 36312 advanceWidths.push(glyph.advanceWidth); 36313 } 36314 36315 var globals = { 36316 xMin: Math.min.apply(null, xMins), 36317 yMin: Math.min.apply(null, yMins), 36318 xMax: Math.max.apply(null, xMaxs), 36319 yMax: Math.max.apply(null, yMaxs), 36320 advanceWidthMax: Math.max.apply(null, advanceWidths), 36321 advanceWidthAvg: average(advanceWidths), 36322 minLeftSideBearing: Math.min.apply(null, leftSideBearings), 36323 maxLeftSideBearing: Math.max.apply(null, leftSideBearings), 36324 minRightSideBearing: Math.min.apply(null, rightSideBearings) 36325 }; 36326 globals.ascender = font.ascender; 36327 globals.descender = font.descender; 36328 36329 var headTable = head.make({ 36330 flags: 3, // 00000011 (baseline for font at y=0; left sidebearing point at x=0) 36331 unitsPerEm: font.unitsPerEm, 36332 xMin: globals.xMin, 36333 yMin: globals.yMin, 36334 xMax: globals.xMax, 36335 yMax: globals.yMax, 36336 lowestRecPPEM: 3, 36337 createdTimestamp: font.createdTimestamp 36338 }); 36339 36340 var hheaTable = hhea.make({ 36341 ascender: globals.ascender, 36342 descender: globals.descender, 36343 advanceWidthMax: globals.advanceWidthMax, 36344 minLeftSideBearing: globals.minLeftSideBearing, 36345 minRightSideBearing: globals.minRightSideBearing, 36346 xMaxExtent: globals.maxLeftSideBearing + (globals.xMax - globals.xMin), 36347 numberOfHMetrics: font.glyphs.length 36348 }); 36349 36350 var maxpTable = maxp.make(font.glyphs.length); 36351 36352 var os2Table = os2.make({ 36353 xAvgCharWidth: Math.round(globals.advanceWidthAvg), 36354 usWeightClass: font.tables.os2.usWeightClass, 36355 usWidthClass: font.tables.os2.usWidthClass, 36356 usFirstCharIndex: firstCharIndex, 36357 usLastCharIndex: lastCharIndex, 36358 ulUnicodeRange1: ulUnicodeRange1, 36359 ulUnicodeRange2: ulUnicodeRange2, 36360 ulUnicodeRange3: ulUnicodeRange3, 36361 ulUnicodeRange4: ulUnicodeRange4, 36362 fsSelection: font.tables.os2.fsSelection, // REGULAR 36363 // See http://typophile.com/node/13081 for more info on vertical metrics. 36364 // We get metrics for typical characters (such as "x" for xHeight). 36365 // We provide some fallback characters if characters are unavailable: their 36366 // ordering was chosen experimentally. 36367 sTypoAscender: globals.ascender, 36368 sTypoDescender: globals.descender, 36369 sTypoLineGap: 0, 36370 usWinAscent: globals.yMax, 36371 usWinDescent: Math.abs(globals.yMin), 36372 ulCodePageRange1: 1, // FIXME: hard-code Latin 1 support for now 36373 sxHeight: metricsForChar(font, 'xyvw', {yMax: Math.round(globals.ascender / 2)}).yMax, 36374 sCapHeight: metricsForChar(font, 'HIKLEFJMNTZBDPRAGOQSUVWXY', globals).yMax, 36375 usDefaultChar: font.hasChar(' ') ? 32 : 0, // Use space as the default character, if available. 36376 usBreakChar: font.hasChar(' ') ? 32 : 0 // Use space as the break character, if available. 36377 }); 36378 36379 var hmtxTable = hmtx.make(font.glyphs); 36380 var cmapTable = cmap.make(font.glyphs); 36381 36382 var englishFamilyName = font.getEnglishName('fontFamily');
36383 var englishStyleName = font.getEnglishName('fontSubfamily'); 36384 var englishFullName = englishFamilyName + ' ' + englishStyleName; 36385 var postScriptName = font.getEnglishName('postScriptName'); 36386 if (!postScriptName) { 36387 postScriptName = englishFamilyName.replace(/\s/g, '') + '-' + englishStyleName; 36388 } 36389 36390 var names = {}; 36391 for (var n in font.names) { 36392 names[n] = font.names[n]; 36393 } 36394 36395 if (!names.uniqueID) { 36396 names.uniqueID = {en: font.getEnglishName('manufacturer') + ':' + englishFullName}; 36397 } 36398 36399 if (!names.postScriptName) { 36400 names.postScriptName = {en: postScriptName}; 36401 } 36402 36403 if (!names.preferredFamily) { 36404 names.preferredFamily = font.names.fontFamily; 36405 } 36406 36407 if (!names.preferredSubfamily) { 36408 names.preferredSubfamily = font.names.fontSubfamily; 36409 } 36410 36411 var languageTags = []; 36412 var nameTable = _name.make(names, languageTags); 36413 var ltagTable = (languageTags.length > 0 ? ltag.make(languageTags) : undefined); 36414 36415 var postTable = post.make(); 36416 var cffTable = cff.make(font.glyphs, { 36417 version: font.getEnglishName('version'), 36418 fullName: englishFullName, 36419 familyName: englishFamilyName, 36420 weightName: englishStyleName, 36421 postScriptName: postScriptName, 36422 unitsPerEm: font.unitsPerEm, 36423 fontBBox: [0, globals.yMin, globals.ascender, globals.advanceWidthMax] 36424 }); 36425 36426 var metaTable = (font.metas && Object.keys(font.metas).length > 0) ? meta.make(font.metas) : undefined; 36427 36428 // The order does not matter because makeSfntTable() will sort them. 36429 var tables = [headTable, hheaTable, maxpTable, os2Table, nameTable, cmapTable, postTable, cffTable, hmtxTable]; 36430 if (ltagTable) { 36431 tables.push(ltagTable); 36432 } 36433 // Optional tables 36434 if (font.tables.gsub) { 36435 tables.push(gsub.make(font.tables.gsub)); 36436 } 36437 if (metaTable) { 36438 tables.push(metaTable); 36439 } 36440 36441 var sfntTable = makeSfntTable(tables); 36442 36443 // Compute the font's checkSum and store it in head.checkSumAdjustment. 36444 var bytes = sfntTable.encode(); 36445 var checkSum = computeCheckSum(bytes); 36446 var tableFields = sfntTable.fields; 36447 var checkSumAdjusted = false; 36448 for (var i$1 = 0; i$1 < tableFields.length; i$1 += 1) { 36449 if (tableFields[i$1].name === 'head table') { 36450 tableFields[i$1].value.checkSumAdjustment = 0xB1B0AFBA - checkSum; 36451 checkSumAdjusted = true; 36452 break; 36453 } 36454 } 36455 36456 if (!checkSumAdjusted) { 36457 throw new Error('Could not find head table with checkSum to adjust.'); 36458 } 36459 36460 return sfntTable; 36461} 36462 36463var sfnt = { make: makeSfntTable, fontToTable: fontToSfntTable, computeCheckSum: computeCheckSum }; 36464 36465// The Layout object is the prototype of Substitution objects, and provides 36466// utility methods to manipulate common layout tables (GPOS, GSUB, GDEF...) 36467 36468function searchTag(arr, tag) { 36469 /* jshint bitwise: false */ 36470 var imin = 0; 36471 var imax = arr.length - 1; 36472 while (imin <= imax) { 36473 var imid = (imin + imax) >>> 1; 36474 var val = arr[imid].tag; 36475 if (val === tag) { 36476 return imid; 36477 } else if (val < tag) { 36478 imin = imid + 1; 36479 } else { imax = imid - 1; } 36480 } 36481 // Not found: return -1-insertion point 36482 return -imin - 1; 36483} 36484 36485function binSearch(arr, value) { 36486 /* jshint bitwise: false */ 36487 var imin = 0; 36488 var imax = arr.length - 1; 36489 while (imin <= imax) { 36490 var imid = (imin + imax) >>> 1; 36491 var val = arr[imid]; 36492 if (val === value) { 36493 return imid; 36494 } else if (val < value) { 36495 imin = imid + 1; 36496 } else { imax = imid - 1; } 36497 } 36498 // Not found: return -1-insertion point 36499 return -imin - 1; 36500} 36501 36502/**
vendor: 18,362 bytes, lines 36503-37005
36503 * @exports opentype.Layout 36504 * @class 36505 */ 36506function Layout(font, tableName) { 36507 this.font = font; 36508 this.tableName = tableName; 36509} 36510 36511Layout.prototype = { 36512 36513 /** 36514 * Binary search an object by "tag" property 36515 * @instance 36516 * @function searchTag 36517 * @memberof opentype.Layout 36518 * @param {Array} arr 36519 * @param {string} tag 36520 * @return {number} 36521 */ 36522 searchTag: searchTag, 36523 36524 /** 36525 * Binary search in a list of numbers 36526 * @instance 36527 * @function binSearch 36528 * @memberof opentype.Layout 36529 * @param {Array} arr 36530 * @param {number} value 36531 * @return {number} 36532 */ 36533 binSearch: binSearch, 36534 36535 /** 36536 * Get or create the Layout table (GSUB, GPOS etc). 36537 * @param {boolean} create - Whether to create a new one. 36538 * @return {Object} The GSUB or GPOS table. 36539 */ 36540 getTable: function(create) { 36541 var layout = this.font.tables[this.tableName]; 36542 if (!layout && create) { 36543 layout = this.font.tables[this.tableName] = this.createDefaultTable(); 36544 } 36545 return layout; 36546 }, 36547 36548 /** 36549 * Returns all scripts in the substitution table. 36550 * @instance 36551 * @return {Array} 36552 */ 36553 getScriptNames: function() { 36554 var layout = this.getTable(); 36555 if (!layout) { return []; } 36556 return layout.scripts.map(function(script) { 36557 return script.tag; 36558 }); 36559 }, 36560 36561 /** 36562 * Returns the best bet for a script name. 36563 * Returns 'DFLT' if it exists. 36564 * If not, returns 'latn' if it exists. 36565 * If neither exist, returns undefined. 36566 */ 36567 getDefaultScriptName: function() { 36568 var layout = this.getTable(); 36569 if (!layout) { return; } 36570 var hasLatn = false; 36571 for (var i = 0; i < layout.scripts.length; i++) { 36572 var name = layout.scripts[i].tag; 36573 if (name === 'DFLT') { return name; } 36574 if (name === 'latn') { hasLatn = true; } 36575 } 36576 if (hasLatn) { return 'latn'; } 36577 }, 36578 36579 /** 36580 * Returns all LangSysRecords in the given script. 36581 * @instance 36582 * @param {string} [script='DFLT'] 36583 * @param {boolean} create - forces the creation of this script table if it doesn't exist. 36584 * @return {Object} An object with tag and script properties. 36585 */ 36586 getScriptTable: function(script, create) { 36587 var layout = this.getTable(create); 36588 if (layout) { 36589 script = script || 'DFLT'; 36590 var scripts = layout.scripts; 36591 var pos = searchTag(layout.scripts, script); 36592 if (pos >= 0) { 36593 return scripts[pos].script; 36594 } else if (create) { 36595 var scr = { 36596 tag: script, 36597 script: { 36598 defaultLangSys: {reserved: 0, reqFeatureIndex: 0xffff, featureIndexes: []}, 36599 langSysRecords: [] 36600 } 36601 }; 36602 scripts.splice(-1 - pos, 0, scr); 36603 return scr.script; 36604 } 36605 } 36606 }, 36607 36608 /** 36609 * Returns a language system table 36610 * @instance 36611 * @param {string} [script='DFLT'] 36612 * @param {string} [language='dlft'] 36613 * @param {boolean} create - forces the creation of this langSysTable if it doesn't exist. 36614 * @return {Object} 36615 */ 36616 getLangSysTable: function(script, language, create) { 36617 var scriptTable = this.getScriptTable(script, create); 36618 if (scriptTable) { 36619 if (!language || language === 'dflt' || language === 'DFLT') { 36620 return scriptTable.defaultLangSys; 36621 } 36622 var pos = searchTag(scriptTable.langSysRecords, language); 36623 if (pos >= 0) { 36624 return scriptTable.langSysRecords[pos].langSys; 36625 } else if (create) { 36626 var langSysRecord = { 36627 tag: language, 36628 langSys: {reserved: 0, reqFeatureIndex: 0xffff, featureIndexes: []} 36629 }; 36630 scriptTable.langSysRecords.splice(-1 - pos, 0, langSysRecord); 36631 return langSysRecord.langSys; 36632 } 36633 } 36634 }, 36635 36636 /** 36637 * Get a specific feature table. 36638 * @instance 36639 * @param {string} [script='DFLT'] 36640 * @param {string} [language='dlft'] 36641 * @param {string} feature - One of the codes listed at https://www.microsoft.com/typography/OTSPEC/featurelist.htm 36642 * @param {boolean} create - forces the creation of the feature table if it doesn't exist. 36643 * @return {Object} 36644 */ 36645 getFeatureTable: function(script, language, feature, create) { 36646 var langSysTable = this.getLangSysTable(script, language, create); 36647 if (langSysTable) { 36648 var featureRecord; 36649 var featIndexes = langSysTable.featureIndexes; 36650 var allFeatures = this.font.tables[this.tableName].features; 36651 // The FeatureIndex array of indices is in arbitrary order, 36652 // even if allFeatures is sorted alphabetically by feature tag. 36653 for (var i = 0; i < featIndexes.length; i++) { 36654 featureRecord = allFeatures[featIndexes[i]]; 36655 if (featureRecord.tag === feature) { 36656 return featureRecord.feature; 36657 } 36658 } 36659 if (create) { 36660 var index = allFeatures.length; 36661 // Automatic ordering of features would require to shift feature indexes in the script list. 36662 check.assert(index === 0 || feature >= allFeatures[index - 1].tag, 'Features must be added in alphabetical order.'); 36663 featureRecord = { 36664 tag: feature, 36665 feature: { params: 0, lookupListIndexes: [] } 36666 }; 36667 allFeatures.push(featureRecord); 36668 featIndexes.push(index); 36669 return featureRecord.feature; 36670 } 36671 } 36672 }, 36673 36674 /** 36675 * Get the lookup tables of a given type for a script/language/feature. 36676 * @instance 36677 * @param {string} [script='DFLT'] 36678 * @param {string} [language='dlft'] 36679 * @param {string} feature - 4-letter feature code 36680 * @param {number} lookupType - 1 to 8 36681 * @param {boolean} create - forces the creation of the lookup table if it doesn't exist, with no subtables. 36682 * @return {Object[]} 36683 */ 36684 getLookupTables: function(script, language, feature, lookupType, create) { 36685 var featureTable = this.getFeatureTable(script, language, feature, create); 36686 var tables = []; 36687 if (featureTable) { 36688 var lookupTable; 36689 var lookupListIndexes = featureTable.lookupListIndexes; 36690 var allLookups = this.font.tables[this.tableName].lookups; 36691 // lookupListIndexes are in no particular order, so use naive search. 36692 for (var i = 0; i < lookupListIndexes.length; i++) { 36693 lookupTable = allLookups[lookupListIndexes[i]]; 36694 if (lookupTable.lookupType === lookupType) { 36695 tables.push(lookupTable); 36696 } 36697 } 36698 if (tables.length === 0 && create) { 36699 lookupTable = { 36700 lookupType: lookupType, 36701 lookupFlag: 0, 36702 subtables: [], 36703 markFilteringSet: undefined 36704 }; 36705 var index = allLookups.length; 36706 allLookups.push(lookupTable); 36707 lookupListIndexes.push(index); 36708 return [lookupTable]; 36709 } 36710 } 36711 return tables; 36712 }, 36713 36714 /** 36715 * Returns the list of glyph indexes of a coverage table. 36716 * Format 1: the list is stored raw 36717 * Format 2: compact list as range records. 36718 * @instance 36719 * @param {Object} coverageTable 36720 * @return {Array} 36721 */ 36722 expandCoverage: function(coverageTable) { 36723 if (coverageTable.format === 1) { 36724 return coverageTable.glyphs; 36725 } else { 36726 var glyphs = []; 36727 var ranges = coverageTable.ranges; 36728 for (var i = 0; i < ranges.length; i++) { 36729 var range = ranges[i]; 36730 var start = range.start; 36731 var end = range.end; 36732 for (var j = start; j <= end; j++) { 36733 glyphs.push(j); 36734 } 36735 } 36736 return glyphs; 36737 } 36738 } 36739 36740}; 36741 36742// The Substitution object provides utility methods to manipulate 36743// the GSUB substitution table. 36744 36745/** 36746 * @exports opentype.Substitution 36747 * @class 36748 * @extends opentype.Layout 36749 * @param {opentype.Font} 36750 * @constructor 36751 */ 36752function Substitution(font) { 36753 Layout.call(this, font, 'gsub'); 36754} 36755 36756// Check if 2 arrays of primitives are equal. 36757function arraysEqual(ar1, ar2) { 36758 var n = ar1.length; 36759 if (n !== ar2.length) { return false; } 36760 for (var i = 0; i < n; i++) { 36761 if (ar1[i] !== ar2[i]) { return false; } 36762 } 36763 return true; 36764} 36765 36766// Find the first subtable of a lookup table in a particular format. 36767function getSubstFormat(lookupTable, format, defaultSubtable) { 36768 var subtables = lookupTable.subtables; 36769 for (var i = 0; i < subtables.length; i++) { 36770 var subtable = subtables[i]; 36771 if (subtable.substFormat === format) { 36772 return subtable; 36773 } 36774 } 36775 if (defaultSubtable) { 36776 subtables.push(defaultSubtable); 36777 return defaultSubtable; 36778 } 36779 return undefined; 36780} 36781 36782Substitution.prototype = Layout.prototype; 36783 36784/** 36785 * Create a default GSUB table. 36786 * @return {Object} gsub - The GSUB table. 36787 */ 36788Substitution.prototype.createDefaultTable = function() { 36789 // Generate a default empty GSUB table with just a DFLT script and dflt lang sys. 36790 return { 36791 version: 1, 36792 scripts: [{ 36793 tag: 'DFLT', 36794 script: { 36795 defaultLangSys: { reserved: 0, reqFeatureIndex: 0xffff, featureIndexes: [] }, 36796 langSysRecords: [] 36797 } 36798 }], 36799 features: [], 36800 lookups: [] 36801 }; 36802}; 36803 36804/** 36805 * List all single substitutions (lookup type 1) for a given script, language, and feature. 36806 * @param {string} [script='DFLT'] 36807 * @param {string} [language='dflt'] 36808 * @param {string} feature - 4-character feature name ('aalt', 'salt', 'ss01'...) 36809 * @return {Array} substitutions - The list of substitutions. 36810 */ 36811Substitution.prototype.getSingle = function(feature, script, language) { 36812 var this$1 = this; 36813 36814 var substitutions = []; 36815 var lookupTables = this.getLookupTables(script, language, feature, 1); 36816 for (var idx = 0; idx < lookupTables.length; idx++) { 36817 var subtables = lookupTables[idx].subtables; 36818 for (var i = 0; i < subtables.length; i++) { 36819 var subtable = subtables[i]; 36820 var glyphs = this$1.expandCoverage(subtable.coverage); 36821 var j = (void 0); 36822 if (subtable.substFormat === 1) { 36823 var delta = subtable.deltaGlyphId; 36824 for (j = 0; j < glyphs.length; j++) { 36825 var glyph = glyphs[j]; 36826 substitutions.push({ sub: glyph, by: glyph + delta }); 36827 } 36828 } else { 36829 var substitute = subtable.substitute; 36830 for (j = 0; j < glyphs.length; j++) { 36831 substitutions.push({ sub: glyphs[j], by: substitute[j] }); 36832 } 36833 } 36834 } 36835 } 36836 return substitutions; 36837}; 36838 36839/** 36840 * List all alternates (lookup type 3) for a given script, language, and feature. 36841 * @param {string} [script='DFLT'] 36842 * @param {string} [language='dflt'] 36843 * @param {string} feature - 4-character feature name ('aalt', 'salt'...) 36844 * @return {Array} alternates - The list of alternates 36845 */ 36846Substitution.prototype.getAlternates = function(feature, script, language) { 36847 var this$1 = this; 36848 36849 var alternates = []; 36850 var lookupTables = this.getLookupTables(script, language, feature, 3); 36851 for (var idx = 0; idx < lookupTables.length; idx++) { 36852 var subtables = lookupTables[idx].subtables; 36853 for (var i = 0; i < subtables.length; i++) { 36854 var subtable = subtables[i]; 36855 var glyphs = this$1.expandCoverage(subtable.coverage); 36856 var alternateSets = subtable.alternateSets; 36857 for (var j = 0; j < glyphs.length; j++) { 36858 alternates.push({ sub: glyphs[j], by: alternateSets[j] }); 36859 } 36860 } 36861 } 36862 return alternates; 36863}; 36864 36865/** 36866 * List all ligatures (lookup type 4) for a given script, language, and feature. 36867 * The result is an array of ligature objects like { sub: [ids], by: id } 36868 * @param {string} feature - 4-letter feature name ('liga', 'rlig', 'dlig'...) 36869 * @param {string} [script='DFLT'] 36870 * @param {string} [language='dflt'] 36871 * @return {Array} ligatures - The list of ligatures. 36872 */ 36873Substitution.prototype.getLigatures = function(feature, script, language) { 36874 var this$1 = this; 36875 36876 var ligatures = []; 36877 var lookupTables = this.getLookupTables(script, language, feature, 4); 36878 for (var idx = 0; idx < lookupTables.length; idx++) { 36879 var subtables = lookupTables[idx].subtables; 36880 for (var i = 0; i < subtables.length; i++) { 36881 var subtable = subtables[i]; 36882 var glyphs = this$1.expandCoverage(subtable.coverage); 36883 var ligatureSets = subtable.ligatureSets; 36884 for (var j = 0; j < glyphs.length; j++) { 36885 var startGlyph = glyphs[j]; 36886 var ligSet = ligatureSets[j]; 36887 for (var k = 0; k < ligSet.length; k++) { 36888 var lig = ligSet[k]; 36889 ligatures.push({ 36890 sub: [startGlyph].concat(lig.components), 36891 by: lig.ligGlyph 36892 }); 36893 } 36894 } 36895 } 36896 } 36897 return ligatures; 36898}; 36899 36900/** 36901 * Add or modify a single substitution (lookup type 1) 36902 * Format 2, more flexible, is always used. 36903 * @param {string} feature - 4-letter feature name ('liga', 'rlig', 'dlig'...) 36904 * @param {Object} substitution - { sub: id, delta: number } for format 1 or { sub: id, by: id } for format 2. 36905 * @param {string} [script='DFLT'] 36906 * @param {string} [language='dflt'] 36907 */ 36908Substitution.prototype.addSingle = function(feature, substitution, script, language) { 36909 var lookupTable = this.getLookupTables(script, language, feature, 1, true)[0]; 36910 var subtable = getSubstFormat(lookupTable, 2, { // lookup type 1 subtable, format 2, coverage format 1 36911 substFormat: 2, 36912 coverage: {format: 1, glyphs: []}, 36913 substitute: [] 36914 }); 36915 check.assert(subtable.coverage.format === 1, 'Ligature: unable to modify coverage table format ' + subtable.coverage.format); 36916 var coverageGlyph = substitution.sub; 36917 var pos = this.binSearch(subtable.coverage.glyphs, coverageGlyph); 36918 if (pos < 0) { 36919 pos = -1 - pos; 36920 subtable.coverage.glyphs.splice(pos, 0, coverageGlyph); 36921 subtable.substitute.splice(pos, 0, 0); 36922 } 36923 subtable.substitute[pos] = substitution.by; 36924}; 36925 36926/** 36927 * Add or modify an alternate substitution (lookup type 1) 36928 * @param {string} feature - 4-letter feature name ('liga', 'rlig', 'dlig'...) 36929 * @param {Object} substitution - { sub: id, by: [ids] } 36930 * @param {string} [script='DFLT'] 36931 * @param {string} [language='dflt'] 36932 */ 36933Substitution.prototype.addAlternate = function(feature, substitution, script, language) { 36934 var lookupTable = this.getLookupTables(script, language, feature, 3, true)[0]; 36935 var subtable = getSubstFormat(lookupTable, 1, { // lookup type 3 subtable, format 1, coverage format 1 36936 substFormat: 1, 36937 coverage: {format: 1, glyphs: []}, 36938 alternateSets: [] 36939 }); 36940 check.assert(subtable.coverage.format === 1, 'Ligature: unable to modify coverage table format ' + subtable.coverage.format); 36941 var coverageGlyph = substitution.sub; 36942 var pos = this.binSearch(subtable.coverage.glyphs, coverageGlyph); 36943 if (pos < 0) { 36944 pos = -1 - pos; 36945 subtable.coverage.glyphs.splice(pos, 0, coverageGlyph); 36946 subtable.alternateSets.splice(pos, 0, 0); 36947 } 36948 subtable.alternateSets[pos] = substitution.by; 36949}; 36950 36951/** 36952 * Add a ligature (lookup type 4) 36953 * Ligatures with more components must be stored ahead of those with fewer components in order to be found 36954 * @param {string} feature - 4-letter feature name ('liga', 'rlig', 'dlig'...) 36955 * @param {Object} ligature - { sub: [ids], by: id } 36956 * @param {string} [script='DFLT'] 36957 * @param {string} [language='dflt'] 36958 */ 36959Substitution.prototype.addLigature = function(feature, ligature, script, language) { 36960 var lookupTable = this.getLookupTables(script, language, feature, 4, true)[0]; 36961 var subtable = lookupTable.subtables[0]; 36962 if (!subtable) { 36963 subtable = { // lookup type 4 subtable, format 1, coverage format 1 36964 substFormat: 1, 36965 coverage: { format: 1, glyphs: [] }, 36966 ligatureSets: [] 36967 }; 36968 lookupTable.subtables[0] = subtable; 36969 } 36970 check.assert(subtable.coverage.format === 1, 'Ligature: unable to modify coverage table format ' + subtable.coverage.format); 36971 var coverageGlyph = ligature.sub[0]; 36972 var ligComponents = ligature.sub.slice(1); 36973 var ligatureTable = { 36974 ligGlyph: ligature.by, 36975 components: ligComponents 36976 }; 36977 var pos = this.binSearch(subtable.coverage.glyphs, coverageGlyph); 36978 if (pos >= 0) { 36979 // ligatureSet already exists 36980 var ligatureSet = subtable.ligatureSets[pos]; 36981 for (var i = 0; i < ligatureSet.length; i++) { 36982 // If ligature already exists, return. 36983 if (arraysEqual(ligatureSet[i].components, ligComponents)) { 36984 return; 36985 } 36986 } 36987 // ligature does not exist: add it. 36988 ligatureSet.push(ligatureTable); 36989 } else { 36990 // Create a new ligatureSet and add coverage for the first glyph. 36991 pos = -1 - pos; 36992 subtable.coverage.glyphs.splice(pos, 0, coverageGlyph); 36993 subtable.ligatureSets.splice(pos, 0, [ligatureTable]); 36994 } 36995}; 36996 36997/** 36998 * List all feature data for a given script and language. 36999 * @param {string} feature - 4-letter feature name 37000 * @param {string} [script='DFLT'] 37001 * @param {string} [language='dflt'] 37002 * @return {Array} substitutions - The list of substitutions. 37003 */ 37004Substitution.prototype.getFeature = function(feature, script, language) { 37005 if (/ss\d\d/.test(feature)) { // ss01 - ss20
37006 return this.getSingle(feature, script, language); 37007 } 37008 switch (feature) { 37009 case 'aalt': 37010 case 'salt': 37011 return this.getSingle(feature, script, language) 37012 .concat(this.getAlternates(feature, script, language)); 37013 case 'dlig': 37014 case 'liga': 37015 case 'rlig': return this.getLigatures(feature, script, language); 37016 } 37017 return undefined; 37018}; 37019 37020/** 37021 * Add a substitution to a feature for a given script and language. 37022 * @param {string} feature - 4-letter feature name 37023 * @param {Object} sub - the substitution to add (an object like { sub: id or [ids], by: id or [ids] }) 37024 * @param {string} [script='DFLT'] 37025 * @param {string} [language='dflt'] 37026 */ 37027Substitution.prototype.add = function(feature, sub, script, language) { 37028 if (/ss\d\d/.test(feature)) { // ss01 - ss20 37029 return this.addSingle(feature, sub, script, language); 37030 } 37031 switch (feature) { 37032 case 'aalt': 37033 case 'salt': 37034 if (typeof sub.by === 'number') { 37035 return this.addSingle(feature, sub, script, language); 37036 } 37037 return this.addAlternate(feature, sub, script, language); 37038 case 'dlig': 37039 case 'liga': 37040 case 'rlig': 37041 return this.addLigature(feature, sub, script, language); 37042 } 37043 return undefined; 37044}; 37045 37046function isBrowser() { 37047 return typeof window !== 'undefined'; 37048} 37049 37050function nodeBufferToArrayBuffer(buffer) { 37051 var ab = new ArrayBuffer(buffer.length); 37052 var view = new Uint8Array(ab); 37053 for (var i = 0; i < buffer.length; ++i) { 37054 view[i] = buffer[i]; 37055 } 37056 37057 return ab; 37058} 37059 37060function arrayBufferToNodeBuffer(ab) { 37061 var buffer = new Buffer(ab.byteLength); 37062 var view = new Uint8Array(ab); 37063 for (var i = 0; i < buffer.length; ++i) { 37064 buffer[i] = view[i]; 37065 } 37066 37067 return buffer; 37068} 37069 37070function checkArgument(expression, message) { 37071 if (!expression) { 37072 throw message; 37073 } 37074} 37075 37076/* A TrueType font hinting interpreter. 37077* 37078* (c) 2017 Axel Kittenberger 37079* 37080* This interpreter has been implemented according to this documentation: 37081* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM05/Chap5.html 37082* 37083* According to the documentation F24DOT6 values are used for pixels. 37084* That means calculation is 1/64 pixel accurate and uses integer operations. 37085* However, Javascript has floating point operations by default and only 37086* those are available. One could make a case to simulate the 1/64 accuracy 37087* exactly by truncating after every division operation 37088* (for example with << 0) to get pixel exactly results as other TrueType 37089* implementations. It may make sense since some fonts are pixel optimized 37090* by hand using DELTAP instructions. The current implementation doesn't 37091* and rather uses full floating point precision. 37092* 37093* xScale, yScale and rotation is currently ignored. 37094* 37095* A few non-trivial instructions are missing as I didn't encounter yet 37096* a font that used them to test a possible implementation. 37097* 37098* Some fonts seem to use undocumented features regarding the twilight zone. 37099* Only some of them are implemented as they were encountered. 37100* 37101* The exports.DEBUG statements are removed on the minified distribution file. 37102*/ 37103var instructionTable; 37104var exec; 37105var execGlyph; 37106var execComponent; 37107 37108/* 37109* Creates a hinting object. 37110* 37111* There ought to be exactly one 37112* for each truetype font that is used for hinting. 37113*/ 37114function Hinting(font) { 37115 // the font this hinting object is for 37116 this.font = font; 37117 37118 // cached states 37119 this._fpgmState = 37120 this._prepState = 37121 undefined; 37122 37123 // errorState 37124 // 0 ... all okay 37125 // 1 ... had an error in a glyf, 37126 // continue working but stop spamming 37127 // the console 37128 // 2 ... error at prep, stop hinting at this ppem 37129 // 3 ... error at fpeg, stop hinting for this font at all 37130 this._errorState = 0; 37131} 37132 37133/* 37134* Not rounding. 37135*/ 37136function roundOff(v) { 37137 return v; 37138} 37139 37140/* 37141* Rounding to grid. 37142*/ 37143function roundToGrid(v) { 37144 //Rounding in TT is supposed to "symmetrical around zero" 37145 return Math.sign(v) * Math.round(Math.abs(v)); 37146} 37147 37148/* 37149* Rounding to double grid. 37150*/ 37151function roundToDoubleGrid(v) { 37152 return Math.sign(v) * Math.round(Math.abs(v * 2)) / 2; 37153} 37154 37155/* 37156* Rounding to half grid. 37157*/ 37158function roundToHalfGrid(v) { 37159 return Math.sign(v) * (Math.round(Math.abs(v) + 0.5) - 0.5); 37160} 37161 37162/* 37163* Rounding to up to grid. 37164*/ 37165function roundUpToGrid(v) { 37166 return Math.sign(v) * Math.ceil(Math.abs(v)); 37167} 37168 37169/* 37170* Rounding to down to grid. 37171*/ 37172function roundDownToGrid(v) { 37173 return Math.sign(v) * Math.floor(Math.abs(v)); 37174} 37175 37176/* 37177* Super rounding. 37178*/
vendor: 56,961 bytes, lines 37179-39631
37179var roundSuper = function (v) { 37180 var period = this.srPeriod; 37181 var phase = this.srPhase; 37182 var threshold = this.srThreshold; 37183 var sign = 1; 37184 37185 if (v < 0) { 37186 v = -v; 37187 sign = -1; 37188 } 37189 37190 v += threshold - phase; 37191 37192 v = Math.trunc(v / period) * period; 37193 37194 v += phase; 37195 37196 // according to http://xgridfit.sourceforge.net/round.html 37197 if (sign > 0 && v < 0) { return phase; } 37198 if (sign < 0 && v > 0) { return -phase; } 37199 37200 return v * sign; 37201}; 37202 37203/* 37204* Unit vector of x-axis. 37205*/ 37206var xUnitVector = { 37207 x: 1, 37208 37209 y: 0, 37210 37211 axis: 'x', 37212 37213 // Gets the projected distance between two points. 37214 // o1/o2 ... if true, respective original position is used. 37215 distance: function (p1, p2, o1, o2) { 37216 return (o1 ? p1.xo : p1.x) - (o2 ? p2.xo : p2.x); 37217 }, 37218 37219 // Moves point p so the moved position has the same relative 37220 // position to the moved positions of rp1 and rp2 than the 37221 // original positions had. 37222 // 37223 // See APPENDIX on INTERPOLATE at the bottom of this file. 37224 interpolate: function (p, rp1, rp2, pv) { 37225 var do1; 37226 var do2; 37227 var doa1; 37228 var doa2; 37229 var dm1; 37230 var dm2; 37231 var dt; 37232 37233 if (!pv || pv === this) { 37234 do1 = p.xo - rp1.xo; 37235 do2 = p.xo - rp2.xo; 37236 dm1 = rp1.x - rp1.xo; 37237 dm2 = rp2.x - rp2.xo; 37238 doa1 = Math.abs(do1); 37239 doa2 = Math.abs(do2); 37240 dt = doa1 + doa2; 37241 37242 if (dt === 0) { 37243 p.x = p.xo + (dm1 + dm2) / 2; 37244 return; 37245 } 37246 37247 p.x = p.xo + (dm1 * doa2 + dm2 * doa1) / dt; 37248 return; 37249 } 37250 37251 do1 = pv.distance(p, rp1, true, true); 37252 do2 = pv.distance(p, rp2, true, true); 37253 dm1 = pv.distance(rp1, rp1, false, true); 37254 dm2 = pv.distance(rp2, rp2, false, true); 37255 doa1 = Math.abs(do1); 37256 doa2 = Math.abs(do2); 37257 dt = doa1 + doa2; 37258 37259 if (dt === 0) { 37260 xUnitVector.setRelative(p, p, (dm1 + dm2) / 2, pv, true); 37261 return; 37262 } 37263 37264 xUnitVector.setRelative(p, p, (dm1 * doa2 + dm2 * doa1) / dt, pv, true); 37265 }, 37266 37267 // Slope of line normal to this 37268 normalSlope: Number.NEGATIVE_INFINITY, 37269 37270 // Sets the point 'p' relative to point 'rp' 37271 // by the distance 'd'. 37272 // 37273 // See APPENDIX on SETRELATIVE at the bottom of this file. 37274 // 37275 // p ... point to set 37276 // rp ... reference point 37277 // d ... distance on projection vector 37278 // pv ... projection vector (undefined = this) 37279 // org ... if true, uses the original position of rp as reference. 37280 setRelative: function (p, rp, d, pv, org) { 37281 if (!pv || pv === this) { 37282 p.x = (org ? rp.xo : rp.x) + d; 37283 return; 37284 } 37285 37286 var rpx = org ? rp.xo : rp.x; 37287 var rpy = org ? rp.yo : rp.y; 37288 var rpdx = rpx + d * pv.x; 37289 var rpdy = rpy + d * pv.y; 37290 37291 p.x = rpdx + (p.y - rpdy) / pv.normalSlope; 37292 }, 37293 37294 // Slope of vector line. 37295 slope: 0, 37296 37297 // Touches the point p. 37298 touch: function (p) { 37299 p.xTouched = true; 37300 }, 37301 37302 // Tests if a point p is touched. 37303 touched: function (p) { 37304 return p.xTouched; 37305 }, 37306 37307 // Untouches the point p. 37308 untouch: function (p) { 37309 p.xTouched = false; 37310 } 37311}; 37312 37313/* 37314* Unit vector of y-axis. 37315*/ 37316var yUnitVector = { 37317 x: 0, 37318 37319 y: 1, 37320 37321 axis: 'y', 37322 37323 // Gets the projected distance between two points. 37324 // o1/o2 ... if true, respective original position is used. 37325 distance: function (p1, p2, o1, o2) { 37326 return (o1 ? p1.yo : p1.y) - (o2 ? p2.yo : p2.y); 37327 }, 37328 37329 // Moves point p so the moved position has the same relative 37330 // position to the moved positions of rp1 and rp2 than the 37331 // original positions had. 37332 // 37333 // See APPENDIX on INTERPOLATE at the bottom of this file. 37334 interpolate: function (p, rp1, rp2, pv) { 37335 var do1; 37336 var do2; 37337 var doa1; 37338 var doa2; 37339 var dm1; 37340 var dm2; 37341 var dt; 37342 37343 if (!pv || pv === this) { 37344 do1 = p.yo - rp1.yo; 37345 do2 = p.yo - rp2.yo; 37346 dm1 = rp1.y - rp1.yo; 37347 dm2 = rp2.y - rp2.yo; 37348 doa1 = Math.abs(do1); 37349 doa2 = Math.abs(do2); 37350 dt = doa1 + doa2; 37351 37352 if (dt === 0) { 37353 p.y = p.yo + (dm1 + dm2) / 2; 37354 return; 37355 } 37356 37357 p.y = p.yo + (dm1 * doa2 + dm2 * doa1) / dt; 37358 return; 37359 } 37360 37361 do1 = pv.distance(p, rp1, true, true); 37362 do2 = pv.distance(p, rp2, true, true); 37363 dm1 = pv.distance(rp1, rp1, false, true); 37364 dm2 = pv.distance(rp2, rp2, false, true); 37365 doa1 = Math.abs(do1); 37366 doa2 = Math.abs(do2); 37367 dt = doa1 + doa2; 37368 37369 if (dt === 0) { 37370 yUnitVector.setRelative(p, p, (dm1 + dm2) / 2, pv, true); 37371 return; 37372 } 37373 37374 yUnitVector.setRelative(p, p, (dm1 * doa2 + dm2 * doa1) / dt, pv, true); 37375 }, 37376 37377 // Slope of line normal to this. 37378 normalSlope: 0, 37379 37380 // Sets the point 'p' relative to point 'rp' 37381 // by the distance 'd' 37382 // 37383 // See APPENDIX on SETRELATIVE at the bottom of this file. 37384 // 37385 // p ... point to set 37386 // rp ... reference point 37387 // d ... distance on projection vector 37388 // pv ... projection vector (undefined = this) 37389 // org ... if true, uses the original position of rp as reference. 37390 setRelative: function (p, rp, d, pv, org) { 37391 if (!pv || pv === this) { 37392 p.y = (org ? rp.yo : rp.y) + d; 37393 return; 37394 } 37395 37396 var rpx = org ? rp.xo : rp.x; 37397 var rpy = org ? rp.yo : rp.y; 37398 var rpdx = rpx + d * pv.x; 37399 var rpdy = rpy + d * pv.y; 37400 37401 p.y = rpdy + pv.normalSlope * (p.x - rpdx); 37402 }, 37403 37404 // Slope of vector line. 37405 slope: Number.POSITIVE_INFINITY, 37406 37407 // Touches the point p. 37408 touch: function (p) { 37409 p.yTouched = true; 37410 }, 37411 37412 // Tests if a point p is touched. 37413 touched: function (p) { 37414 return p.yTouched; 37415 }, 37416 37417 // Untouches the point p. 37418 untouch: function (p) { 37419 p.yTouched = false; 37420 } 37421}; 37422 37423Object.freeze(xUnitVector); 37424Object.freeze(yUnitVector); 37425 37426/* 37427* Creates a unit vector that is not x- or y-axis. 37428*/ 37429function UnitVector(x, y) { 37430 this.x = x; 37431 this.y = y; 37432 this.axis = undefined; 37433 this.slope = y / x; 37434 this.normalSlope = -x / y; 37435 Object.freeze(this); 37436} 37437 37438/* 37439* Gets the projected distance between two points. 37440* o1/o2 ... if true, respective original position is used. 37441*/ 37442UnitVector.prototype.distance = function(p1, p2, o1, o2) { 37443 return ( 37444 this.x * xUnitVector.distance(p1, p2, o1, o2) + 37445 this.y * yUnitVector.distance(p1, p2, o1, o2) 37446 ); 37447}; 37448 37449/* 37450* Moves point p so the moved position has the same relative 37451* position to the moved positions of rp1 and rp2 than the 37452* original positions had. 37453* 37454* See APPENDIX on INTERPOLATE at the bottom of this file. 37455*/ 37456UnitVector.prototype.interpolate = function(p, rp1, rp2, pv) { 37457 var dm1; 37458 var dm2; 37459 var do1; 37460 var do2; 37461 var doa1; 37462 var doa2; 37463 var dt; 37464 37465 do1 = pv.distance(p, rp1, true, true); 37466 do2 = pv.distance(p, rp2, true, true); 37467 dm1 = pv.distance(rp1, rp1, false, true); 37468 dm2 = pv.distance(rp2, rp2, false, true); 37469 doa1 = Math.abs(do1); 37470 doa2 = Math.abs(do2); 37471 dt = doa1 + doa2; 37472 37473 if (dt === 0) { 37474 this.setRelative(p, p, (dm1 + dm2) / 2, pv, true); 37475 return; 37476 } 37477 37478 this.setRelative(p, p, (dm1 * doa2 + dm2 * doa1) / dt, pv, true); 37479}; 37480 37481/* 37482* Sets the point 'p' relative to point 'rp' 37483* by the distance 'd' 37484* 37485* See APPENDIX on SETRELATIVE at the bottom of this file. 37486* 37487* p ... point to set 37488* rp ... reference point 37489* d ... distance on projection vector 37490* pv ... projection vector (undefined = this) 37491* org ... if true, uses the original position of rp as reference. 37492*/ 37493UnitVector.prototype.setRelative = function(p, rp, d, pv, org) { 37494 pv = pv || this; 37495 37496 var rpx = org ? rp.xo : rp.x; 37497 var rpy = org ? rp.yo : rp.y; 37498 var rpdx = rpx + d * pv.x; 37499 var rpdy = rpy + d * pv.y; 37500 37501 var pvns = pv.normalSlope; 37502 var fvs = this.slope; 37503 37504 var px = p.x; 37505 var py = p.y; 37506 37507 p.x = (fvs * px - pvns * rpdx + rpdy - py) / (fvs - pvns); 37508 p.y = fvs * (p.x - px) + py; 37509}; 37510 37511/* 37512* Touches the point p. 37513*/ 37514UnitVector.prototype.touch = function(p) { 37515 p.xTouched = true; 37516 p.yTouched = true; 37517}; 37518 37519/* 37520* Returns a unit vector with x/y coordinates. 37521*/ 37522function getUnitVector(x, y) { 37523 var d = Math.sqrt(x * x + y * y); 37524 37525 x /= d; 37526 y /= d; 37527 37528 if (x === 1 && y === 0) { return xUnitVector; } 37529 else if (x === 0 && y === 1) { return yUnitVector; } 37530 else { return new UnitVector(x, y); } 37531} 37532 37533/* 37534* Creates a point in the hinting engine. 37535*/ 37536function HPoint( 37537 x, 37538 y, 37539 lastPointOfContour, 37540 onCurve 37541) { 37542 this.x = this.xo = Math.round(x * 64) / 64; // hinted x value and original x-value 37543 this.y = this.yo = Math.round(y * 64) / 64; // hinted y value and original y-value 37544 37545 this.lastPointOfContour = lastPointOfContour; 37546 this.onCurve = onCurve; 37547 this.prevPointOnContour = undefined; 37548 this.nextPointOnContour = undefined; 37549 this.xTouched = false; 37550 this.yTouched = false; 37551 37552 Object.preventExtensions(this); 37553} 37554 37555/* 37556* Returns the next touched point on the contour. 37557* 37558* v ... unit vector to test touch axis. 37559*/ 37560HPoint.prototype.nextTouched = function(v) { 37561 var p = this.nextPointOnContour; 37562 37563 while (!v.touched(p) && p !== this) { p = p.nextPointOnContour; } 37564 37565 return p; 37566}; 37567 37568/* 37569* Returns the previous touched point on the contour 37570* 37571* v ... unit vector to test touch axis. 37572*/ 37573HPoint.prototype.prevTouched = function(v) { 37574 var p = this.prevPointOnContour; 37575 37576 while (!v.touched(p) && p !== this) { p = p.prevPointOnContour; } 37577 37578 return p; 37579}; 37580 37581/* 37582* The zero point. 37583*/ 37584var HPZero = Object.freeze(new HPoint(0, 0)); 37585 37586/* 37587* The default state of the interpreter. 37588* 37589* Note: Freezing the defaultState and then deriving from it 37590* makes the V8 Javascript engine going awkward, 37591* so this is avoided, albeit the defaultState shouldn't 37592* ever change. 37593*/ 37594var defaultState = { 37595 cvCutIn: 17 / 16, // control value cut in 37596 deltaBase: 9, 37597 deltaShift: 0.125, 37598 loop: 1, // loops some instructions 37599 minDis: 1, // minimum distance 37600 autoFlip: true 37601}; 37602 37603/* 37604* The current state of the interpreter. 37605* 37606* env ... 'fpgm' or 'prep' or 'glyf' 37607* prog ... the program 37608*/ 37609function State(env, prog) { 37610 this.env = env; 37611 this.stack = []; 37612 this.prog = prog; 37613 37614 switch (env) { 37615 case 'glyf' : 37616 this.zp0 = this.zp1 = this.zp2 = 1; 37617 this.rp0 = this.rp1 = this.rp2 = 0; 37618 /* fall through */ 37619 case 'prep' : 37620 this.fv = this.pv = this.dpv = xUnitVector; 37621 this.round = roundToGrid; 37622 } 37623} 37624 37625/* 37626* Executes a glyph program. 37627* 37628* This does the hinting for each glyph. 37629* 37630* Returns an array of moved points. 37631* 37632* glyph: the glyph to hint 37633* ppem: the size the glyph is rendered for 37634*/ 37635Hinting.prototype.exec = function(glyph, ppem) { 37636 if (typeof ppem !== 'number') { 37637 throw new Error('Point size is not a number!'); 37638 } 37639 37640 // Received a fatal error, don't do any hinting anymore. 37641 if (this._errorState > 2) { return; } 37642 37643 var font = this.font; 37644 var prepState = this._prepState; 37645 37646 if (!prepState || prepState.ppem !== ppem) { 37647 var fpgmState = this._fpgmState; 37648 37649 if (!fpgmState) { 37650 // Executes the fpgm state. 37651 // This is used by fonts to define functions. 37652 State.prototype = defaultState; 37653 37654 fpgmState = 37655 this._fpgmState = 37656 new State('fpgm', font.tables.fpgm); 37657 37658 fpgmState.funcs = [ ]; 37659 fpgmState.font = font; 37660 37661 if (exports.DEBUG) { 37662 console.log('---EXEC FPGM---'); 37663 fpgmState.step = -1; 37664 } 37665 37666 try { 37667 exec(fpgmState); 37668 } catch (e) { 37669 console.log('Hinting error in FPGM:' + e); 37670 this._errorState = 3; 37671 return; 37672 } 37673 } 37674 37675 // Executes the prep program for this ppem setting. 37676 // This is used by fonts to set cvt values 37677 // depending on to be rendered font size. 37678 37679 State.prototype = fpgmState; 37680 prepState = 37681 this._prepState = 37682 new State('prep', font.tables.prep); 37683 37684 prepState.ppem = ppem; 37685 37686 // Creates a copy of the cvt table 37687 // and scales it to the current ppem setting. 37688 var oCvt = font.tables.cvt; 37689 if (oCvt) { 37690 var cvt = prepState.cvt = new Array(oCvt.length); 37691 var scale = ppem / font.unitsPerEm; 37692 for (var c = 0; c < oCvt.length; c++) { 37693 cvt[c] = oCvt[c] * scale; 37694 } 37695 } else { 37696 prepState.cvt = []; 37697 } 37698 37699 if (exports.DEBUG) { 37700 console.log('---EXEC PREP---'); 37701 prepState.step = -1; 37702 } 37703 37704 try { 37705 exec(prepState); 37706 } catch (e) { 37707 if (this._errorState < 2) { 37708 console.log('Hinting error in PREP:' + e); 37709 } 37710 this._errorState = 2; 37711 } 37712 } 37713 37714 if (this._errorState > 1) { return; } 37715 37716 try { 37717 return execGlyph(glyph, prepState); 37718 } catch (e) { 37719 if (this._errorState < 1) { 37720 console.log('Hinting error:' + e); 37721 console.log('Note: further hinting errors are silenced'); 37722 } 37723 this._errorState = 1; 37724 return undefined; 37725 } 37726}; 37727 37728/* 37729* Executes the hinting program for a glyph. 37730*/ 37731execGlyph = function(glyph, prepState) { 37732 // original point positions 37733 var xScale = prepState.ppem / prepState.font.unitsPerEm; 37734 var yScale = xScale; 37735 var components = glyph.components; 37736 var contours; 37737 var gZone; 37738 var state; 37739 37740 State.prototype = prepState; 37741 if (!components) { 37742 state = new State('glyf', glyph.instructions); 37743 if (exports.DEBUG) { 37744 console.log('---EXEC GLYPH---'); 37745 state.step = -1; 37746 } 37747 execComponent(glyph, state, xScale, yScale); 37748 gZone = state.gZone; 37749 } else { 37750 var font = prepState.font; 37751 gZone = []; 37752 contours = []; 37753 for (var i = 0; i < components.length; i++) { 37754 var c = components[i]; 37755 var cg = font.glyphs.get(c.glyphIndex); 37756 37757 state = new State('glyf', cg.instructions); 37758 37759 if (exports.DEBUG) { 37760 console.log('---EXEC COMP ' + i + '---'); 37761 state.step = -1; 37762 } 37763 37764 execComponent(cg, state, xScale, yScale); 37765 // appends the computed points to the result array 37766 // post processes the component points 37767 var dx = Math.round(c.dx * xScale); 37768 var dy = Math.round(c.dy * yScale); 37769 var gz = state.gZone; 37770 var cc = state.contours; 37771 for (var pi = 0; pi < gz.length; pi++) { 37772 var p = gz[pi]; 37773 p.xTouched = p.yTouched = false; 37774 p.xo = p.x = p.x + dx; 37775 p.yo = p.y = p.y + dy; 37776 } 37777 37778 var gLen = gZone.length; 37779 gZone.push.apply(gZone, gz); 37780 for (var j = 0; j < cc.length; j++) { 37781 contours.push(cc[j] + gLen); 37782 } 37783 } 37784 37785 if (glyph.instructions && !state.inhibitGridFit) { 37786 // the composite has instructions on its own 37787 state = new State('glyf', glyph.instructions); 37788 37789 state.gZone = state.z0 = state.z1 = state.z2 = gZone; 37790 37791 state.contours = contours; 37792 37793 // note: HPZero cannot be used here, since 37794 // the point might be modified 37795 gZone.push( 37796 new HPoint(0, 0), 37797 new HPoint(Math.round(glyph.advanceWidth * xScale), 0) 37798 ); 37799 37800 if (exports.DEBUG) { 37801 console.log('---EXEC COMPOSITE---'); 37802 state.step = -1; 37803 } 37804 37805 exec(state); 37806 37807 gZone.length -= 2; 37808 } 37809 } 37810 37811 return gZone; 37812}; 37813 37814/* 37815* Executes the hinting program for a component of a multi-component glyph 37816* or of the glyph itself by a non-component glyph. 37817*/ 37818execComponent = function(glyph, state, xScale, yScale) 37819{ 37820 var points = glyph.points || []; 37821 var pLen = points.length; 37822 var gZone = state.gZone = state.z0 = state.z1 = state.z2 = []; 37823 var contours = state.contours = []; 37824 37825 // Scales the original points and 37826 // makes copies for the hinted points. 37827 var cp; // current point 37828 for (var i = 0; i < pLen; i++) { 37829 cp = points[i]; 37830 37831 gZone[i] = new HPoint( 37832 cp.x * xScale, 37833 cp.y * yScale, 37834 cp.lastPointOfContour, 37835 cp.onCurve 37836 ); 37837 } 37838 37839 // Chain links the contours. 37840 var sp; // start point 37841 var np; // next point 37842 37843 for (var i$1 = 0; i$1 < pLen; i$1++) { 37844 cp = gZone[i$1]; 37845 37846 if (!sp) { 37847 sp = cp; 37848 contours.push(i$1); 37849 } 37850 37851 if (cp.lastPointOfContour) { 37852 cp.nextPointOnContour = sp; 37853 sp.prevPointOnContour = cp; 37854 sp = undefined; 37855 } else { 37856 np = gZone[i$1 + 1]; 37857 cp.nextPointOnContour = np; 37858 np.prevPointOnContour = cp; 37859 } 37860 } 37861 37862 if (state.inhibitGridFit) { return; } 37863 37864 gZone.push( 37865 new HPoint(0, 0), 37866 new HPoint(Math.round(glyph.advanceWidth * xScale), 0) 37867 ); 37868 37869 exec(state); 37870 37871 // Removes the extra points. 37872 gZone.length -= 2; 37873 37874 if (exports.DEBUG) { 37875 console.log('FINISHED GLYPH', state.stack); 37876 for (var i$2 = 0; i$2 < pLen; i$2++) { 37877 console.log(i$2, gZone[i$2].x, gZone[i$2].y); 37878 } 37879 } 37880}; 37881 37882/* 37883* Executes the program loaded in state. 37884*/ 37885exec = function(state) { 37886 var prog = state.prog; 37887 37888 if (!prog) { return; } 37889 37890 var pLen = prog.length; 37891 var ins; 37892 37893 for (state.ip = 0; state.ip < pLen; state.ip++) { 37894 if (exports.DEBUG) { state.step++; } 37895 ins = instructionTable[prog[state.ip]]; 37896 37897 if (!ins) { 37898 throw new Error( 37899 'unknown instruction: 0x' + 37900 Number(prog[state.ip]).toString(16) 37901 ); 37902 } 37903 37904 ins(state); 37905 37906 // very extensive debugging for each step 37907 /* 37908 if (exports.DEBUG) { 37909 var da; 37910 if (state.gZone) { 37911 da = []; 37912 for (let i = 0; i < state.gZone.length; i++) 37913 { 37914 da.push(i + ' ' + 37915 state.gZone[i].x * 64 + ' ' + 37916 state.gZone[i].y * 64 + ' ' + 37917 (state.gZone[i].xTouched ? 'x' : '') + 37918 (state.gZone[i].yTouched ? 'y' : '') 37919 ); 37920 } 37921 console.log('GZ', da); 37922 } 37923 37924 if (state.tZone) { 37925 da = []; 37926 for (let i = 0; i < state.tZone.length; i++) { 37927 da.push(i + ' ' + 37928 state.tZone[i].x * 64 + ' ' + 37929 state.tZone[i].y * 64 + ' ' + 37930 (state.tZone[i].xTouched ? 'x' : '') + 37931 (state.tZone[i].yTouched ? 'y' : '') 37932 ); 37933 } 37934 console.log('TZ', da); 37935 } 37936 37937 if (state.stack.length > 10) { 37938 console.log( 37939 state.stack.length, 37940 '...', state.stack.slice(state.stack.length - 10) 37941 ); 37942 } else { 37943 console.log(state.stack.length, state.stack); 37944 } 37945 } 37946 */ 37947 } 37948}; 37949 37950/* 37951* Initializes the twilight zone. 37952* 37953* This is only done if a SZPx instruction 37954* refers to the twilight zone. 37955*/ 37956function initTZone(state) 37957{ 37958 var tZone = state.tZone = new Array(state.gZone.length); 37959 37960 // no idea if this is actually correct... 37961 for (var i = 0; i < tZone.length; i++) 37962 { 37963 tZone[i] = new HPoint(0, 0); 37964 } 37965} 37966 37967/* 37968* Skips the instruction pointer ahead over an IF/ELSE block. 37969* handleElse .. if true breaks on matching ELSE 37970*/ 37971function skip(state, handleElse) 37972{ 37973 var prog = state.prog; 37974 var ip = state.ip; 37975 var nesting = 1; 37976 var ins; 37977 37978 do { 37979 ins = prog[++ip]; 37980 if (ins === 0x58) // IF 37981 { nesting++; } 37982 else if (ins === 0x59) // EIF 37983 { nesting--; } 37984 else if (ins === 0x40) // NPUSHB 37985 { ip += prog[ip + 1] + 1; } 37986 else if (ins === 0x41) // NPUSHW 37987 { ip += 2 * prog[ip + 1] + 1; } 37988 else if (ins >= 0xB0 && ins <= 0xB7) // PUSHB 37989 { ip += ins - 0xB0 + 1; } 37990 else if (ins >= 0xB8 && ins <= 0xBF) // PUSHW 37991 { ip += (ins - 0xB8 + 1) * 2; } 37992 else if (handleElse && nesting === 1 && ins === 0x1B) // ELSE 37993 { break; } 37994 } while (nesting > 0); 37995 37996 state.ip = ip; 37997} 37998 37999/*----------------------------------------------------------* 38000* And then a lot of instructions... * 38001*----------------------------------------------------------*/ 38002 38003// SVTCA[a] Set freedom and projection Vectors To Coordinate Axis 38004// 0x00-0x01 38005function SVTCA(v, state) { 38006 if (exports.DEBUG) { console.log(state.step, 'SVTCA[' + v.axis + ']'); } 38007 38008 state.fv = state.pv = state.dpv = v; 38009} 38010 38011// SPVTCA[a] Set Projection Vector to Coordinate Axis 38012// 0x02-0x03 38013function SPVTCA(v, state) { 38014 if (exports.DEBUG) { console.log(state.step, 'SPVTCA[' + v.axis + ']'); } 38015 38016 state.pv = state.dpv = v; 38017} 38018 38019// SFVTCA[a] Set Freedom Vector to Coordinate Axis 38020// 0x04-0x05 38021function SFVTCA(v, state) { 38022 if (exports.DEBUG) { console.log(state.step, 'SFVTCA[' + v.axis + ']'); } 38023 38024 state.fv = v; 38025} 38026 38027// SPVTL[a] Set Projection Vector To Line 38028// 0x06-0x07 38029function SPVTL(a, state) { 38030 var stack = state.stack; 38031 var p2i = stack.pop(); 38032 var p1i = stack.pop(); 38033 var p2 = state.z2[p2i]; 38034 var p1 = state.z1[p1i]; 38035 38036 if (exports.DEBUG) { console.log('SPVTL[' + a + ']', p2i, p1i); } 38037 38038 var dx; 38039 var dy; 38040 38041 if (!a) { 38042 dx = p1.x - p2.x; 38043 dy = p1.y - p2.y; 38044 } else { 38045 dx = p2.y - p1.y; 38046 dy = p1.x - p2.x; 38047 } 38048 38049 state.pv = state.dpv = getUnitVector(dx, dy); 38050} 38051 38052// SFVTL[a] Set Freedom Vector To Line 38053// 0x08-0x09 38054function SFVTL(a, state) { 38055 var stack = state.stack; 38056 var p2i = stack.pop(); 38057 var p1i = stack.pop(); 38058 var p2 = state.z2[p2i]; 38059 var p1 = state.z1[p1i]; 38060 38061 if (exports.DEBUG) { console.log('SFVTL[' + a + ']', p2i, p1i); } 38062 38063 var dx; 38064 var dy; 38065 38066 if (!a) { 38067 dx = p1.x - p2.x; 38068 dy = p1.y - p2.y; 38069 } else { 38070 dx = p2.y - p1.y; 38071 dy = p1.x - p2.x; 38072 } 38073 38074 state.fv = getUnitVector(dx, dy); 38075} 38076 38077// SPVFS[] Set Projection Vector From Stack 38078// 0x0A 38079function SPVFS(state) { 38080 var stack = state.stack; 38081 var y = stack.pop(); 38082 var x = stack.pop(); 38083 38084 if (exports.DEBUG) { console.log(state.step, 'SPVFS[]', y, x); } 38085 38086 state.pv = state.dpv = getUnitVector(x, y); 38087} 38088 38089// SFVFS[] Set Freedom Vector From Stack 38090// 0x0B 38091function SFVFS(state) { 38092 var stack = state.stack; 38093 var y = stack.pop(); 38094 var x = stack.pop(); 38095 38096 if (exports.DEBUG) { console.log(state.step, 'SPVFS[]', y, x); } 38097 38098 state.fv = getUnitVector(x, y); 38099} 38100 38101// GPV[] Get Projection Vector 38102// 0x0C 38103function GPV(state) { 38104 var stack = state.stack; 38105 var pv = state.pv; 38106 38107 if (exports.DEBUG) { console.log(state.step, 'GPV[]'); } 38108 38109 stack.push(pv.x * 0x4000); 38110 stack.push(pv.y * 0x4000); 38111} 38112 38113// GFV[] Get Freedom Vector 38114// 0x0C 38115function GFV(state) { 38116 var stack = state.stack; 38117 var fv = state.fv; 38118 38119 if (exports.DEBUG) { console.log(state.step, 'GFV[]'); } 38120 38121 stack.push(fv.x * 0x4000); 38122 stack.push(fv.y * 0x4000); 38123} 38124 38125// SFVTPV[] Set Freedom Vector To Projection Vector 38126// 0x0E 38127function SFVTPV(state) { 38128 state.fv = state.pv; 38129 38130 if (exports.DEBUG) { console.log(state.step, 'SFVTPV[]'); } 38131} 38132 38133// ISECT[] moves point p to the InterSECTion of two lines 38134// 0x0F 38135function ISECT(state) 38136{ 38137 var stack = state.stack; 38138 var pa0i = stack.pop(); 38139 var pa1i = stack.pop(); 38140 var pb0i = stack.pop(); 38141 var pb1i = stack.pop(); 38142 var pi = stack.pop(); 38143 var z0 = state.z0; 38144 var z1 = state.z1; 38145 var pa0 = z0[pa0i]; 38146 var pa1 = z0[pa1i]; 38147 var pb0 = z1[pb0i]; 38148 var pb1 = z1[pb1i]; 38149 var p = state.z2[pi]; 38150 38151 if (exports.DEBUG) { console.log('ISECT[], ', pa0i, pa1i, pb0i, pb1i, pi); } 38152 38153 // math from 38154 // en.wikipedia.org/wiki/Line%E2%80%93line_intersection#Given_two_points_on_each_line 38155 38156 var x1 = pa0.x; 38157 var y1 = pa0.y; 38158 var x2 = pa1.x; 38159 var y2 = pa1.y; 38160 var x3 = pb0.x; 38161 var y3 = pb0.y; 38162 var x4 = pb1.x; 38163 var y4 = pb1.y; 38164 38165 var div = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4); 38166 var f1 = x1 * y2 - y1 * x2; 38167 var f2 = x3 * y4 - y3 * x4; 38168 38169 p.x = (f1 * (x3 - x4) - f2 * (x1 - x2)) / div; 38170 p.y = (f1 * (y3 - y4) - f2 * (y1 - y2)) / div; 38171} 38172 38173// SRP0[] Set Reference Point 0 38174// 0x10 38175function SRP0(state) { 38176 state.rp0 = state.stack.pop(); 38177 38178 if (exports.DEBUG) { console.log(state.step, 'SRP0[]', state.rp0); } 38179} 38180 38181// SRP1[] Set Reference Point 1 38182// 0x11 38183function SRP1(state) { 38184 state.rp1 = state.stack.pop(); 38185 38186 if (exports.DEBUG) { console.log(state.step, 'SRP1[]', state.rp1); } 38187} 38188 38189// SRP1[] Set Reference Point 2 38190// 0x12 38191function SRP2(state) { 38192 state.rp2 = state.stack.pop(); 38193 38194 if (exports.DEBUG) { console.log(state.step, 'SRP2[]', state.rp2); } 38195} 38196 38197// SZP0[] Set Zone Pointer 0 38198// 0x13 38199function SZP0(state) { 38200 var n = state.stack.pop(); 38201 38202 if (exports.DEBUG) { console.log(state.step, 'SZP0[]', n); } 38203 38204 state.zp0 = n; 38205 38206 switch (n) { 38207 case 0: 38208 if (!state.tZone) { initTZone(state); } 38209 state.z0 = state.tZone; 38210 break; 38211 case 1 : 38212 state.z0 = state.gZone; 38213 break; 38214 default : 38215 throw new Error('Invalid zone pointer'); 38216 } 38217} 38218 38219// SZP1[] Set Zone Pointer 1 38220// 0x14 38221function SZP1(state) { 38222 var n = state.stack.pop(); 38223 38224 if (exports.DEBUG) { console.log(state.step, 'SZP1[]', n); } 38225 38226 state.zp1 = n; 38227 38228 switch (n) { 38229 case 0: 38230 if (!state.tZone) { initTZone(state); } 38231 state.z1 = state.tZone; 38232 break; 38233 case 1 : 38234 state.z1 = state.gZone; 38235 break; 38236 default : 38237 throw new Error('Invalid zone pointer'); 38238 } 38239} 38240 38241// SZP2[] Set Zone Pointer 2 38242// 0x15 38243function SZP2(state) { 38244 var n = state.stack.pop(); 38245 38246 if (exports.DEBUG) { console.log(state.step, 'SZP2[]', n); } 38247 38248 state.zp2 = n; 38249 38250 switch (n) { 38251 case 0: 38252 if (!state.tZone) { initTZone(state); } 38253 state.z2 = state.tZone; 38254 break; 38255 case 1 : 38256 state.z2 = state.gZone; 38257 break; 38258 default : 38259 throw new Error('Invalid zone pointer'); 38260 } 38261} 38262 38263// SZPS[] Set Zone PointerS 38264// 0x16 38265function SZPS(state) { 38266 var n = state.stack.pop(); 38267 38268 if (exports.DEBUG) { console.log(state.step, 'SZPS[]', n); } 38269 38270 state.zp0 = state.zp1 = state.zp2 = n; 38271 38272 switch (n) { 38273 case 0: 38274 if (!state.tZone) { initTZone(state); } 38275 state.z0 = state.z1 = state.z2 = state.tZone; 38276 break; 38277 case 1 : 38278 state.z0 = state.z1 = state.z2 = state.gZone; 38279 break; 38280 default : 38281 throw new Error('Invalid zone pointer'); 38282 } 38283} 38284 38285// SLOOP[] Set LOOP variable 38286// 0x17 38287function SLOOP(state) { 38288 state.loop = state.stack.pop(); 38289 38290 if (exports.DEBUG) { console.log(state.step, 'SLOOP[]', state.loop); } 38291} 38292 38293// RTG[] Round To Grid 38294// 0x18 38295function RTG(state) { 38296 if (exports.DEBUG) { console.log(state.step, 'RTG[]'); } 38297 38298 state.round = roundToGrid; 38299} 38300 38301// RTHG[] Round To Half Grid 38302// 0x19 38303function RTHG(state) { 38304 if (exports.DEBUG) { console.log(state.step, 'RTHG[]'); } 38305 38306 state.round = roundToHalfGrid; 38307} 38308 38309// SMD[] Set Minimum Distance 38310// 0x1A 38311function SMD(state) { 38312 var d = state.stack.pop(); 38313 38314 if (exports.DEBUG) { console.log(state.step, 'SMD[]', d); } 38315 38316 state.minDis = d / 0x40; 38317} 38318 38319// ELSE[] ELSE clause 38320// 0x1B 38321function ELSE(state) { 38322 // This instruction has been reached by executing a then branch 38323 // so it just skips ahead until matching EIF. 38324 // 38325 // In case the IF was negative the IF[] instruction already 38326 // skipped forward over the ELSE[] 38327 38328 if (exports.DEBUG) { console.log(state.step, 'ELSE[]'); } 38329 38330 skip(state, false); 38331} 38332 38333// JMPR[] JuMP Relative 38334// 0x1C 38335function JMPR(state) { 38336 var o = state.stack.pop(); 38337 38338 if (exports.DEBUG) { console.log(state.step, 'JMPR[]', o); } 38339 38340 // A jump by 1 would do nothing. 38341 state.ip += o - 1; 38342} 38343 38344// SCVTCI[] Set Control Value Table Cut-In 38345// 0x1D 38346function SCVTCI(state) { 38347 var n = state.stack.pop(); 38348 38349 if (exports.DEBUG) { console.log(state.step, 'SCVTCI[]', n); } 38350 38351 state.cvCutIn = n / 0x40; 38352} 38353 38354// DUP[] DUPlicate top stack element 38355// 0x20 38356function DUP(state) { 38357 var stack = state.stack; 38358 38359 if (exports.DEBUG) { console.log(state.step, 'DUP[]'); } 38360 38361 stack.push(stack[stack.length - 1]); 38362} 38363 38364// POP[] POP top stack element 38365// 0x21 38366function POP(state) { 38367 if (exports.DEBUG) { console.log(state.step, 'POP[]'); } 38368 38369 state.stack.pop(); 38370} 38371 38372// CLEAR[] CLEAR the stack 38373// 0x22 38374function CLEAR(state) { 38375 if (exports.DEBUG) { console.log(state.step, 'CLEAR[]'); } 38376 38377 state.stack.length = 0; 38378} 38379 38380// SWAP[] SWAP the top two elements on the stack 38381// 0x23 38382function SWAP(state) { 38383 var stack = state.stack; 38384 38385 var a = stack.pop(); 38386 var b = stack.pop(); 38387 38388 if (exports.DEBUG) { console.log(state.step, 'SWAP[]'); } 38389 38390 stack.push(a); 38391 stack.push(b); 38392} 38393 38394// DEPTH[] DEPTH of the stack 38395// 0x24 38396function DEPTH(state) { 38397 var stack = state.stack; 38398 38399 if (exports.DEBUG) { console.log(state.step, 'DEPTH[]'); } 38400 38401 stack.push(stack.length); 38402} 38403 38404// LOOPCALL[] LOOPCALL function 38405// 0x2A 38406function LOOPCALL(state) { 38407 var stack = state.stack; 38408 var fn = stack.pop(); 38409 var c = stack.pop(); 38410 38411 if (exports.DEBUG) { console.log(state.step, 'LOOPCALL[]', fn, c); } 38412 38413 // saves callers program 38414 var cip = state.ip; 38415 var cprog = state.prog; 38416 38417 state.prog = state.funcs[fn]; 38418 38419 // executes the function 38420 for (var i = 0; i < c; i++) { 38421 exec(state); 38422 38423 if (exports.DEBUG) { console.log( 38424 ++state.step, 38425 i + 1 < c ? 'next loopcall' : 'done loopcall', 38426 i 38427 ); } 38428 } 38429 38430 // restores the callers program 38431 state.ip = cip; 38432 state.prog = cprog; 38433} 38434 38435// CALL[] CALL function 38436// 0x2B 38437function CALL(state) { 38438 var fn = state.stack.pop(); 38439 38440 if (exports.DEBUG) { console.log(state.step, 'CALL[]', fn); } 38441 38442 // saves callers program 38443 var cip = state.ip; 38444 var cprog = state.prog; 38445 38446 state.prog = state.funcs[fn]; 38447 38448 // executes the function 38449 exec(state); 38450 38451 // restores the callers program 38452 state.ip = cip; 38453 state.prog = cprog; 38454 38455 if (exports.DEBUG) { console.log(++state.step, 'returning from', fn); } 38456} 38457 38458// CINDEX[] Copy the INDEXed element to the top of the stack 38459// 0x25 38460function CINDEX(state) { 38461 var stack = state.stack; 38462 var k = stack.pop(); 38463 38464 if (exports.DEBUG) { console.log(state.step, 'CINDEX[]', k); } 38465 38466 // In case of k == 1, it copies the last element after popping 38467 // thus stack.length - k. 38468 stack.push(stack[stack.length - k]); 38469} 38470 38471// MINDEX[] Move the INDEXed element to the top of the stack 38472// 0x26 38473function MINDEX(state) { 38474 var stack = state.stack; 38475 var k = stack.pop(); 38476 38477 if (exports.DEBUG) { console.log(state.step, 'MINDEX[]', k); } 38478 38479 stack.push(stack.splice(stack.length - k, 1)[0]); 38480} 38481 38482// FDEF[] Function DEFinition 38483// 0x2C 38484function FDEF(state) { 38485 if (state.env !== 'fpgm') { throw new Error('FDEF not allowed here'); } 38486 var stack = state.stack; 38487 var prog = state.prog; 38488 var ip = state.ip; 38489 38490 var fn = stack.pop(); 38491 var ipBegin = ip; 38492 38493 if (exports.DEBUG) { console.log(state.step, 'FDEF[]', fn); } 38494 38495 while (prog[++ip] !== 0x2D){ } 38496 38497 state.ip = ip; 38498 state.funcs[fn] = prog.slice(ipBegin + 1, ip); 38499} 38500 38501// MDAP[a] Move Direct Absolute Point 38502// 0x2E-0x2F 38503function MDAP(round, state) { 38504 var pi = state.stack.pop(); 38505 var p = state.z0[pi]; 38506 var fv = state.fv; 38507 var pv = state.pv; 38508 38509 if (exports.DEBUG) { console.log(state.step, 'MDAP[' + round + ']', pi); } 38510 38511 var d = pv.distance(p, HPZero); 38512 38513 if (round) { d = state.round(d); } 38514 38515 fv.setRelative(p, HPZero, d, pv); 38516 fv.touch(p); 38517 38518 state.rp0 = state.rp1 = pi; 38519} 38520 38521// IUP[a] Interpolate Untouched Points through the outline 38522// 0x30 38523function IUP(v, state) { 38524 var z2 = state.z2; 38525 var pLen = z2.length - 2; 38526 var cp; 38527 var pp; 38528 var np; 38529 38530 if (exports.DEBUG) { console.log(state.step, 'IUP[' + v.axis + ']'); } 38531 38532 for (var i = 0; i < pLen; i++) { 38533 cp = z2[i]; // current point 38534 38535 // if this point has been touched go on 38536 if (v.touched(cp)) { continue; } 38537 38538 pp = cp.prevTouched(v); 38539 38540 // no point on the contour has been touched? 38541 if (pp === cp) { continue; } 38542 38543 np = cp.nextTouched(v); 38544 38545 if (pp === np) { 38546 // only one point on the contour has been touched 38547 // so simply moves the point like that 38548 38549 v.setRelative(cp, cp, v.distance(pp, pp, false, true), v, true); 38550 } 38551 38552 v.interpolate(cp, pp, np, v); 38553 } 38554} 38555 38556// SHP[] SHift Point using reference point 38557// 0x32-0x33 38558function SHP(a, state) { 38559 var stack = state.stack; 38560 var rpi = a ? state.rp1 : state.rp2; 38561 var rp = (a ? state.z0 : state.z1)[rpi]; 38562 var fv = state.fv; 38563 var pv = state.pv; 38564 var loop = state.loop; 38565 var z2 = state.z2; 38566 38567 while (loop--) 38568 { 38569 var pi = stack.pop(); 38570 var p = z2[pi]; 38571 38572 var d = pv.distance(rp, rp, false, true); 38573 fv.setRelative(p, p, d, pv); 38574 fv.touch(p); 38575 38576 if (exports.DEBUG) { 38577 console.log( 38578 state.step, 38579 (state.loop > 1 ? 38580 'loop ' + (state.loop - loop) + ': ' : 38581 '' 38582 ) + 38583 'SHP[' + (a ? 'rp1' : 'rp2') + ']', pi 38584 ); 38585 } 38586 } 38587 38588 state.loop = 1; 38589} 38590 38591// SHC[] SHift Contour using reference point 38592// 0x36-0x37 38593function SHC(a, state) { 38594 var stack = state.stack; 38595 var rpi = a ? state.rp1 : state.rp2; 38596 var rp = (a ? state.z0 : state.z1)[rpi]; 38597 var fv = state.fv; 38598 var pv = state.pv; 38599 var ci = stack.pop(); 38600 var sp = state.z2[state.contours[ci]]; 38601 var p = sp; 38602 38603 if (exports.DEBUG) { console.log(state.step, 'SHC[' + a + ']', ci); } 38604 38605 var d = pv.distance(rp, rp, false, true); 38606 38607 do { 38608 if (p !== rp) { fv.setRelative(p, p, d, pv); } 38609 p = p.nextPointOnContour; 38610 } while (p !== sp); 38611} 38612 38613// SHZ[] SHift Zone using reference point 38614// 0x36-0x37 38615function SHZ(a, state) { 38616 var stack = state.stack; 38617 var rpi = a ? state.rp1 : state.rp2; 38618 var rp = (a ? state.z0 : state.z1)[rpi]; 38619 var fv = state.fv; 38620 var pv = state.pv; 38621 38622 var e = stack.pop(); 38623 38624 if (exports.DEBUG) { console.log(state.step, 'SHZ[' + a + ']', e); } 38625 38626 var z; 38627 switch (e) { 38628 case 0 : z = state.tZone; break; 38629 case 1 : z = state.gZone; break; 38630 default : throw new Error('Invalid zone'); 38631 } 38632 38633 var p; 38634 var d = pv.distance(rp, rp, false, true); 38635 var pLen = z.length - 2; 38636 for (var i = 0; i < pLen; i++) 38637 { 38638 p = z[i]; 38639 if (p !== rp) { fv.setRelative(p, p, d, pv); } 38640 } 38641} 38642 38643// SHPIX[] SHift point by a PIXel amount 38644// 0x38 38645function SHPIX(state) { 38646 var stack = state.stack; 38647 var loop = state.loop; 38648 var fv = state.fv; 38649 var d = stack.pop() / 0x40; 38650 var z2 = state.z2; 38651 38652 while (loop--) { 38653 var pi = stack.pop(); 38654 var p = z2[pi]; 38655 38656 if (exports.DEBUG) { 38657 console.log( 38658 state.step, 38659 (state.loop > 1 ? 'loop ' + (state.loop - loop) + ': ' : '') + 38660 'SHPIX[]', pi, d 38661 ); 38662 } 38663 38664 fv.setRelative(p, p, d); 38665 fv.touch(p); 38666 } 38667 38668 state.loop = 1; 38669} 38670 38671// IP[] Interpolate Point 38672// 0x39 38673function IP(state) { 38674 var stack = state.stack; 38675 var rp1i = state.rp1; 38676 var rp2i = state.rp2; 38677 var loop = state.loop; 38678 var rp1 = state.z0[rp1i]; 38679 var rp2 = state.z1[rp2i]; 38680 var fv = state.fv; 38681 var pv = state.dpv; 38682 var z2 = state.z2; 38683 38684 while (loop--) { 38685 var pi = stack.pop(); 38686 var p = z2[pi]; 38687 38688 if (exports.DEBUG) { 38689 console.log( 38690 state.step, 38691 (state.loop > 1 ? 'loop ' + (state.loop - loop) + ': ' : '') + 38692 'IP[]', pi, rp1i, '<->', rp2i 38693 ); 38694 } 38695 38696 fv.interpolate(p, rp1, rp2, pv); 38697 38698 fv.touch(p); 38699 } 38700 38701 state.loop = 1; 38702} 38703 38704// MSIRP[a] Move Stack Indirect Relative Point 38705// 0x3A-0x3B 38706function MSIRP(a, state) { 38707 var stack = state.stack; 38708 var d = stack.pop() / 64; 38709 var pi = stack.pop(); 38710 var p = state.z1[pi]; 38711 var rp0 = state.z0[state.rp0]; 38712 var fv = state.fv; 38713 var pv = state.pv; 38714 38715 fv.setRelative(p, rp0, d, pv); 38716 fv.touch(p); 38717 38718 if (exports.DEBUG) { console.log(state.step, 'MSIRP[' + a + ']', d, pi); } 38719 38720 state.rp1 = state.rp0; 38721 state.rp2 = pi; 38722 if (a) { state.rp0 = pi; } 38723} 38724 38725// ALIGNRP[] Align to reference point. 38726// 0x3C 38727function ALIGNRP(state) { 38728 var stack = state.stack; 38729 var rp0i = state.rp0; 38730 var rp0 = state.z0[rp0i]; 38731 var loop = state.loop; 38732 var fv = state.fv; 38733 var pv = state.pv; 38734 var z1 = state.z1; 38735 38736 while (loop--) { 38737 var pi = stack.pop(); 38738 var p = z1[pi]; 38739 38740 if (exports.DEBUG) { 38741 console.log( 38742 state.step, 38743 (state.loop > 1 ? 'loop ' + (state.loop - loop) + ': ' : '') + 38744 'ALIGNRP[]', pi 38745 ); 38746 } 38747 38748 fv.setRelative(p, rp0, 0, pv); 38749 fv.touch(p); 38750 } 38751 38752 state.loop = 1; 38753} 38754 38755// RTG[] Round To Double Grid 38756// 0x3D 38757function RTDG(state) { 38758 if (exports.DEBUG) { console.log(state.step, 'RTDG[]'); } 38759 38760 state.round = roundToDoubleGrid; 38761} 38762 38763// MIAP[a] Move Indirect Absolute Point 38764// 0x3E-0x3F 38765function MIAP(round, state) { 38766 var stack = state.stack; 38767 var n = stack.pop(); 38768 var pi = stack.pop(); 38769 var p = state.z0[pi]; 38770 var fv = state.fv; 38771 var pv = state.pv; 38772 var cv = state.cvt[n]; 38773 38774 // TODO cvtcutin should be considered here 38775 if (round) { cv = state.round(cv); } 38776 38777 if (exports.DEBUG) { 38778 console.log( 38779 state.step, 38780 'MIAP[' + round + ']', 38781 n, '(', cv, ')', pi 38782 ); 38783 } 38784 38785 fv.setRelative(p, HPZero, cv, pv); 38786 38787 if (state.zp0 === 0) { 38788 p.xo = p.x; 38789 p.yo = p.y; 38790 } 38791 38792 fv.touch(p); 38793 38794 state.rp0 = state.rp1 = pi; 38795} 38796 38797// NPUSB[] PUSH N Bytes 38798// 0x40 38799function NPUSHB(state) { 38800 var prog = state.prog; 38801 var ip = state.ip; 38802 var stack = state.stack; 38803 38804 var n = prog[++ip]; 38805 38806 if (exports.DEBUG) { console.log(state.step, 'NPUSHB[]', n); } 38807 38808 for (var i = 0; i < n; i++) { stack.push(prog[++ip]); } 38809 38810 state.ip = ip; 38811} 38812 38813// NPUSHW[] PUSH N Words 38814// 0x41 38815function NPUSHW(state) { 38816 var ip = state.ip; 38817 var prog = state.prog; 38818 var stack = state.stack; 38819 var n = prog[++ip]; 38820 38821 if (exports.DEBUG) { console.log(state.step, 'NPUSHW[]', n); } 38822 38823 for (var i = 0; i < n; i++) { 38824 var w = (prog[++ip] << 8) | prog[++ip]; 38825 if (w & 0x8000) { w = -((w ^ 0xffff) + 1); } 38826 stack.push(w); 38827 } 38828 38829 state.ip = ip; 38830} 38831 38832// WS[] Write Store 38833// 0x42 38834function WS(state) { 38835 var stack = state.stack; 38836 var store = state.store; 38837 38838 if (!store) { store = state.store = []; } 38839 38840 var v = stack.pop(); 38841 var l = stack.pop(); 38842 38843 if (exports.DEBUG) { console.log(state.step, 'WS', v, l); } 38844 38845 store[l] = v; 38846} 38847 38848// RS[] Read Store 38849// 0x43 38850function RS(state) { 38851 var stack = state.stack; 38852 var store = state.store; 38853 38854 var l = stack.pop(); 38855 38856 if (exports.DEBUG) { console.log(state.step, 'RS', l); } 38857 38858 var v = (store && store[l]) || 0; 38859 38860 stack.push(v); 38861} 38862 38863// WCVTP[] Write Control Value Table in Pixel units 38864// 0x44 38865function WCVTP(state) { 38866 var stack = state.stack; 38867 38868 var v = stack.pop(); 38869 var l = stack.pop(); 38870 38871 if (exports.DEBUG) { console.log(state.step, 'WCVTP', v, l); } 38872 38873 state.cvt[l] = v / 0x40; 38874} 38875 38876// RCVT[] Read Control Value Table entry 38877// 0x45 38878function RCVT(state) { 38879 var stack = state.stack; 38880 var cvte = stack.pop(); 38881 38882 if (exports.DEBUG) { console.log(state.step, 'RCVT', cvte); } 38883 38884 stack.push(state.cvt[cvte] * 0x40); 38885} 38886 38887// GC[] Get Coordinate projected onto the projection vector 38888// 0x46-0x47 38889function GC(a, state) { 38890 var stack = state.stack; 38891 var pi = stack.pop(); 38892 var p = state.z2[pi]; 38893 38894 if (exports.DEBUG) { console.log(state.step, 'GC[' + a + ']', pi); } 38895 38896 stack.push(state.dpv.distance(p, HPZero, a, false) * 0x40); 38897} 38898 38899// MD[a] Measure Distance 38900// 0x49-0x4A 38901function MD(a, state) { 38902 var stack = state.stack; 38903 var pi2 = stack.pop(); 38904 var pi1 = stack.pop(); 38905 var p2 = state.z1[pi2]; 38906 var p1 = state.z0[pi1]; 38907 var d = state.dpv.distance(p1, p2, a, a); 38908 38909 if (exports.DEBUG) { console.log(state.step, 'MD[' + a + ']', pi2, pi1, '->', d); } 38910 38911 state.stack.push(Math.round(d * 64)); 38912} 38913 38914// MPPEM[] Measure Pixels Per EM 38915// 0x4B 38916function MPPEM(state) { 38917 if (exports.DEBUG) { console.log(state.step, 'MPPEM[]'); } 38918 state.stack.push(state.ppem); 38919} 38920 38921// FLIPON[] set the auto FLIP Boolean to ON 38922// 0x4D 38923function FLIPON(state) { 38924 if (exports.DEBUG) { console.log(state.step, 'FLIPON[]'); } 38925 state.autoFlip = true; 38926} 38927 38928// LT[] Less Than 38929// 0x50 38930function LT(state) { 38931 var stack = state.stack; 38932 var e2 = stack.pop(); 38933 var e1 = stack.pop(); 38934 38935 if (exports.DEBUG) { console.log(state.step, 'LT[]', e2, e1); } 38936 38937 stack.push(e1 < e2 ? 1 : 0); 38938} 38939 38940// LTEQ[] Less Than or EQual 38941// 0x53 38942function LTEQ(state) { 38943 var stack = state.stack; 38944 var e2 = stack.pop(); 38945 var e1 = stack.pop(); 38946 38947 if (exports.DEBUG) { console.log(state.step, 'LTEQ[]', e2, e1); } 38948 38949 stack.push(e1 <= e2 ? 1 : 0); 38950} 38951 38952// GTEQ[] Greater Than 38953// 0x52 38954function GT(state) { 38955 var stack = state.stack; 38956 var e2 = stack.pop(); 38957 var e1 = stack.pop(); 38958 38959 if (exports.DEBUG) { console.log(state.step, 'GT[]', e2, e1); } 38960 38961 stack.push(e1 > e2 ? 1 : 0); 38962} 38963 38964// GTEQ[] Greater Than or EQual 38965// 0x53 38966function GTEQ(state) { 38967 var stack = state.stack; 38968 var e2 = stack.pop(); 38969 var e1 = stack.pop(); 38970 38971 if (exports.DEBUG) { console.log(state.step, 'GTEQ[]', e2, e1); } 38972 38973 stack.push(e1 >= e2 ? 1 : 0); 38974} 38975 38976// EQ[] EQual 38977// 0x54 38978function EQ(state) { 38979 var stack = state.stack; 38980 var e2 = stack.pop(); 38981 var e1 = stack.pop(); 38982 38983 if (exports.DEBUG) { console.log(state.step, 'EQ[]', e2, e1); } 38984 38985 stack.push(e2 === e1 ? 1 : 0); 38986} 38987 38988// NEQ[] Not EQual 38989// 0x55 38990function NEQ(state) { 38991 var stack = state.stack; 38992 var e2 = stack.pop(); 38993 var e1 = stack.pop(); 38994 38995 if (exports.DEBUG) { console.log(state.step, 'NEQ[]', e2, e1); } 38996 38997 stack.push(e2 !== e1 ? 1 : 0); 38998} 38999 39000// ODD[] ODD 39001// 0x56 39002function ODD(state) { 39003 var stack = state.stack; 39004 var n = stack.pop(); 39005 39006 if (exports.DEBUG) { console.log(state.step, 'ODD[]', n); } 39007 39008 stack.push(Math.trunc(n) % 2 ? 1 : 0); 39009} 39010 39011// EVEN[] EVEN 39012// 0x57 39013function EVEN(state) { 39014 var stack = state.stack; 39015 var n = stack.pop(); 39016 39017 if (exports.DEBUG) { console.log(state.step, 'EVEN[]', n); } 39018 39019 stack.push(Math.trunc(n) % 2 ? 0 : 1); 39020} 39021 39022// IF[] IF test 39023// 0x58 39024function IF(state) { 39025 var test = state.stack.pop(); 39026 var ins; 39027 39028 if (exports.DEBUG) { console.log(state.step, 'IF[]', test); } 39029 39030 // if test is true it just continues 39031 // if not the ip is skipped until matching ELSE or EIF 39032 if (!test) { 39033 skip(state, true); 39034 39035 if (exports.DEBUG) { console.log(state.step, ins === 0x1B ? 'ELSE[]' : 'EIF[]'); } 39036 } 39037} 39038 39039// EIF[] End IF 39040// 0x59 39041function EIF(state) { 39042 // this can be reached normally when 39043 // executing an else branch. 39044 // -> just ignore it 39045 39046 if (exports.DEBUG) { console.log(state.step, 'EIF[]'); } 39047} 39048 39049// AND[] logical AND 39050// 0x5A 39051function AND(state) { 39052 var stack = state.stack; 39053 var e2 = stack.pop(); 39054 var e1 = stack.pop(); 39055 39056 if (exports.DEBUG) { console.log(state.step, 'AND[]', e2, e1); } 39057 39058 stack.push(e2 && e1 ? 1 : 0); 39059} 39060 39061// OR[] logical OR 39062// 0x5B 39063function OR(state) { 39064 var stack = state.stack; 39065 var e2 = stack.pop(); 39066 var e1 = stack.pop(); 39067 39068 if (exports.DEBUG) { console.log(state.step, 'OR[]', e2, e1); } 39069 39070 stack.push(e2 || e1 ? 1 : 0); 39071} 39072 39073// NOT[] logical NOT 39074// 0x5C 39075function NOT(state) { 39076 var stack = state.stack; 39077 var e = stack.pop(); 39078 39079 if (exports.DEBUG) { console.log(state.step, 'NOT[]', e); } 39080 39081 stack.push(e ? 0 : 1); 39082} 39083 39084// DELTAP1[] DELTA exception P1 39085// DELTAP2[] DELTA exception P2 39086// DELTAP3[] DELTA exception P3 39087// 0x5D, 0x71, 0x72 39088function DELTAP123(b, state) { 39089 var stack = state.stack; 39090 var n = stack.pop(); 39091 var fv = state.fv; 39092 var pv = state.pv; 39093 var ppem = state.ppem; 39094 var base = state.deltaBase + (b - 1) * 16; 39095 var ds = state.deltaShift; 39096 var z0 = state.z0; 39097 39098 if (exports.DEBUG) { console.log(state.step, 'DELTAP[' + b + ']', n, stack); } 39099 39100 for (var i = 0; i < n; i++) 39101 { 39102 var pi = stack.pop(); 39103 var arg = stack.pop(); 39104 var appem = base + ((arg & 0xF0) >> 4); 39105 if (appem !== ppem) { continue; } 39106 39107 var mag = (arg & 0x0F) - 8; 39108 if (mag >= 0) { mag++; } 39109 if (exports.DEBUG) { console.log(state.step, 'DELTAPFIX', pi, 'by', mag * ds); } 39110 39111 var p = z0[pi]; 39112 fv.setRelative(p, p, mag * ds, pv); 39113 } 39114} 39115 39116// SDB[] Set Delta Base in the graphics state 39117// 0x5E 39118function SDB(state) { 39119 var stack = state.stack; 39120 var n = stack.pop(); 39121 39122 if (exports.DEBUG) { console.log(state.step, 'SDB[]', n); } 39123 39124 state.deltaBase = n; 39125} 39126 39127// SDS[] Set Delta Shift in the graphics state 39128// 0x5F 39129function SDS(state) { 39130 var stack = state.stack; 39131 var n = stack.pop(); 39132 39133 if (exports.DEBUG) { console.log(state.step, 'SDS[]', n); } 39134 39135 state.deltaShift = Math.pow(0.5, n); 39136} 39137 39138// ADD[] ADD 39139// 0x60 39140function ADD(state) { 39141 var stack = state.stack; 39142 var n2 = stack.pop(); 39143 var n1 = stack.pop(); 39144 39145 if (exports.DEBUG) { console.log(state.step, 'ADD[]', n2, n1); } 39146 39147 stack.push(n1 + n2); 39148} 39149 39150// SUB[] SUB 39151// 0x61 39152function SUB(state) { 39153 var stack = state.stack; 39154 var n2 = stack.pop(); 39155 var n1 = stack.pop(); 39156 39157 if (exports.DEBUG) { console.log(state.step, 'SUB[]', n2, n1); } 39158 39159 stack.push(n1 - n2); 39160} 39161 39162// DIV[] DIV 39163// 0x62 39164function DIV(state) { 39165 var stack = state.stack; 39166 var n2 = stack.pop(); 39167 var n1 = stack.pop(); 39168 39169 if (exports.DEBUG) { console.log(state.step, 'DIV[]', n2, n1); } 39170 39171 stack.push(n1 * 64 / n2); 39172} 39173 39174// MUL[] MUL 39175// 0x63 39176function MUL(state) { 39177 var stack = state.stack; 39178 var n2 = stack.pop(); 39179 var n1 = stack.pop(); 39180 39181 if (exports.DEBUG) { console.log(state.step, 'MUL[]', n2, n1); } 39182 39183 stack.push(n1 * n2 / 64); 39184} 39185 39186// ABS[] ABSolute value 39187// 0x64 39188function ABS(state) { 39189 var stack = state.stack; 39190 var n = stack.pop(); 39191 39192 if (exports.DEBUG) { console.log(state.step, 'ABS[]', n); } 39193 39194 stack.push(Math.abs(n)); 39195} 39196 39197// NEG[] NEGate 39198// 0x65 39199function NEG(state) { 39200 var stack = state.stack; 39201 var n = stack.pop(); 39202 39203 if (exports.DEBUG) { console.log(state.step, 'NEG[]', n); } 39204 39205 stack.push(-n); 39206} 39207 39208// FLOOR[] FLOOR 39209// 0x66 39210function FLOOR(state) { 39211 var stack = state.stack; 39212 var n = stack.pop(); 39213 39214 if (exports.DEBUG) { console.log(state.step, 'FLOOR[]', n); } 39215 39216 stack.push(Math.floor(n / 0x40) * 0x40); 39217} 39218 39219// CEILING[] CEILING 39220// 0x67 39221function CEILING(state) { 39222 var stack = state.stack; 39223 var n = stack.pop(); 39224 39225 if (exports.DEBUG) { console.log(state.step, 'CEILING[]', n); } 39226 39227 stack.push(Math.ceil(n / 0x40) * 0x40); 39228} 39229 39230// ROUND[ab] ROUND value 39231// 0x68-0x6B 39232function ROUND(dt, state) { 39233 var stack = state.stack; 39234 var n = stack.pop(); 39235 39236 if (exports.DEBUG) { console.log(state.step, 'ROUND[]'); } 39237 39238 stack.push(state.round(n / 0x40) * 0x40); 39239} 39240 39241// WCVTF[] Write Control Value Table in Funits 39242// 0x70 39243function WCVTF(state) { 39244 var stack = state.stack; 39245 var v = stack.pop(); 39246 var l = stack.pop(); 39247 39248 if (exports.DEBUG) { console.log(state.step, 'WCVTF[]', v, l); } 39249 39250 state.cvt[l] = v * state.ppem / state.font.unitsPerEm; 39251} 39252 39253// DELTAC1[] DELTA exception C1 39254// DELTAC2[] DELTA exception C2 39255// DELTAC3[] DELTA exception C3 39256// 0x73, 0x74, 0x75 39257function DELTAC123(b, state) { 39258 var stack = state.stack; 39259 var n = stack.pop(); 39260 var ppem = state.ppem; 39261 var base = state.deltaBase + (b - 1) * 16; 39262 var ds = state.deltaShift; 39263 39264 if (exports.DEBUG) { console.log(state.step, 'DELTAC[' + b + ']', n, stack); } 39265 39266 for (var i = 0; i < n; i++) { 39267 var c = stack.pop(); 39268 var arg = stack.pop(); 39269 var appem = base + ((arg & 0xF0) >> 4); 39270 if (appem !== ppem) { continue; } 39271 39272 var mag = (arg & 0x0F) - 8; 39273 if (mag >= 0) { mag++; } 39274 39275 var delta = mag * ds; 39276 39277 if (exports.DEBUG) { console.log(state.step, 'DELTACFIX', c, 'by', delta); } 39278 39279 state.cvt[c] += delta; 39280 } 39281} 39282 39283// SROUND[] Super ROUND 39284// 0x76 39285function SROUND(state) { 39286 var n = state.stack.pop(); 39287 39288 if (exports.DEBUG) { console.log(state.step, 'SROUND[]', n); } 39289 39290 state.round = roundSuper; 39291 39292 var period; 39293 39294 switch (n & 0xC0) { 39295 case 0x00: 39296 period = 0.5; 39297 break; 39298 case 0x40: 39299 period = 1; 39300 break; 39301 case 0x80: 39302 period = 2; 39303 break; 39304 default: 39305 throw new Error('invalid SROUND value'); 39306 } 39307 39308 state.srPeriod = period; 39309 39310 switch (n & 0x30) { 39311 case 0x00: 39312 state.srPhase = 0; 39313 break; 39314 case 0x10: 39315 state.srPhase = 0.25 * period; 39316 break; 39317 case 0x20: 39318 state.srPhase = 0.5 * period; 39319 break; 39320 case 0x30: 39321 state.srPhase = 0.75 * period; 39322 break; 39323 default: throw new Error('invalid SROUND value'); 39324 } 39325 39326 n &= 0x0F; 39327 39328 if (n === 0) { state.srThreshold = 0; } 39329 else { state.srThreshold = (n / 8 - 0.5) * period; } 39330} 39331 39332// S45ROUND[] Super ROUND 45 degrees 39333// 0x77 39334function S45ROUND(state) { 39335 var n = state.stack.pop(); 39336 39337 if (exports.DEBUG) { console.log(state.step, 'S45ROUND[]', n); } 39338 39339 state.round = roundSuper; 39340 39341 var period; 39342 39343 switch (n & 0xC0) { 39344 case 0x00: 39345 period = Math.sqrt(2) / 2; 39346 break; 39347 case 0x40: 39348 period = Math.sqrt(2); 39349 break; 39350 case 0x80: 39351 period = 2 * Math.sqrt(2); 39352 break; 39353 default: 39354 throw new Error('invalid S45ROUND value'); 39355 } 39356 39357 state.srPeriod = period; 39358 39359 switch (n & 0x30) { 39360 case 0x00: 39361 state.srPhase = 0; 39362 break; 39363 case 0x10: 39364 state.srPhase = 0.25 * period; 39365 break; 39366 case 0x20: 39367 state.srPhase = 0.5 * period; 39368 break; 39369 case 0x30: 39370 state.srPhase = 0.75 * period; 39371 break; 39372 default: 39373 throw new Error('invalid S45ROUND value'); 39374 } 39375 39376 n &= 0x0F; 39377 39378 if (n === 0) { state.srThreshold = 0; } 39379 else { state.srThreshold = (n / 8 - 0.5) * period; } 39380} 39381 39382// ROFF[] Round Off 39383// 0x7A 39384function ROFF(state) { 39385 if (exports.DEBUG) { console.log(state.step, 'ROFF[]'); } 39386 39387 state.round = roundOff; 39388} 39389 39390// RUTG[] Round Up To Grid 39391// 0x7C 39392function RUTG(state) { 39393 if (exports.DEBUG) { console.log(state.step, 'RUTG[]'); } 39394 39395 state.round = roundUpToGrid; 39396} 39397 39398// RDTG[] Round Down To Grid 39399// 0x7D 39400function RDTG(state) { 39401 if (exports.DEBUG) { console.log(state.step, 'RDTG[]'); } 39402 39403 state.round = roundDownToGrid; 39404} 39405 39406// SCANCTRL[] SCAN conversion ConTRoL 39407// 0x85 39408function SCANCTRL(state) { 39409 var n = state.stack.pop(); 39410 39411 // ignored by opentype.js 39412 39413 if (exports.DEBUG) { console.log(state.step, 'SCANCTRL[]', n); } 39414} 39415 39416// SDPVTL[a] Set Dual Projection Vector To Line 39417// 0x86-0x87 39418function SDPVTL(a, state) { 39419 var stack = state.stack; 39420 var p2i = stack.pop(); 39421 var p1i = stack.pop(); 39422 var p2 = state.z2[p2i]; 39423 var p1 = state.z1[p1i]; 39424 39425 if (exports.DEBUG) { console.log('SDPVTL[' + a + ']', p2i, p1i); } 39426 39427 var dx; 39428 var dy; 39429 39430 if (!a) { 39431 dx = p1.x - p2.x; 39432 dy = p1.y - p2.y; 39433 } else { 39434 dx = p2.y - p1.y; 39435 dy = p1.x - p2.x; 39436 } 39437 39438 state.dpv = getUnitVector(dx, dy); 39439} 39440 39441// GETINFO[] GET INFOrmation 39442// 0x88 39443function GETINFO(state) { 39444 var stack = state.stack; 39445 var sel = stack.pop(); 39446 var r = 0; 39447 39448 if (exports.DEBUG) { console.log(state.step, 'GETINFO[]', sel); } 39449 39450 // v35 as in no subpixel hinting 39451 if (sel & 0x01) { r = 35; } 39452 39453 // TODO rotation and stretch currently not supported 39454 // and thus those GETINFO are always 0. 39455 39456 // opentype.js is always gray scaling 39457 if (sel & 0x20) { r |= 0x1000; } 39458 39459 stack.push(r); 39460} 39461 39462// ROLL[] ROLL the top three stack elements 39463// 0x8A 39464function ROLL(state) { 39465 var stack = state.stack; 39466 var a = stack.pop(); 39467 var b = stack.pop(); 39468 var c = stack.pop(); 39469 39470 if (exports.DEBUG) { console.log(state.step, 'ROLL[]'); } 39471 39472 stack.push(b); 39473 stack.push(a); 39474 stack.push(c); 39475} 39476 39477// MAX[] MAXimum of top two stack elements 39478// 0x8B 39479function MAX(state) { 39480 var stack = state.stack; 39481 var e2 = stack.pop(); 39482 var e1 = stack.pop(); 39483 39484 if (exports.DEBUG) { console.log(state.step, 'MAX[]', e2, e1); } 39485 39486 stack.push(Math.max(e1, e2)); 39487} 39488 39489// MIN[] MINimum of top two stack elements 39490// 0x8C 39491function MIN(state) { 39492 var stack = state.stack; 39493 var e2 = stack.pop(); 39494 var e1 = stack.pop(); 39495 39496 if (exports.DEBUG) { console.log(state.step, 'MIN[]', e2, e1); } 39497 39498 stack.push(Math.min(e1, e2)); 39499} 39500 39501// SCANTYPE[] SCANTYPE 39502// 0x8D 39503function SCANTYPE(state) { 39504 var n = state.stack.pop(); 39505 // ignored by opentype.js 39506 if (exports.DEBUG) { console.log(state.step, 'SCANTYPE[]', n); } 39507} 39508 39509// INSTCTRL[] INSTCTRL 39510// 0x8D 39511function INSTCTRL(state) { 39512 var s = state.stack.pop(); 39513 var v = state.stack.pop(); 39514 39515 if (exports.DEBUG) { console.log(state.step, 'INSTCTRL[]', s, v); } 39516 39517 switch (s) { 39518 case 1 : state.inhibitGridFit = !!v; return; 39519 case 2 : state.ignoreCvt = !!v; return; 39520 default: throw new Error('invalid INSTCTRL[] selector'); 39521 } 39522} 39523 39524// PUSHB[abc] PUSH Bytes 39525// 0xB0-0xB7 39526function PUSHB(n, state) { 39527 var stack = state.stack; 39528 var prog = state.prog; 39529 var ip = state.ip; 39530 39531 if (exports.DEBUG) { console.log(state.step, 'PUSHB[' + n + ']'); } 39532 39533 for (var i = 0; i < n; i++) { stack.push(prog[++ip]); } 39534 39535 state.ip = ip; 39536} 39537 39538// PUSHW[abc] PUSH Words 39539// 0xB8-0xBF 39540function PUSHW(n, state) { 39541 var ip = state.ip; 39542 var prog = state.prog; 39543 var stack = state.stack; 39544 39545 if (exports.DEBUG) { console.log(state.ip, 'PUSHW[' + n + ']'); } 39546 39547 for (var i = 0; i < n; i++) { 39548 var w = (prog[++ip] << 8) | prog[++ip]; 39549 if (w & 0x8000) { w = -((w ^ 0xffff) + 1); } 39550 stack.push(w); 39551 } 39552 39553 state.ip = ip; 39554} 39555 39556// MDRP[abcde] Move Direct Relative Point 39557// 0xD0-0xEF 39558// (if indirect is 0) 39559// 39560// and 39561// 39562// MIRP[abcde] Move Indirect Relative Point 39563// 0xE0-0xFF 39564// (if indirect is 1) 39565 39566function MDRP_MIRP(indirect, setRp0, keepD, ro, dt, state) { 39567 var stack = state.stack; 39568 var cvte = indirect && stack.pop(); 39569 var pi = stack.pop(); 39570 var rp0i = state.rp0; 39571 var rp = state.z0[rp0i]; 39572 var p = state.z1[pi]; 39573 39574 var md = state.minDis; 39575 var fv = state.fv; 39576 var pv = state.dpv; 39577 var od; // original distance 39578 var d; // moving distance 39579 var sign; // sign of distance 39580 var cv; 39581 39582 d = od = pv.distance(p, rp, true, true); 39583 sign = d >= 0 ? 1 : -1; // Math.sign would be 0 in case of 0 39584 39585 // TODO consider autoFlip 39586 d = Math.abs(d); 39587 39588 if (indirect) { 39589 cv = state.cvt[cvte]; 39590 39591 if (ro && Math.abs(d - cv) < state.cvCutIn) { d = cv; } 39592 } 39593 39594 if (keepD && d < md) { d = md; } 39595 39596 if (ro) { d = state.round(d); } 39597 39598 fv.setRelative(p, rp, sign * d, pv); 39599 fv.touch(p); 39600 39601 if (exports.DEBUG) { 39602 console.log( 39603 state.step, 39604 (indirect ? 'MIRP[' : 'MDRP[') + 39605 (setRp0 ? 'M' : 'm') + 39606 (keepD ? '>' : '_') + 39607 (ro ? 'R' : '_') + 39608 (dt === 0 ? 'Gr' : (dt === 1 ? 'Bl' : (dt === 2 ? 'Wh' : ''))) + 39609 ']', 39610 indirect ? 39611 cvte + '(' + state.cvt[cvte] + ',' + cv + ')' : 39612 '', 39613 pi, 39614 '(d =', od, '->', sign * d, ')' 39615 ); 39616 } 39617 39618 state.rp1 = state.rp0; 39619 state.rp2 = pi; 39620 if (setRp0) { state.rp0 = pi; } 39621} 39622 39623/* 39624* The instruction table. 39625*/ 39626instructionTable = [ 39627 /* 0x00 */ SVTCA.bind(undefined, yUnitVector), 39628 /* 0x01 */ SVTCA.bind(undefined, xUnitVector), 39629 /* 0x02 */ SPVTCA.bind(undefined, yUnitVector), 39630 /* 0x03 */ SPVTCA.bind(undefined, xUnitVector), 39631 /* 0x04 */ SFVTCA.bind(undefined, yUnitVec
39631tor), 39632 /* 0x05 */ SFVTCA.bind(undefined, xUnitVector), 39633 /* 0x06 */ SPVTL.bind(undefined, 0), 39634 /* 0x07 */ SPVTL.bind(undefined, 1), 39635 /* 0x08 */ SFVTL.bind(undefined, 0), 39636 /* 0x09 */ SFVTL.bind(undefined, 1), 39637 /* 0x0A */ SPVFS, 39638 /* 0x0B */ SFVFS, 39639 /* 0x0C */ GPV, 39640 /* 0x0D */ GFV, 39641 /* 0x0E */ SFVTPV, 39642 /* 0x0F */ ISECT, 39643 /* 0x10 */ SRP0, 39644 /* 0x11 */ SRP1, 39645 /* 0x12 */ SRP2, 39646 /* 0x13 */ SZP0, 39647 /* 0x14 */ SZP1, 39648 /* 0x15 */ SZP2, 39649 /* 0x16 */ SZPS, 39650 /* 0x17 */ SLOOP, 39651 /* 0x18 */ RTG, 39652 /* 0x19 */ RTHG, 39653 /* 0x1A */ SMD, 39654 /* 0x1B */ ELSE, 39655 /* 0x1C */ JMPR, 39656 /* 0x1D */ SCVTCI, 39657 /* 0x1E */ undefined, // TODO SSWCI 39658 /* 0x1F */ undefined, // TODO SSW 39659 /* 0x20 */ DUP, 39660 /* 0x21 */ POP, 39661 /* 0x22 */ CLEAR, 39662 /* 0x23 */ SWAP, 39663 /* 0x24 */ DEPTH, 39664 /* 0x25 */ CINDEX, 39665 /* 0x26 */ MINDEX, 39666 /* 0x27 */ undefined, // TODO ALIGNPTS 39667 /* 0x28 */ undefined, 39668 /* 0x29 */ undefined, // TODO UTP 39669 /* 0x2A */ LOOPCALL, 39670 /* 0x2B */ CALL, 39671 /* 0x2C */ FDEF, 39672 /* 0x2D */ undefined, // ENDF (eaten by FDEF) 39673 /* 0x2E */ MDAP.bind(undefined, 0), 39674 /* 0x2F */ MDAP.bind(undefined, 1), 39675 /* 0x30 */ IUP.bind(undefined, yUnitVector), 39676 /* 0x31 */ IUP.bind(undefined, xUnitVector), 39677 /* 0x32 */ SHP.bind(undefined, 0), 39678 /* 0x33 */ SHP.bind(undefined, 1), 39679 /* 0x34 */ SHC.bind(undefined, 0), 39680 /* 0x35 */ SHC.bind(undefined, 1), 39681 /* 0x36 */ SHZ.bind(undefined, 0), 39682 /* 0x37 */ SHZ.bind(undefined, 1), 39683 /* 0x38 */ SHPIX, 39684 /* 0x39 */ IP, 39685 /* 0x3A */ MSIRP.bind(undefined, 0), 39686 /* 0x3B */ MSIRP.bind(undefined, 1), 39687 /* 0x3C */ ALIGNRP, 39688 /* 0x3D */ RTDG, 39689 /* 0x3E */ MIAP.bind(undefined, 0), 39690 /* 0x3F */ MIAP.bind(undefined, 1), 39691 /* 0x40 */ NPUSHB, 39692 /* 0x41 */ NPUSHW, 39693 /* 0x42 */ WS, 39694 /* 0x43 */ RS, 39695 /* 0x44 */ WCVTP, 39696 /* 0x45 */ RCVT, 39697 /* 0x46 */ GC.bind(undefined, 0), 39698 /* 0x47 */ GC.bind(undefined, 1), 39699 /* 0x48 */ undefined, // TODO SCFS 39700 /* 0x49 */ MD.bind(undefined, 0), 39701 /* 0x4A */ MD.bind(undefined, 1), 39702 /* 0x4B */ MPPEM, 39703 /* 0x4C */ undefined, // TODO MPS 39704 /* 0x4D */ FLIPON, 39705 /* 0x4E */ undefined, // TODO FLIPOFF 39706 /* 0x4F */ undefined, // TODO DEBUG 39707 /* 0x50 */ LT, 39708 /* 0x51 */ LTEQ, 39709 /* 0x52 */ GT, 39710 /* 0x53 */ GTEQ, 39711 /* 0x54 */ EQ, 39712 /* 0x55 */ NEQ, 39713 /* 0x56 */ ODD, 39714 /* 0x57 */ EVEN, 39715 /* 0x58 */ IF, 39716 /* 0x59 */ EIF, 39717 /* 0x5A */ AND, 39718 /* 0x5B */ OR, 39719 /* 0x5C */ NOT, 39720 /* 0x5D */ DELTAP123.bind(undefined, 1), 39721 /* 0x5E */ SDB, 39722 /* 0x5F */ SDS, 39723 /* 0x60 */ ADD, 39724 /* 0x61 */ SUB, 39725 /* 0x62 */ DIV, 39726 /* 0x63 */ MUL, 39727 /* 0x64 */ ABS, 39728 /* 0x65 */ NEG, 39729 /* 0x66 */ FLOOR, 39730 /* 0x67 */ CEILING, 39731 /* 0x68 */ ROUND.bind(undefined, 0), 39732 /* 0x69 */ ROUND.bind(undefined, 1), 39733 /* 0x6A */ ROUND.bind(undefined, 2), 39734 /* 0x6B */ ROUND.bind(undefined, 3), 39735 /* 0x6C */ undefined, // TODO NROUND[ab] 39736 /* 0x6D */ undefined, // TODO NROUND[ab] 39737 /* 0x6E */ undefined, // TODO NROUND[ab] 39738 /* 0x6F */ undefined, // TODO NROUND[ab] 39739 /* 0x70 */ WCVTF, 39740 /* 0x71 */ DELTAP123.bind(undefined, 2), 39741 /* 0x72 */ DELTAP123.bind(undefined, 3), 39742 /* 0x73 */ DELTAC123.bind(undefined, 1), 39743 /* 0x74 */ DELTAC123.bind(undefined, 2), 39744 /* 0x75 */ DELTAC123.bind(undefined, 3), 39745 /* 0x76 */ SROUND, 39746 /* 0x77 */ S45ROUND, 39747 /* 0x78 */ undefined, // TODO JROT[] 39748 /* 0x79 */ undefined, // TODO JROF[] 39749 /* 0x7A */ ROFF, 39750 /* 0x7B */ undefined, 39751 /* 0x7C */ RUTG, 39752 /* 0x7D */ RDTG, 39753 /* 0x7E */ POP, // actually SANGW, supposed to do only a pop though 39754 /* 0x7F */ POP, // actually AA, supposed to do only a pop though 39755 /* 0x80 */ undefined, // TODO FLIPPT 39756 /* 0x81 */ undefined, // TODO FLIPRGON 39757 /* 0x82 */ undefined, // TODO FLIPRGOFF 39758 /* 0x83 */ undefined, 39759 /* 0x84 */ undefined, 39760 /* 0x85 */ SCANCTRL, 39761 /* 0x86 */ SDPVTL.bind(undefined, 0), 39762 /* 0x87 */ SDPVTL.bind(undefined, 1), 39763 /* 0x88 */ GETINFO, 39764 /* 0x89 */ undefined, // TODO IDEF 39765 /* 0x8A */ ROLL, 39766 /* 0x8B */ MAX, 39767 /* 0x8C */ MIN, 39768 /* 0x8D */ SCANTYPE, 39769 /* 0x8E */ INSTCTRL, 39770 /* 0x8F */ undefined, 39771 /* 0x90 */ undefined, 39772 /* 0x91 */ undefined, 39773 /* 0x92 */ undefined, 39774 /* 0x93 */ undefined, 39775 /* 0x94 */ undefined, 39776 /* 0x95 */ undefined, 39777 /* 0x96 */ undefined, 39778 /* 0x97 */ undefined, 39779 /* 0x98 */ undefined, 39780 /* 0x99 */ undefined, 39781 /* 0x9A */ undefined, 39782 /* 0x9B */ undefined, 39783 /* 0x9C */ undefined, 39784 /* 0x9D */ undefined, 39785 /* 0x9E */ undefined, 39786 /* 0x9F */ undefined, 39787 /* 0xA0 */ undefined, 39788 /* 0xA1 */ undefined, 39789 /* 0xA2 */ undefined, 39790 /* 0xA3 */ undefined, 39791 /* 0xA4 */ undefined, 39792 /* 0xA5 */ undefined, 39793 /* 0xA6 */ undefined, 39794 /* 0xA7 */ undefined, 39795 /* 0xA8 */ undefined, 39796 /* 0xA9 */ undefined, 39797 /* 0xAA */ undefined, 39798 /* 0xAB */ undefined, 39799 /* 0xAC */ undefined, 39800 /* 0xAD */ undefined, 39801 /* 0xAE */ undefined, 39802 /* 0xAF */ undefined, 39803 /* 0xB0 */ PUSHB.bind(undefined, 1), 39804 /* 0xB1 */ PUSHB.bind(undefined, 2), 39805 /* 0xB2 */ PUSHB.bind(undefined, 3), 39806 /* 0xB3 */ PUSHB.bind(undefined, 4), 39807 /* 0xB4 */ PUSHB.bind(undefined, 5), 39808 /* 0xB5 */ PUSHB.bind(undefined, 6), 39809 /* 0xB6 */ PUSHB.bind(undefined, 7), 39810 /* 0xB7 */ PUSHB.bind(undefined, 8), 39811 /* 0xB8 */ PUSHW.bind(undefined, 1), 39812 /* 0xB9 */ PUSHW.bind(undefined, 2), 39813 /* 0xBA */ PUSHW.bind(undefined, 3), 39814 /* 0xBB */ PUSHW.bind(undefined, 4), 39815 /* 0xBC */ PUSHW.bind(undefined, 5), 39816 /* 0xBD */ PUSHW.bind(undefined, 6), 39817 /* 0xBE */ PUSHW.bind(undefined, 7), 39818 /* 0xBF */ PUSHW.bind(undefined, 8), 39819 /* 0xC0 */ MDRP_MIRP.bind(undefined, 0, 0, 0, 0, 0), 39820 /* 0xC1 */ MDRP_MIRP.bind(undefined, 0, 0, 0, 0, 1), 39821 /* 0xC2 */ MDRP_MIRP.bind(undefined, 0, 0, 0, 0, 2), 39822 /* 0xC3 */ MDRP_MIRP.bind(undefined, 0, 0, 0, 0, 3), 39823 /* 0xC4 */ MDRP_MIRP.bind(undefined, 0, 0, 0, 1, 0), 39824 /* 0xC5 */ MDRP_MIRP.bind(undefined, 0, 0, 0, 1, 1), 39825 /* 0xC6 */ MDRP_MIRP.bind(undefined, 0, 0, 0, 1, 2), 39826 /* 0xC7 */ MDRP_MIRP.bind(undefined, 0, 0, 0, 1, 3), 39827 /* 0xC8 */ MDRP_MIRP.bind(undefined, 0, 0, 1, 0, 0), 39828 /* 0xC9 */ MDRP_MIRP.bind(undefined, 0, 0, 1, 0, 1), 39829 /* 0xCA */ MDRP_MIRP.bind(undefined, 0, 0, 1, 0, 2), 39830 /* 0xCB */ MDRP_MIRP.bind(undefined, 0, 0, 1, 0, 3), 39831 /* 0xCC */ MDRP_MIRP.bind(undefined, 0, 0, 1, 1, 0), 39832 /* 0xCD */ MDRP_MIRP.bind(undefined, 0, 0, 1, 1, 1), 39833 /* 0xCE */ MDRP_MIRP.bind(undefined, 0, 0, 1, 1, 2), 39834 /* 0xCF */ MDRP_MIRP.bind(undefined, 0, 0, 1, 1, 3), 39835 /* 0xD0 */ MDRP_MIRP.bind(undefined, 0, 1, 0, 0, 0), 39836 /* 0xD1 */ MDRP_MIRP.bind(undefined, 0, 1, 0, 0, 1), 39837 /* 0xD2 */ MDRP_MIRP.bind(undefined, 0, 1, 0, 0, 2), 39838 /* 0xD3 */ MDRP_MIRP.bind(undefined, 0, 1, 0, 0, 3), 39839 /* 0xD4 */ MDRP_MIRP.bind(undefined, 0, 1, 0, 1, 0), 39840 /* 0xD5 */ MDRP_MIRP.bind(undefined, 0, 1, 0, 1, 1), 39841 /* 0xD6 */ MDRP_MIRP.bind(undefined, 0, 1, 0, 1, 2), 39842 /* 0xD7 */ MDRP_MIRP.bind(undefined, 0, 1, 0, 1, 3), 39843 /* 0xD8 */ MDRP_MIRP.bind(undefined, 0, 1, 1, 0, 0), 39844 /* 0xD9 */ MDRP_MIRP.bind(undefined, 0, 1, 1, 0, 1), 39845 /* 0xDA */ MDRP_MIRP.bind(undefined, 0, 1, 1, 0, 2), 39846 /* 0xDB */ MDRP_MIRP.bind(undefined, 0, 1, 1, 0, 3), 39847 /* 0xDC */ MDRP_MIRP.bind(undefined, 0, 1, 1, 1, 0), 39848 /* 0xDD */ MDRP_MIRP.bind(undefined, 0, 1, 1, 1, 1), 39849 /* 0xDE */ MDRP_MIRP.bind(undefined, 0, 1, 1, 1, 2), 39850 /* 0xDF */ MDRP_MIRP.bind(undefined, 0, 1, 1, 1, 3), 39851 /* 0xE0 */ MDRP_MIRP.bind(undefined, 1, 0, 0, 0, 0), 39852 /* 0xE1 */ MDRP_MIRP.bind(undefined, 1, 0, 0, 0, 1), 39853 /* 0xE2 */ MDRP_MIRP.bind(undefined, 1, 0, 0, 0, 2), 39854 /* 0xE3 */ MDRP_MIRP.bind(undefined, 1, 0, 0, 0, 3), 39855 /* 0xE4 */ MDRP_MIRP.bind(undefined, 1, 0, 0, 1, 0), 39856 /* 0xE5 */ MDRP_MIRP.bind(undefined, 1, 0, 0, 1, 1), 39857 /* 0xE6 */ MDRP_MIRP.bind(undefined, 1, 0, 0, 1, 2), 39858 /* 0xE7 */ MDRP_MIRP.bind(undefined, 1, 0, 0, 1, 3), 39859 /* 0xE8 */ MDRP_MIRP.bind(undefined, 1, 0, 1, 0, 0), 39860 /* 0xE9 */ MDRP_MIRP.bind(undefined, 1, 0, 1, 0, 1), 39861 /* 0xEA */ MDRP_MIRP.bind(undefined, 1, 0, 1, 0, 2), 39862 /* 0xEB */ MDRP_MIRP.bind(undefined, 1, 0, 1, 0, 3), 39863 /* 0xEC */ MDRP_MIRP.bind(undefined, 1, 0, 1, 1, 0), 39864 /* 0xED */ MDRP_MIRP.bind(undefined, 1, 0, 1, 1, 1), 39865 /* 0xEE */ MDRP_MIRP.bind(undefined, 1, 0, 1, 1, 2), 39866 /* 0xEF */ MDRP_MIRP.bind(undefined, 1, 0, 1, 1, 3), 39867 /* 0xF0 */ MDRP_MIRP.bind(undefined, 1, 1, 0, 0, 0), 39868 /* 0xF1 */ MDRP_MIRP.bind(undefined, 1, 1, 0, 0, 1), 39869 /* 0xF2 */ MDRP_MIRP.bind(undefined, 1, 1, 0, 0, 2), 39870 /* 0xF3 */ MDRP_MIRP.bind(undefined, 1, 1, 0, 0, 3), 39871 /* 0xF4 */ MDRP_MIRP.bind(undefined, 1, 1, 0, 1, 0), 39872 /* 0xF5 */ MDRP_MIRP.bind(undefined, 1, 1, 0, 1, 1), 39873 /* 0xF6 */ MDRP_MIRP.bind(undefined, 1, 1, 0, 1, 2), 39874 /* 0xF7 */ MDRP_MIRP.bind(undefined, 1, 1, 0, 1, 3), 39875 /* 0xF8 */ MDRP_MIRP.bind(undefined, 1, 1, 1, 0, 0), 39876 /* 0xF9 */ MDRP_MIRP.bind(undefined, 1, 1, 1, 0, 1), 39877 /* 0xFA */ MDRP_MIRP.bind(undefined, 1, 1, 1, 0, 2), 39878 /* 0xFB */ MDRP_MIRP.bind(undefined, 1, 1, 1, 0, 3), 39879 /* 0xFC */ MDRP_MIRP.bind(undefined, 1, 1, 1, 1, 0), 39880 /* 0xFD */ MDRP_MIRP.bind(undefined, 1, 1, 1, 1, 1), 39881 /* 0xFE */ MDRP_MIRP.bind(undefined, 1, 1, 1, 1, 2), 39882 /* 0xFF */ MDRP_MIRP.bind(undefined, 1, 1, 1, 1, 3) 39883]; 39884 39885 39886 39887/***************************** 39888 Mathematical Considerations 39889****************************** 39890 39891fv ... refers to freedom vector 39892pv ... refers to projection vector 39893rp ... refers to reference point 39894p ... refers to to point being operated on 39895d ... refers to distance 39896 39897SETRELATIVE: 39898============ 39899 39900case freedom vector == x-axis: 39901------------------------------ 39902 39903 (pv) 39904 .-' 39905 rpd .-' 39906 .-* 39907 d .-'90°' 39908 .-' ' 39909 .-' ' 39910 *-' ' b 39911 rp ' 39912 ' 39913 ' 39914 p *----------*-------------- (fv) 39915 pm 39916 39917 rpdx = rpx + d * pv.x 39918 rpdy = rpy + d * pv.y 39919 39920 equation of line b 39921 39922 y - rpdy = pvns * (x- rpdx) 39923 39924 y = p.y 39925 39926 x = rpdx + ( p.y - rpdy ) / pvns 39927 39928 39929case freedom vector == y-axis: 39930------------------------------ 39931 39932 * pm 39933 |\ 39934 | \ 39935 | \ 39936 | \ 39937 | \ 39938 | \ 39939 | \ 39940 | \ 39941 | \ 39942 | \ b 39943 | \ 39944 | \ 39945 | \ .-' (pv) 39946 | 90° \.-' 39947 | .-'* rpd 39948 | .-' 39949 * *-' d 39950 p rp 39951 39952 rpdx = rpx + d * pv.x 39953 rpdy = rpy + d * pv.y 39954 39955 equation of line b: 39956 pvns ... normal slope to pv 39957 39958 y - rpdy = pvns * (x - rpdx) 39959 39960 x = p.x 39961 39962 y = rpdy + pvns * (p.x - rpdx) 39963 39964 39965 39966generic case: 39967------------- 39968 39969 39970 .'(fv) 39971 .' 39972 .* pm 39973 .' ! 39974 .' . 39975 .' ! 39976 .' . b 39977 .' ! 39978 * . 39979 p ! 39980 90° . ... (pv) 39981 ...-*-''' 39982 ...---''' rpd 39983 ...---''' d 39984 *--''' 39985 rp 39986 39987 rpdx = rpx + d * pv.x 39988 rpdy = rpy + d * pv.y 39989 39990 equation of line b: 39991 pvns... normal slope to pv 39992 39993 y - rpdy = pvns * (x - rpdx) 39994 39995 equation of freedom vector line: 39996 fvs ... slope of freedom vector (=fy/fx) 39997
39998 y - py = fvs * (x - px) 39999 40000 40001 on pm both equations are true for same x/y 40002 40003 y - rpdy = pvns * (x - rpdx) 40004 40005 y - py = fvs * (x - px) 40006 40007 form to y and set equal: 40008 40009 pvns * (x - rpdx) + rpdy = fvs * (x - px) + py 40010 40011 expand: 40012 40013 pvns * x - pvns * rpdx + rpdy = fvs * x - fvs * px + py 40014 40015 switch: 40016 40017 fvs * x - fvs * px + py = pvns * x - pvns * rpdx + rpdy 40018 40019 solve for x: 40020 40021 fvs * x - pvns * x = fvs * px - pvns * rpdx - py + rpdy 40022 40023 40024 40025 fvs * px - pvns * rpdx + rpdy - py 40026 x = ----------------------------------- 40027 fvs - pvns 40028 40029 and: 40030 40031 y = fvs * (x - px) + py 40032 40033 40034 40035INTERPOLATE: 40036============ 40037 40038Examples of point interpolation. 40039 40040The weight of the movement of the reference point gets bigger 40041the further the other reference point is away, thus the safest 40042option (that is avoiding 0/0 divisions) is to weight the 40043original distance of the other point by the sum of both distances. 40044 40045If the sum of both distances is 0, then move the point by the 40046arithmetic average of the movement of both reference points. 40047 40048 40049 40050 40051 (+6) 40052 rp1o *---->*rp1 40053 . . (+12) 40054 . . rp2o *---------->* rp2 40055 . . . . 40056 . . . . 40057 . 10 20 . . 40058 |.........|...................| . 40059 . . . 40060 . . (+8) . 40061 po *------>*p . 40062 . . . 40063 . 12 . 24 . 40064 |...........|.......................| 40065 36 40066 40067 40068------- 40069 40070 40071 40072 (+10) 40073 rp1o *-------->*rp1 40074 . . (-10) 40075 . . rp2 *<---------* rpo2 40076 . . . . 40077 . . . . 40078 . 10 . 30 . . 40079 |.........|.............................| 40080 . . 40081 . (+5) . 40082 po *--->* p . 40083 . . . 40084 . . 20 . 40085 |....|..............| 40086 5 15 40087 40088 40089------- 40090 40091 40092 (+10) 40093 rp1o *-------->*rp1 40094 . . 40095 . . 40096 rp2o *-------->*rp2 40097 40098 40099 (+10) 40100 po *-------->* p 40101 40102------- 40103 40104 40105 (+10) 40106 rp1o *-------->*rp1 40107 . . 40108 . .(+30) 40109 rp2o *---------------------------->*rp2 40110 40111 40112 (+25) 40113 po *----------------------->* p 40114 40115 40116 40117vim: set ts=4 sw=4 expandtab: 40118*****/ 40119 40120// The Font object 40121 40122/** 40123 * @typedef FontOptions 40124 * @type Object 40125 * @property {Boolean} empty - whether to create a new empty font 40126 * @property {string} familyName 40127 * @property {string} styleName 40128 * @property {string=} fullName 40129 * @property {string=} postScriptName 40130 * @property {string=} designer 40131 * @property {string=} designerURL 40132 * @property {string=} manufacturer 40133 * @property {string=} manufacturerURL 40134 * @property {string=} license 40135 * @property {string=} licenseURL 40136 * @property {string=} version 40137 * @property {string=} description 40138 * @property {string=} copyright 40139 * @property {string=} trademark 40140 * @property {Number} unitsPerEm 40141 * @property {Number} ascender 40142 * @property {Number} descender 40143 * @property {Number} createdTimestamp 40144 * @property {string=} weightClass 40145 * @property {string=} widthClass 40146 * @property {string=} fsSelection 40147 */ 40148 40149/** 40150 * A Font represents a loaded OpenType font file. 40151 * It contains a set of glyphs and methods to draw text on a drawing context, 40152 * or to get a path representing the text. 40153 * @exports opentype.Font 40154 * @class 40155 * @param {FontOptions} 40156 * @constructor 40157 */ 40158function Font(options) { 40159 options = options || {}; 40160 40161 if (!options.empty) { 40162 // Check that we've provided the minimum set of names. 40163 checkArgument(options.familyName, 'When creating a new Font object, familyName is required.'); 40164 checkArgument(options.styleName, 'When creating a new Font object, styleName is required.'); 40165 checkArgument(options.unitsPerEm, 'When creating a new Font object, unitsPerEm is required.'); 40166 checkArgument(options.ascender, 'When creating a new Font object, ascender is required.'); 40167 checkArgument(options.descender, 'When creating a new Font object, descender is required.'); 40168 checkArgument(options.descender < 0, 'Descender should be negative (e.g. -512).'); 40169
40170 // OS X will complain if the names are empty, so we put a single space everywhere by default. 40171 this.names = { 40172 fontFamily: {en: options.familyName || ' '}, 40173 fontSubfamily: {en: options.styleName || ' '}, 40174 fullName: {en: options.fullName || options.familyName + ' ' + options.styleName}, 40175 postScriptName: {en: options.postScriptName || options.familyName + options.styleName}, 40176 designer: {en: options.designer || ' '}, 40177 designerURL: {en: options.designerURL || ' '}, 40178 manufacturer: {en: options.manufacturer || ' '}, 40179 manufacturerURL: {en: options.manufacturerURL || ' '}, 40180 license: {en: options.license || ' '}, 40181 licenseURL: {en: options.licenseURL || ' '}, 40182 version: {en: options.version || 'Version 0.1'}, 40183 description: {en: options.description || ' '}, 40184 copyright: {en: options.copyright || ' '}, 40185 trademark: {en: options.trademark || ' '} 40186 }; 40187 this.unitsPerEm = options.unitsPerEm || 1000; 40188 this.ascender = options.ascender; 40189 this.descender = options.descender; 40190 this.createdTimestamp = options.createdTimestamp; 40191 this.tables = { os2: { 40192 usWeightClass: options.weightClass || this.usWeightClasses.MEDIUM, 40193 usWidthClass: options.widthClass || this.usWidthClasses.MEDIUM, 40194 fsSelection: options.fsSelection || this.fsSelectionValues.REGULAR 40195 } }; 40196 } 40197 40198 this.supported = true; // Deprecated: parseBuffer will throw an error if font is not supported. 40199 this.glyphs = new glyphset.GlyphSet(this, options.glyphs || []); 40200 this.encoding = new DefaultEncoding(this); 40201 this.substitution = new Substitution(this); 40202 this.tables = this.tables || {}; 40203 40204 Object.defineProperty(this, 'hinting', { 40205 get: function() { 40206 if (this._hinting) { return this._hinting; } 40207 if (this.outlinesFormat === 'truetype') { 40208 return (this._hinting = new Hinting(this)); 40209 } 40210 } 40211 }); 40212} 40213 40214/** 40215 * Check if the font has a glyph for the given character. 40216 * @param {string} 40217 * @return {Boolean} 40218 */ 40219Font.prototype.hasChar = function(c) { 40220 return this.encoding.charToGlyphIndex(c) !== null; 40221}; 40222 40223/** 40224 * Convert the given character to a single glyph index. 40225 * Note that this function assumes that there is a one-to-one mapping between 40226 * the given character and a glyph; for complex scripts this might not be the case. 40227 * @param {string} 40228 * @return {Number} 40229 */ 40230Font.prototype.charToGlyphIndex = function(s) { 40231 return this.encoding.charToGlyphIndex(s); 40232}; 40233 40234/** 40235 * Convert the given character to a single Glyph object. 40236 * Note that this function assumes that there is a one-to-one mapping between 40237 * the given character and a glyph; for complex scripts this might not be the case. 40238 * @param {string} 40239 * @return {opentype.Glyph} 40240 */ 40241Font.prototype.charToGlyph = function(c) { 40242 var glyphIndex = this.charToGlyphIndex(c); 40243 var glyph = this.glyphs.get(glyphIndex); 40244 if (!glyph) { 40245 // .notdef 40246 glyph = this.glyphs.get(0); 40247 } 40248 40249 return glyph; 40250}; 40251 40252/** 40253 * Convert the given text to a list of Glyph objects. 40254 * Note that there is no strict one-to-one mapping between characters and 40255 * glyphs, so the list of returned glyphs can be larger or smaller than the 40256 * length of the given string. 40257 * @param {string} 40258 * @param {GlyphRenderOptions} [options] 40259 * @return {opentype.Glyph[]} 40260 */ 40261Font.prototype.stringToGlyphs = function(s, options) { 40262 var this$1 = this; 40263 40264 options = options || this.defaultRenderOptions; 40265 // Get glyph indexes 40266 var indexes = []; 40267 for (var i = 0; i < s.length; i += 1) { 40268 var c = s[i]; 40269 indexes.push(this$1.charToGlyphIndex(c)); 40270 } 40271 var length = indexes.length; 40272 40273 // Apply substitutions on glyph indexes 40274 if (options.features) { 40275 var script = options.script || this.substitution.getDefaultScriptName(); 40276 var manyToOne = []; 40277 if (options.features.liga) { manyToOne = manyToOne.concat(this.substitution.getFeature('liga', script, options.language)); } 40278 if (options.features.rlig) { manyToOne = manyToOne.concat(this.substitution.getFeature('rlig', script, options.language)); } 40279 for (var i$1 = 0; i$1 < length; i$1 += 1) { 40280 for (var j = 0; j < manyToOne.length; j++) { 40281 var ligature = manyToOne[j]; 40282 var components = ligature.sub; 40283 var compCount = components.length; 40284 var k = 0; 40285 while (k < compCount && components[k] === indexes[i$1 + k]) { k++; } 40286 if (k === compCount) { 40287 indexes.splice(i$1, compCount, ligature.by); 40288 length = length - compCount + 1; 40289 } 40290 } 40291 } 40292 } 40293 40294 // convert glyph indexes to glyph objects 40295 var glyphs = new Array(length); 40296 var notdef = this.glyphs.get(0); 40297 for (var i$2 = 0; i$2 < length; i$2 += 1) { 40298 glyphs[i$2] = this$1.glyphs.get(indexes[i$2]) || notdef; 40299 } 40300 return glyphs; 40301}; 40302 40303/** 40304 * @param {string} 40305 * @return {Number} 40306 */ 40307Font.prototype.nameToGlyphIndex = function(name) { 40308 return this.glyphNames.nameToGlyphIndex(name); 40309}; 40310 40311/** 40312 * @param {string} 40313 * @return {opentype.Glyph} 40314 */ 40315Font.prototype.nameToGlyph = function(name) { 40316 var glyphIndex = this.nameToGlyphIndex(name); 40317 var glyph = this.glyphs.get(glyphIndex); 40318 if (!glyph) { 40319 // .notdef 40320 glyph = this.glyphs.get(0); 40321 } 40322 40323 return glyph; 40324}; 40325 40326/** 40327 * @param {Number} 40328 * @return {String} 40329 */ 40330Font.prototype.glyphIndexToName = function(gid) { 40331 if (!this.glyphNames.glyphIndexToName) { 40332 return ''; 40333 } 40334 40335 return this.glyphNames.glyphIndexToName(gid); 40336}; 40337 40338/** 40339 * Retrieve the value of the kerning pair between the left glyph (or its index) 40340 * and the right glyph (or its index). If no kerning pair is found, return 0. 40341 * The kerning value gets added to the advance width when calculating the spacing 40342 * between glyphs. 40343 * @param {opentype.Glyph} leftGlyph 40344 * @param {opentype.Glyph} rightGlyph 40345 * @return {Number} 40346 */ 40347Font.prototype.getKerningValue = function(leftGlyph, rightGlyph) { 40348 leftGlyph = leftGlyph.index || leftGlyph; 40349 rightGlyph = rightGlyph.index || rightGlyph; 40350 var gposKerning = this.getGposKerningValue; 40351 return gposKerning ? gposKerning(leftGlyph, rightGlyph) : 40352 (this.kerningPairs[leftGlyph + ',' + rightGlyph] || 0); 40353}; 40354 40355/** 40356 * @typedef GlyphRenderOptions 40357 * @type Object 40358 * @property {string} [script] - script used to determine which features to apply. By default, 'DFLT' or 'latn' is used. 40359 * See https://www.microsoft.com/typography/otspec/scripttags.htm 40360 * @property {string} [language='dflt'] - language system used to determine which features to apply. 40361 * See https://www.microsoft.com/typography/developers/opentype/languagetags.aspx 40362 * @property {boolean} [kerning=true] - whether to include kerning values 40363 * @property {object} [features] - OpenType Layout feature tags. Used to enable or disable the features of the given script/language system. 40364 * See https://www.microsoft.com/typography/otspec/featuretags.htm 40365 */ 40366Font.prototype.defaultRenderOptions = { 40367 kerning: true, 40368 features: { 40369 liga: true, 40370 rlig: true 40371 } 40372}; 40373 40374/** 40375 * Helper function that invokes the given callback for each glyph in the given text. 40376 * The callback gets `(glyph, x, y, fontSize, options)`.* @param {string} text 40377 * @param {string} text - The text to apply. 40378 * @param {number} [x=0] - Horizontal position of the beginning of the text. 40379 * @param {number} [y=0] - Vertical position of the *baseline* of the text. 40380 * @param {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. 40381 * @param {GlyphRenderOptions=} options 40382 * @param {Function} callback 40383 */ 40384Font.prototype.forEachGlyph = function(text, x, y, fontSize, options, callback) { 40385 var this$1 = this; 40386 40387 x = x !== undefined ? x : 0; 40388 y = y !== undefined ? y : 0; 40389 fontSize = fontSize !== undefined ? fontSize : 72; 40390 options = options || this.defaultRenderOptions; 40391 var fontScale = 1 / this.unitsPerEm * fontSize; 40392 var glyphs = this.stringToGlyphs(text, options); 40393 for (var i = 0; i < glyphs.length; i += 1) { 40394 var glyph = glyphs[i]; 40395 callback.call(this$1, glyph, x, y, fontSize, options); 40396 if (glyph.advanceWidth) { 40397 x += glyph.advanceWidth * fontScale; 40398 } 40399 40400 if (options.kerning && i < glyphs.length - 1) { 40401 var kerningValue = this$1.getKerningValue(glyph, glyphs[i + 1]); 40402 x += kerningValue * fontScale; 40403 } 40404 40405 if (options.letterSpacing) { 40406 x += options.letterSpacing * fontSize; 40407 } else if (options.tracking) { 40408 x += (options.tracking / 1000) * fontSize; 40409 } 40410 } 40411 return x; 40412}; 40413 40414/** 40415 * Create a Path object that represents the given text. 40416 * @param {string} text - The text to create. 40417 * @param {number} [x=0] - Horizontal position of the beginning of the text. 40418 * @param {number} [y=0] - Vertical position of the *baseline* of the text. 40419 * @param {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. 40420 * @param {GlyphRenderOptions=} options 40421 * @return {opentype.Path} 40422 */ 40423Font.prototype.getPath = function(text, x, y, fontSize, options) { 40424 var fullPath = new Path(); 40425 this.forEachGlyph(text, x, y, fontSize, options, function(glyph, gX, gY, gFontSize) { 40426 var glyphPath = glyph.getPath(gX, gY, gFontSize, options, this); 40427 fullPath.extend(glyphPath); 40428 }); 40429 return fullPath; 40430}; 40431 40432/** 40433 * Create an array of Path objects that represent the glyphs of a given text. 40434 * @param {string} text - The text to create. 40435 * @param {number} [x=0] - Horizontal position of the beginning of the text. 40436 * @param {number} [y=0] - Vertical position of the *baseline* of the text. 40437 * @param {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. 40438 * @param {GlyphRenderOptions=} options 40439 * @return {opentype.Path[]} 40440 */ 40441Font.prototype.getPaths = function(text, x, y, fontSize, options) { 40442 var glyphPaths = []; 40443 this.forEachGlyph(text, x, y, fontSize, options, function(glyph, gX, gY, gFontSize) { 40444 var glyphPath = glyph.getPath(gX, gY, gFontSize, options, this); 40445 glyphPaths.push(glyphPath); 40446 }); 40447 40448 return glyphPaths; 40449}; 40450 40451/** 40452 * Returns the advance width of a text. 40453 * 40454 * This is something different than Path.getBoundingBox() as for example a 40455 * suffixed whitespace increases the advanceWidth but not the bounding box 40456 * or an overhanging letter like a calligraphic 'f' might have a quite larger 40457 * bounding box than its advance width. 40458 * 40459 * This corresponds to canvas2dContext.measureText(text).width 40460 * 40461 * @param {string} text - The text to create. 40462 * @param {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. 40463 * @param {GlyphRenderOptions=} options 40464 * @return advance width 40465 */ 40466Font.prototype.getAdvanceWidth = function(text, fontSize, options) { 40467 return this.forEachGlyph(text, 0, 0, fontSize, options, function() {}); 40468}; 40469 40470/** 40471 * Draw the text on the given drawing context.
40472 * @param {CanvasRenderingContext2D} ctx - A 2D drawing context, like Canvas. 40473 * @param {string} text - The text to create. 40474 * @param {number} [x=0] - Horizontal position of the beginning of the text. 40475 * @param {number} [y=0] - Vertical position of the *baseline* of the text. 40476 * @param {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. 40477 * @param {GlyphRenderOptions=} options 40478 */ 40479Font.prototype.draw = function(ctx, text, x, y, fontSize, options) { 40480 this.getPath(text, x, y, fontSize, options).draw(ctx); 40481}; 40482 40483/** 40484 * Draw the points of all glyphs in the text. 40485 * On-curve points will be drawn in blue, off-curve points will be drawn in red. 40486 * @param {CanvasRenderingContext2D} ctx - A 2D drawing context, like Canvas. 40487 * @param {string} text - The text to create. 40488 * @param {number} [x=0] - Horizontal position of the beginning of the text. 40489 * @param {number} [y=0] - Vertical position of the *baseline* of the text. 40490 * @param {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. 40491 * @param {GlyphRenderOptions=} options 40492 */ 40493Font.prototype.drawPoints = function(ctx, text, x, y, fontSize, options) { 40494 this.forEachGlyph(text, x, y, fontSize, options, function(glyph, gX, gY, gFontSize) { 40495 glyph.drawPoints(ctx, gX, gY, gFontSize); 40496 }); 40497}; 40498 40499/** 40500 * Draw lines indicating important font measurements for all glyphs in the text. 40501 * Black lines indicate the origin of the coordinate system (point 0,0). 40502 * Blue lines indicate the glyph bounding box. 40503 * Green line indicates the advance width of the glyph. 40504 * @param {CanvasRenderingContext2D} ctx - A 2D drawing context, like Canvas. 40505 * @param {string} text - The text to create. 40506 * @param {number} [x=0] - Horizontal position of the beginning of the text. 40507 * @param {number} [y=0] - Vertical position of the *baseline* of the text. 40508 * @param {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. 40509 * @param {GlyphRenderOptions=} options 40510 */ 40511Font.prototype.drawMetrics = function(ctx, text, x, y, fontSize, options) { 40512 this.forEachGlyph(text, x, y, fontSize, options, function(glyph, gX, gY, gFontSize) { 40513 glyph.drawMetrics(ctx, gX, gY, gFontSize); 40514 }); 40515}; 40516 40517/** 40518 * @param {string} 40519 * @return {string} 40520 */ 40521Font.prototype.getEnglishName = function(name) { 40522 var translations = this.names[name]; 40523 if (translations) { 40524 return translations.en; 40525 } 40526}; 40527 40528/** 40529 * Validate 40530 */ 40531Font.prototype.validate = function() { 40532 var warnings = []; 40533 var _this = this; 40534 40535 function assert(predicate, message) { 40536 if (!predicate) { 40537 warnings.push(message); 40538 } 40539 } 40540 40541 function assertNamePresent(name) { 40542 var englishName = _this.getEnglishName(name); 40543 assert(englishName && englishName.trim().length > 0, 40544 'No English ' + name + ' specified.'); 40545 } 40546 40547 // Identification information 40548 assertNamePresent('fontFamily'); 40549 assertNamePresent('weightName'); 40550 assertNamePresent('manufacturer'); 40551 assertNamePresent('copyright'); 40552 assertNamePresent('version'); 40553 40554 // Dimension information 40555 assert(this.unitsPerEm > 0, 'No unitsPerEm specified.'); 40556}; 40557 40558/** 40559 * Convert the font object to a SFNT data structure. 40560 * This structure contains all the necessary tables and metadata to create a binary OTF file. 40561 * @return {opentype.Table} 40562 */ 40563Font.prototype.toTables = function() { 40564 return sfnt.fontToTable(this); 40565}; 40566/** 40567 * @deprecated Font.toBuffer is deprecated. Use Font.toArrayBuffer instead. 40568 */ 40569Font.prototype.toBuffer = function() { 40570 console.warn('Font.toBuffer is deprecated. Use Font.toArrayBuffer instead.'); 40571 return this.toArrayBuffer(); 40572}; 40573/** 40574 * Converts a `opentype.Font` into an `ArrayBuffer` 40575 * @return {ArrayBuffer} 40576 */ 40577Font.prototype.toArrayBuffer = function() { 40578 var sfntTable = this.toTables(); 40579 var bytes = sfntTable.encode(); 40580 var buffer = new ArrayBuffer(bytes.length); 40581 var intArray = new Uint8Array(buffer); 40582 for (var i = 0; i < bytes.length; i++) { 40583 intArray[i] = bytes[i]; 40584 } 40585 40586 return buffer; 40587}; 40588 40589/** 40590 * Initiate a download of the OpenType font. 40591 */ 40592Font.prototype.download = function(fileName) { 40593 var familyName = this.getEnglishName('fontFamily');
40594 var styleName = this.getEnglishName('fontSubfamily'); 40595 fileName = fileName || familyName.replace(/\s/g, '') + '-' + styleName + '.otf'; 40596 var arrayBuffer = this.toArrayBuffer(); 40597 40598 if (isBrowser()) { 40599 window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem; 40600 window.requestFileSystem(window.TEMPORARY, arrayBuffer.byteLength, function(fs) { 40601 fs.root.getFile(fileName, {create: true}, function(fileEntry) { 40602 fileEntry.createWriter(function(writer) { 40603 var dataView = new DataView(arrayBuffer); 40604 var blob = new Blob([dataView], {type: 'font/opentype'}); 40605 writer.write(blob); 40606 40607 writer.addEventListener('writeend', function() { 40608 // Navigating to the file will download it. 40609 location.href = fileEntry.toURL(); 40610 }, false); 40611 }); 40612 }); 40613 }, 40614 function(err) { 40615 throw new Error(err.name + ': ' + err.message); 40616 }); 40617 } else { 40618 var fs = _dereq_('fs'); 40619 var buffer = arrayBufferToNodeBuffer(arrayBuffer); 40620 fs.writeFileSync(fileName, buffer); 40621 } 40622}; 40623/** 40624 * @private 40625 */ 40626Font.prototype.fsSelectionValues = { 40627 ITALIC: 0x001, //1 40628 UNDERSCORE: 0x002, //2 40629 NEGATIVE: 0x004, //4 40630 OUTLINED: 0x008, //8 40631 STRIKEOUT: 0x010, //16 40632 BOLD: 0x020, //32 40633 REGULAR: 0x040, //64 40634 USER_TYPO_METRICS: 0x080, //128 40635 WWS: 0x100, //256 40636 OBLIQUE: 0x200 //512 40637}; 40638 40639/** 40640 * @private 40641 */ 40642Font.prototype.usWidthClasses = { 40643 ULTRA_CONDENSED: 1, 40644 EXTRA_CONDENSED: 2, 40645 CONDENSED: 3, 40646 SEMI_CONDENSED: 4, 40647 MEDIUM: 5, 40648 SEMI_EXPANDED: 6, 40649 EXPANDED: 7, 40650 EXTRA_EXPANDED: 8, 40651 ULTRA_EXPANDED: 9 40652}; 40653 40654/** 40655 * @private 40656 */ 40657Font.prototype.usWeightClasses = { 40658 THIN: 100, 40659 EXTRA_LIGHT: 200, 40660 LIGHT: 300, 40661 NORMAL: 400, 40662 MEDIUM: 500, 40663 SEMI_BOLD: 600, 40664 BOLD: 700, 40665 EXTRA_BOLD: 800, 40666 BLACK: 900 40667}; 40668 40669// The `fvar` table stores font variation axes and instances. 40670// https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6fvar.html 40671 40672function addName(name, names) { 40673 var nameString = JSON.stringify(name); 40674 var nameID = 256; 40675 for (var nameKey in names) { 40676 var n = parseInt(nameKey); 40677 if (!n || n < 256) { 40678 continue; 40679 } 40680 40681 if (JSON.stringify(names[nameKey]) === nameString) { 40682 return n; 40683 } 40684 40685 if (nameID <= n) { 40686 nameID = n + 1; 40687 } 40688 } 40689 40690 names[nameID] = name; 40691 return nameID; 40692} 40693 40694function makeFvarAxis(n, axis, names) { 40695 var nameID = addName(axis.name, names); 40696 return [ 40697 {name: 'tag_' + n, type: 'TAG', value: axis.tag}, 40698 {name: 'minValue_' + n, type: 'FIXED', value: axis.minValue << 16}, 40699 {name: 'defaultValue_' + n, type: 'FIXED', value: axis.defaultValue << 16}, 40700 {name: 'maxValue_' + n, type: 'FIXED', value: axis.maxValue << 16}, 40701 {name: 'flags_' + n, type: 'USHORT', value: 0}, 40702 {name: 'nameID_' + n, type: 'USHORT', value: nameID} 40703 ]; 40704} 40705 40706function parseFvarAxis(data, start, names) { 40707 var axis = {}; 40708 var p = new parse.Parser(data, start); 40709 axis.tag = p.parseTag(); 40710 axis.minValue = p.parseFixed(); 40711 axis.defaultValue = p.parseFixed(); 40712 axis.maxValue = p.parseFixed();
40713 p.skip('uShort', 1); // reserved for flags; no values defined 40714 axis.name = names[p.parseUShort()] || {}; 40715 return axis; 40716} 40717 40718function makeFvarInstance(n, inst, axes, names) { 40719 var nameID = addName(inst.name, names); 40720 var fields = [ 40721 {name: 'nameID_' + n, type: 'USHORT', value: nameID}, 40722 {name: 'flags_' + n, type: 'USHORT', value: 0} 40723 ]; 40724 40725 for (var i = 0; i < axes.length; ++i) { 40726 var axisTag = axes[i].tag; 40727 fields.push({ 40728 name: 'axis_' + n + ' ' + axisTag, 40729 type: 'FIXED', 40730 value: inst.coordinates[axisTag] << 16 40731 }); 40732 } 40733 40734 return fields; 40735} 40736 40737function parseFvarInstance(data, start, axes, names) { 40738 var inst = {}; 40739 var p = new parse.Parser(data, start); 40740 inst.name = names[p.parseUShort()] || {}; 40741 p.skip('uShort', 1); // reserved for flags; no values defined 40742 40743 inst.coordinates = {}; 40744 for (var i = 0; i < axes.length; ++i) { 40745 inst.coordinates[axes[i].tag] = p.parseFixed(); 40746 } 40747 40748 return inst; 40749} 40750 40751function makeFvarTable(fvar, names) { 40752 var result = new table.Table('fvar', [ 40753 {name: 'version', type: 'ULONG', value: 0x10000}, 40754 {name: 'offsetToData', type: 'USHORT', value: 0}, 40755 {name: 'countSizePairs', type: 'USHORT', value: 2}, 40756 {name: 'axisCount', type: 'USHORT', value: fvar.axes.length}, 40757 {name: 'axisSize', type: 'USHORT', value: 20}, 40758 {name: 'instanceCount', type: 'USHORT', value: fvar.instances.length}, 40759 {name: 'instanceSize', type: 'USHORT', value: 4 + fvar.axes.length * 4} 40760 ]); 40761 result.offsetToData = result.sizeOf(); 40762 40763 for (var i = 0; i < fvar.axes.length; i++) { 40764 result.fields = result.fields.concat(makeFvarAxis(i, fvar.axes[i], names)); 40765 } 40766 40767 for (var j = 0; j < fvar.instances.length; j++) { 40768 result.fields = result.fields.concat(makeFvarInstance(j, fvar.instances[j], fvar.axes, names)); 40769 } 40770 40771 return result; 40772} 40773 40774function parseFvarTable(data, start, names) { 40775 var p = new parse.Parser(data, start); 40776 var tableVersion = p.parseULong(); 40777 check.argument(tableVersion === 0x00010000, 'Unsupported fvar table version.'); 40778 var offsetToData = p.parseOffset16(); 40779 // Skip countSizePairs.
40780 p.skip('uShort', 1); 40781 var axisCount = p.parseUShort(); 40782 var axisSize = p.parseUShort(); 40783 var instanceCount = p.parseUShort(); 40784 var instanceSize = p.parseUShort(); 40785 40786 var axes = []; 40787 for (var i = 0; i < axisCount; i++) { 40788 axes.push(parseFvarAxis(data, start + offsetToData + i * axisSize, names)); 40789 } 40790 40791 var instances = []; 40792 var instanceStart = start + offsetToData + axisCount * axisSize; 40793 for (var j = 0; j < instanceCount; j++) { 40794 instances.push(parseFvarInstance(data, instanceStart + j * instanceSize, axes, names)); 40795 } 40796 40797 return {axes: axes, instances: instances}; 40798} 40799 40800var fvar = { make: makeFvarTable, parse: parseFvarTable }; 40801 40802// The `GPOS` table contains kerning pairs, among other things. 40803// https://www.microsoft.com/typography/OTSPEC/gpos.htm 40804 40805// Parse ScriptList and FeatureList tables of GPOS, GSUB, GDEF, BASE, JSTF tables. 40806// These lists are unused by now, this function is just the basis for a real parsing. 40807function parseTaggedListTable(data, start) { 40808 var p = new parse.Parser(data, start); 40809 var n = p.parseUShort(); 40810 var list = []; 40811 for (var i = 0; i < n; i++) { 40812 list[p.parseTag()] = { offset: p.parseUShort() }; 40813 } 40814 40815 return list; 40816} 40817 40818// Parse a coverage table in a GSUB, GPOS or GDEF table. 40819// Format 1 is a simple list of glyph ids, 40820// Format 2 is a list of ranges. It is expanded in a list of glyphs, maybe not the best idea. 40821function parseCoverageTable(data, start) { 40822 var p = new parse.Parser(data, start); 40823 var format = p.parseUShort(); 40824 var count = p.parseUShort(); 40825 if (format === 1) { 40826 return p.parseUShortList(count); 40827 } else if (format === 2) { 40828 var coverage = []; 40829 for (; count--;) { 40830 var begin = p.parseUShort(); 40831 var end = p.parseUShort(); 40832 var index = p.parseUShort(); 40833 for (var i = begin; i <= end; i++) { 40834 coverage[index++] = i; 40835 } 40836 } 40837 40838 return coverage; 40839 } 40840} 40841 40842// Parse a Class Definition Table in a GSUB, GPOS or GDEF table. 40843// Returns a function that gets a class value from a glyph ID. 40844function parseClassDefTable(data, start) { 40845 var p = new parse.Parser(data, start); 40846 var format = p.parseUShort(); 40847 if (format === 1) { 40848 // Format 1 specifies a range of consecutive glyph indices, one class per glyph ID. 40849 var startGlyph = p.parseUShort(); 40850 var glyphCount = p.parseUShort(); 40851 var classes = p.parseUShortList(glyphCount); 40852 return function(glyphID) { 40853 return classes[glyphID - startGlyph] || 0; 40854 }; 40855 } else if (format === 2) { 40856 // Format 2 defines multiple groups of glyph indices that belong to the same class. 40857 var rangeCount = p.parseUShort(); 40858 var startGlyphs = []; 40859 var endGlyphs = []; 40860 var classValues = []; 40861 for (var i = 0; i < rangeCount; i++) { 40862 startGlyphs[i] = p.parseUShort(); 40863 endGlyphs[i] = p.parseUShort(); 40864 classValues[i] = p.parseUShort(); 40865 } 40866 40867 return function(glyphID) { 40868 var l = 0; 40869 var r = startGlyphs.length - 1; 40870 while (l < r) { 40871 var c = (l + r + 1) >> 1; 40872 if (glyphID < startGlyphs[c]) { 40873 r = c - 1; 40874 } else { 40875 l = c; 40876 } 40877 } 40878 40879 if (startGlyphs[l] <= glyphID && glyphID <= endGlyphs[l]) { 40880 return classValues[l] || 0; 40881 } 40882 40883 return 0; 40884 }; 40885 } 40886} 40887 40888// Parse a pair adjustment positioning subtable, format 1 or format 2 40889// The subtable is returned in the form of a lookup function. 40890function parsePairPosSubTable(data, start) { 40891 var p = new parse.Parser(data, start); 40892 // This part is common to format 1 and format 2 subtables 40893 var format = p.parseUShort(); 40894 var coverageOffset = p.parseUShort(); 40895 var coverage = parseCoverageTable(data, start + coverageOffset); 40896 // valueFormat 4: XAdvance only, 1: XPlacement only, 0: no ValueRecord for second glyph 40897 // Only valueFormat1=4 and valueFormat2=0 is supported. 40898 var valueFormat1 = p.parseUShort(); 40899 var valueFormat2 = p.parseUShort(); 40900 var value1; 40901 var value2; 40902 if (valueFormat1 !== 4 || valueFormat2 !== 0) { return; } 40903 var sharedPairSets = {}; 40904 if (format === 1) { 40905 // Pair Positioning Adjustment: Format 1 40906 var pairSetCount = p.parseUShort(); 40907 var pairSet = []; 40908 // Array of offsets to PairSet tables-from beginning of PairPos subtable-ordered by Coverage Index 40909 var pairSetOffsets = p.parseOffset16List(pairSetCount); 40910 for (var firstGlyph = 0; firstGlyph < pairSetCount; firstGlyph++) { 40911 var pairSetOffset = pairSetOffsets[firstGlyph]; 40912 var sharedPairSet = sharedPairSets[pairSetOffset]; 40913 if (!sharedPairSet) { 40914 // Parse a pairset table in a pair adjustment subtable format 1 40915 sharedPairSet = {}; 40916 p.relativeOffset = pairSetOffset; 40917 var pairValueCount = p.parseUShort(); 40918 for (; pairValueCount--;) { 40919 var secondGlyph = p.parseUShort(); 40920 if (valueFormat1) { value1 = p.parseShort(); } 40921 if (valueFormat2) { value2 = p.parseShort(); } 40922 // We only support valueFormat1 = 4 and valueFormat2 = 0, 40923 // so value1 is the XAdvance and value2 is empty. 40924 sharedPairSet[secondGlyph] = value1; 40925 } 40926 } 40927 40928 pairSet[coverage[firstGlyph]] = sharedPairSet; 40929 } 40930 40931 return function(leftGlyph, rightGlyph) { 40932 var pairs = pairSet[leftGlyph]; 40933 if (pairs) { return pairs[rightGlyph]; } 40934 }; 40935 } else if (format === 2) { 40936 // Pair Positioning Adjustment: Format 2 40937 var classDef1Offset = p.parseUShort(); 40938 var classDef2Offset = p.parseUShort(); 40939 var class1Count = p.parseUShort();
40940 var class2Count = p.parseUShort(); 40941 var getClass1 = parseClassDefTable(data, start + classDef1Offset); 40942 var getClass2 = parseClassDefTable(data, start + classDef2Offset); 40943 40944 // Parse kerning values by class pair. 40945 var kerningMatrix = []; 40946 for (var i = 0; i < class1Count; i++) { 40947 var kerningRow = kerningMatrix[i] = []; 40948 for (var j = 0; j < class2Count; j++) { 40949 if (valueFormat1) { value1 = p.parseShort(); } 40950 if (valueFormat2) { value2 = p.parseShort(); } 40951 // We only support valueFormat1 = 4 and valueFormat2 = 0, 40952 // so value1 is the XAdvance and value2 is empty. 40953 kerningRow[j] = value1; 40954 } 40955 } 40956 40957 // Convert coverage list to a hash 40958 var covered = {}; 40959 for (var i$1 = 0; i$1 < coverage.length; i$1++) { 40960 covered[coverage[i$1]] = 1; 40961 } 40962 40963 // Get the kerning value for a specific glyph pair. 40964 return function(leftGlyph, rightGlyph) { 40965 if (!covered[leftGlyph]) { return; } 40966 var class1 = getClass1(leftGlyph); 40967 var class2 = getClass2(rightGlyph); 40968 var kerningRow = kerningMatrix[class1]; 40969 40970 if (kerningRow) { 40971 return kerningRow[class2]; 40972 } 40973 }; 40974 } 40975} 40976 40977// Parse a LookupTable (present in of GPOS, GSUB, GDEF, BASE, JSTF tables). 40978function parseLookupTable(data, start) { 40979 var p = new parse.Parser(data, start); 40980 var lookupType = p.parseUShort(); 40981 var lookupFlag = p.parseUShort(); 40982 var useMarkFilteringSet = lookupFlag & 0x10; 40983 var subTableCount = p.parseUShort(); 40984 var subTableOffsets = p.parseOffset16List(subTableCount); 40985 var table = { 40986 lookupType: lookupType, 40987 lookupFlag: lookupFlag, 40988 markFilteringSet: useMarkFilteringSet ? p.parseUShort() : -1 40989 }; 40990 // LookupType 2, Pair adjustment 40991 if (lookupType === 2) { 40992 var subtables = []; 40993 for (var i = 0; i < subTableCount; i++) { 40994 var pairPosSubTable = parsePairPosSubTable(data, start + subTableOffsets[i]); 40995 if (pairPosSubTable) { subtables.push(pairPosSubTable); } 40996 } 40997 // Return a function which finds the kerning values in the subtables. 40998 table.getKerningValue = function(leftGlyph, rightGlyph) { 40999 for (var i = subtables.length; i--;) { 41000 var value = subtables[i](leftGlyph, rightGlyph); 41001 if (value !== undefined) { return value; } 41002 } 41003 41004 return 0; 41005 }; 41006 } 41007 41008 return table; 41009} 41010 41011// Parse the `GPOS` table which contains, among other things, kerning pairs. 41012// https://www.microsoft.com/typography/OTSPEC/gpos.htm 41013function parseGposTable(data, start, font) { 41014 var p = new parse.Parser(data, start); 41015 var tableVersion = p.parseFixed(); 41016 check.argument(tableVersion === 1, 'Unsupported GPOS table version.'); 41017 41018 // ScriptList and FeatureList - ignored for now 41019 parseTaggedListTable(data, start + p.parseUShort()); 41020 // 'kern' is the feature we are looking for. 41021 parseTaggedListTable(data, start + p.parseUShort()); 41022 41023 // LookupList 41024 var lookupListOffset = p.parseUShort(); 41025 p.relativeOffset = lookupListOffset; 41026 var lookupCount = p.parseUShort(); 41027 var lookupTableOffsets = p.parseOffset16List(lookupCount); 41028 var lookupListAbsoluteOffset = start + lookupListOffset; 41029 for (var i = 0; i < lookupCount; i++) { 41030 var table = parseLookupTable(data, lookupListAbsoluteOffset + lookupTableOffsets[i]); 41031 if (table.lookupType === 2 && !font.getGposKerningValue) { font.getGposKerningValue = table.getKerningValue; } 41032 } 41033} 41034 41035var gpos = { parse: parseGposTable }; 41036 41037// The `kern` table contains kerning pairs. 41038// Note that some fonts use the GPOS OpenType layout table to specify kerning. 41039// https://www.microsoft.com/typography/OTSPEC/kern.htm 41040 41041function parseWindowsKernTable(p) { 41042 var pairs = {}; 41043 // Skip nTables. 41044 p.skip('uShort'); 41045 var subtableVersion = p.parseUShort(); 41046 check.argument(subtableVersion === 0, 'Unsupported kern sub-table version.'); 41047 // Skip subtableLength, subtableCoverage 41048 p.skip('uShort', 2); 41049 var nPairs = p.parseUShort();
vendor: 4,149 bytes, lines 41050-41165
41050 // Skip searchRange, entrySelector, rangeShift. 41051 p.skip('uShort', 3); 41052 for (var i = 0; i < nPairs; i += 1) { 41053 var leftIndex = p.parseUShort(); 41054 var rightIndex = p.parseUShort(); 41055 var value = p.parseShort(); 41056 pairs[leftIndex + ',' + rightIndex] = value; 41057 } 41058 return pairs; 41059} 41060 41061function parseMacKernTable(p) { 41062 var pairs = {}; 41063 // The Mac kern table stores the version as a fixed (32 bits) but we only loaded the first 16 bits. 41064 // Skip the rest. 41065 p.skip('uShort'); 41066 var nTables = p.parseULong(); 41067 //check.argument(nTables === 1, 'Only 1 subtable is supported (got ' + nTables + ').'); 41068 if (nTables > 1) { 41069 console.warn('Only the first kern subtable is supported.'); 41070 } 41071 p.skip('uLong'); 41072 var coverage = p.parseUShort(); 41073 var subtableVersion = coverage & 0xFF; 41074 p.skip('uShort'); 41075 if (subtableVersion === 0) { 41076 var nPairs = p.parseUShort(); 41077 // Skip searchRange, entrySelector, rangeShift. 41078 p.skip('uShort', 3); 41079 for (var i = 0; i < nPairs; i += 1) { 41080 var leftIndex = p.parseUShort(); 41081 var rightIndex = p.parseUShort(); 41082 var value = p.parseShort(); 41083 pairs[leftIndex + ',' + rightIndex] = value; 41084 } 41085 } 41086 return pairs; 41087} 41088 41089// Parse the `kern` table which contains kerning pairs. 41090function parseKernTable(data, start) { 41091 var p = new parse.Parser(data, start); 41092 var tableVersion = p.parseUShort(); 41093 if (tableVersion === 0) { 41094 return parseWindowsKernTable(p); 41095 } else if (tableVersion === 1) { 41096 return parseMacKernTable(p); 41097 } else { 41098 throw new Error('Unsupported kern table version (' + tableVersion + ').'); 41099 } 41100} 41101 41102var kern = { parse: parseKernTable }; 41103 41104// The `loca` table stores the offsets to the locations of the glyphs in the font. 41105// https://www.microsoft.com/typography/OTSPEC/loca.htm 41106 41107// Parse the `loca` table. This table stores the offsets to the locations of the glyphs in the font, 41108// relative to the beginning of the glyphData table. 41109// The number of glyphs stored in the `loca` table is specified in the `maxp` table (under numGlyphs) 41110// The loca table has two versions: a short version where offsets are stored as uShorts, and a long 41111// version where offsets are stored as uLongs. The `head` table specifies which version to use 41112// (under indexToLocFormat). 41113function parseLocaTable(data, start, numGlyphs, shortVersion) { 41114 var p = new parse.Parser(data, start); 41115 var parseFn = shortVersion ? p.parseUShort : p.parseULong; 41116 // There is an extra entry after the last index element to compute the length of the last glyph. 41117 // That's why we use numGlyphs + 1. 41118 var glyphOffsets = []; 41119 for (var i = 0; i < numGlyphs + 1; i += 1) { 41120 var glyphOffset = parseFn.call(p); 41121 if (shortVersion) { 41122 // The short table version stores the actual offset divided by 2. 41123 glyphOffset *= 2; 41124 } 41125 41126 glyphOffsets.push(glyphOffset); 41127 } 41128 41129 return glyphOffsets; 41130} 41131 41132var loca = { parse: parseLocaTable }; 41133 41134// opentype.js 41135// https://github.com/nodebox/opentype.js 41136// (c) 2015 Frederik De Bleser 41137// opentype.js may be freely distributed under the MIT license. 41138 41139/* global DataView, Uint8Array, XMLHttpRequest */ 41140 41141/** 41142 * The opentype library. 41143 * @namespace opentype 41144 */ 41145 41146// File loaders ///////////////////////////////////////////////////////// 41147/** 41148 * Loads a font from a file. The callback throws an error message as the first parameter if it fails 41149 * and the font as an ArrayBuffer in the second parameter if it succeeds. 41150 * @param {string} path - The path of the file 41151 * @param {Function} callback - The function to call when the font load completes 41152 */ 41153function loadFromFile(path, callback) { 41154 var fs = _dereq_('fs'); 41155 fs.readFile(path, function(err, buffer) { 41156 if (err) { 41157 return callback(err.message); 41158 } 41159 41160 callback(null, nodeBufferToArrayBuffer(buffer)); 41161 }); 41162} 41163/** 41164 * Loads a font from a URL. The callback throws an error message as the first parameter if it fails 41165 * and the font as an ArrayBuffer in the second parameter if it succeeds.
41166 * @param {string} url - The URL of the font file. 41167 * @param {Function} callback - The function to call when the font load completes 41168 */ 41169function loadFromUrl(url, callback) { 41170 var request = new XMLHttpRequest(); 41171 request.open('get', url, true); 41172 request.responseType = 'arraybuffer'; 41173 request.onload = function() { 41174 if (request.status !== 200) { 41175 return callback('Font could not be loaded: ' + request.statusText); 41176 } 41177 41178 return callback(null, request.response); 41179 }; 41180 41181 request.onerror = function () { 41182 callback('Font could not be loaded'); 41183 }; 41184 41185 request.send(); 41186} 41187 41188// Table Directory Entries ////////////////////////////////////////////// 41189/** 41190 * Parses OpenType table entries. 41191 * @param {DataView} 41192 * @param {Number} 41193 * @return {Object[]} 41194 */ 41195function parseOpenTypeTableEntries(data, numTables) { 41196 var tableEntries = []; 41197 var p = 12; 41198 for (var i = 0; i < numTables; i += 1) { 41199 var tag = parse.getTag(data, p); 41200 var checksum = parse.getULong(data, p + 4); 41201 var offset = parse.getULong(data, p + 8); 41202 var length = parse.getULong(data, p + 12); 41203 tableEntries.push({tag: tag, checksum: checksum, offset: offset, length: length, compression: false}); 41204 p += 16; 41205 } 41206 41207 return tableEntries; 41208} 41209 41210/** 41211 * Parses WOFF table entries. 41212 * @param {DataView} 41213 * @param {Number} 41214 * @return {Object[]} 41215 */ 41216function parseWOFFTableEntries(data, numTables) { 41217 var tableEntries = []; 41218 var p = 44; // offset to the first table directory entry. 41219 for (var i = 0; i < numTables; i += 1) { 41220 var tag = parse.getTag(data, p); 41221 var offset = parse.getULong(data, p + 4); 41222 var compLength = parse.getULong(data, p + 8); 41223 var origLength = parse.getULong(data, p + 12); 41224 var compression = (void 0); 41225 if (compLength < origLength) { 41226 compression = 'WOFF'; 41227 } else { 41228 compression = false; 41229 } 41230 41231 tableEntries.push({tag: tag, offset: offset, compression: compression, 41232 compressedLength: compLength, length: origLength}); 41233 p += 20; 41234 } 41235 41236 return tableEntries; 41237} 41238 41239/** 41240 * @typedef TableData 41241 * @type Object 41242 * @property {DataView} data - The DataView 41243 * @property {number} offset - The data offset. 41244 */ 41245 41246/** 41247 * @param {DataView} 41248 * @param {Object} 41249 * @return {TableData} 41250 */ 41251function uncompressTable(data, tableEntry) { 41252 if (tableEntry.compression === 'WOFF') { 41253 var inBuffer = new Uint8Array(data.buffer, tableEntry.offset + 2, tableEntry.compressedLength - 2); 41254 var outBuffer = new Uint8Array(tableEntry.length); 41255 index(inBuffer, outBuffer); 41256 if (outBuffer.byteLength !== tableEntry.length) { 41257 throw new Error('Decompression error: ' + tableEntry.tag + ' decompressed length doesn\'t match recorded length'); 41258 } 41259 41260 var view = new DataView(outBuffer.buffer, 0); 41261 return {data: view, offset: 0}; 41262 } else { 41263 return {data: data, offset: tableEntry.offset}; 41264 } 41265} 41266 41267// Public API /////////////////////////////////////////////////////////// 41268 41269/** 41270 * Parse the OpenType file data (as an ArrayBuffer) and return a Font object. 41271 * Throws an error if the font could not be parsed. 41272 * @param {ArrayBuffer} 41273 * @return {opentype.Font} 41274 */ 41275function parseBuffer(buffer) { 41276 var indexToLocFormat; 41277 var ltagTable; 41278 41279 // Since the constructor can also be called to create new fonts from scratch, we indicate this 41280 // should be an empty font that we'll fill with our own data. 41281 var font = new Font({empty: true}); 41282 41283 // OpenType fonts use big endian byte ordering. 41284 // We can't rely on typed array view types, because they operate with the endianness of the host computer. 41285 // Instead we use DataViews where we can specify endianness. 41286 var data = new DataView(buffer, 0); 41287 var numTables; 41288 var tableEntries = []; 41289 var signature = parse.getTag(data, 0); 41290 if (signature === String.fromCharCode(0, 1, 0, 0) || signature === 'true' || signature === 'typ1') { 41291 font.outlinesFormat = 'truetype'; 41292 numTables = parse.getUShort(data, 4); 41293 tableEntries = parseOpenTypeTableEntries(data, numTables); 41294 } else if (signature === 'OTTO') { 41295 font.outlinesFormat = 'cff'; 41296 numTables = parse.getUShort(data, 4); 41297 tableEntries = parseOpenTypeTableEntries(data, numTables); 41298 } else if (signature === 'wOFF') { 41299 var flavor = parse.getTag(data, 4); 41300 if (flavor === String.fromCharCode(0, 1, 0, 0)) { 41301 font.outlinesFormat = 'truetype'; 41302 } else if (flavor === 'OTTO') { 41303 font.outlinesFormat = 'cff'; 41304 } else { 41305 throw new Error('Unsupported OpenType flavor ' + signature); 41306 } 41307 41308 numTables = parse.getUShort(data, 12); 41309 tableEntries = parseWOFFTableEntries(data, numTables); 41310 } else { 41311 throw new Error('Unsupported OpenType signature ' + signature); 41312 } 41313 41314 var cffTableEntry; 41315 var fvarTableEntry; 41316 var glyfTableEntry; 41317 var gposTableEntry; 41318 var gsubTableEntry; 41319 var hmtxTableEntry; 41320 var kernTableEntry; 41321 var locaTableEntry; 41322 var nameTableEntry; 41323 var metaTableEntry; 41324 var p; 41325 41326 for (var i = 0; i < numTables; i += 1) { 41327 var tableEntry = tableEntries[i]; 41328 var table = (void 0); 41329 switch (tableEntry.tag) { 41330 case 'cmap':
vendor: 4,048 bytes, lines 41331-41424
41331 table = uncompressTable(data, tableEntry); 41332 font.tables.cmap = cmap.parse(table.data, table.offset); 41333 font.encoding = new CmapEncoding(font.tables.cmap); 41334 break; 41335 case 'cvt ' : 41336 table = uncompressTable(data, tableEntry); 41337 p = new parse.Parser(table.data, table.offset); 41338 font.tables.cvt = p.parseShortList(tableEntry.length / 2); 41339 break; 41340 case 'fvar': 41341 fvarTableEntry = tableEntry; 41342 break; 41343 case 'fpgm' : 41344 table = uncompressTable(data, tableEntry); 41345 p = new parse.Parser(table.data, table.offset); 41346 font.tables.fpgm = p.parseByteList(tableEntry.length); 41347 break; 41348 case 'head': 41349 table = uncompressTable(data, tableEntry); 41350 font.tables.head = head.parse(table.data, table.offset); 41351 font.unitsPerEm = font.tables.head.unitsPerEm; 41352 indexToLocFormat = font.tables.head.indexToLocFormat; 41353 break; 41354 case 'hhea': 41355 table = uncompressTable(data, tableEntry); 41356 font.tables.hhea = hhea.parse(table.data, table.offset); 41357 font.ascender = font.tables.hhea.ascender; 41358 font.descender = font.tables.hhea.descender; 41359 font.numberOfHMetrics = font.tables.hhea.numberOfHMetrics; 41360 break; 41361 case 'hmtx': 41362 hmtxTableEntry = tableEntry; 41363 break; 41364 case 'ltag': 41365 table = uncompressTable(data, tableEntry); 41366 ltagTable = ltag.parse(table.data, table.offset); 41367 break; 41368 case 'maxp': 41369 table = uncompressTable(data, tableEntry); 41370 font.tables.maxp = maxp.parse(table.data, table.offset); 41371 font.numGlyphs = font.tables.maxp.numGlyphs; 41372 break; 41373 case 'name': 41374 nameTableEntry = tableEntry; 41375 break; 41376 case 'OS/2': 41377 table = uncompressTable(data, tableEntry); 41378 font.tables.os2 = os2.parse(table.data, table.offset); 41379 break; 41380 case 'post': 41381 table = uncompressTable(data, tableEntry); 41382 font.tables.post = post.parse(table.data, table.offset); 41383 font.glyphNames = new GlyphNames(font.tables.post); 41384 break; 41385 case 'prep' : 41386 table = uncompressTable(data, tableEntry); 41387 p = new parse.Parser(table.data, table.offset); 41388 font.tables.prep = p.parseByteList(tableEntry.length); 41389 break; 41390 case 'glyf': 41391 glyfTableEntry = tableEntry; 41392 break; 41393 case 'loca': 41394 locaTableEntry = tableEntry; 41395 break; 41396 case 'CFF ': 41397 cffTableEntry = tableEntry; 41398 break; 41399 case 'kern': 41400 kernTableEntry = tableEntry; 41401 break; 41402 case 'GPOS': 41403 gposTableEntry = tableEntry; 41404 break; 41405 case 'GSUB': 41406 gsubTableEntry = tableEntry; 41407 break; 41408 case 'meta': 41409 metaTableEntry = tableEntry; 41410 break; 41411 } 41412 } 41413 41414 var nameTable = uncompressTable(data, nameTableEntry); 41415 font.tables.name = _name.parse(nameTable.data, nameTable.offset, ltagTable); 41416 font.names = font.tables.name; 41417 41418 if (glyfTableEntry && locaTableEntry) { 41419 var shortVersion = indexToLocFormat === 0; 41420 var locaTable = uncompressTable(data, locaTableEntry); 41421 var locaOffsets = loca.parse(locaTable.data, locaTable.offset, font.numGlyphs, shortVersion); 41422 var glyfTable = uncompressTable(data, glyfTableEntry); 41423 font.glyphs = glyf.parse(glyfTable.data, glyfTable.offset, locaOffsets, font); 41424 } else if (cffTableEntry) {
41425 var cffTable = uncompressTable(data, cffTableEntry); 41426 cff.parse(cffTable.data, cffTable.offset, font); 41427 } else { 41428 throw new Error('Font doesn\'t contain TrueType or CFF outlines.'); 41429 } 41430 41431 var hmtxTable = uncompressTable(data, hmtxTableEntry); 41432 hmtx.parse(hmtxTable.data, hmtxTable.offset, font.numberOfHMetrics, font.numGlyphs, font.glyphs); 41433 addGlyphNames(font); 41434 41435 if (kernTableEntry) { 41436 var kernTable = uncompressTable(data, kernTableEntry); 41437 font.kerningPairs = kern.parse(kernTable.data, kernTable.offset); 41438 } else { 41439 font.kerningPairs = {}; 41440 } 41441 41442 if (gposTableEntry) { 41443 var gposTable = uncompressTable(data, gposTableEntry); 41444 gpos.parse(gposTable.data, gposTable.offset, font); 41445 } 41446 41447 if (gsubTableEntry) { 41448 var gsubTable = uncompressTable(data, gsubTableEntry); 41449 font.tables.gsub = gsub.parse(gsubTable.data, gsubTable.offset); 41450 } 41451 41452 if (fvarTableEntry) { 41453 var fvarTable = uncompressTable(data, fvarTableEntry); 41454 font.tables.fvar = fvar.parse(fvarTable.data, fvarTable.offset, font.names); 41455 } 41456 41457 if (metaTableEntry) { 41458 var metaTable = uncompressTable(data, metaTableEntry); 41459 font.tables.meta = meta.parse(metaTable.data, metaTable.offset); 41460 font.metas = font.tables.meta; 41461 } 41462 41463 return font; 41464} 41465 41466/** 41467 * Asynchronously load the font from a URL or a filesystem. When done, call the callback 41468 * with two arguments `(err, font)`. The `err` will be null on success, 41469 * the `font` is a Font object. 41470 * We use the node.js callback convention so that 41471 * opentype.js can integrate with frameworks like async.js. 41472 * @alias opentype.load 41473 * @param {string} url - The URL of the font to load. 41474 * @param {Function} callback - The callback. 41475 */ 41476function load(url, callback) { 41477 var isNode$$1 = typeof window === 'undefined'; 41478 var loadFn = isNode$$1 ? loadFromFile : loadFromUrl; 41479 loadFn(url, function(err, arrayBuffer) { 41480 if (err) { 41481 return callback(err); 41482 } 41483 var font; 41484 try { 41485 font = parseBuffer(arrayBuffer); 41486 } catch (e) { 41487 return callback(e, null); 41488 } 41489 return callback(null, font); 41490 }); 41491} 41492 41493/** 41494 * Synchronously load the font from a URL or file. 41495 * When done, returns the font object or throws an error. 41496 * @alias opentype.loadSync 41497 * @param {string} url - The URL of the font to load. 41498 * @return {opentype.Font} 41499 */ 41500function loadSync(url) { 41501 var fs = _dereq_('fs'); 41502 var buffer = fs.readFileSync(url); 41503 return parseBuffer(nodeBufferToArrayBuffer(buffer)); 41504} 41505 41506exports.Font = Font; 41507exports.Glyph = Glyph; 41508exports.Path = Path; 41509exports.BoundingBox = BoundingBox; 41510exports._parse = parse; 41511exports.parse = parseBuffer; 41512exports.load = load; 41513exports.loadSync = loadSync; 41514 41515Object.defineProperty(exports, '__esModule', { value: true }); 41516 41517}))); 41518 41519 41520}).call(this,_dereq_("buffer").Buffer) 41521},{"buffer":4,"fs":3}],11:[function(_dereq_,module,exports){ 41522// shim for using process in browser 41523var process = module.exports = {}; 41524 41525// cached from whatever global is present so that test runners that stub it 41526// don't break things. But we need to wrap it in a try catch in case it is 41527// wrapped in strict mode code which doesn't define any globals. It's inside a 41528// function because try/catches deoptimize in certain engines. 41529 41530var cachedSetTimeout; 41531var cachedClearTimeout; 41532 41533function defaultSetTimout() { 41534 throw new Error('setTimeout has not been defined'); 41535} 41536function defaultClearTimeout () { 41537 throw new Error('clearTimeout has not been defined'); 41538} 41539(function () { 41540 try { 41541 if (typeof setTimeout === 'function') { 41542 cachedSetTimeout = setTimeout; 41543 } else { 41544 cachedSetTimeout = defaultSetTimout; 41545 } 41546 } catch (e) { 41547 cachedSetTimeout = defaultSetTimout; 41548 } 41549 try { 41550 if (typeof clearTimeout === 'function') { 41551 cachedClearTimeout = clearTimeout; 41552 } else { 41553 cachedClearTimeout = defaultClearTimeout; 41554 } 41555 } catch (e) { 41556 cachedClearTimeout = defaultClearTimeout; 41557 } 41558} ()) 41559function runTimeout(fun) { 41560 if (cachedSetTimeout === setTimeout) { 41561 //normal enviroments in sane situations 41562 return setTimeout(fun, 0); 41563 } 41564 // if setTimeout wasn't available but was latter defined 41565 if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { 41566 cachedSetTimeout = setTimeout; 41567 return setTimeout(fun, 0); 41568 } 41569 try { 41570 // when when somebody has screwed with setTimeout but no I.E. maddness 41571 return cachedSetTimeout(fun, 0); 41572 } catch(e){ 41573 try { 41574 // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally 41575 return cachedSetTimeout.call(null, fun, 0); 41576 } catch(e){ 41577 // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error 41578 return cachedSetTimeout.call(this, fun, 0); 41579 } 41580 } 41581 41582 41583} 41584function runClearTimeout(marker) { 41585 if (cachedClearTimeout === clearTimeout) { 41586 //normal enviroments in sane situations 41587 return clearTimeout(marker); 41588 } 41589 // if clearTimeout wasn't available but was latter defined 41590 if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { 41591 cachedClearTimeout = clearTimeout; 41592 return clearTimeout(marker); 41593 } 41594 try { 41595 // when when somebody has screwed with setTimeout but no I.E. maddness 41596 return cachedClearTimeout(marker); 41597 } catch (e){ 41598 try { 41599 // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally 41600 return cachedClearTimeout.call(null, marker); 41601 } catch (e){ 41602 // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. 41603 // Some versions of I.E. have different rules for clearTimeout vs setTimeout 41604 return cachedClearTimeout.call(this, marker); 41605 } 41606 } 41607 41608 41609 41610} 41611var queue = []; 41612var draining = false;
vendor: 14,572 bytes, lines 41613-42159
41613var currentQueue; 41614var queueIndex = -1; 41615 41616function cleanUpNextTick() { 41617 if (!draining || !currentQueue) { 41618 return; 41619 } 41620 draining = false; 41621 if (currentQueue.length) { 41622 queue = currentQueue.concat(queue); 41623 } else { 41624 queueIndex = -1; 41625 } 41626 if (queue.length) { 41627 drainQueue(); 41628 } 41629} 41630 41631function drainQueue() { 41632 if (draining) { 41633 return; 41634 } 41635 var timeout = runTimeout(cleanUpNextTick); 41636 draining = true; 41637 41638 var len = queue.length; 41639 while(len) { 41640 currentQueue = queue; 41641 queue = []; 41642 while (++queueIndex < len) { 41643 if (currentQueue) { 41644 currentQueue[queueIndex].run(); 41645 } 41646 } 41647 queueIndex = -1; 41648 len = queue.length; 41649 } 41650 currentQueue = null; 41651 draining = false; 41652 runClearTimeout(timeout); 41653} 41654 41655process.nextTick = function (fun) { 41656 var args = new Array(arguments.length - 1); 41657 if (arguments.length > 1) { 41658 for (var i = 1; i < arguments.length; i++) { 41659 args[i - 1] = arguments[i]; 41660 } 41661 } 41662 queue.push(new Item(fun, args)); 41663 if (queue.length === 1 && !draining) { 41664 runTimeout(drainQueue); 41665 } 41666}; 41667 41668// v8 likes predictible objects 41669function Item(fun, array) { 41670 this.fun = fun; 41671 this.array = array; 41672} 41673Item.prototype.run = function () { 41674 this.fun.apply(null, this.array); 41675}; 41676process.title = 'browser'; 41677process.browser = true; 41678process.env = {}; 41679process.argv = []; 41680process.version = ''; // empty string to avoid regexp issues 41681process.versions = {}; 41682 41683function noop() {} 41684 41685process.on = noop; 41686process.addListener = noop; 41687process.once = noop; 41688process.off = noop; 41689process.removeListener = noop; 41690process.removeAllListeners = noop; 41691process.emit = noop; 41692process.prependListener = noop; 41693process.prependOnceListener = noop; 41694 41695process.listeners = function (name) { return [] } 41696 41697process.binding = function (name) { 41698 throw new Error('process.binding is not supported'); 41699}; 41700 41701process.cwd = function () { return '/' }; 41702process.chdir = function (dir) { 41703 throw new Error('process.chdir is not supported'); 41704}; 41705process.umask = function() { return 0; }; 41706 41707},{}],12:[function(_dereq_,module,exports){ 41708(function(self) { 41709 'use strict'; 41710 41711 if (self.fetch) { 41712 return 41713 } 41714 41715 var support = { 41716 searchParams: 'URLSearchParams' in self, 41717 iterable: 'Symbol' in self && 'iterator' in Symbol, 41718 blob: 'FileReader' in self && 'Blob' in self && (function() { 41719 try { 41720 new Blob() 41721 return true 41722 } catch(e) { 41723 return false 41724 } 41725 })(), 41726 formData: 'FormData' in self, 41727 arrayBuffer: 'ArrayBuffer' in self 41728 } 41729 41730 if (support.arrayBuffer) { 41731 var viewClasses = [ 41732 '[object Int8Array]', 41733 '[object Uint8Array]', 41734 '[object Uint8ClampedArray]', 41735 '[object Int16Array]', 41736 '[object Uint16Array]', 41737 '[object Int32Array]', 41738 '[object Uint32Array]', 41739 '[object Float32Array]', 41740 '[object Float64Array]' 41741 ] 41742 41743 var isDataView = function(obj) { 41744 return obj && DataView.prototype.isPrototypeOf(obj) 41745 } 41746 41747 var isArrayBufferView = ArrayBuffer.isView || function(obj) { 41748 return obj && viewClasses.indexOf(Object.prototype.toString.call(obj)) > -1 41749 } 41750 } 41751 41752 function normalizeName(name) { 41753 if (typeof name !== 'string') { 41754 name = String(name) 41755 } 41756 if (/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(name)) { 41757 throw new TypeError('Invalid character in header field name') 41758 } 41759 return name.toLowerCase() 41760 } 41761 41762 function normalizeValue(value) { 41763 if (typeof value !== 'string') { 41764 value = String(value) 41765 } 41766 return value 41767 } 41768 41769 // Build a destructive iterator for the value list 41770 function iteratorFor(items) { 41771 var iterator = { 41772 next: function() { 41773 var value = items.shift() 41774 return {done: value === undefined, value: value} 41775 } 41776 } 41777 41778 if (support.iterable) { 41779 iterator[Symbol.iterator] = function() { 41780 return iterator 41781 } 41782 } 41783 41784 return iterator 41785 } 41786 41787 function Headers(headers) { 41788 this.map = {} 41789 41790 if (headers instanceof Headers) { 41791 headers.forEach(function(value, name) { 41792 this.append(name, value) 41793 }, this) 41794 } else if (Array.isArray(headers)) { 41795 headers.forEach(function(header) { 41796 this.append(header[0], header[1]) 41797 }, this) 41798 } else if (headers) { 41799 Object.getOwnPropertyNames(headers).forEach(function(name) { 41800 this.append(name, headers[name]) 41801 }, this) 41802 } 41803 } 41804 41805 Headers.prototype.append = function(name, value) { 41806 name = normalizeName(name) 41807 value = normalizeValue(value) 41808 var oldValue = this.map[name] 41809 this.map[name] = oldValue ? oldValue+','+value : value 41810 } 41811 41812 Headers.prototype['delete'] = function(name) { 41813 delete this.map[normalizeName(name)] 41814 } 41815 41816 Headers.prototype.get = function(name) { 41817 name = normalizeName(name) 41818 return this.has(name) ? this.map[name] : null 41819 } 41820 41821 Headers.prototype.has = function(name) { 41822 return this.map.hasOwnProperty(normalizeName(name)) 41823 } 41824 41825 Headers.prototype.set = function(name, value) { 41826 this.map[normalizeName(name)] = normalizeValue(value) 41827 } 41828 41829 Headers.prototype.forEach = function(callback, thisArg) { 41830 for (var name in this.map) { 41831 if (this.map.hasOwnProperty(name)) { 41832 callback.call(thisArg, this.map[name], name, this) 41833 } 41834 } 41835 } 41836 41837 Headers.prototype.keys = function() { 41838 var items = [] 41839 this.forEach(function(value, name) { items.push(name) }) 41840 return iteratorFor(items) 41841 } 41842 41843 Headers.prototype.values = function() { 41844 var items = [] 41845 this.forEach(function(value) { items.push(value) }) 41846 return iteratorFor(items) 41847 } 41848 41849 Headers.prototype.entries = function() { 41850 var items = [] 41851 this.forEach(function(value, name) { items.push([name, value]) }) 41852 return iteratorFor(items) 41853 } 41854 41855 if (support.iterable) { 41856 Headers.prototype[Symbol.iterator] = Headers.prototype.entries 41857 } 41858 41859 function consumed(body) { 41860 if (body.bodyUsed) { 41861 return Promise.reject(new TypeError('Already read')) 41862 } 41863 body.bodyUsed = true 41864 } 41865 41866 function fileReaderReady(reader) { 41867 return new Promise(function(resolve, reject) { 41868 reader.onload = function() { 41869 resolve(reader.result) 41870 } 41871 reader.onerror = function() { 41872 reject(reader.error) 41873 } 41874 }) 41875 } 41876 41877 function readBlobAsArrayBuffer(blob) { 41878 var reader = new FileReader() 41879 var promise = fileReaderReady(reader) 41880 reader.readAsArrayBuffer(blob) 41881 return promise 41882 } 41883 41884 function readBlobAsText(blob) { 41885 var reader = new FileReader() 41886 var promise = fileReaderReady(reader) 41887 reader.readAsText(blob) 41888 return promise 41889 } 41890 41891 function readArrayBufferAsText(buf) { 41892 var view = new Uint8Array(buf) 41893 var chars = new Array(view.length) 41894 41895 for (var i = 0; i < view.length; i++) { 41896 chars[i] = String.fromCharCode(view[i]) 41897 } 41898 return chars.join('') 41899 } 41900 41901 function bufferClone(buf) { 41902 if (buf.slice) { 41903 return buf.slice(0) 41904 } else { 41905 var view = new Uint8Array(buf.byteLength) 41906 view.set(new Uint8Array(buf)) 41907 return view.buffer 41908 } 41909 } 41910 41911 function Body() { 41912 this.bodyUsed = false 41913 41914 this._initBody = function(body) { 41915 this._bodyInit = body 41916 if (!body) { 41917 this._bodyText = '' 41918 } else if (typeof body === 'string') { 41919 this._bodyText = body 41920 } else if (support.blob && Blob.prototype.isPrototypeOf(body)) { 41921 this._bodyBlob = body 41922 } else if (support.formData && FormData.prototype.isPrototypeOf(body)) { 41923 this._bodyFormData = body 41924 } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) { 41925 this._bodyText = body.toString() 41926 } else if (support.arrayBuffer && support.blob && isDataView(body)) { 41927 this._bodyArrayBuffer = bufferClone(body.buffer) 41928 // IE 10-11 can't handle a DataView body. 41929 this._bodyInit = new Blob([this._bodyArrayBuffer]) 41930 } else if (support.arrayBuffer && (ArrayBuffer.prototype.isPrototypeOf(body) || isArrayBufferView(body))) { 41931 this._bodyArrayBuffer = bufferClone(body) 41932 } else { 41933 throw new Error('unsupported BodyInit type') 41934 } 41935 41936 if (!this.headers.get('content-type')) { 41937 if (typeof body === 'string') { 41938 this.headers.set('content-type', 'text/plain;charset=UTF-8') 41939 } else if (this._bodyBlob && this._bodyBlob.type) { 41940 this.headers.set('content-type', this._bodyBlob.type) 41941 } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) { 41942 this.headers.set('content-type', 'application/x-www-form-urlencoded;charset=UTF-8') 41943 } 41944 } 41945 } 41946 41947 if (support.blob) { 41948 this.blob = function() { 41949 var rejected = consumed(this) 41950 if (rejected) { 41951 return rejected 41952 } 41953 41954 if (this._bodyBlob) { 41955 return Promise.resolve(this._bodyBlob) 41956 } else if (this._bodyArrayBuffer) { 41957 return Promise.resolve(new Blob([this._bodyArrayBuffer])) 41958 } else if (this._bodyFormData) { 41959 throw new Error('could not read FormData body as blob') 41960 } else { 41961 return Promise.resolve(new Blob([this._bodyText])) 41962 } 41963 } 41964 41965 this.arrayBuffer = function() { 41966 if (this._bodyArrayBuffer) { 41967 return consumed(this) || Promise.resolve(this._bodyArrayBuffer) 41968 } else { 41969 return this.blob().then(readBlobAsArrayBuffer) 41970 } 41971 } 41972 } 41973 41974 this.text = function() { 41975 var rejected = consumed(this) 41976 if (rejected) { 41977 return rejected 41978 } 41979 41980 if (this._bodyBlob) { 41981 return readBlobAsText(this._bodyBlob) 41982 } else if (this._bodyArrayBuffer) { 41983 return Promise.resolve(readArrayBufferAsText(this._bodyArrayBuffer)) 41984 } else if (this._bodyFormData) { 41985 throw new Error('could not read FormData body as text') 41986 } else { 41987 return Promise.resolve(this._bodyText) 41988 } 41989 } 41990 41991 if (support.formData) { 41992 this.formData = function() { 41993 return this.text().then(decode) 41994 } 41995 } 41996 41997 this.json = function() { 41998 return this.text().then(JSON.parse) 41999 } 42000 42001 return this 42002 } 42003 42004 // HTTP methods whose capitalization should be normalized 42005 var methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT'] 42006 42007 function normalizeMethod(method) { 42008 var upcased = method.toUpperCase() 42009 return (methods.indexOf(upcased) > -1) ? upcased : method 42010 } 42011 42012 function Request(input, options) { 42013 options = options || {} 42014 var body = options.body 42015 42016 if (input instanceof Request) { 42017 if (input.bodyUsed) { 42018 throw new TypeError('Already read') 42019 } 42020 this.url = input.url 42021 this.credentials = input.credentials 42022 if (!options.headers) { 42023 this.headers = new Headers(input.headers) 42024 } 42025 this.method = input.method 42026 this.mode = input.mode 42027 if (!body && input._bodyInit != null) { 42028 body = input._bodyInit 42029 input.bodyUsed = true 42030 } 42031 } else { 42032 this.url = String(input) 42033 } 42034 42035 this.credentials = options.credentials || this.credentials || 'omit' 42036 if (options.headers || !this.headers) { 42037 this.headers = new Headers(options.headers) 42038 } 42039 this.method = normalizeMethod(options.method || this.method || 'GET') 42040 this.mode = options.mode || this.mode || null 42041 this.referrer = null 42042 42043 if ((this.method === 'GET' || this.method === 'HEAD') && body) { 42044 throw new TypeError('Body not allowed for GET or HEAD requests') 42045 } 42046 this._initBody(body) 42047 } 42048 42049 Request.prototype.clone = function() { 42050 return new Request(this, { body: this._bodyInit }) 42051 } 42052 42053 function decode(body) { 42054 var form = new FormData() 42055 body.trim().split('&').forEach(function(bytes) { 42056 if (bytes) { 42057 var split = bytes.split('=') 42058 var name = split.shift().replace(/\+/g, ' ') 42059 var value = split.join('=').replace(/\+/g, ' ') 42060 form.append(decodeURIComponent(name), decodeURIComponent(value)) 42061 } 42062 }) 42063 return form 42064 } 42065 42066 function parseHeaders(rawHeaders) { 42067 var headers = new Headers() 42068 rawHeaders.split(/\r?\n/).forEach(function(line) { 42069 var parts = line.split(':') 42070 var key = parts.shift().trim() 42071 if (key) { 42072 var value = parts.join(':').trim() 42073 headers.append(key, value) 42074 } 42075 }) 42076 return headers 42077 } 42078 42079 Body.call(Request.prototype) 42080 42081 function Response(bodyInit, options) { 42082 if (!options) { 42083 options = {} 42084 } 42085 42086 this.type = 'default' 42087 this.status = 'status' in options ? options.status : 200 42088 this.ok = this.status >= 200 && this.status < 300 42089 this.statusText = 'statusText' in options ? options.statusText : 'OK' 42090 this.headers = new Headers(options.headers) 42091 this.url = options.url || '' 42092 this._initBody(bodyInit) 42093 } 42094 42095 Body.call(Response.prototype) 42096 42097 Response.prototype.clone = function() { 42098 return new Response(this._bodyInit, { 42099 status: this.status, 42100 statusText: this.statusText, 42101 headers: new Headers(this.headers), 42102 url: this.url 42103 }) 42104 } 42105 42106 Response.error = function() { 42107 var response = new Response(null, {status: 0, statusText: ''}) 42108 response.type = 'error' 42109 return response 42110 } 42111 42112 var redirectStatuses = [301, 302, 303, 307, 308] 42113 42114 Response.redirect = function(url, status) { 42115 if (redirectStatuses.indexOf(status) === -1) { 42116 throw new RangeError('Invalid status code') 42117 } 42118 42119 return new Response(null, {status: status, headers: {location: url}}) 42120 } 42121 42122 self.Headers = Headers 42123 self.Request = Request 42124 self.Response = Response 42125 42126 self.fetch = function(input, init) { 42127 return new Promise(function(resolve, reject) { 42128 var request = new Request(input, init) 42129 var xhr = new XMLHttpRequest() 42130 42131 xhr.onload = function() { 42132 var options = { 42133 status: xhr.status, 42134 statusText: xhr.statusText, 42135 headers: parseHeaders(xhr.getAllResponseHeaders() || '') 42136 } 42137 options.url = 'responseURL' in xhr ? xhr.responseURL : options.headers.get('X-Request-URL') 42138 var body = 'response' in xhr ? xhr.response : xhr.responseText 42139 resolve(new Response(body, options)) 42140 } 42141 42142 xhr.onerror = function() { 42143 reject(new TypeError('Network request failed')) 42144 } 42145 42146 xhr.ontimeout = function() { 42147 reject(new TypeError('Network request failed')) 42148 } 42149 42150 xhr.open(request.method, request.url, true) 42151 42152 if (request.credentials === 'include') { 42153 xhr.withCredentials = true 42154 } 42155 42156 if ('responseType' in xhr && support.blob) { 42157 xhr.responseType = 'blob' 42158 } 42159
42160 request.headers.forEach(function(value, name) { 42161 xhr.setRequestHeader(name, value) 42162 }) 42163 42164 xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit) 42165 }) 42166 } 42167 self.fetch.polyfill = true 42168})(typeof self !== 'undefined' ? self : this); 42169 42170},{}],13:[function(_dereq_,module,exports){ 42171'use strict'; 42172 42173var p5 = _dereq_('./core/core'); 42174_dereq_('./color/p5.Color'); 42175_dereq_('./core/p5.Element'); 42176_dereq_('./typography/p5.Font'); 42177_dereq_('./core/p5.Graphics'); 42178_dereq_('./core/p5.Renderer2D'); 42179 42180_dereq_('./image/p5.Image'); 42181_dereq_('./math/p5.Vector'); 42182_dereq_('./io/p5.TableRow'); 42183_dereq_('./io/p5.Table'); 42184_dereq_('./io/p5.XML'); 42185 42186_dereq_('./color/creating_reading'); 42187_dereq_('./color/setting'); 42188_dereq_('./core/constants'); 42189_dereq_('./utilities/conversion'); 42190_dereq_('./utilities/array_functions'); 42191_dereq_('./utilities/string_functions'); 42192_dereq_('./core/environment'); 42193_dereq_('./image/image'); 42194_dereq_('./image/loading_displaying'); 42195_dereq_('./image/pixels'); 42196_dereq_('./io/files'); 42197_dereq_('./events/keyboard'); 42198_dereq_('./events/acceleration'); //john 42199_dereq_('./events/mouse'); 42200_dereq_('./utilities/time_date'); 42201_dereq_('./events/touch'); 42202_dereq_('./math/math'); 42203_dereq_('./math/calculation'); 42204_dereq_('./math/random'); 42205_dereq_('./math/noise'); 42206_dereq_('./math/trigonometry'); 42207_dereq_('./core/rendering'); 42208_dereq_('./core/2d_primitives'); 42209 42210_dereq_('./core/attributes'); 42211_dereq_('./core/curves'); 42212_dereq_('./core/vertex'); 42213_dereq_('./core/structure'); 42214_dereq_('./core/transform'); 42215_dereq_('./typography/attributes'); 42216_dereq_('./typography/loading_displaying'); 42217 42218_dereq_('./data/p5.TypedDict'); 42219 42220_dereq_('./webgl/p5.RendererGL'); 42221_dereq_('./webgl/p5.Geometry'); 42222_dereq_('./webgl/p5.RendererGL.Retained'); 42223_dereq_('./webgl/p5.RendererGL.Immediate'); 42224_dereq_('./webgl/primitives'); 42225_dereq_('./webgl/loading'); 42226_dereq_('./webgl/p5.Matrix'); 42227_dereq_('./webgl/material'); 42228_dereq_('./webgl/light'); 42229_dereq_('./webgl/p5.Shader'); 42230_dereq_('./webgl/camera'); 42231_dereq_('./webgl/interaction'); 42232 42233_dereq_('./core/init.js'); 42234 42235module.exports = p5; 42236 42237},{"./color/creating_reading":15,"./color/p5.Color":16,"./color/setting":17,"./core/2d_primitives":18,"./core/attributes":19,"./core/constants":21,"./core/core":22,"./core/curves":23,"./core/environment":24,"./core/init.js":26,"./core/p5.Element":27,"./core/p5.Graphics":28,"./core/p5.Renderer2D":30,"./core/rendering":31,"./core/structure":33,"./core/transform":34,"./core/vertex":35,"./data/p5.TypedDict":36,"./events/acceleration":37,"./events/keyboard":38,"./events/mouse":39,"./events/touch":40,"./image/image":42,"./image/loading_displaying":43,"./image/p5.Image":44,"./image/pixels":45,"./io/files":46,"./io/p5.Table":47,"./io/p5.TableRow":48,"./io/p5.XML":49,"./math/calculation":50,"./math/math":51,"./math/noise":52,"./math/p5.Vector":53,"./math/random":54,"./math/trigonometry":55,"./typography/attributes":56,"./typography/loading_displaying":57,"./typography/p5.Font":58,"./utilities/array_functions":59,"./utilities/conversion":60,"./utilities/string_functions":61,"./utilities/time_date":62,"./webgl/camera":63,"./webgl/interaction":64,"./webgl/light":65,"./webgl/loading":66,"./webgl/material":67,"./webgl/p5.Geometry":68,"./webgl/p5.Matrix":69,"./webgl/p5.RendererGL":72,"./webgl/p5.RendererGL.Immediate":70,"./webgl/p5.RendererGL.Retained":71,"./webgl/p5.Shader":73,"./webgl/primitives":75}],14:[function(_dereq_,module,exports){ 42238/** 42239 * @module Conversion 42240 * @submodule Color Conversion 42241 * @for p5 42242 * @requires core 42243 */ 42244 42245'use strict'; 42246 42247/** 42248 * Conversions adapted from <http://www.easyrgb.com/en/math.php>. 42249 * 42250 * In these functions, hue is always in the range [0,1); all other components 42251 * are in the range [0,1]. 'Brightness' and 'value' are used interchangeably. 42252 */ 42253 42254var p5 = _dereq_('../core/core'); 42255p5.ColorConversion = {}; 42256 42257/** 42258 * Convert an HSBA array to HSLA. 42259 */ 42260p5.ColorConversion._hsbaToHSLA = function(hsba) { 42261 var hue = hsba[0]; 42262 var sat = hsba[1]; 42263 var val = hsba[2]; 42264 42265 // Calculate lightness. 42266 var li = (2 - sat) * val / 2; 42267 42268 // Convert saturation. 42269 if (li !== 0) { 42270 if (li === 1) { 42271 sat = 0; 42272 } else if (li < 0.5) { 42273 sat = sat / (2 - sat); 42274 } else { 42275 sat = sat * val / (2 - li * 2); 42276 } 42277 } 42278 42279 // Hue and alpha stay the same. 42280 return [hue, sat, li, hsba[3]]; 42281}; 42282 42283/** 42284 * Convert an HSBA array to RGBA. 42285 */ 42286p5.ColorConversion._hsbaToRGBA = function(hsba) { 42287 var hue = hsba[0] * 6; // We will split hue into 6 sectors. 42288 var sat = hsba[1]; 42289 var val = hsba[2]; 42290 42291 var RGBA = []; 42292 42293 if (sat === 0) { 42294 RGBA = [val, val, val, hsba[3]]; // Return early if grayscale. 42295 } else { 42296 var sector = Math.floor(hue);
42297 var tint1 = val * (1 - sat); 42298 var tint2 = val * (1 - sat * (hue - sector)); 42299 var tint3 = val * (1 - sat * (1 + sector - hue)); 42300 var red, green, blue; 42301 if (sector === 1) { 42302 // Yellow to green. 42303 red = tint2; 42304 green = val; 42305 blue = tint1; 42306 } else if (sector === 2) { 42307 // Green to cyan. 42308 red = tint1; 42309 green = val; 42310 blue = tint3; 42311 } else if (sector === 3) { 42312 // Cyan to blue. 42313 red = tint1; 42314 green = tint2; 42315 blue = val; 42316 } else if (sector === 4) { 42317 // Blue to magenta. 42318 red = tint3; 42319 green = tint1; 42320 blue = val; 42321 } else if (sector === 5) { 42322 // Magenta to red. 42323 red = val; 42324 green = tint1; 42325 blue = tint2; 42326 } else { 42327 // Red to yellow (sector could be 0 or 6). 42328 red = val; 42329 green = tint3; 42330 blue = tint1; 42331 } 42332 RGBA = [red, green, blue, hsba[3]]; 42333 } 42334 42335 return RGBA; 42336}; 42337 42338/** 42339 * Convert an HSLA array to HSBA. 42340 */ 42341p5.ColorConversion._hslaToHSBA = function(hsla) { 42342 var hue = hsla[0]; 42343 var sat = hsla[1]; 42344 var li = hsla[2]; 42345 42346 // Calculate brightness. 42347 var val; 42348 if (li < 0.5) { 42349 val = (1 + sat) * li; 42350 } else { 42351 val = li + sat - li * sat; 42352 } 42353 42354 // Convert saturation. 42355 sat = 2 * (val - li) / val; 42356 42357 // Hue and alpha stay the same. 42358 return [hue, sat, val, hsla[3]]; 42359}; 42360 42361/** 42362 * Convert an HSLA array to RGBA. 42363 * 42364 * We need to change basis from HSLA to something that can be more easily be 42365 * projected onto RGBA. We will choose hue and brightness as our first two 42366 * components, and pick a convenient third one ('zest') so that we don't need 42367 * to calculate formal HSBA saturation. 42368 */ 42369p5.ColorConversion._hslaToRGBA = function(hsla) { 42370 var hue = hsla[0] * 6; // We will split hue into 6 sectors. 42371 var sat = hsla[1]; 42372 var li = hsla[2]; 42373 42374 var RGBA = []; 42375 42376 if (sat === 0) { 42377 RGBA = [li, li, li, hsla[3]]; // Return early if grayscale. 42378 } else { 42379 // Calculate brightness. 42380 var val; 42381 if (li < 0.5) { 42382 val = (1 + sat) * li; 42383 } else { 42384 val = li + sat - li * sat; 42385 } 42386 42387 // Define zest. 42388 var zest = 2 * li - val; 42389 42390 // Implement projection (project onto green by default). 42391 var hzvToRGB = function(hue, zest, val) { 42392 if (hue < 0) { 42393 // Hue must wrap to allow projection onto red and blue. 42394 hue += 6; 42395 } else if (hue >= 6) { 42396 hue -= 6; 42397 } 42398 if (hue < 1) { 42399 // Red to yellow (increasing green). 42400 return zest + (val - zest) * hue; 42401 } else if (hue < 3) { 42402 // Yellow to cyan (greatest green). 42403 return val; 42404 } else if (hue < 4) { 42405 // Cyan to blue (decreasing green). 42406 return zest + (val - zest) * (4 - hue); 42407 } else { 42408 // Blue to red (least green). 42409 return zest; 42410 } 42411 }; 42412 42413 // Perform projections, offsetting hue as necessary. 42414 RGBA = [ 42415 hzvToRGB(hue + 2, zest, val), 42416 hzvToRGB(hue, zest, val), 42417 hzvToRGB(hue - 2, zest, val), 42418 hsla[3] 42419 ]; 42420 } 42421 42422 return RGBA; 42423}; 42424 42425/** 42426 * Convert an RGBA array to HSBA. 42427 */ 42428p5.ColorConversion._rgbaToHSBA = function(rgba) { 42429 var red = rgba[0]; 42430 var green = rgba[1]; 42431 var blue = rgba[2]; 42432 42433 var val = Math.max(red, green, blue); 42434 var chroma = val - Math.min(red, green, blue); 42435 42436 var hue, sat; 42437 if (chroma === 0) { 42438 // Return early if grayscale. 42439 hue = 0; 42440 sat = 0; 42441 } else { 42442 sat = chroma / val; 42443 if (red === val) { 42444 // Magenta to yellow. 42445 hue = (green - blue) / chroma; 42446 } else if (green === val) { 42447 // Yellow to cyan. 42448 hue = 2 + (blue - red) / chroma; 42449 } else if (blue === val) { 42450 // Cyan to magenta. 42451 hue = 4 + (red - green) / chroma; 42452 } 42453 if (hue < 0) { 42454 // Confine hue to the interval [0, 1). 42455 hue += 6; 42456 } else if (hue >= 6) { 42457 hue -= 6; 42458 } 42459 } 42460 42461 return [hue / 6, sat, val, rgba[3]]; 42462}; 42463 42464/** 42465 * Convert an RGBA array to HSLA. 42466 */ 42467p5.ColorConversion._rgbaToHSLA = function(rgba) { 42468 var red = rgba[0]; 42469 var green = rgba[1]; 42470 var blue = rgba[2]; 42471 42472 var val = Math.max(red, green, blue); 42473 var min = Math.min(red, green, blue); 42474 var li = val + min; // We will halve this later. 42475 var chroma = val - min; 42476 42477 var hue, sat; 42478 if (chroma === 0) { 42479 // Return early if grayscale. 42480 hue = 0; 42481 sat = 0; 42482 } else { 42483 if (li < 1) { 42484 sat = chroma / li; 42485 } else { 42486 sat = chroma / (2 - li); 42487 } 42488 if (red === val) { 42489 // Magenta to yellow. 42490 hue = (green - blue) / chroma; 42491 } else if (green === val) { 42492 // Yellow to cyan. 42493 hue = 2 + (blue - red) / chroma; 42494 } else if (blue === val) { 42495 // Cyan to magenta. 42496 hue = 4 + (red - green) / chroma; 42497 } 42498 if (hue < 0) { 42499 // Confine hue to the interval [0, 1). 42500 hue += 6; 42501 } else if (hue >= 6) { 42502 hue -= 6; 42503 } 42504 } 42505 42506 return [hue / 6, sat, li / 2, rgba[3]]; 42507}; 42508 42509module.exports = p5.ColorConversion; 42510 42511},{"../core/core":22}],15:[function(_dereq_,module,exports){ 42512/** 42513 * @module Color 42514 * @submodule Creating & Reading 42515 * @for p5 42516 * @requires core 42517 * @requires constants 42518 */ 42519 42520'use strict'; 42521 42522var p5 = _dereq_('../core/core'); 42523var constants = _dereq_('../core/constants'); 42524_dereq_('./p5.Color'); 42525_dereq_('../core/error_helpers'); 42526 42527/** 42528 * Extracts the alpha value from a color or pixel array. 42529 * 42530 * @method alpha 42531 * @param {p5.Color|Number[]|String} color p5.Color object, color components, 42532 * or CSS color 42533 * @return {Number} the alpha value 42534 * @example 42535 * <div> 42536 * <code> 42537 * noStroke(); 42538 * var c = color(0, 126, 255, 102); 42539 * fill(c); 42540 * rect(15, 15, 35, 70); 42541 * var value = alpha(c); // Sets 'value' to 102 42542 * fill(value); 42543 * rect(50, 15, 35, 70); 42544 * </code> 42545 * </div> 42546 * 42547 * @alt 42548 * Left half of canvas light blue and right half light charcoal grey. 42549 * Left half of canvas light purple and right half a royal blue. 42550 * Left half of canvas salmon pink and the right half white. 42551 * Yellow rect in middle right of canvas, with 55 pixel width and height. 42552 * Yellow ellipse in top left canvas, black ellipse in bottom right,both 80x80. 42553 * Bright fuschia rect in middle of canvas, 60 pixel width and height. 42554 * Two bright green rects on opposite sides of the canvas, both 45x80. 42555 * Four blue rects in each corner of the canvas, each are 35x35. 42556 * Bright sea green rect on left and darker rect on right of canvas, both 45x80. 42557 * Dark green rect on left and light green rect on right of canvas, both 45x80. 42558 * Dark blue rect on left and light teal rect on right of canvas, both 45x80. 42559 * blue rect on left and green on right, both with black outlines & 35x60. 42560 * salmon pink rect on left and black on right, both 35x60. 42561 * 4 rects, tan, brown, brownish purple and purple, with white outlines & 20x60. 42562 * light pastel green rect on left and dark grey rect on right, both 35x60. 42563 * yellow rect on left and red rect on right, both with black outlines & 35x60. 42564 * grey canvas 42565 * deep pink rect on left and grey rect on right, both 35x60. 42566 */ 42567p5.prototype.alpha = function(c) { 42568 p5._validateParameters('alpha', arguments); 42569 return this.color(c)._getAlpha(); 42570}; 42571 42572/** 42573 * Extracts the blue value from a color or pixel array. 42574 * 42575 * @method blue 42576 * @param {p5.Color|Number[]|String} color p5.Color object, color components, 42577 * or CSS color 42578 * @return {Number} the blue value 42579 * @example 42580 * <div> 42581 * <code> 42582 * var c = color(175, 100, 220); // Define color 'c' 42583 * fill(c); // Use color variable 'c' as fill color 42584 * rect(15, 20, 35, 60); // Draw left rectangle 42585 * 42586 * var blueValue = blue(c); // Get blue in 'c' 42587 * print(blueValue); // Prints "220.0" 42588 * fill(0, 0, blueValue); // Use 'blueValue' in new fill 42589 * rect(50, 20, 35, 60); // Draw right rectangle 42590 * </code> 42591 * </div> 42592 * 42593 * @alt 42594 * Left half of canvas light purple and right half a royal blue. 42595 * 42596 */ 42597p5.prototype.blue = function(c) { 42598 p5._validateParameters('blue', arguments); 42599 return this.color(c)._getBlue(); 42600}; 42601 42602/** 42603 * Extracts the HSB brightness value from a color or pixel array. 42604 * 42605 * @method brightness 42606 * @param {p5.Color|Number[]|String} color p5.Color object, color components, 42607 * or CSS color 42608 * @return {Number} the brightness value 42609 * @example 42610 * <div> 42611 * <code> 42612 * noStroke(); 42613 * colorMode(HSB, 255); 42614 * var c = color(0, 126, 255); 42615 * fill(c); 42616 * rect(15, 20, 35, 60); 42617 * var value = brightness(c); // Sets 'value' to 255 42618 * fill(value); 42619 * rect(50, 20, 35, 60); 42620 * </code> 42621 * </div> 42622 * 42623 * @alt 42624 * Left half of canvas salmon pink and the right half white. 42625 * 42626 */ 42627p5.prototype.brightness = function(c) { 42628 p5._validateParameters('brightness', arguments); 42629 return this.color(c)._getBrightness(); 42630}; 42631 42632/** 42633 * Creates colors for storing in variables of the color datatype. The 42634 * parameters are interpreted as RGB or HSB values depending on the 42635 * current colorMode(). The default mode is RGB values from 0 to 255 42636 * and, therefore, the function call color(255, 204, 0) will return a 42637 * bright yellow color. 42638 * <br><br> 42639 * Note that if only one value is provided to color(), it will be interpreted 42640 * as a grayscale value. Add a second value, and it will be used for alpha 42641 * transparency. When three values are specified, they are interpreted as 42642 * either RGB or HSB values. Adding a fourth value applies alpha 42643 * transparency. 42644 * <br><br>
42645 * If a single string argument is provided, RGB, RGBA and Hex CSS color 42646 * strings and all named color strings are supported. In this case, an alpha 42647 * number value as a second argument is not supported, the RGBA form should be 42648 * used. 42649 * 42650 * @method color 42651 * @param {Number} gray number specifying value between white 42652 * and black. 42653 * @param {Number} [alpha] alpha value relative to current color range 42654 * (default is 0-255) 42655 * @return {p5.Color} resulting color 42656 * 42657 * @example 42658 * <div> 42659 * <code> 42660 * var c = color(255, 204, 0); // Define color 'c' 42661 * fill(c); // Use color variable 'c' as fill color 42662 * noStroke(); // Don't draw a stroke around shapes 42663 * rect(30, 20, 55, 55); // Draw rectangle 42664 * </code> 42665 * </div> 42666 * 42667 * <div> 42668 * <code> 42669 * var c = color(255, 204, 0); // Define color 'c' 42670 * fill(c); // Use color variable 'c' as fill color 42671 * noStroke(); // Don't draw a stroke around shapes 42672 * ellipse(25, 25, 80, 80); // Draw left circle 42673 * 42674 * // Using only one value with color() 42675 * // generates a grayscale value. 42676 * c = color(65); // Update 'c' with grayscale value 42677 * fill(c); // Use updated 'c' as fill color 42678 * ellipse(75, 75, 80, 80); // Draw right circle 42679 * </code> 42680 * </div> 42681 * 42682 * <div> 42683 * <code> 42684 * // Named SVG & CSS colors may be used, 42685 * var c = color('magenta'); 42686 * fill(c); // Use 'c' as fill color 42687 * noStroke(); // Don't draw a stroke around shapes 42688 * rect(20, 20, 60, 60); // Draw rectangle 42689 * </code> 42690 * </div> 42691 * 42692 * <div> 42693 * <code> 42694 * // as can hex color codes: 42695 * noStroke(); // Don't draw a stroke around shapes 42696 * var c = color('#0f0'); 42697 * fill(c); // Use 'c' as fill color 42698 * rect(0, 10, 45, 80); // Draw rectangle 42699 * 42700 * c = color('#00ff00'); 42701 * fill(c); // Use updated 'c' as fill color 42702 * rect(55, 10, 45, 80); // Draw rectangle 42703 * </code> 42704 * </div> 42705 * 42706 * <div> 42707 * <code> 42708 * // RGB and RGBA color strings are also supported: 42709 * // these all set to the same color (solid blue) 42710 * var c; 42711 * noStroke(); // Don't draw a stroke around shapes 42712 * c = color('rgb(0,0,255)'); 42713 * fill(c); // Use 'c' as fill color 42714 * rect(10, 10, 35, 35); // Draw rectangle 42715 * 42716 * c = color('rgb(0%, 0%, 100%)'); 42717 * fill(c); // Use updated 'c' as fill color 42718 * rect(55, 10, 35, 35); // Draw rectangle 42719 * 42720 * c = color('rgba(0, 0, 255, 1)'); 42721 * fill(c); // Use updated 'c' as fill color 42722 * rect(10, 55, 35, 35); // Draw rectangle 42723 * 42724 * c = color('rgba(0%, 0%, 100%, 1)'); 42725 * fill(c); // Use updated 'c' as fill color 42726 * rect(55, 55, 35, 35); // Draw rectangle 42727 * </code> 42728 * </div> 42729 * 42730 * <div> 42731 * <code> 42732 * // HSL color is also supported and can be specified 42733 * // by value 42734 * var c; 42735 * noStroke(); // Don't draw a stroke around shapes 42736 * c = color('hsl(160, 100%, 50%)'); 42737 * fill(c); // Use 'c' as fill color 42738 * rect(0, 10, 45, 80); // Draw rectangle 42739 * 42740 * c = color('hsla(160, 100%, 50%, 0.5)'); 42741 * fill(c); // Use updated 'c' as fill color 42742 * rect(55, 10, 45, 80); // Draw rectangle 42743 * </code> 42744 * </div> 42745 * 42746 * <div> 42747 * <code> 42748 * // HSB color is also supported and can be specified 42749 * // by value 42750 * var c; 42751 * noStroke(); // Don't draw a stroke around shapes 42752 * c = color('hsb(160, 100%, 50%)'); 42753 * fill(c); // Use 'c' as fill color 42754 * rect(0, 10, 45, 80); // Draw rectangle 42755 * 42756 * c = color('hsba(160, 100%, 50%, 0.5)'); 42757 * fill(c); // Use updated 'c' as fill color 42758 * rect(55, 10, 45, 80); // Draw rectangle 42759 * </code> 42760 * </div> 42761 * 42762 * <div> 42763 * <code> 42764 * var c; // Declare color 'c' 42765 * noStroke(); // Don't draw a stroke around shapes 42766 * 42767 * // If no colorMode is specified, then the 42768 * // default of RGB with scale of 0-255 is used. 42769 * c = color(50, 55, 100); // Create a color for 'c' 42770 * fill(c); // Use color variable 'c' as fill color 42771 * rect(0, 10, 45, 80); // Draw left rect 42772 * 42773 * colorMode(HSB, 100); // Use HSB with scale of 0-100 42774 * c = color(50, 55, 100); // Update 'c' with new color 42775 * fill(c); // Use updated 'c' as fill color 42776 * rect(55, 10, 45, 80); // Draw right rect 42777 * </code> 42778 * </div> 42779 * 42780 * @alt 42781 * Yellow rect in middle right of canvas, with 55 pixel width and height. 42782 * Yellow ellipse in top left of canvas, black ellipse in bottom right,both 80x80. 42783 * Bright fuschia rect in middle of canvas, 60 pixel width and height. 42784 * Two bright green rects on opposite sides of the canvas, both 45x80. 42785 * Four blue rects in each corner of the canvas, each are 35x35. 42786 * Bright sea green rect on left and darker rect on right of canvas, both 45x80. 42787 * Dark green rect on left and lighter green rect on right of canvas, both 45x80. 42788 * Dark blue rect on left and light teal rect on right of canvas, both 45x80. 42789 * 42790 */ 42791/** 42792 * @method color 42793 * @param {Number} v1 red or hue value relative to 42794 * the current color range 42795 * @param {Number} v2 green or saturation value 42796 * relative to the current color range 42797 * @param {Number} v3 blue or brightness value 42798 * relative to the current color range 42799 * @param {Number} [alpha] 42800 * @return {p5.Color} 42801 */ 42802 42803/** 42804 * @method color 42805 * @param {String} value a color string 42806 * @return {p5.Color} 42807 */ 42808/** 42809 * @method color 42810 * @param {Number[]} values an array containing the red,green,blue & 42811 * and alpha components of the color 42812 * @return {p5.Color} 42813 */ 42814/** 42815 * @method color 42816 * @param {p5.Color} color 42817 * @return {p5.Color} 42818 */ 42819 42820p5.prototype.color = function() { 42821 p5._validateParameters('color', arguments); 42822 if (arguments[0] instanceof p5.Color) { 42823 return arguments[0];
42823 // Do nothing if argument is already a color object. 42824 } 42825 42826 var args = arguments[0] instanceof Array ? arguments[0] : arguments; 42827 return new p5.Color(this, args); 42828}; 42829 42830/** 42831 * Extracts the green value from a color or pixel array. 42832 * 42833 * @method green 42834 * @param {p5.Color|Number[]|String} color p5.Color object, color components, 42835 * or CSS color 42836 * @return {Number} the green value 42837 * @example 42838 * <div> 42839 * <code> 42840 * var c = color(20, 75, 200); // Define color 'c' 42841 * fill(c); // Use color variable 'c' as fill color 42842 * rect(15, 20, 35, 60); // Draw left rectangle 42843 * 42844 * var greenValue = green(c); // Get green in 'c' 42845 * print(greenValue); // Print "75.0" 42846 * fill(0, greenValue, 0); // Use 'greenValue' in new fill 42847 * rect(50, 20, 35, 60); // Draw right rectangle 42848 * </code> 42849 * </div> 42850 * 42851 * @alt 42852 * blue rect on left and green on right, both with black outlines & 35x60. 42853 * 42854 */ 42855 42856p5.prototype.green = function(c) { 42857 p5._validateParameters('green', arguments); 42858 return this.color(c)._getGreen(); 42859}; 42860 42861/** 42862 * Extracts the hue value from a color or pixel array. 42863 * 42864 * Hue exists in both HSB and HSL. This function will return the 42865 * HSB-normalized hue when supplied with an HSB color object (or when supplied 42866 * with a pixel array while the color mode is HSB), but will default to the 42867 * HSL-normalized hue otherwise. (The values will only be different if the 42868 * maximum hue setting for each system is different.) 42869 * 42870 * @method hue 42871 * @param {p5.Color|Number[]|String} color p5.Color object, color components, 42872 * or CSS color 42873 * @return {Number} the hue 42874 * @example 42875 * <div> 42876 * <code> 42877 * noStroke(); 42878 * colorMode(HSB, 255); 42879 * var c = color(0, 126, 255); 42880 * fill(c); 42881 * rect(15, 20, 35, 60); 42882 * var value = hue(c); // Sets 'value' to "0" 42883 * fill(value); 42884 * rect(50, 20, 35, 60); 42885 * </code> 42886 * </div> 42887 * 42888 * @alt 42889 * salmon pink rect on left and black on right, both 35x60. 42890 * 42891 */ 42892 42893p5.prototype.hue = function(c) { 42894 p5._validateParameters('hue', arguments); 42895 return this.color(c)._getHue(); 42896}; 42897 42898/** 42899 * Blends two colors to find a third color somewhere between them. The amt 42900 * parameter is the amount to interpolate between the two values where 0.0 42901 * equal to the first color, 0.1 is very near the first color, 0.5 is halfway 42902 * in between, etc. An amount below 0 will be treated as 0. Likewise, amounts 42903 * above 1 will be capped at 1. This is different from the behavior of lerp(), 42904 * but necessary because otherwise numbers outside the range will produce 42905 * strange and unexpected colors. 42906 * <br><br> 42907 * The way that colours are interpolated depends on the current color mode. 42908 * 42909 * @method lerpColor 42910 * @param {p5.Color} c1 interpolate from this color 42911 * @param {p5.Color} c2 interpolate to this color 42912 * @param {Number} amt number between 0 and 1 42913 * @return {p5.Color} interpolated color 42914 * @example 42915 * <div> 42916 * <code> 42917 * colorMode(RGB); 42918 * stroke(255); 42919 * background(51); 42920 * var from = color(218, 165, 32); 42921 * var to = color(72, 61, 139); 42922 * colorMode(RGB); // Try changing to HSB. 42923 * var interA = lerpColor(from, to, 0.33); 42924 * var interB = lerpColor(from, to, 0.66); 42925 * fill(from); 42926 * rect(10, 20, 20, 60); 42927 * fill(interA); 42928 * rect(30, 20, 20, 60); 42929 * fill(interB); 42930 * rect(50, 20, 20, 60); 42931 * fill(to); 42932 * rect(70, 20, 20, 60); 42933 * </code> 42934 * </div> 42935 * 42936 * @alt 42937 * 4 rects one tan, brown, brownish purple, purple, with white outlines & 20x60 42938 * 42939 */ 42940 42941p5.prototype.lerpColor = function(c1, c2, amt) { 42942 p5._validateParameters('lerpColor', arguments); 42943 var mode = this._colorMode; 42944 var maxes = this._colorMaxes; 42945 var l0, l1, l2, l3; 42946 var fromArray, toArray; 42947 42948 if (mode === constants.RGB) { 42949 fromArray = c1.levels.map(function(level) { 42950 return level / 255; 42951 }); 42952 toArray = c2.levels.map(function(level) { 42953 return level / 255; 42954 }); 42955 } else if (mode === constants.HSB) { 42956 c1._getBrightness(); // Cache hsba so it definitely exists. 42957 c2._getBrightness(); 42958 fromArray = c1.hsba; 42959 toArray = c2.hsba; 42960 } else if (mode === constants.HSL) { 42961 c1._getLightness();
42961 // Cache hsla so it definitely exists. 42962 c2._getLightness(); 42963 fromArray = c1.hsla; 42964 toArray = c2.hsla; 42965 } else { 42966 throw new Error(mode + 'cannot be used for interpolation.'); 42967 } 42968 42969 // Prevent extrapolation. 42970 amt = Math.max(Math.min(amt, 1), 0); 42971 42972 // Define lerp here itself if user isn't using math module. 42973 // Maintains the definition as found in math/calculation.js 42974 if (typeof this.lerp === 'undefined') { 42975 this.lerp = function(start, stop, amt) { 42976 return amt * (stop - start) + start; 42977 }; 42978 } 42979 42980 // Perform interpolation. 42981 l0 = this.lerp(fromArray[0], toArray[0], amt); 42982 l1 = this.lerp(fromArray[1], toArray[1], amt); 42983 l2 = this.lerp(fromArray[2], toArray[2], amt); 42984 l3 = this.lerp(fromArray[3], toArray[3], amt); 42985 42986 // Scale components. 42987 l0 *= maxes[mode][0]; 42988 l1 *= maxes[mode][1]; 42989 l2 *= maxes[mode][2]; 42990 l3 *= maxes[mode][3]; 42991 42992 return this.color(l0, l1, l2, l3); 42993}; 42994 42995/** 42996 * Extracts the HSL lightness value from a color or pixel array. 42997 * 42998 * @method lightness 42999 * @param {p5.Color|Number[]|String} color p5.Color object, color components, 43000 * or CSS color 43001 * @return {Number} the lightness 43002 * @example 43003 * <div> 43004 * <code> 43005 * noStroke(); 43006 * colorMode(HSL); 43007 * var c = color(156, 100, 50, 1); 43008 * fill(c); 43009 * rect(15, 20, 35, 60); 43010 * var value = lightness(c); // Sets 'value' to 50 43011 * fill(value); 43012 * rect(50, 20, 35, 60); 43013 * </code> 43014 * </div> 43015 * 43016 * @alt 43017 * light pastel green rect on left and dark grey rect on right, both 35x60. 43018 * 43019 */ 43020p5.prototype.lightness = function(c) { 43021 p5._validateParameters('lightness', arguments); 43022 return this.color(c)._getLightness(); 43023}; 43024 43025/** 43026 * Extracts the red value from a color or pixel array. 43027 * 43028 * @method red 43029 * @param {p5.Color|Number[]|String} color p5.Color object, color components, 43030 * or CSS color 43031 * @return {Number} the red value 43032 * @example 43033 * <div> 43034 * <code> 43035 * var c = color(255, 204, 0); // Define color 'c' 43036 * fill(c); // Use color variable 'c' as fill color 43037 * rect(15, 20, 35, 60); // Draw left rectangle 43038 * 43039 * var redValue = red(c); // Get red in 'c' 43040 * print(redValue); // Print "255.0" 43041 * fill(redValue, 0, 0); // Use 'redValue' in new fill 43042 * rect(50, 20, 35, 60); // Draw right rectangle 43043 * </code> 43044 * </div> 43045 * 43046 * <div> 43047 * <code> 43048 * colorMode(RGB, 255); 43049 * var c = color(127, 255, 0); 43050 * colorMode(RGB, 1); 43051 * var myColor = red(c); 43052 * print(myColor); 43053 * </code> 43054 * </div> 43055 * 43056 * @alt 43057 * yellow rect on left and red rect on right, both with black outlines and 35x60. 43058 * grey canvas 43059 */ 43060p5.prototype.red = function(c) { 43061 p5._validateParameters('red', arguments); 43062 return this.color(c)._getRed(); 43063}; 43064 43065/** 43066 * Extracts the saturation value from a color or pixel array. 43067 * 43068 * Saturation is scaled differently in HSB and HSL. This function will return 43069 * the HSB saturation when supplied with an HSB color object (or when supplied 43070 * with a pixel array while the color mode is HSB), but will default to the 43071 * HSL saturation otherwise. 43072 * 43073 * @method saturation 43074 * @param {p5.Color|Number[]|String} color p5.Color object, color components, 43075 * or CSS color 43076 * @return {Number} the saturation value 43077 * @example 43078 * <div> 43079 * <code> 43080 * noStroke(); 43081 * colorMode(HSB, 255); 43082 * var c = color(0, 126, 255); 43083 * fill(c); 43084 * rect(15, 20, 35, 60); 43085 * var value = saturation(c); // Sets 'value' to 126 43086 * fill(value); 43087 * rect(50, 20, 35, 60); 43088 * </code> 43089 * </div> 43090 * 43091 * @alt 43092 *deep pink rect on left and grey rect on right, both 35x60. 43093 * 43094 */ 43095 43096p5.prototype.saturation = function(c) { 43097 p5._validateParameters('saturation', arguments); 43098 return this.color(c)._getSaturation(); 43099}; 43100 43101module.exports = p5; 43102 43103},{"../core/constants":21,"../core/core":22,"../core/error_helpers":25,"./p5.Color":16}],16:[function(_dereq_,module,exports){ 43104/** 43105 * @module Color 43106 * @submodule Creating & Reading 43107 * @for p5 43108 * @requires core 43109 * @requires constants 43110 * @requires color_conversion 43111 */ 43112 43113'use strict'; 43114 43115var p5 = _dereq_('../core/core'); 43116var constants = _dereq_('../core/constants'); 43117var color_conversion = _dereq_('./color_conversion'); 43118 43119/** 43120 * Each color stores the color mode and level maxes that applied at the 43121 * time of its construction. These are used to interpret the input arguments 43122 * (at construction and later for that instance of color) and to format the 43123 * output e.g. when saturation() is requested. 43124 * 43125 * Internally we store an array representing the ideal RGBA values in floating 43126 * point form, normalized from 0 to 1. From this we calculate the closest 43127 * screen color (RGBA levels from 0 to 255) and expose this to the renderer. 43128 * 43129 * We also cache normalized, floating point components of the color in various 43130 * representations as they are calculated. This is done to prevent repeating a 43131 * conversion that has already been performed. 43132 * 43133 * @class p5.Color 43134 */ 43135p5.Color = function(pInst, vals) { 43136 // Record color mode and maxes at time of construction. 43137 this._storeModeAndMaxes(pInst._colorMode, pInst._colorMaxes); 43138 43139 // Calculate normalized RGBA values. 43140 if ( 43141 this.mode !== constants.RGB && 43142 this.mode !== constants.HSL && 43143 this.mode !== constants.HSB 43144 ) {
43145 throw new Error(this.mode + ' is an invalid colorMode.'); 43146 } else { 43147 this._array = p5.Color._parseInputs.apply(this, vals); 43148 } 43149 43150 // Expose closest screen color. 43151 this._calculateLevels(); 43152 return this; 43153}; 43154 43155/** 43156 * This function returns the color formatted as a string. This can be useful 43157 * for debugging, or for using p5.js with other libraries. 43158 * @method toString 43159 * @param {String} [format] How the color string will be formatted. 43160 * Leaving this empty formats the string as rgba(r, g, b, a). 43161 * '#rgb' '#rgba' '#rrggbb' and '#rrggbbaa' format as hexadecimal color codes. 43162 * 'rgb' 'hsb' and 'hsl' return the color formatted in the specified color mode. 43163 * 'rgba' 'hsba' and 'hsla' are the same as above but with alpha channels. 43164 * 'rgb%' 'hsb%' 'hsl%' 'rgba%' 'hsba%' and 'hsla%' format as percentages. 43165 * @return {String} the formatted string 43166 * @example 43167 * <div> 43168 * <code> 43169 * var myColor; 43170 * function setup() { 43171 * createCanvas(200, 200); 43172 * stroke(255); 43173 * myColor = color(100, 100, 250); 43174 * fill(myColor); 43175 * } 43176 * 43177 * function draw() { 43178 * text(myColor.toString(), 10, 10); 43179 * text(myColor.toString('#rrggbb'), 10, 95); 43180 * text(myColor.toString('rgba%'), 10, 180); 43181 * } 43182 * </code> 43183 * </div> 43184 * 43185 * @alt 43186 * canvas with text representation of color 43187 */ 43188p5.Color.prototype.toString = function(format) { 43189 if (!this.hsba) this.hsba = color_conversion._rgbaToHSBA(this._array); 43190 if (!this.hsla) this.hsla = color_conversion._rgbaToHSLA(this._array); 43191 43192 var a = this.levels; 43193 var f = this._array; 43194 var alpha = f[3]; // String representation uses normalized alpha 43195 43196 switch (format) { 43197 case '#rrggbb': 43198 return '#'.concat( 43199 a[0] < 16 ? '0'.concat(a[0].toString(16)) : a[0].toString(16), 43200 a[1] < 16 ? '0'.concat(a[1].toString(16)) : a[1].toString(16), 43201 a[2] < 16 ? '0'.concat(a[2].toString(16)) : a[2].toString(16) 43202 ); 43203 43204 case '#rrggbbaa': 43205 return '#'.concat( 43206 a[0] < 16 ? '0'.concat(a[0].toString(16)) : a[0].toString(16), 43207 a[1] < 16 ? '0'.concat(a[1].toString(16)) : a[1].toString(16), 43208 a[2] < 16 ? '0'.concat(a[2].toString(16)) : a[2].toString(16), 43209 a[3] < 16 ? '0'.concat(a[2].toString(16)) : a[3].toString(16) 43210 ); 43211 43212 case '#rgb': 43213 return '#'.concat( 43214 Math.round(f[0] * 15).toString(16), 43215 Math.round(f[1] * 15).toString(16), 43216 Math.round(f[2] * 15).toString(16) 43217 ); 43218 43219 case '#rgba': 43220 return '#'.concat( 43221 Math.round(f[0] * 15).toString(16), 43222 Math.round(f[1] * 15).toString(16), 43223 Math.round(f[2] * 15).toString(16), 43224 Math.round(f[3] * 15).toString(16) 43225 ); 43226 43227 case 'rgb': 43228 return 'rgb('.concat(a[0], ', ', a[1], ', ', a[2], ')'); 43229 43230 case 'rgb%': 43231 return 'rgb('.concat( 43232 (100 * f[0]).toPrecision(3), 43233 '%, ', 43234 (100 * f[1]).toPrecision(3), 43235 '%, ', 43236 (100 * f[2]).toPrecision(3), 43237 '%)' 43238 ); 43239 43240 case 'rgba%': 43241 return 'rgba('.concat( 43242 (100 * f[0]).toPrecision(3), 43243 '%, ', 43244 (100 * f[1]).toPrecision(3), 43245 '%, ', 43246 (100 * f[2]).toPrecision(3), 43247 '%, ', 43248 (100 * f[3]).toPrecision(3), 43249 '%)' 43250 ); 43251 43252 case 'hsb': 43253 case 'hsv': 43254 return 'hsb('.concat( 43255 this.hsba[0] * this.maxes[constants.HSB][0], 43256 ', ', 43257 this.hsba[1] * this.maxes[constants.HSB][1], 43258 ', ', 43259 this.hsba[2] * this.maxes[constants.HSB][2], 43260 ')' 43261 ); 43262 43263 case 'hsb%': 43264 case 'hsv%': 43265 return 'hsb('.concat( 43266 (100 * this.hsba[0]).toPrecision(3), 43267 '%, ', 43268 (100 * this.hsba[1]).toPrecision(3), 43269 '%, ', 43270 (100 * this.hsba[2]).toPrecision(3), 43271 '%)' 43272 ); 43273 43274 case 'hsba': 43275 case 'hsva': 43276 return 'hsba('.concat( 43277 this.hsba[0] * this.maxes[constants.HSB][0], 43278 ', ', 43279 this.hsba[1] * this.maxes[constants.HSB][1], 43280 ', ', 43281 this.hsba[2] * this.maxes[constants.HSB][2], 43282 ', ', 43283 alpha, 43284 ')' 43285 ); 43286 43287 case 'hsba%': 43288 case 'hsva%': 43289 return 'hsba('.concat( 43290 (100 * this.hsba[0]).toPrecision(3), 43291 '%, ', 43292 (100 * this.hsba[1]).toPrecision(3), 43293 '%, ', 43294 (100 * this.hsba[2]).toPrecision(3), 43295 '%, ', 43296 (100 * alpha).toPrecision(3), 43297 '%)' 43298 ); 43299 43300 case 'hsl': 43301 return 'hsl('.concat(
43302 this.hsla[0] * this.maxes[constants.HSL][0], 43303 ', ', 43304 this.hsla[1] * this.maxes[constants.HSL][1], 43305 ', ', 43306 this.hsla[2] * this.maxes[constants.HSL][2], 43307 ')' 43308 ); 43309 43310 case 'hsl%': 43311 return 'hsl('.concat( 43312 (100 * this.hsla[0]).toPrecision(3), 43313 '%, ', 43314 (100 * this.hsla[1]).toPrecision(3), 43315 '%, ', 43316 (100 * this.hsla[2]).toPrecision(3), 43317 '%)' 43318 ); 43319 43320 case 'hsla': 43321 return 'hsla('.concat( 43322 this.hsla[0] * this.maxes[constants.HSL][0], 43323 ', ', 43324 this.hsla[1] * this.maxes[constants.HSL][1], 43325 ', ', 43326 this.hsla[2] * this.maxes[constants.HSL][2], 43327 ', ', 43328 alpha, 43329 ')' 43330 ); 43331 43332 case 'hsla%': 43333 return 'hsl('.concat( 43334 (100 * this.hsla[0]).toPrecision(3), 43335 '%, ', 43336 (100 * this.hsla[1]).toPrecision(3), 43337 '%, ', 43338 (100 * this.hsla[2]).toPrecision(3), 43339 '%, ', 43340 (100 * alpha).toPrecision(3), 43341 '%)' 43342 ); 43343 43344 case 'rgba': 43345 default: 43346 return 'rgba(' + a[0] + ',' + a[1] + ',' + a[2] + ',' + alpha + ')'; 43347 } 43348}; 43349 43350/** 43351 * @method setRed 43352 * @param {Number} red the new red value 43353 * @example 43354 * <div> 43355 * <code> 43356 * var backgroundColor; 43357 * 43358 * function setup() { 43359 * backgroundColor = color(100, 50, 150); 43360 * } 43361 * 43362 * function draw() { 43363 * backgroundColor.setRed(128 + 128 * sin(millis() / 1000)); 43364 * background(backgroundColor); 43365 * } 43366 * </code> 43367 * </div> 43368 * 43369 * @alt 43370 * canvas with gradually changing background color 43371 */ 43372p5.Color.prototype.setRed = function(new_red) { 43373 this._array[0] = new_red / this.maxes[constants.RGB][0]; 43374 this._calculateLevels(); 43375}; 43376 43377/** 43378 * @method setGreen 43379 * @param {Number} green the new green value 43380 * @example 43381 * <div> 43382 * <code> 43383 * var backgroundColor; 43384 * 43385 * function setup() { 43386 * backgroundColor = color(100, 50, 150); 43387 * } 43388 * 43389 * function draw() { 43390 * backgroundColor.setGreen(128 + 128 * sin(millis() / 1000)); 43391 * background(backgroundColor); 43392 * } 43393 * </code> 43394 * </div> 43395 * 43396 * @alt 43397 * canvas with gradually changing background color 43398 **/ 43399p5.Color.prototype.setGreen = function(new_green) { 43400 this._array[1] = new_green / this.maxes[constants.RGB][1]; 43401 this._calculateLevels(); 43402}; 43403 43404/** 43405 * @method setBlue 43406 * @param {Number} blue the new blue value 43407 * @example 43408 * <div> 43409 * <code> 43410 * var backgroundColor; 43411 * 43412 * function setup() { 43413 * backgroundColor = color(100, 50, 150); 43414 * } 43415 * 43416 * function draw() { 43417 * backgroundColor.setBlue(128 + 128 * sin(millis() / 1000)); 43418 * background(backgroundColor); 43419 * } 43420 * </code> 43421 * </div> 43422 * 43423 * @alt 43424 * canvas with gradually changing background color 43425 **/ 43426p5.Color.prototype.setBlue = function(new_blue) { 43427 this._array[2] = new_blue / this.maxes[constants.RGB][2]; 43428 this._calculateLevels(); 43429}; 43430 43431/** 43432 * @method setAlpha 43433 * @param {Number} alpha the new alpha value 43434 * @example 43435 * <div> 43436 * <code> 43437 * var squareColor; 43438 * 43439 * function setup() { 43440 * ellipseMode(CORNERS); 43441 * strokeWeight(4); 43442 * squareColor = color(100, 50, 150); 43443 * } 43444 * 43445 * function draw() { 43446 * background(255); 43447 * 43448 * noFill(); 43449 * stroke(0); 43450 * ellipse(10, 10, width - 10, height - 10); 43451 * 43452 * squareColor.setAlpha(128 + 128 * sin(millis() / 1000)); 43453 * fill(squareColor); 43454 * noStroke(); 43455 * rect(13, 13, width - 26, height - 26); 43456 * } 43457 * </code> 43458 * </div> 43459 * 43460 * @alt 43461 * circle behind a square with gradually changing opacity 43462 **/ 43463p5.Color.prototype.setAlpha = function(new_alpha) { 43464 this._array[3] = new_alpha / this.maxes[this.mode][3]; 43465 this._calculateLevels(); 43466}; 43467 43468// calculates and stores the closest screen levels 43469p5.Color.prototype._calculateLevels = function() { 43470 this.levels = this._array.map(function(level) { 43471 return Math.round(level * 255); 43472 }); 43473}; 43474 43475p5.Color.prototype._getAlpha = function() { 43476 return this._array[3] * this.maxes[this.mode][3]; 43477}; 43478 43479// stores the color mode and maxes in this instance of Color 43480// for later use (by _parseInputs()) 43481p5.Color.prototype._storeModeAndMaxes = function(new_mode, new_maxes) { 43482 this.mode = new_mode; 43483 this.maxes = new_maxes; 43484}; 43485 43486p5.Color.prototype._getMode = function() { 43487 return this.mode; 43488}; 43489 43490p5.Color.prototype._getMaxes = function() { 43491 return this.maxes; 43492}; 43493 43494p5.Color.prototype._getBlue = function() {
43495 return this._array[2] * this.maxes[constants.RGB][2]; 43496}; 43497 43498p5.Color.prototype._getBrightness = function() { 43499 if (!this.hsba) { 43500 this.hsba = color_conversion._rgbaToHSBA(this._array); 43501 } 43502 return this.hsba[2] * this.maxes[constants.HSB][2]; 43503}; 43504 43505p5.Color.prototype._getGreen = function() { 43506 return this._array[1] * this.maxes[constants.RGB][1]; 43507}; 43508 43509/** 43510 * Hue is the same in HSB and HSL, but the maximum value may be different. 43511 * This function will return the HSB-normalized saturation when supplied with 43512 * an HSB color object, but will default to the HSL-normalized saturation 43513 * otherwise. 43514 */ 43515p5.Color.prototype._getHue = function() { 43516 if (this.mode === constants.HSB) { 43517 if (!this.hsba) { 43518 this.hsba = color_conversion._rgbaToHSBA(this._array); 43519 } 43520 return this.hsba[0] * this.maxes[constants.HSB][0]; 43521 } else { 43522 if (!this.hsla) { 43523 this.hsla = color_conversion._rgbaToHSLA(this._array); 43524 } 43525 return this.hsla[0] * this.maxes[constants.HSL][0]; 43526 } 43527}; 43528 43529p5.Color.prototype._getLightness = function() { 43530 if (!this.hsla) { 43531 this.hsla = color_conversion._rgbaToHSLA(this._array); 43532 } 43533 return this.hsla[2] * this.maxes[constants.HSL][2]; 43534}; 43535 43536p5.Color.prototype._getRed = function() { 43537 return this._array[0] * this.maxes[constants.RGB][0]; 43538}; 43539 43540/** 43541 * Saturation is scaled differently in HSB and HSL. This function will return 43542 * the HSB saturation when supplied with an HSB color object, but will default 43543 * to the HSL saturation otherwise. 43544 */ 43545p5.Color.prototype._getSaturation = function() { 43546 if (this.mode === constants.HSB) { 43547 if (!this.hsba) { 43548 this.hsba = color_conversion._rgbaToHSBA(this._array); 43549 } 43550 return this.hsba[1] * this.maxes[constants.HSB][1]; 43551 } else { 43552 if (!this.hsla) { 43553 this.hsla = color_conversion._rgbaToHSLA(this._array); 43554 } 43555 return this.hsla[1] * this.maxes[constants.HSL][1]; 43556 } 43557}; 43558 43559/** 43560 * CSS named colors. 43561 */ 43562var namedColors = { 43563 aliceblue: '#f0f8ff', 43564 antiquewhite: '#faebd7', 43565 aqua: '#00ffff', 43566 aquamarine: '#7fffd4', 43567 azure: '#f0ffff', 43568 beige: '#f5f5dc', 43569 bisque: '#ffe4c4', 43570 black: '#000000', 43571 blanchedalmond: '#ffebcd', 43572 blue: '#0000ff', 43573 blueviolet: '#8a2be2', 43574 brown: '#a52a2a', 43575 burlywood: '#deb887', 43576 cadetblue: '#5f9ea0', 43577 chartreuse: '#7fff00', 43578 chocolate: '#d2691e', 43579 coral: '#ff7f50', 43580 cornflowerblue: '#6495ed', 43581 cornsilk: '#fff8dc', 43582 crimson: '#dc143c', 43583 cyan: '#00ffff', 43584 darkblue: '#00008b', 43585 darkcyan: '#008b8b', 43586 darkgoldenrod: '#b8860b', 43587 darkgray: '#a9a9a9', 43588 darkgreen: '#006400', 43589 darkgrey: '#a9a9a9', 43590 darkkhaki: '#bdb76b', 43591 darkmagenta: '#8b008b', 43592 darkolivegreen: '#556b2f', 43593 darkorange: '#ff8c00', 43594 darkorchid: '#9932cc', 43595 darkred: '#8b0000', 43596 darksalmon: '#e9967a', 43597 darkseagreen: '#8fbc8f', 43598 darkslateblue: '#483d8b', 43599 darkslategray: '#2f4f4f', 43600 darkslategrey: '#2f4f4f', 43601 darkturquoise: '#00ced1', 43602 darkviolet: '#9400d3', 43603 deeppink: '#ff1493', 43604 deepskyblue: '#00bfff', 43605 dimgray: '#696969', 43606 dimgrey: '#696969', 43607 dodgerblue: '#1e90ff', 43608 firebrick: '#b22222', 43609 floralwhite: '#fffaf0', 43610 forestgreen: '#228b22', 43611 fuchsia: '#ff00ff', 43612 gainsboro: '#dcdcdc', 43613 ghostwhite: '#f8f8ff', 43614 gold: '#ffd700', 43615 goldenrod: '#daa520', 43616 gray: '#808080', 43617 green: '#008000', 43618 greenyellow: '#adff2f', 43619 grey: '#808080', 43620 honeydew: '#f0fff0', 43621 hotpink: '#ff69b4', 43622 indianred: '#cd5c5c', 43623 indigo: '#4b0082', 43624 ivory: '#fffff0', 43625 khaki: '#f0e68c', 43626 lavender: '#e6e6fa', 43627 lavenderblush: '#fff0f5', 43628 lawngreen: '#7cfc00', 43629 lemonchiffon: '#fffacd', 43630 lightblue: '#add8e6', 43631 lightcoral: '#f08080', 43632 lightcyan: '#e0ffff', 43633 lightgoldenrodyellow: '#fafad2', 43634 lightgray: '#d3d3d3', 43635 lightgreen: '#90ee90', 43636 lightgrey: '#d3d3d3', 43637 lightpink: '#ffb6c1', 43638 lightsalmon: '#ffa07a', 43639 lightseagreen: '#20b2aa', 43640 lightskyblue: '#87cefa', 43641 lightslategray: '#778899', 43642 lightslategrey: '#778899', 43643 lightsteelblue: '#b0c4de', 43644 lightyellow: '#ffffe0', 43645 lime: '#00ff00', 43646 limegreen: '#32cd32', 43647 linen: '#faf0e6', 43648 magenta: '#ff00ff', 43649 maroon: '#800000', 43650 mediumaquamarine: '#66cdaa', 43651 mediumblue: '#0000cd', 43652 mediumorchid: '#ba55d3', 43653 mediumpurple: '#9370db', 43654 mediumseagreen: '#3cb371', 43655 mediumslateblue: '#7b68ee', 43656 mediumspringgreen: '#00fa9a', 43657 mediumturquoise: '#48d1cc', 43658 mediumvioletred: '#c71585', 43659 midnightblue: '#191970', 43660 mintcream: '#f5fffa', 43661 mistyrose: '#ffe4e1', 43662 moccasin: '#ffe4b5', 43663 navajowhite: '#ffdead', 43664 navy: '#000080', 43665 oldlace: '#fdf5e6', 43666 olive: '#808000', 43667 olivedrab: '#6b8e23', 43668 orange: '#ffa500', 43669 orangered: '#ff4500', 43670 orchid: '#da70d6', 43671 palegoldenrod: '#eee8aa', 43672 palegreen: '#98fb98', 43673 paleturquoise: '#afeeee', 43674 palevioletred: '#db7093', 43675 papayawhip: '#ffefd5', 43676 peachpuff: '#ffdab9', 43677 peru: '#cd853f', 43678 pink: '#ffc0cb', 43679 plum: '#dda0dd', 43680 powderblue: '#b0e0e6', 43681 purple: '#800080', 43682 red: '#ff0000', 43683 rosybrown: '#bc8f8f', 43684 royalblue: '#4169e1', 43685 saddlebrown: '#8b4513', 43686 salmon: '#fa8072', 43687 sandybrown: '#f4a460', 43688 seagreen: '#2e8b57', 43689 seashell: '#fff5ee', 43690 sienna: '#a0522d', 43691 silver: '#c0c0c0', 43692 skyblue: '#87ceeb', 43693 slateblue: '#6a5acd', 43694 slategray: '#708090', 43695 slategrey: '#708090', 43696 snow: '#fffafa', 43697 springgreen: '#00ff7f', 43698 steelblue: '#4682b4', 43699 tan: '#d2b48c', 43700 teal: '#008080', 43701 thistle: '#d8bfd8', 43702 tomato: '#ff6347', 43703 turquoise: '#40e0d0', 43704 violet: '#ee82ee', 43705 wheat: '#f5deb3', 43706 white: '#ffffff', 43707 whitesmoke: '#f5f5f5', 43708 yellow: '#ffff00', 43709 yellowgreen: '#9acd32' 43710}; 43711 43712/** 43713 * These regular expressions are used to build up the patterns for matching 43714 * viable CSS color strings: fragmenting the regexes in this way increases the 43715 * legibility and comprehensibility of the code. 43716 *
43717 * Note that RGB values of .9 are not parsed by IE, but are supported here for 43718 * color string consistency. 43719 */ 43720var WHITESPACE = /\s*/; // Match zero or more whitespace characters. 43721var INTEGER = /(\d{1,3})/; // Match integers: 79, 255, etc. 43722var DECIMAL = /((?:\d+(?:\.\d+)?)|(?:\.\d+))/; // Match 129.6, 79, .9, etc. 43723var PERCENT = new RegExp(DECIMAL.source + '%'); // Match 12.9%, 79%, .9%, etc. 43724 43725/** 43726 * Full color string patterns. The capture groups are necessary. 43727 */ 43728var colorPatterns = { 43729 // Match colors in format #XXX, e.g. #416. 43730 HEX3: /^#([a-f0-9])([a-f0-9])([a-f0-9])$/i, 43731 43732 // Match colors in format #XXXX, e.g. #5123. 43733 HEX4: /^#([a-f0-9])([a-f0-9])([a-f0-9])([a-f0-9])$/i, 43734 43735 // Match colors in format #XXXXXX, e.g. #b4d455. 43736 HEX6: /^#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})$/i, 43737 43738 // Match colors in format #XXXXXXXX, e.g. #b4d45535. 43739 HEX8: /^#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})$/i, 43740 43741 // Match colors in format rgb(R, G, B), e.g. rgb(255, 0, 128). 43742 RGB: new RegExp( 43743 [ 43744 '^rgb\\(', 43745 INTEGER.source, 43746 ',', 43747 INTEGER.source, 43748 ',', 43749 INTEGER.source, 43750 '\\)$' 43751 ].join(WHITESPACE.source), 43752 'i' 43753 ), 43754 43755 // Match colors in format rgb(R%, G%, B%), e.g. rgb(100%, 0%, 28.9%). 43756 RGB_PERCENT: new RegExp( 43757 [ 43758 '^rgb\\(', 43759 PERCENT.source, 43760 ',', 43761 PERCENT.source, 43762 ',', 43763 PERCENT.source, 43764 '\\)$' 43765 ].join(WHITESPACE.source), 43766 'i' 43767 ), 43768 43769 // Match colors in format rgb(R, G, B, A), e.g. rgb(255, 0, 128, 0.25). 43770 RGBA: new RegExp( 43771 [ 43772 '^rgba\\(', 43773 INTEGER.source, 43774 ',', 43775 INTEGER.source, 43776 ',', 43777 INTEGER.source, 43778 ',', 43779 DECIMAL.source, 43780 '\\)$' 43781 ].join(WHITESPACE.source), 43782 'i' 43783 ), 43784 43785 // Match colors in format rgb(R%, G%, B%, A), e.g. rgb(100%, 0%, 28.9%, 0.5). 43786 RGBA_PERCENT: new RegExp( 43787 [ 43788 '^rgba\\(', 43789 PERCENT.source, 43790 ',', 43791 PERCENT.source, 43792 ',', 43793 PERCENT.source, 43794 ',', 43795 DECIMAL.source, 43796 '\\)$' 43797 ].join(WHITESPACE.source), 43798 'i' 43799 ), 43800 43801 // Match colors in format hsla(H, S%, L%), e.g. hsl(100, 40%, 28.9%). 43802 HSL: new RegExp( 43803 [ 43804 '^hsl\\(', 43805 INTEGER.source, 43806 ',', 43807 PERCENT.source, 43808 ',', 43809 PERCENT.source, 43810 '\\)$' 43811 ].join(WHITESPACE.source), 43812 'i' 43813 ), 43814 43815 // Match colors in format hsla(H, S%, L%, A), e.g. hsla(100, 40%, 28.9%, 0.5). 43816 HSLA: new RegExp( 43817 [ 43818 '^hsla\\(', 43819 INTEGER.source, 43820 ',', 43821 PERCENT.source, 43822 ',', 43823 PERCENT.source, 43824 ',', 43825 DECIMAL.source, 43826 '\\)$' 43827 ].join(WHITESPACE.source), 43828 'i' 43829 ), 43830 43831 // Match colors in format hsb(H, S%, B%), e.g. hsb(100, 40%, 28.9%). 43832 HSB: new RegExp( 43833 [ 43834 '^hsb\\(', 43835 INTEGER.source, 43836 ',', 43837 PERCENT.source, 43838 ',', 43839 PERCENT.source, 43840 '\\)$' 43841 ].join(WHITESPACE.source), 43842 'i' 43843 ), 43844 43845 // Match colors in format hsba(H, S%, B%, A), e.g. hsba(100, 40%, 28.9%, 0.5). 43846 HSBA: new RegExp( 43847 [ 43848 '^hsba\\(', 43849 INTEGER.source, 43850 ',', 43851 PERCENT.source, 43852 ',', 43853 PERCENT.source, 43854 ',', 43855 DECIMAL.source, 43856 '\\)$' 43857 ].join(WHITESPACE.source), 43858 'i' 43859 ) 43860}; 43861 43862/** 43863 * For a number of different inputs, returns a color formatted as [r, g, b, a] 43864 * arrays, with each component normalized between 0 and 1. 43865 * 43866 * @private 43867 * @param {Array} [...args] An 'array-like' object that represents a list of 43868 * arguments 43869 * @return {Number[]} a color formatted as [r, g, b, a] 43870 * Example: 43871 * input ==> output 43872 * g ==> [g, g, g, 255] 43873 * g,a ==> [g, g, g, a] 43874 * r, g, b ==> [r, g, b, 255] 43875 * r, g, b, a ==> [r, g, b, a] 43876 * [g] ==> [g, g, g, 255] 43877 * [g, a] ==> [g, g, g, a] 43878 * [r, g, b] ==> [r, g, b, 255] 43879 * [r, g, b, a] ==> [r, g, b, a] 43880 * @example 43881 * <div> 43882 * <code> 43883 * // todo 43884 * </code> 43885 * </div> 43886 * 43887 * @alt 43888 * //todo 43889 * 43890 */ 43891p5.Color._parseInputs = function(r, g, b, a) { 43892 var numArgs = arguments.length; 43893 var mode = this.mode; 43894 var maxes = this.maxes; 43895 var results = []; 43896 43897 if (numArgs >= 3) { 43898 // Argument is a list of component values. 43899 43900 results[0] = r / maxes[mode][0]; 43901 results[1] = g / maxes[mode][1]; 43902 results[2] = b / maxes[mode][2]; 43903 43904 // Alpha may be undefined, so default it to 100%. 43905 if (typeof a === 'number') { 43906 results[3] = a / maxes[mode][3]; 43907 } else { 43908 results[3] = 1; 43909 } 43910 43911 // Constrain components to the range [0,1]. 43912 results = results.map(function(value) {
43913 return Math.max(Math.min(value, 1), 0); 43914 }); 43915 43916 // Convert to RGBA and return. 43917 if (mode === constants.HSL) { 43918 return color_conversion._hslaToRGBA(results); 43919 } else if (mode === constants.HSB) { 43920 return color_conversion._hsbaToRGBA(results); 43921 } else { 43922 return results; 43923 } 43924 } else if (numArgs === 1 && typeof r === 'string') { 43925 var str = r.trim().toLowerCase(); 43926 43927 // Return if string is a named colour. 43928 if (namedColors[str]) { 43929 return p5.Color._parseInputs.call(this, namedColors[str]); 43930 } 43931 43932 // Try RGBA pattern matching. 43933 if (colorPatterns.HEX3.test(str)) { 43934 // #rgb 43935 results = colorPatterns.HEX3.exec(str) 43936 .slice(1) 43937 .map(function(color) { 43938 return parseInt(color + color, 16) / 255; 43939 }); 43940 results[3] = 1; 43941 return results; 43942 } else if (colorPatterns.HEX6.test(str)) { 43943 // #rrggbb 43944 results = colorPatterns.HEX6.exec(str) 43945 .slice(1) 43946 .map(function(color) { 43947 return parseInt(color, 16) / 255; 43948 }); 43949 results[3] = 1; 43950 return results; 43951 } else if (colorPatterns.HEX4.test(str)) { 43952 // #rgba 43953 results = colorPatterns.HEX4.exec(str) 43954 .slice(1) 43955 .map(function(color) { 43956 return parseInt(color + color, 16) / 255; 43957 }); 43958 return results; 43959 } else if (colorPatterns.HEX8.test(str)) { 43960 // #rrggbbaa 43961 results = colorPatterns.HEX8.exec(str) 43962 .slice(1) 43963 .map(function(color) { 43964 return parseInt(color, 16) / 255; 43965 }); 43966 return results; 43967 } else if (colorPatterns.RGB.test(str)) { 43968 // rgb(R,G,B) 43969 results = colorPatterns.RGB.exec(str) 43970 .slice(1) 43971 .map(function(color) { 43972 return color / 255; 43973 }); 43974 results[3] = 1; 43975 return results; 43976 } else if (colorPatterns.RGB_PERCENT.test(str)) { 43977 // rgb(R%,G%,B%) 43978 results = colorPatterns.RGB_PERCENT.exec(str) 43979 .slice(1) 43980 .map(function(color) { 43981 return parseFloat(color) / 100; 43982 }); 43983 results[3] = 1; 43984 return results; 43985 } else if (colorPatterns.RGBA.test(str)) { 43986 // rgba(R,G,B,A) 43987 results = colorPatterns.RGBA.exec(str) 43988 .slice(1) 43989 .map(function(color, idx) { 43990 if (idx === 3) { 43991 return parseFloat(color); 43992 } 43993 return color / 255; 43994 }); 43995 return results; 43996 } else if (colorPatterns.RGBA_PERCENT.test(str)) { 43997 // rgba(R%,G%,B%,A%) 43998 results = colorPatterns.RGBA_PERCENT.exec(str) 43999 .slice(1) 44000 .map(function(color, idx) { 44001 if (idx === 3) { 44002 return parseFloat(color); 44003 } 44004 return parseFloat(color) / 100; 44005 }); 44006 return results; 44007 } 44008 44009 // Try HSLA pattern matching. 44010 if (colorPatterns.HSL.test(str)) { 44011 // hsl(H,S,L) 44012 results = colorPatterns.HSL.exec(str) 44013 .slice(1) 44014 .map(function(color, idx) { 44015 if (idx === 0) { 44016 return parseInt(color, 10) / 360; 44017 } 44018 return parseInt(color, 10) / 100; 44019 }); 44020 results[3] = 1; 44021 } else if (colorPatterns.HSLA.test(str)) { 44022 // hsla(H,S,L,A) 44023 results = colorPatterns.HSLA.exec(str) 44024 .slice(1) 44025 .map(function(color, idx) { 44026 if (idx === 0) { 44027 return parseInt(color, 10) / 360; 44028 } else if (idx === 3) { 44029 return parseFloat(color); 44030 } 44031 return parseInt(color, 10) / 100; 44032 }); 44033 } 44034 results = results.map(function(value) { 44035 return Math.max(Math.min(value, 1), 0); 44036 }); 44037 if (results.length) { 44038 return color_conversion._hslaToRGBA(results); 44039 } 44040 44041 // Try HSBA pattern matching. 44042 if (colorPatterns.HSB.test(str)) { 44043 // hsb(H,S,B) 44044 results = colorPatterns.HSB.exec(str) 44045 .slice(1) 44046 .map(function(color, idx) { 44047 if (idx === 0) { 44048 return parseInt(color, 10) / 360; 44049 } 44050 return parseInt(color, 10) / 100; 44051 }); 44052 results[3] = 1; 44053 } else if (colorPatterns.HSBA.test(str)) { 44054 // hsba(H,S,B,A) 44055 results = colorPatterns.HSBA.exec(str) 44056 .slice(1) 44057 .map(function(color, idx) { 44058 if (idx === 0) { 44059 return parseInt(color, 10) / 360; 44060 } else if (idx === 3) { 44061 return parseFloat(color); 44062 } 44063 return parseInt(color, 10) / 100; 44064 }); 44065 } 44066 results = results.map(function(value) {
44067 return Math.max(Math.min(value, 1), 0); 44068 }); 44069 44070 if (results.length) { 44071 return color_conversion._hsbaToRGBA(results); 44072 } 44073 44074 // Input did not match any CSS color pattern: default to white. 44075 results = [1, 1, 1, 1]; 44076 } else if ((numArgs === 1 || numArgs === 2) && typeof r === 'number') { 44077 // 'Grayscale' mode. 44078 44079 /** 44080 * For HSB and HSL, interpret the gray level as a brightness/lightness 44081 * value (they are equivalent when chroma is zero). For RGB, normalize the 44082 * gray level according to the blue maximum. 44083 */ 44084 results[0] = r / maxes[mode][2]; 44085 results[1] = r / maxes[mode][2]; 44086 results[2] = r / maxes[mode][2]; 44087 44088 // Alpha may be undefined, so default it to 100%. 44089 if (typeof g === 'number') { 44090 results[3] = g / maxes[mode][3]; 44091 } else { 44092 results[3] = 1; 44093 } 44094 44095 // Constrain components to the range [0,1]. 44096 results = results.map(function(value) { 44097 return Math.max(Math.min(value, 1), 0); 44098 }); 44099 } else { 44100 throw new Error(arguments + 'is not a valid color representation.'); 44101 } 44102 44103 return results; 44104}; 44105 44106module.exports = p5.Color; 44107 44108},{"../core/constants":21,"../core/core":22,"./color_conversion":14}],17:[function(_dereq_,module,exports){ 44109/** 44110 * @module Color 44111 * @submodule Setting 44112 * @for p5 44113 * @requires core 44114 * @requires constants 44115 */ 44116 44117'use strict'; 44118 44119var p5 = _dereq_('../core/core'); 44120var constants = _dereq_('../core/constants'); 44121_dereq_('./p5.Color'); 44122 44123/** 44124 * The background() function sets the color used for the background of the 44125 * p5.js canvas. The default background is light gray. This function is 44126 * typically used within draw() to clear the display window at the beginning 44127 * of each frame, but it can be used inside setup() to set the background on 44128 * the first frame of animation or if the background need only be set once. 44129 * <br><br> 44130 * The color is either specified in terms of the RGB, HSB, or HSL color 44131 * depending on the current colorMode. (The default color space is RGB, with 44132 * each value in the range from 0 to 255). The alpha range by default is also 0 to 255. 44133 * <br><br> 44134 * If a single string argument is provided, RGB, RGBA and Hex CSS color strings 44135 * and all named color strings are supported. In this case, an alpha number 44136 * value as a second argument is not supported, the RGBA form should be used. 44137 * <br><br> 44138 * A p5.Color object can also be provided to set the background color. 44139 * <br><br> 44140 * A p5.Image can also be provided to set the background image. 44141 * 44142 * @method background 44143 * @param {p5.Color} color any value created by the color() function 44144 * @chainable 44145 * 44146 * @example 44147 * <div> 44148 * <code> 44149 * // Grayscale integer value 44150 * background(51); 44151 * </code> 44152 * </div> 44153 * 44154 * <div> 44155 * <code> 44156 * // R, G & B integer values 44157 * background(255, 204, 0); 44158 * </code> 44159 * </div> 44160 * 44161 * <div> 44162 * <code> 44163 * // H, S & B integer values 44164 * colorMode(HSB); 44165 * background(255, 204, 100); 44166 * </code> 44167 * </div> 44168 * 44169 * <div> 44170 * <code> 44171 * // Named SVG/CSS color string 44172 * background('red'); 44173 * </code> 44174 * </div> 44175 * 44176 * <div> 44177 * <code> 44178 * // three-digit hexadecimal RGB notation 44179 * background('#fae'); 44180 * </code> 44181 * </div> 44182 * 44183 * <div> 44184 * <code> 44185 * // six-digit hexadecimal RGB notation 44186 * background('#222222'); 44187 * </code> 44188 * </div> 44189 * 44190 * <div> 44191 * <code> 44192 * // integer RGB notation 44193 * background('rgb(0,255,0)'); 44194 * </code> 44195 * </div> 44196 * 44197 * <div> 44198 * <code> 44199 * // integer RGBA notation 44200 * background('rgba(0,255,0, 0.25)'); 44201 * </code> 44202 * </div> 44203 * 44204 * <div> 44205 * <code> 44206 * // percentage RGB notation 44207 * background('rgb(100%,0%,10%)'); 44208 * </code> 44209 * </div> 44210 * 44211 * <div> 44212 * <code> 44213 * // percentage RGBA notation 44214 * background('rgba(100%,0%,100%,0.5)'); 44215 * </code> 44216 * </div> 44217 * 44218 * <div> 44219 * <code> 44220 * // p5 Color object 44221 * background(color(0, 0, 255)); 44222 * </code> 44223 * </div> 44224 * 44225 * @alt 44226 * canvas with darkest charcoal grey background. 44227 * canvas with yellow background. 44228 * canvas with royal blue background. 44229 * canvas with red background. 44230 * canvas with pink background. 44231 * canvas with black background. 44232 * canvas with bright green background. 44233 * canvas with soft green background. 44234 * canvas with red background. 44235 * canvas with light purple background. 44236 * canvas with blue background. 44237 */ 44238 44239/** 44240 * @method background 44241 * @param {String} colorstring color string, possible formats include: integer 44242 * rgb() or rgba(), percentage rgb() or rgba(), 44243 * 3-digit hex, 6-digit hex 44244 * @param {Number} [a] opacity of the background relative to current 44245 * color range (default is 0-255) 44246 * @chainable 44247 */ 44248 44249/** 44250 * @method background 44251 * @param {Number} gray specifies a value between white and black 44252 * @param {Number} [a] 44253 * @chainable 44254 */ 44255 44256/** 44257 * @method background 44258 * @param {Number} v1 red or hue value (depending on the current color 44259 * mode) 44260 * @param {Number} v2 green or saturation value (depending on the current 44261 * color mode) 44262 * @param {Number} v3 blue or brightness value (depending on the current 44263 * color mode) 44264 * @param {Number} [a] 44265 * @chainable 44266 */ 44267 44268/** 44269 * @method background 44270 * @param {Number[]} values an array containing the red,green,blue & 44271 * and alpha components of the color 44272 * @chainable 44273 */ 44274 44275/** 44276 * @method background 44277 * @param {p5.Image} image image created with loadImage() or createImage(), 44278 * to set as background 44279 * (must be same size as the sketch window) 44280 * @param {Number} [a] 44281 * @chainable 44282 */ 44283 44284p5.prototype.background = function() { 44285 if (arguments[0] instanceof p5.Image) { 44286 this.image(arguments[0], 0, 0, this.width, this.height); 44287 } else { 44288 this._renderer.background.apply(this._renderer, arguments); 44289 } 44290 return this; 44291}; 44292 44293/** 44294 * Clears the pixels within a buffer. This function only works on p5.Canvas 44295 * objects created with the createCanvas() function; it won't work with the 44296 * main display window. Unlike the main graphics context, pixels in 44297 * additional graphics areas created with createGraphics() can be entirely 44298 * or partially transparent. This function clears everything to make all of 44299 * the pixels 100% transparent. 44300 * 44301 * @method clear 44302 * @chainable 44303 * @example 44304 * <div> 44305 * <code> 44306 * // Clear the screen on mouse press. 44307 * function setup() { 44308 * createCanvas(100, 100); 44309 * } 44310 * 44311 * function draw() { 44312 * ellipse(mouseX, mouseY, 20, 20); 44313 * } 44314 * 44315 * function mousePressed() { 44316 * clear(); 44317 * } 44318 * </code> 44319 * </div> 44320 * 44321 * @alt
44322 * 20x20 white ellipses are continually drawn at mouse x and y coordinates. 44323 * 44324 */ 44325 44326p5.prototype.clear = function() { 44327 this._renderer.clear(); 44328 return this; 44329}; 44330 44331/** 44332 * colorMode() changes the way p5.js interprets color data. By default, the 44333 * parameters for fill(), stroke(), background(), and color() are defined by 44334 * values between 0 and 255 using the RGB color model. This is equivalent to 44335 * setting colorMode(RGB, 255). Setting colorMode(HSB) lets you use the HSB 44336 * system instead. By default, this is colorMode(HSB, 360, 100, 100, 1). You 44337 * can also use HSL. 44338 * <br><br> 44339 * Note: existing color objects remember the mode that they were created in, 44340 * so you can change modes as you like without affecting their appearance. 44341 * 44342 * 44343 * @method colorMode 44344 * @param {Constant} mode either RGB, HSB or HSL, corresponding to 44345 * Red/Green/Blue and Hue/Saturation/Brightness 44346 * (or Lightness) 44347 * @param {Number} [max] range for all values 44348 * @chainable 44349 * 44350 * @example 44351 * <div> 44352 * <code> 44353 * noStroke(); 44354 * colorMode(RGB, 100); 44355 * for (var i = 0; i < 100; i++) { 44356 * for (var j = 0; j < 100; j++) { 44357 * stroke(i, j, 0); 44358 * point(i, j); 44359 * } 44360 * } 44361 * </code> 44362 * </div> 44363 * 44364 * <div> 44365 * <code> 44366 * noStroke(); 44367 * colorMode(HSB, 100); 44368 * for (var i = 0; i < 100; i++) { 44369 * for (var j = 0; j < 100; j++) { 44370 * stroke(i, j, 100); 44371 * point(i, j); 44372 * } 44373 * } 44374 * </code> 44375 * </div> 44376 * 44377 * <div> 44378 * <code> 44379 * colorMode(RGB, 255); 44380 * var c = color(127, 255, 0); 44381 * 44382 * colorMode(RGB, 1); 44383 * var myColor = c._getRed(); 44384 * text(myColor, 10, 10, 80, 80); 44385 * </code> 44386 * </div> 44387 * 44388 * <div> 44389 * <code> 44390 * noFill(); 44391 * colorMode(RGB, 255, 255, 255, 1); 44392 * background(255); 44393 * 44394 * strokeWeight(4); 44395 * stroke(255, 0, 10, 0.3); 44396 * ellipse(40, 40, 50, 50); 44397 * ellipse(50, 50, 40, 40); 44398 * </code> 44399 * </div> 44400 * 44401 * @alt 44402 *Green to red gradient from bottom L to top R. shading originates from top left. 44403 *Rainbow gradient from left to right. Brightness increasing to white at top. 44404 *unknown image. 44405 *50x50 ellipse at middle L & 40x40 ellipse at center. Transluscent pink outlines. 44406 * 44407 */ 44408/** 44409 * @method colorMode 44410 * @param {Constant} mode 44411 * @param {Number} max1 range for the red or hue depending on the 44412 * current color mode 44413 * @param {Number} max2 range for the green or saturation depending 44414 * on the current color mode 44415 * @param {Number} max3 range for the blue or brightness/lighntess 44416 * depending on the current color mode 44417 * @param {Number} [maxA] range for the alpha 44418 * @chainable 44419 */ 44420p5.prototype.colorMode = function(mode, max1, max2, max3, maxA) { 44421 p5._validateParameters('colorMode', arguments); 44422 if ( 44423 mode === constants.RGB || 44424 mode === constants.HSB || 44425 mode === constants.HSL 44426 ) { 44427 // Set color mode. 44428 this._colorMode = mode; 44429 44430 // Set color maxes. 44431 var maxes = this._colorMaxes[mode]; 44432 if (arguments.length === 2) { 44433 maxes[0] = max1; // Red 44434 maxes[1] = max1; // Green 44435 maxes[2] = max1; // Blue 44436 maxes[3] = max1; // Alpha 44437 } else if (arguments.length === 4) { 44438 maxes[0] = max1; // Red 44439 maxes[1] = max2; // Green 44440 maxes[2] = max3; // Blue 44441 } else if (arguments.length === 5) { 44442 maxes[0] = max1; // Red 44443 maxes[1] = max2; // Green 44444 maxes[2] = max3; // Blue 44445 maxes[3] = maxA; // Alpha 44446 } 44447 } 44448 44449 return this; 44450}; 44451 44452/** 44453 * Sets the color used to fill shapes. For example, if you run 44454 * fill(204, 102, 0), all subsequent shapes will be filled with orange. This 44455 * color is either specified in terms of the RGB or HSB color depending on 44456 * the current colorMode(). (The default color space is RGB, with each value 44457 * in the range from 0 to 255). The alpha range by default is also 0 to 255. 44458 * <br><br> 44459 * If a single string argument is provided, RGB, RGBA and Hex CSS color strings 44460 * and all named color strings are supported. In this case, an alpha number 44461 * value as a second argument is not supported, the RGBA form should be used. 44462 * <br><br> 44463 * A p5 Color object can also be provided to set the fill color. 44464 * 44465 * @method fill 44466 * @param {Number} v1 red or hue value relative to 44467 * the current color range 44468 * @param {Number} v2 green or saturation value 44469 * relative to the current color range 44470 * @param {Number} v3 blue or brightness value 44471 * relative to the current color range 44472 * @param {Number} [alpha] 44473 * @chainable 44474 * @example 44475 * <div> 44476 * <code> 44477 * // Grayscale integer value 44478 * fill(51); 44479 * rect(20, 20, 60, 60); 44480 * </code> 44481 * </div> 44482 * 44483 * <div> 44484 * <code> 44485 * // R, G & B integer values 44486 * fill(255, 204, 0); 44487 * rect(20, 20, 60, 60); 44488 * </code> 44489 * </div> 44490 * 44491 * <div> 44492 * <code> 44493 * // H, S & B integer values 44494 * colorMode(HSB); 44495 * fill(255, 204, 100); 44496 * rect(20, 20, 60, 60); 44497 * </code> 44498 * </div> 44499 * 44500 * <div> 44501 * <code> 44502 * // Named SVG/CSS color string 44503 * fill('red'); 44504 * rect(20, 20, 60, 60); 44505 * </code> 44506 * </div> 44507 * 44508 * <div> 44509 * <code> 44510 * // three-digit hexadecimal RGB notation 44511 * fill('#fae'); 44512 * rect(20, 20, 60, 60); 44513 * </code> 44514 * </div> 44515 * 44516 * <div> 44517 * <code> 44518 * // six-digit hexadecimal RGB notation 44519 * fill('#222222'); 44520 * rect(20, 20, 60, 60); 44521 * </code> 44522 * </div> 44523 * 44524 * <div> 44525 * <code> 44526 * // integer RGB notation 44527 * fill('rgb(0,255,0)'); 44528 * rect(20, 20, 60, 60); 44529 * </code> 44530 * </div> 44531 * 44532 * <div> 44533 * <code> 44534 * // integer RGBA notation 44535 * fill('rgba(0,255,0, 0.25)'); 44536 * rect(20, 20, 60, 60); 44537 * </code> 44538 * </div> 44539 * 44540 * <div> 44541 * <code> 44542 * // percentage RGB notation 44543 * fill('rgb(100%,0%,10%)'); 44544 * rect(20, 20, 60, 60); 44545 * </code> 44546 * </div> 44547 * 44548 * <div> 44549 * <code> 44550 * // percentage RGBA notation 44551 * fill('rgba(100%,0%,100%,0.5)'); 44552 * rect(20, 20, 60, 60); 44553 * </code> 44554 * </div> 44555 * 44556 * <div> 44557 * <code> 44558 * // p5 Color object 44559 * fill(color(0, 0, 255)); 44560 * rect(20, 20, 60, 60); 44561 * </code> 44562 * </div> 44563 * @alt 44564 * 60x60 dark charcoal grey rect with black outline in center of canvas. 44565 * 60x60 yellow rect with black outline in center of canvas. 44566 * 60x60 royal blue rect with black outline in center of canvas. 44567 * 60x60 red rect with black outline in center of canvas. 44568 * 60x60 pink rect with black outline in center of canvas. 44569 * 60x60 black rect with black outline in center of canvas. 44570 * 60x60 light green rect with black outline in center of canvas. 44571 * 60x60 soft green rect with black outline in center of canvas. 44572 * 60x60 red rect with black outline in center of canvas. 44573 * 60x60 dark fushcia rect with black outline in center of canvas. 44574 * 60x60 blue rect with black outline in center of canvas. 44575 */ 44576 44577/** 44578 * @method fill 44579 * @param {String} value a color string 44580 * @chainable 44581 */ 44582 44583/** 44584 * @method fill 44585 * @param {Number} gray a gray value 44586 * @param {Number} [alpha] 44587 * @chainable 44588 */ 44589 44590/** 44591 * @method fill 44592 * @param {Number[]} values an array containing the red,green,blue & 44593 * and alpha components of the color 44594 * @chainable 44595 */ 44596 44597/** 44598 * @method fill 44599 * @param {p5.Color} color the fill color 44600 * @chainable 44601 */ 44602p5.prototype.fill = function() { 44603 this._renderer._setProperty('_fillSet', true); 44604 this._renderer._setProperty('_doFill', true);
44605 this._renderer.fill.apply(this._renderer, arguments); 44606 return this; 44607}; 44608 44609/** 44610 * Disables filling geometry. If both noStroke() and noFill() are called, 44611 * nothing will be drawn to the screen. 44612 * 44613 * @method noFill 44614 * @chainable 44615 * @example 44616 * <div> 44617 * <code> 44618 * rect(15, 10, 55, 55); 44619 * noFill(); 44620 * rect(20, 20, 60, 60); 44621 * </code> 44622 * </div> 44623 * 44624 * <div modernizr='webgl'> 44625 * <code> 44626 * function setup() { 44627 * createCanvas(100, 100, WEBGL); 44628 * } 44629 * 44630 * function draw() { 44631 * background(0); 44632 * noFill(); 44633 * stroke(100, 100, 240); 44634 * rotateX(frameCount * 0.01); 44635 * rotateY(frameCount * 0.01); 44636 * box(45, 45, 45); 44637 * } 44638 * </code> 44639 * </div> 44640 * 44641 * @alt 44642 * white rect top middle and noFill rect center. Both 60x60 with black outlines. 44643 * black canvas with purple cube wireframe spinning 44644 */ 44645p5.prototype.noFill = function() { 44646 this._renderer._setProperty('_doFill', false); 44647 return this; 44648}; 44649 44650/** 44651 * Disables drawing the stroke (outline). If both noStroke() and noFill() 44652 * are called, nothing will be drawn to the screen. 44653 * 44654 * @method noStroke 44655 * @chainable 44656 * @example 44657 * <div> 44658 * <code> 44659 * noStroke(); 44660 * rect(20, 20, 60, 60); 44661 * </code> 44662 * </div> 44663 * 44664 * <div modernizr='webgl'> 44665 * <code> 44666 * function setup() { 44667 * createCanvas(100, 100, WEBGL); 44668 * } 44669 * 44670 * function draw() { 44671 * background(0); 44672 * noStroke(); 44673 * fill(240, 150, 150); 44674 * rotateX(frameCount * 0.01); 44675 * rotateY(frameCount * 0.01); 44676 * box(45, 45, 45); 44677 * } 44678 * </code> 44679 * </div> 44680 * 44681 * @alt 44682 * 60x60 white rect at center. no outline. 44683 * black canvas with pink cube spinning 44684 */ 44685p5.prototype.noStroke = function() { 44686 this._renderer._setProperty('_doStroke', false); 44687 return this; 44688}; 44689 44690/** 44691 * Sets the color used to draw lines and borders around shapes. This color 44692 * is either specified in terms of the RGB or HSB color depending on the 44693 * current colorMode() (the default color space is RGB, with each value in 44694 * the range from 0 to 255). The alpha range by default is also 0 to 255. 44695 * <br><br> 44696 * If a single string argument is provided, RGB, RGBA and Hex CSS color 44697 * strings and all named color strings are supported. In this case, an alpha 44698 * number value as a second argument is not supported, the RGBA form should be 44699 * used. 44700 * <br><br> 44701 * A p5 Color object can also be provided to set the stroke color. 44702 * 44703 * 44704 * @method stroke 44705 * @param {Number} v1 red or hue value relative to 44706 * the current color range 44707 * @param {Number} v2 green or saturation value 44708 * relative to the current color range 44709 * @param {Number} v3 blue or brightness value 44710 * relative to the current color range 44711 * @param {Number} [alpha] 44712 * @chainable 44713 * 44714 * @example 44715 * <div> 44716 * <code> 44717 * // Grayscale integer value 44718 * strokeWeight(4); 44719 * stroke(51); 44720 * rect(20, 20, 60, 60); 44721 * </code> 44722 * </div> 44723 * 44724 * <div> 44725 * <code> 44726 * // R, G & B integer values 44727 * stroke(255, 204, 0); 44728 * strokeWeight(4); 44729 * rect(20, 20, 60, 60); 44730 * </code> 44731 * </div> 44732 * 44733 * <div> 44734 * <code> 44735 * // H, S & B integer values 44736 * colorMode(HSB); 44737 * strokeWeight(4); 44738 * stroke(255, 204, 100); 44739 * rect(20, 20, 60, 60); 44740 * </code> 44741 * </div> 44742 * 44743 * <div> 44744 * <code> 44745 * // Named SVG/CSS color string 44746 * stroke('red'); 44747 * strokeWeight(4); 44748 * rect(20, 20, 60, 60); 44749 * </code> 44750 * </div> 44751 * 44752 * <div> 44753 * <code> 44754 * // three-digit hexadecimal RGB notation 44755 * stroke('#fae'); 44756 * strokeWeight(4); 44757 * rect(20, 20, 60, 60); 44758 * </code> 44759 * </div> 44760 * 44761 * <div> 44762 * <code> 44763 * // six-digit hexadecimal RGB notation 44764 * stroke('#222222'); 44765 * strokeWeight(4); 44766 * rect(20, 20, 60, 60); 44767 * </code> 44768 * </div> 44769 * 44770 * <div> 44771 * <code> 44772 * // integer RGB notation 44773 * stroke('rgb(0,255,0)'); 44774 * strokeWeight(4); 44775 * rect(20, 20, 60, 60); 44776 * </code> 44777 * </div> 44778 * 44779 * <div> 44780 * <code> 44781 * // integer RGBA notation 44782 * stroke('rgba(0,255,0,0.25)'); 44783 * strokeWeight(4); 44784 * rect(20, 20, 60, 60); 44785 * </code> 44786 * </div> 44787 * 44788 * <div> 44789 * <code> 44790 * // percentage RGB notation 44791 * stroke('rgb(100%,0%,10%)'); 44792 * strokeWeight(4); 44793 * rect(20, 20, 60, 60); 44794 * </code> 44795 * </div> 44796 * 44797 * <div> 44798 * <code> 44799 * // percentage RGBA notation 44800 * stroke('rgba(100%,0%,100%,0.5)'); 44801 * strokeWeight(4); 44802 * rect(20, 20, 60, 60); 44803 * </code> 44804 * </div> 44805 * 44806 * <div> 44807 * <code> 44808 * // p5 Color object
44809 * stroke(color(0, 0, 255)); 44810 * strokeWeight(4); 44811 * rect(20, 20, 60, 60); 44812 * </code> 44813 * </div> 44814 * 44815 * @alt 44816 * 60x60 white rect at center. Dark charcoal grey outline. 44817 * 60x60 white rect at center. Yellow outline. 44818 * 60x60 white rect at center. Royal blue outline. 44819 * 60x60 white rect at center. Red outline. 44820 * 60x60 white rect at center. Pink outline. 44821 * 60x60 white rect at center. Black outline. 44822 * 60x60 white rect at center. Bright green outline. 44823 * 60x60 white rect at center. Soft green outline. 44824 * 60x60 white rect at center. Red outline. 44825 * 60x60 white rect at center. Dark fushcia outline. 44826 * 60x60 white rect at center. Blue outline. 44827 */ 44828 44829/** 44830 * @method stroke 44831 * @param {String} value a color string 44832 * @chainable 44833 */ 44834 44835/** 44836 * @method stroke 44837 * @param {Number} gray a gray value 44838 * @param {Number} [alpha] 44839 * @chainable 44840 */ 44841 44842/** 44843 * @method stroke 44844 * @param {Number[]} values an array containing the red,green,blue & 44845 * and alpha components of the color 44846 * @chainable 44847 */ 44848 44849/** 44850 * @method stroke 44851 * @param {p5.Color} color the stroke color 44852 * @chainable 44853 */ 44854 44855p5.prototype.stroke = function() { 44856 this._renderer._setProperty('_strokeSet', true); 44857 this._renderer._setProperty('_doStroke', true); 44858 this._renderer.stroke.apply(this._renderer, arguments); 44859 return this; 44860}; 44861 44862module.exports = p5; 44863 44864},{"../core/constants":21,"../core/core":22,"./p5.Color":16}],18:[function(_dereq_,module,exports){ 44865/** 44866 * @module Shape 44867 * @submodule 2D Primitives 44868 * @for p5 44869 * @requires core 44870 * @requires constants 44871 */ 44872 44873'use strict'; 44874 44875var p5 = _dereq_('./core'); 44876var constants = _dereq_('./constants'); 44877var canvas = _dereq_('./canvas'); 44878_dereq_('./error_helpers'); 44879 44880/** 44881 * Draw an arc to the screen. If called with only x, y, w, h, start, and 44882 * stop, the arc will be drawn and filled as an open pie segment. If a mode parameter is provided, the arc 44883 * will be filled like an open semi-circle (OPEN) , a closed semi-circle (CHORD), or as a closed pie segment (PIE). The 44884 * origin may be changed with the ellipseMode() function.<br><br> 44885 * Note that drawing a full circle (ex: 0 to TWO_PI) will appear blank 44886 * because 0 and TWO_PI are the same position on the unit circle. The 44887 * best way to handle this is by using the ellipse() function instead 44888 * to create a closed ellipse, and to use the arc() function 44889 * only to draw parts of an ellipse. 44890 * 44891 * @method arc 44892 * @param {Number} x x-coordinate of the arc's ellipse 44893 * @param {Number} y y-coordinate of the arc's ellipse 44894 * @param {Number} w width of the arc's ellipse by default 44895 * @param {Number} h height of the arc's ellipse by default 44896 * @param {Number} start angle to start the arc, specified in radians 44897 * @param {Number} stop angle to stop the arc, specified in radians 44898 * @param {Constant} [mode] optional parameter to determine the way of drawing 44899 * the arc. either CHORD, PIE or OPEN 44900 * @chainable 44901 * @example 44902 * <div> 44903 * <code> 44904 * arc(50, 55, 50, 50, 0, HALF_PI); 44905 * noFill(); 44906 * arc(50, 55, 60, 60, HALF_PI, PI); 44907 * arc(50, 55, 70, 70, PI, PI + QUARTER_PI); 44908 * arc(50, 55, 80, 80, PI + QUARTER_PI, TWO_PI); 44909 * </code> 44910 * </div> 44911 * 44912 * <div> 44913 * <code> 44914 * arc(50, 50, 80, 80, 0, PI + QUARTER_PI); 44915 * </code> 44916 * </div> 44917 * 44918 * <div> 44919 * <code> 44920 * arc(50, 50, 80, 80, 0, PI + QUARTER_PI, OPEN); 44921 * </code> 44922 * </div> 44923 * 44924 * <div> 44925 * <code> 44926 * arc(50, 50, 80, 80, 0, PI + QUARTER_PI, CHORD); 44927 * </code> 44928 * </div> 44929 * 44930 * <div> 44931 * <code> 44932 * arc(50, 50, 80, 80, 0, PI + QUARTER_PI, PIE); 44933 * </code> 44934 * </div> 44935 * 44936 * @alt 44937 *shattered outline of an ellipse with a quarter of a white circle bottom-right. 44938 *white ellipse with top right quarter missing. 44939 *white ellipse with black outline with top right missing. 44940 *white ellipse with top right missing with black outline around shape. 44941 *white ellipse with top right quarter missing with black outline around the shape. 44942 * 44943 */ 44944p5.prototype.arc = function(x, y, w, h, start, stop, mode) { 44945 p5._validateParameters('arc', arguments); 44946 if (!this._renderer._doStroke && !this._renderer._doFill) { 44947 return this; 44948 } 44949 44950 start = this._toRadians(start); 44951 stop = this._toRadians(stop); 44952 44953 // Make all angles positive... 44954 while (start < 0) { 44955 start += constants.TWO_PI; 44956 } 44957 while (stop < 0) { 44958 stop += constants.TWO_PI; 44959 } 44960 // ...and confine them to the interval [0,TWO_PI). 44961 start %= constants.TWO_PI; 44962 stop %= constants.TWO_PI; 44963 44964 // account for full circle 44965 if (stop === start) { 44966 stop += constants.TWO_PI; 44967 } 44968 44969 // Adjust angles to counter linear scaling. 44970 if (start <= constants.HALF_PI) { 44971 start = Math.atan(w / h * Math.tan(start)); 44972 } else if (start > constants.HALF_PI && start <= 3 * constants.HALF_PI) { 44973 start = Math.atan(w / h * Math.tan(start)) + constants.PI; 44974 } else { 44975 start = Math.atan(w / h * Math.tan(start)) + constants.TWO_PI; 44976 } 44977 if (stop <= constants.HALF_PI) { 44978 stop = Math.atan(w / h * Math.tan(stop)); 44979 } else if (stop > constants.HALF_PI && stop <= 3 * constants.HALF_PI) { 44980 stop = Math.atan(w / h * Math.tan(stop)) + constants.PI; 44981 } else { 44982 stop = Math.atan(w / h * Math.tan(stop)) + constants.TWO_PI; 44983 } 44984 44985 // Exceed the interval if necessary in order to preserve the size and 44986 // orientation of the arc. 44987 if (start > stop) { 44988 stop += constants.TWO_PI; 44989 } 44990 // p5 supports negative width and heights for ellipses 44991 w = Math.abs(w); 44992 h = Math.abs(h); 44993 this._renderer.arc(x, y, w, h, start, stop, mode); 44994 return this; 44995}; 44996 44997/** 44998 * Draws an ellipse (oval) to the screen. An ellipse with equal width and 44999 * height is a circle. By default, the first two parameters set the location, 45000 * and the third and fourth parameters set the shape's width and height. If 45001 * no height is specified, the value of width is used for both the width and 45002 * height. If a negative height or width is specified, the absolute value is taken. 45003 * The origin may be changed with the ellipseMode() function. 45004 * 45005 * @method ellipse 45006 * @param {Number} x x-coordinate of the ellipse. 45007 * @param {Number} y y-coordinate of the ellipse. 45008 * @param {Number} w width of the ellipse. 45009 * @param {Number} [h] height of the ellipse. 45010 * @chainable 45011 * @example 45012 * <div> 45013 * <code> 45014 * ellipse(56, 46, 55, 55); 45015 * </code> 45016 * </div> 45017 * 45018 * @alt 45019 *white ellipse with black outline in middle-right of canvas that is 55x55. 45020 * 45021 */ 45022/** 45023 * @method ellipse 45024 * @param {Number} x 45025 * @param {Number} y 45026 * @param {Number} w 45027 * @param {Number} h 45028 * @param {Integer} detail number of radial sectors to draw 45029 */ 45030p5.prototype.ellipse = function(x, y, w, h, detailX) { 45031 p5._validateParameters('ellipse', arguments); 45032 45033 // p5 supports negative width and heights for rects 45034 if (w < 0) { 45035 w = Math.abs(w); 45036 } 45037 45038 if (typeof h === 'undefined') { 45039 // Duplicate 3rd argument if only 3 given. 45040 h = w; 45041 } else if (h < 0) { 45042 h = Math.abs(h); 45043 } 45044 45045 if (this._renderer._doStroke || this._renderer._doFill) { 45046 var vals = canvas.modeAdjust(x, y, w, h, this._renderer._ellipseMode); 45047 this._renderer.ellipse([vals.x, vals.y, vals.w, vals.h, detailX]); 45048 } 45049 45050 return this; 45051}; 45052/** 45053 * Draws a line (a direct path between two points) to the screen. The version 45054 * of line() with four parameters draws the line in 2D. To color a line, use 45055 * the stroke() function. A line cannot be filled, therefore the fill() 45056 * function will not affect the color of a line. 2D lines are drawn with a 45057 * width of one pixel by default, but this can be changed with the
45058 * strokeWeight() function. 45059 * 45060 * @method line 45061 * @param {Number} x1 the x-coordinate of the first point 45062 * @param {Number} y1 the y-coordinate of the first point 45063 * @param {Number} x2 the x-coordinate of the second point 45064 * @param {Number} y2 the y-coordinate of the second point 45065 * @chainable 45066 * @example 45067 * <div> 45068 * <code> 45069 * line(30, 20, 85, 75); 45070 * </code> 45071 * </div> 45072 * 45073 * <div> 45074 * <code> 45075 * line(30, 20, 85, 20); 45076 * stroke(126); 45077 * line(85, 20, 85, 75); 45078 * stroke(255); 45079 * line(85, 75, 30, 75); 45080 * </code> 45081 * </div> 45082 * 45083 * @alt 45084 *line 78 pixels long running from mid-top to bottom-right of canvas. 45085 *3 lines of various stroke sizes. Form top, bottom and right sides of a square. 45086 * 45087 */ 45088/** 45089 * @method line 45090 * @param {Number} x1 45091 * @param {Number} y1 45092 * @param {Number} z1 the z-coordinate of the first point 45093 * @param {Number} x2 45094 * @param {Number} y2 45095 * @param {Number} z2 the z-coordinate of the second point 45096 * @chainable 45097 */ 45098p5.prototype.line = function() { 45099 p5._validateParameters('line', arguments); 45100 45101 if (this._renderer._doStroke) { 45102 this._renderer.line.apply(this._renderer, arguments); 45103 } 45104 45105 return this; 45106}; 45107 45108/** 45109 * Draws a point, a coordinate in space at the dimension of one pixel. 45110 * The first parameter is the horizontal value for the point, the second 45111 * value is the vertical value for the point. The color of the point is 45112 * determined by the current stroke. 45113 * 45114 * @method point 45115 * @param {Number} x the x-coordinate 45116 * @param {Number} y the y-coordinate 45117 * @param {Number} [z] the z-coordinate (for WEBGL mode) 45118 * @chainable 45119 * @example 45120 * <div> 45121 * <code> 45122 * point(30, 20); 45123 * point(85, 20); 45124 * point(85, 75); 45125 * point(30, 75); 45126 * </code> 45127 * </div> 45128 * 45129 * @alt 45130 *4 points centered in the middle-right of the canvas. 45131 * 45132 */ 45133p5.prototype.point = function() { 45134 p5._validateParameters('point', arguments); 45135 45136 if (this._renderer._doStroke) { 45137 this._renderer.point.apply(this._renderer, arguments); 45138 } 45139 45140 return this; 45141}; 45142 45143/** 45144 * Draw a quad. A quad is a quadrilateral, a four sided polygon. It is 45145 * similar to a rectangle, but the angles between its edges are not 45146 * constrained to ninety degrees. The first pair of parameters (x1,y1) 45147 * sets the first vertex and the subsequent pairs should proceed 45148 * clockwise or counter-clockwise around the defined shape. 45149 * 45150 * @method quad 45151 * @param {Number} x1 the x-coordinate of the first point 45152 * @param {Number} y1 the y-coordinate of the first point 45153 * @param {Number} x2 the x-coordinate of the second point 45154 * @param {Number} y2 the y-coordinate of the second point 45155 * @param {Number} x3 the x-coordinate of the third point 45156 * @param {Number} y3 the y-coordinate of the third point 45157 * @param {Number} x4 the x-coordinate of the fourth point 45158 * @param {Number} y4 the y-coordinate of the fourth point 45159 * @chainable 45160 * @example 45161 * <div> 45162 * <code> 45163 * quad(38, 31, 86, 20, 69, 63, 30, 76); 45164 * </code> 45165 * </div> 45166 * 45167 * @alt 45168 *irregular white quadrilateral shape with black outline mid-right of canvas. 45169 * 45170 */ 45171/** 45172 * @method quad 45173 * @param {Number} x1 45174 * @param {Number} y1 45175 * @param {Number} z1 45176 * @param {Number} x2 45177 * @param {Number} y2 45178 * @param {Number} z2 45179 * @param {Number} x3 45180 * @param {Number} y3 45181 * @param {Number} z3 45182 * @param {Number} x4 45183 * @param {Number} y4 45184 * @param {Number} z4 45185 * @chainable 45186 */ 45187p5.prototype.quad = function() { 45188 p5._validateParameters('quad', arguments); 45189 45190 if (this._renderer._doStroke || this._renderer._doFill) { 45191 this._renderer.quad.apply(this._renderer, arguments); 45192 } 45193 45194 return this; 45195}; 45196 45197/** 45198 * Draws a rectangle to the screen. A rectangle is a four-sided shape with 45199 * every angle at ninety degrees. By default, the first two parameters set 45200 * the location of the upper-left corner, the third sets the width, and the 45201 * fourth sets the height. The way these parameters are interpreted, however, 45202 * may be changed with the rectMode() function. 45203 * <br><br> 45204 * The fifth, sixth, seventh and eighth parameters, if specified, 45205 * determine corner radius for the top-right, top-left, lower-right and 45206 * lower-left corners, respectively. An omitted corner radius parameter is set 45207 * to the value of the previously specified radius value in the parameter list. 45208 * 45209 * @method rect 45210 * @param {Number} x x-coordinate of the rectangle. 45211 * @param {Number} y y-coordinate of the rectangle. 45212 * @param {Number} w width of the rectangle. 45213 * @param {Number} h height of the rectangle. 45214 * @param {Number} [tl] optional radius of top-left corner. 45215 * @param {Number} [tr] optional radius of top-right corner. 45216 * @param {Number} [br] optional radius of bottom-right corner. 45217 * @param {Number} [bl] optional radius of bottom-left corner. 45218 * @chainable 45219 * @example 45220 * <div> 45221 * <code> 45222 * // Draw a rectangle at location (30, 20) with a width and height of 55. 45223 * rect(30, 20, 55, 55); 45224 * </code> 45225 * </div> 45226 * 45227 * <div> 45228 * <code> 45229 * // Draw a rectangle with rounded corners, each having a radius of 20. 45230 * rect(30, 20, 55, 55, 20); 45231 * </code> 45232 * </div> 45233 * 45234 * <div> 45235 * <code> 45236 * // Draw a rectangle with rounded corners having the following radii: 45237 * // top-left = 20, top-right = 15, bottom-right = 10, bottom-left = 5. 45238 * rect(30, 20, 55, 55, 20, 15, 10, 5); 45239 * </code> 45240 * </div> 45241 * 45242 * @alt 45243 * 55x55 white rect with black outline in mid-right of canvas. 45244 * 55x55 white rect with black outline and rounded edges in mid-right of canvas. 45245 * 55x55 white rect with black outline and rounded edges of different radii. 45246 */ 45247/** 45248 * @method rect 45249 * @param {Number} x 45250 * @param {Number} y 45251 * @param {Number} w 45252 * @param {Number} h 45253 * @param {Integer} [detailX] number of segments in the x-direction 45254 * @param {Integer} [detailY] number of segments in the y-direction 45255 * @chainable 45256 */ 45257p5.prototype.rect = function() { 45258 p5._validateParameters('rect', arguments); 45259 45260 if (this._renderer._doStroke || this._renderer._doFill) { 45261 var vals = canvas.modeAdjust( 45262 arguments[0], 45263 arguments[1], 45264 arguments[2], 45265 arguments[3], 45266 this._renderer._rectMode 45267 ); 45268 var args = [vals.x, vals.y, vals.w, vals.h]; 45269 // append the additional arguments (either cornder radii, or 45270 // segment details) to the argument list 45271 for (var i = 4; i < arguments.length; i++) { 45272 args[i] = arguments[i]; 45273 } 45274 this._renderer.rect(args); 45275 } 45276 45277 return this; 45278}; 45279 45280/** 45281 * A triangle is a plane created by connecting three points. The first two 45282 * arguments specify the first point, the middle two arguments specify the 45283 * second point, and the last two arguments specify the third point. 45284 * 45285 * @method triangle 45286 * @param {Number} x1 x-coordinate of the first point 45287 * @param {Number} y1 y-coordinate of the first point 45288 * @param {Number} x2 x-coordinate of the second point 45289 * @param {Number} y2 y-coordinate of the second point 45290 * @param {Number} x3 x-coordinate of the third point 45291 * @param {Number} y3 y-coordinate of the third point 45292 * @chainable 45293 * @example 45294 * <div> 45295 * <code> 45296 * triangle(30, 75, 58, 20, 86, 75); 45297 * </code> 45298 * </div> 45299 * 45300 *@alt 45301 * white triangle with black outline in mid-right of canvas. 45302 * 45303 */ 45304p5.prototype.triangle = function() { 45305 p5._validateParameters('triangle', arguments); 45306 45307 if (this._renderer._doStroke || this._renderer._doFill) { 45308 this._renderer.triangle(arguments); 45309 } 45310 45311 return this; 45312}; 45313 45314module.exports = p5; 45315 45316},{"./canvas":20,"./constants":21,"./core":22,"./error_helpers":25}],19:[function(_dereq_,module,exports){ 45317/** 45318 * @module Shape 45319 * @submodule Attributes 45320 * @for p5 45321 * @requires core 45322 * @requires constants 45323 */ 45324 45325'use strict'; 45326 45327var p5 = _dereq_('./core'); 45328var constants = _dereq_('./constants'); 45329 45330/** 45331 * Modifies the location from which ellipses are drawn by changing the way 45332 * in which parameters given to ellipse() are interpreted. 45333 * <br><br> 45334 * The default mode is ellipseMode(CENTER), which interprets the first two 45335 * parameters of ellipse() as the shape's center point, while the third and 45336 * fourth parameters are its width and height. 45337 * <br><br> 45338 * ellipseMode(RADIUS) also uses the first two parameters of ellipse() as 45339 * the shape's center point, but uses the third and fourth parameters to 45340 * specify half of the shapes's width and height. 45341 * <br><br> 45342 * ellipseMode(CORNER) interprets the first two parameters of ellipse() as 45343 * the upper-left corner of the shape, while the third and fourth parameters 45344 * are its width and height. 45345 * <br><br> 45346 * ellipseMode(CORNERS) interprets the first two parameters of ellipse() as 45347 * the location of one corner of the ellipse's bounding box, and the third 45348 * and fourth parameters as the location of the opposite corner. 45349 * <br><br> 45350 * The parameter must be written in ALL CAPS because Javascript is a 45351 * case-sensitive language. 45352 * 45353 * @method ellipseMode 45354 * @param {Constant} mode either CENTER, RADIUS, CORNER, or CORNERS 45355 * @chainable 45356 * @example 45357 * <div> 45358 * <code> 45359 * ellipseMode(RADIUS); // Set ellipseMode to RADIUS 45360 * fill(255); // Set fill to white 45361 * ellipse(50, 50, 30, 30); // Draw white ellipse using RADIUS mode 45362 * 45363 * ellipseMode(CENTER); // Set ellipseMode to CENTER 45364 * fill(100); // Set fill to gray 45365 * ellipse(50, 50, 30, 30); // Draw gray ellipse using CENTER mode 45366 * </code> 45367 * </div> 45368 * 45369 * <div> 45370 * <code> 45371 * ellipseMode(CORNER); // Set ellipseMode is CORNER 45372 * fill(255); // Set fill to white 45373 * ellipse(25, 25, 50, 50); // Draw white ellipse using CORNER mode 45374 * 45375 * ellipseMode(CORNERS); // Set ellipseMode to CORNERS 45376 * fill(100); // Set fill to gray 45377 * ellipse(25, 25, 50, 50); // Draw gray ellipse using CORNERS mode 45378 * </code> 45379 * </div> 45380 * 45381 * @alt 45382 * 60x60 white ellipse and 30x30 grey ellipse with black outlines at center. 45383 * 60x60 white ellipse @center and 30x30 grey ellipse top-right, black outlines. 45384 * 45385 */ 45386p5.prototype.ellipseMode = function(m) { 45387 p5._validateParameters('ellipseMode', arguments); 45388 if ( 45389 m === constants.CORNER || 45390 m === constants.CORNERS || 45391 m === constants.RADIUS || 45392 m === constants.CENTER 45393 ) { 45394 this._renderer._ellipseMode = m; 45395 } 45396 return this; 45397}; 45398 45399/** 45400 * Draws all geometry with jagged (aliased) edges. Note that smooth() is 45401 * active by default, so it is necessary to call noSmooth() to disable 45402 * smoothing of geometry, images, and fonts. 45403 * 45404 * @method noSmooth 45405 * @chainable 45406 * @example 45407 * <div> 45408 * <code> 45409 * background(0); 45410 * noStroke();
45411 * smooth(); 45412 * ellipse(30, 48, 36, 36); 45413 * noSmooth(); 45414 * ellipse(70, 48, 36, 36); 45415 * </code> 45416 * </div> 45417 * 45418 * @alt 45419 * 2 pixelated 36x36 white ellipses to left & right of center, black background 45420 * 45421 */ 45422p5.prototype.noSmooth = function() { 45423 this._renderer.noSmooth(); 45424 return this; 45425}; 45426 45427/** 45428 * Modifies the location from which rectangles are drawn by changing the way 45429 * in which parameters given to rect() are interpreted. 45430 * <br><br> 45431 * The default mode is rectMode(CORNER), which interprets the first two 45432 * parameters of rect() as the upper-left corner of the shape, while the 45433 * third and fourth parameters are its width and height. 45434 * <br><br> 45435 * rectMode(CORNERS) interprets the first two parameters of rect() as the 45436 * location of one corner, and the third and fourth parameters as the 45437 * location of the opposite corner. 45438 * <br><br> 45439 * rectMode(CENTER) interprets the first two parameters of rect() as the 45440 * shape's center point, while the third and fourth parameters are its 45441 * width and height. 45442 * <br><br> 45443 * rectMode(RADIUS) also uses the first two parameters of rect() as the 45444 * shape's center point, but uses the third and fourth parameters to specify 45445 * half of the shapes's width and height. 45446 * <br><br> 45447 * The parameter must be written in ALL CAPS because Javascript is a 45448 * case-sensitive language. 45449 * 45450 * @method rectMode 45451 * @param {Constant} mode either CORNER, CORNERS, CENTER, or RADIUS 45452 * @chainable 45453 * @example 45454 * <div> 45455 * <code> 45456 * rectMode(CORNER); // Default rectMode is CORNER 45457 * fill(255); // Set fill to white 45458 * rect(25, 25, 50, 50); // Draw white rect using CORNER mode 45459 * 45460 * rectMode(CORNERS); // Set rectMode to CORNERS 45461 * fill(100); // Set fill to gray 45462 * rect(25, 25, 50, 50); // Draw gray rect using CORNERS mode 45463 * </code> 45464 * </div> 45465 * 45466 * <div> 45467 * <code> 45468 * rectMode(RADIUS); // Set rectMode to RADIUS 45469 * fill(255); // Set fill to white 45470 * rect(50, 50, 30, 30); // Draw white rect using RADIUS mode 45471 * 45472 * rectMode(CENTER); // Set rectMode to CENTER 45473 * fill(100); // Set fill to gray 45474 * rect(50, 50, 30, 30); // Draw gray rect using CENTER mode 45475 * </code> 45476 * </div> 45477 * 45478 * @alt 45479 * 50x50 white rect at center and 25x25 grey rect in the top left of the other. 45480 * 50x50 white rect at center and 25x25 grey rect in the center of the other. 45481 * 45482 */ 45483p5.prototype.rectMode = function(m) { 45484 p5._validateParameters('rectMode', arguments); 45485 if ( 45486 m === constants.CORNER || 45487 m === constants.CORNERS || 45488 m === constants.RADIUS || 45489 m === constants.CENTER 45490 ) { 45491 this._renderer._rectMode = m; 45492 } 45493 return this; 45494}; 45495 45496/** 45497 * Draws all geometry with smooth (anti-aliased) edges. smooth() will also 45498 * improve image quality of resized images. Note that smooth() is active by 45499 * default; noSmooth() can be used to disable smoothing of geometry, 45500 * images, and fonts. 45501 * 45502 * @method smooth 45503 * @chainable 45504 * @example 45505 * <div> 45506 * <code> 45507 * background(0); 45508 * noStroke(); 45509 * smooth(); 45510 * ellipse(30, 48, 36, 36); 45511 * noSmooth(); 45512 * ellipse(70, 48, 36, 36); 45513 * </code> 45514 * </div> 45515 * 45516 * @alt 45517 * 2 pixelated 36x36 white ellipses one left one right of center. On black. 45518 * 45519 */ 45520p5.prototype.smooth = function() { 45521 this._renderer.smooth(); 45522 return this; 45523}; 45524 45525/** 45526 * Sets the style for rendering line endings. These ends are either squared, 45527 * extended, or rounded, each of which specified with the corresponding 45528 * parameters: SQUARE, PROJECT, and ROUND. The default cap is ROUND. 45529 * 45530 * @method strokeCap 45531 * @param {Constant} cap either SQUARE, PROJECT, or ROUND 45532 * @chainable 45533 * @example 45534 * <div> 45535 * <code> 45536 * strokeWeight(12.0); 45537 * strokeCap(ROUND); 45538 * line(20, 30, 80, 30); 45539 * strokeCap(SQUARE); 45540 * line(20, 50, 80, 50); 45541 * strokeCap(PROJECT); 45542 * line(20, 70, 80, 70); 45543 * </code> 45544 * </div> 45545 * 45546 * @alt 45547 * 3 lines. Top line: rounded ends, mid: squared, bottom:longer squared ends. 45548 * 45549 */ 45550p5.prototype.strokeCap = function(cap) { 45551 p5._validateParameters('strokeCap', arguments); 45552 if ( 45553 cap === constants.ROUND || 45554 cap === constants.SQUARE || 45555 cap === constants.PROJECT 45556 ) { 45557 this._renderer.strokeCap(cap); 45558 } 45559 return this; 45560}; 45561 45562/** 45563 * Sets the style of the joints which connect line segments. These joints 45564 * are either mitered, beveled, or rounded and specified with the 45565 * corresponding parameters MITER, BEVEL, and ROUND. The default joint is 45566 * MITER. 45567 * 45568 * @method strokeJoin 45569 * @param {Constant} join either MITER, BEVEL, ROUND 45570 * @chainable 45571 * @example 45572 * <div> 45573 * <code> 45574 * noFill(); 45575 * strokeWeight(10.0); 45576 * strokeJoin(MITER); 45577 * beginShape(); 45578 * vertex(35, 20); 45579 * vertex(65, 50); 45580 * vertex(35, 80); 45581 * endShape(); 45582 * </code> 45583 * </div> 45584 * 45585 * <div> 45586 * <code> 45587 * noFill(); 45588 * strokeWeight(10.0); 45589 * strokeJoin(BEVEL); 45590 * beginShape(); 45591 * vertex(35, 20); 45592 * vertex(65, 50); 45593 * vertex(35, 80); 45594 * endShape(); 45595 * </code> 45596 * </div> 45597 * 45598 * <div> 45599 * <code> 45600 * noFill(); 45601 * strokeWeight(10.0); 45602 * strokeJoin(ROUND); 45603 * beginShape(); 45604 * vertex(35, 20); 45605 * vertex(65, 50); 45606 * vertex(35, 80); 45607 * endShape(); 45608 * </code> 45609 * </div> 45610 * 45611 * @alt 45612 * Right-facing arrowhead shape with pointed tip in center of canvas. 45613 * Right-facing arrowhead shape with flat tip in center of canvas. 45614 * Right-facing arrowhead shape with rounded tip in center of canvas. 45615 * 45616 */ 45617p5.prototype.strokeJoin = function(join) { 45618 p5._validateParameters('strokeJoin', arguments); 45619 if ( 45620 join === constants.ROUND || 45621 join === constants.BEVEL || 45622 join === constants.MITER 45623 ) { 45624 this._renderer.strokeJoin(join); 45625 } 45626 return this; 45627}; 45628 45629/** 45630 * Sets the width of the stroke used for lines, points, and the border 45631 * around shapes. All widths are set in units of pixels. 45632 * 45633 * @method strokeWeight 45634 * @param {Number} weight the weight (in pixels) of the stroke 45635 * @chainable 45636 * @example 45637 * <div> 45638 * <code> 45639 * strokeWeight(1); // Default 45640 * line(20, 20, 80, 20);
45641 * strokeWeight(4); // Thicker 45642 * line(20, 40, 80, 40); 45643 * strokeWeight(10); // Beastly 45644 * line(20, 70, 80, 70); 45645 * </code> 45646 * </div> 45647 * 45648 * @alt 45649 * 3 horizontal black lines. Top line: thin, mid: medium, bottom:thick. 45650 * 45651 */ 45652p5.prototype.strokeWeight = function(w) { 45653 p5._validateParameters('strokeWeight', arguments); 45654 this._renderer.strokeWeight(w); 45655 return this; 45656}; 45657 45658module.exports = p5; 45659 45660},{"./constants":21,"./core":22}],20:[function(_dereq_,module,exports){ 45661/** 45662 * @requires constants 45663 */ 45664 45665'use strict'; 45666 45667var constants = _dereq_('./constants'); 45668 45669module.exports = { 45670 modeAdjust: function(a, b, c, d, mode) { 45671 if (mode === constants.CORNER) { 45672 return { x: a, y: b, w: c, h: d }; 45673 } else if (mode === constants.CORNERS) { 45674 return { x: a, y: b, w: c - a, h: d - b }; 45675 } else if (mode === constants.RADIUS) { 45676 return { x: a - c, y: b - d, w: 2 * c, h: 2 * d }; 45677 } else if (mode === constants.CENTER) { 45678 return { x: a - c * 0.5, y: b - d * 0.5, w: c, h: d }; 45679 } 45680 }, 45681 45682 arcModeAdjust: function(a, b, c, d, mode) { 45683 if (mode === constants.CORNER) { 45684 return { x: a + c * 0.5, y: b + d * 0.5, w: c, h: d }; 45685 } else if (mode === constants.CORNERS) { 45686 return { x: a, y: b, w: c + a, h: d + b }; 45687 } else if (mode === constants.RADIUS) { 45688 return { x: a, y: b, w: 2 * c, h: 2 * d }; 45689 } else if (mode === constants.CENTER) { 45690 return { x: a, y: b, w: c, h: d }; 45691 } 45692 } 45693}; 45694 45695},{"./constants":21}],21:[function(_dereq_,module,exports){ 45696/** 45697 * @module Constants 45698 * @submodule Constants 45699 * @for p5 45700 */ 45701 45702'use strict'; 45703 45704var PI = Math.PI; 45705 45706module.exports = { 45707 // GRAPHICS RENDERER 45708 /** 45709 * @property {String} P2D 45710 * @final 45711 */ 45712 P2D: 'p2d', 45713 /** 45714 * @property {String} WEBGL 45715 * @final 45716 */ 45717 WEBGL: 'webgl', 45718 45719 // ENVIRONMENT 45720 ARROW: 'default', 45721 CROSS: 'crosshair', 45722 HAND: 'pointer', 45723 MOVE: 'move', 45724 TEXT: 'text', 45725 WAIT: 'wait', 45726 45727 // TRIGONOMETRY 45728 45729 /** 45730 * HALF_PI is a mathematical constant with the value 45731 * 1.57079632679489661923. It is half the ratio of the 45732 * circumference of a circle to its diameter. It is useful in 45733 * combination with the trigonometric functions sin() and cos(). 45734 * 45735 * @property {Number} HALF_PI 45736 * @final 45737 * 45738 * @example 45739 * <div><code> 45740 * arc(50, 50, 80, 80, 0, HALF_PI); 45741 * </code></div> 45742 * 45743 * @alt 45744 * 80x80 white quarter-circle with curve toward bottom right of canvas. 45745 * 45746 */ 45747 HALF_PI: PI / 2, 45748 /** 45749 * PI is a mathematical constant with the value 45750 * 3.14159265358979323846. It is the ratio of the circumference 45751 * of a circle to its diameter. It is useful in combination with 45752 * the trigonometric functions sin() and cos(). 45753 * 45754 * @property {Number} PI 45755 * @final 45756 * 45757 * @example 45758 * <div><code> 45759 * arc(50, 50, 80, 80, 0, PI); 45760 * </code></div> 45761 * 45762 * @alt 45763 * white half-circle with curve toward bottom of canvas. 45764 * 45765 */ 45766 PI: PI, 45767 /** 45768 * QUARTER_PI is a mathematical constant with the value 0.7853982. 45769 * It is one quarter the ratio of the circumference of a circle to 45770 * its diameter. It is useful in combination with the trigonometric 45771 * functions sin() and cos(). 45772 * 45773 * @property {Number} QUARTER_PI 45774 * @final 45775 * 45776 * @example 45777 * <div><code> 45778 * arc(50, 50, 80, 80, 0, QUARTER_PI); 45779 * </code></div> 45780 * 45781 * @alt 45782 * white eighth-circle rotated about 40 degrees with curve bottom right canvas. 45783 * 45784 */ 45785 QUARTER_PI: PI / 4, 45786 /** 45787 * TAU is an alias for TWO_PI, a mathematical constant with the 45788 * value 6.28318530717958647693. It is twice the ratio of the 45789 * circumference of a circle to its diameter. It is useful in 45790 * combination with the trigonometric functions sin() and cos(). 45791 * 45792 * @property {Number} TAU 45793 * @final 45794 * 45795 * @example 45796 * <div><code> 45797 * arc(50, 50, 80, 80, 0, TAU); 45798 * </code></div> 45799 * 45800 * @alt 45801 * 80x80 white ellipse shape in center of canvas. 45802 * 45803 */ 45804 TAU: PI * 2, 45805 /** 45806 * TWO_PI is a mathematical constant with the value 45807 * 6.28318530717958647693. It is twice the ratio of the 45808 * circumference of a circle to its diameter. It is useful in 45809 * combination with the trigonometric functions sin() and cos(). 45810 * 45811 * @property {Number} TWO_PI 45812 * @final 45813 * 45814 * @example 45815 * <div><code> 45816 * arc(50, 50, 80, 80, 0, TWO_PI); 45817 * </code></div> 45818 * 45819 * @alt 45820 * 80x80 white ellipse shape in center of canvas. 45821 * 45822 */ 45823 TWO_PI: PI * 2, 45824 /** 45825 * Constant to be used with angleMode() function, to set the mode which 45826 * p5.js interprates and calculates angles (either DEGREES or RADIANS). 45827 * @property {String} DEGREES 45828 * @final 45829 * 45830 * @example 45831 * <div class='norender'><code> 45832 * function setup() { 45833 * angleMode(DEGREES); 45834 * } 45835 * </code></div> 45836 */ 45837 DEGREES: 'degrees', 45838 /** 45839 * Constant to be used with angleMode() function, to set the mode which 45840 * p5.js interprates and calculates angles (either RADIANS or DEGREES). 45841 * @property {String} RADIANS 45842 * @final 45843 * 45844 * @example 45845 * <div class='norender'><code> 45846 * function setup() { 45847 * angleMode(RADIANS); 45848 * } 45849 * </code></div> 45850 */ 45851 RADIANS: 'radians', 45852 DEG_TO_RAD: PI / 180.0, 45853 RAD_TO_DEG: 180.0 / PI, 45854 45855 // SHAPE 45856 /** 45857 * @property {String} CORNER 45858 * @final 45859 */ 45860 CORNER: 'corner', 45861 /** 45862 * @property {String} CORNERS 45863 * @final 45864 */ 45865 CORNERS: 'corners', 45866 /** 45867 * @property {String} RADIUS 45868 * @final 45869 */ 45870 RADIUS: 'radius', 45871 /** 45872 * @property {String} RIGHT 45873 * @final 45874 */ 45875 RIGHT: 'right', 45876 /** 45877 * @property {String} LEFT 45878 * @final 45879 */ 45880 LEFT: 'left', 45881 /** 45882 * @property {String} CENTER 45883 * @final 45884 */ 45885 CENTER: 'center', 45886 /** 45887 * @property {String} TOP 45888 * @final 45889 */ 45890 TOP: 'top', 45891 /** 45892 * @property {String} BOTTOM 45893 * @final 45894 */ 45895 BOTTOM: 'bottom', 45896 /** 45897 * @property {String} BASELINE 45898 * @final 45899 * @default alphabetic 45900 */ 45901 BASELINE: 'alphabetic', 45902 /** 45903 * @property {Number} POINTS 45904 * @final 45905 * @default 0x0000 45906 */ 45907 POINTS: 0x0000, 45908 /** 45909 * @property {Number} LINES 45910 * @final 45911 * @default 0x0001 45912 */ 45913 LINES: 0x0001, 45914 /** 45915 * @property {Number} LINE_STRIP 45916 * @final 45917 * @default 0x0003 45918 */ 45919 LINE_STRIP: 0x0003, 45920 /** 45921 * @property {Number} LINE_LOOP 45922 * @final 45923 * @default 0x0002 45924 */ 45925 LINE_LOOP: 0x0002, 45926 /** 45927 * @property {Number} TRIANGLES 45928 * @final 45929 * @default 0x0004 45930 */ 45931 TRIANGLES: 0x0004, 45932 /** 45933 * @property {Number} TRIANGLE_FAN 45934 * @final 45935 * @default 0x0006 45936 */ 45937 TRIANGLE_FAN: 0x0006, 45938 /** 45939 * @property {Number} TRIANGLE_STRIP 45940 * @final 45941 * @default 0x0005 45942 */ 45943 TRIANGLE_STRIP: 0x0005, 45944 /** 45945 * @property {String} QUADS 45946 * @final 45947 */ 45948 QUADS: 'quads', 45949 /** 45950 * @property {String} QUAD_STRIP 45951 * @final 45952 * @default quad_strip 45953 */ 45954 QUAD_STRIP: 'quad_strip', 45955 /** 45956 * @property {String} CLOSE 45957 * @final 45958 */ 45959 CLOSE: 'close', 45960 /** 45961 * @property {String} OPEN 45962 * @final 45963 */ 45964 OPEN: 'open', 45965 /** 45966 * @property {String} CHORD 45967 * @final 45968 */ 45969 CHORD: 'chord', 45970 /** 45971 * @property {String} PIE 45972 * @final 45973 */ 45974 PIE: 'pie', 45975 /** 45976 * @property {String} PROJECT 45977 * @final 45978 * @default square 45979 */ 45980 PROJECT: 'square', // PEND: careful this is counterintuitive 45981 /** 45982 * @property {String} SQUARE 45983 * @final 45984 * @default butt 45985 */ 45986 SQUARE: 'butt', 45987 /** 45988 * @property {String} ROUND 45989 * @final 45990 */ 45991 ROUND: 'round', 45992 /** 45993 * @property {String} BEVEL 45994 * @final 45995 */ 45996 BEVEL: 'bevel', 45997 /** 45998 * @property {String} MITER 45999 * @final 46000 */ 46001 MITER: 'miter', 46002 46003 // COLOR 46004 /** 46005 * @property {String} RGB 46006 * @final 46007 */ 46008 RGB: 'rgb', 46009 /** 46010 * @property {String} HSB 46011 * @final 46012 */ 46013 HSB: 'hsb', 46014 /** 46015 * @property {String} HSL 46016 * @final 46017 */ 46018 HSL: 'hsl', 46019 46020 // DOM EXTENSION 46021 AUTO: 'auto', 46022 46023 // INPUT 46024 ALT: 18, 46025 BACKSPACE: 8, 46026 CONTROL: 17, 46027 DELETE: 46, 46028 DOWN_ARROW: 40, 46029 ENTER: 13, 46030 ESCAPE: 27, 46031 LEFT_ARROW: 37, 46032 OPTION: 18, 46033 RETURN: 13, 46034 RIGHT_ARROW: 39, 46035 SHIFT: 16, 46036 TAB: 9, 46037 UP_ARROW: 38, 46038 46039 // RENDERING 46040 /** 46041 * @property {String} BLEND 46042 * @final 46043 * @default source-over 46044 */ 46045 BLEND: 'source-over', 46046 /** 46047 * @property {String} ADD 46048 * @final 46049 * @default lighter 46050 */ 46051 ADD: 'lighter', 46052 //ADD: 'add', // 46053 //SUBTRACT: 'subtract', // 46054 /** 46055 * @property {String} DARKEST 46056 * @final 46057 */ 46058 DARKEST: 'darken', 46059 /** 46060 * @property {String} LIGHTEST 46061 * @final 46062 * @default lighten 46063 */ 46064 LIGHTEST: 'lighten', 46065 /** 46066 * @property {String} DIFFERENCE 46067 * @final 46068 */ 46069 DIFFERENCE: 'difference', 46070 /** 46071 * @property {String} EXCLUSION 46072 * @final 46073 */ 46074 EXCLUSION: 'exclusion', 46075 /** 46076 * @property {String} MULTIPLY 46077 * @final 46078 */ 46079 MULTIPLY: 'multiply', 46080 /** 46081 * @property {String} SCREEN 46082 * @final 46083 */ 46084 SCREEN: 'screen', 46085 /** 46086 * @property {String} REPLACE 46087 * @final 46088 * @default copy 46089 */ 46090 REPLACE: 'copy', 46091 /** 46092 * @property {String} OVERLAY 46093 * @final 46094 */ 46095 OVERLAY: 'overlay', 46096 /** 46097 * @property {String} HARD_LIGHT 46098 * @final 46099 */ 46100 HARD_LIGHT: 'hard-light', 46101 /** 46102 * @property {String} SOFT_LIGHT 46103 * @final 46104 */ 46105 SOFT_LIGHT: 'soft-light', 46106 /** 46107 * @property {String} DODGE 46108 * @final 46109 * @default color-dodge 46110 */ 46111 DODGE: 'color-dodge', 46112 /** 46113 * @property {String} BURN 46114 * @final 46115 * @default color-burn 46116 */ 46117 BURN: 'color-burn', 46118 46119 // FILTERS 46120 /** 46121 * @property {String} THRESHOLD 46122 * @final 46123 */ 46124 THRESHOLD: 'threshold', 46125 /** 46126 * @property {String} GRAY 46127 * @final 46128 */ 46129 GRAY: 'gray', 46130 /** 46131 * @property {String} OPAQUE 46132 * @final 46133 */
46134 OPAQUE: 'opaque', 46135 /** 46136 * @property {String} INVERT 46137 * @final 46138 */ 46139 INVERT: 'invert', 46140 /** 46141 * @property {String} POSTERIZE 46142 * @final 46143 */ 46144 POSTERIZE: 'posterize', 46145 /** 46146 * @property {String} DILATE 46147 * @final 46148 */ 46149 DILATE: 'dilate', 46150 /** 46151 * @property {String} ERODE 46152 * @final 46153 */ 46154 ERODE: 'erode', 46155 /** 46156 * @property {String} BLUR 46157 * @final 46158 */ 46159 BLUR: 'blur', 46160 46161 // TYPOGRAPHY 46162 /** 46163 * @property {String} NORMAL 46164 * @final 46165 */ 46166 NORMAL: 'normal', 46167 /** 46168 * @property {String} ITALIC 46169 * @final 46170 */ 46171 ITALIC: 'italic', 46172 /** 46173 * @property {String} BOLD 46174 * @final 46175 */ 46176 BOLD: 'bold', 46177 46178 // TYPOGRAPHY-INTERNAL 46179 _DEFAULT_TEXT_FILL: '#000000', 46180 _DEFAULT_LEADMULT: 1.25, 46181 _CTX_MIDDLE: 'middle', 46182 46183 // VERTICES 46184 LINEAR: 'linear', 46185 QUADRATIC: 'quadratic', 46186 BEZIER: 'bezier', 46187 CURVE: 'curve', 46188 46189 // WEBGL DRAWMODES 46190 STROKE: 'stroke', 46191 FILL: 'fill', 46192 TEXTURE: 'texture', 46193 IMMEDIATE: 'immediate', 46194 46195 // DEVICE-ORIENTATION 46196 /** 46197 * @property {String} LANDSCAPE 46198 * @final 46199 */ 46200 LANDSCAPE: 'landscape', 46201 /** 46202 * @property {String} PORTRAIT 46203 * @final 46204 */ 46205 PORTRAIT: 'portrait', 46206 46207 // DEFAULTS 46208 _DEFAULT_STROKE: '#000000', 46209 _DEFAULT_FILL: '#FFFFFF' 46210}; 46211 46212},{}],22:[function(_dereq_,module,exports){ 46213/** 46214 * @module Structure 46215 * @submodule Structure 46216 * @for p5 46217 * @requires constants 46218 */ 46219 46220'use strict'; 46221 46222_dereq_('./shim'); 46223 46224// Core needs the PVariables object 46225var constants = _dereq_('./constants'); 46226 46227/** 46228 * This is the p5 instance constructor. 46229 * 46230 * A p5 instance holds all the properties and methods related to 46231 * a p5 sketch. It expects an incoming sketch closure and it can also 46232 * take an optional node parameter for attaching the generated p5 canvas 46233 * to a node. The sketch closure takes the newly created p5 instance as 46234 * its sole argument and may optionally set preload(), setup(), and/or 46235 * draw() properties on it for running a sketch. 46236 * 46237 * A p5 sketch can run in "global" or "instance" mode: 46238 * "global" - all properties and methods are attached to the window 46239 * "instance" - all properties and methods are bound to this p5 object 46240 * 46241 * @class p5 46242 * @constructor 46243 * @param {function} sketch a closure that can set optional preload(), 46244 * setup(), and/or draw() properties on the 46245 * given p5 instance 46246 * @param {HTMLElement|Boolean} [node] element to attach canvas to, if a 46247 * boolean is passed in use it as sync 46248 * @param {Boolean} [sync] start synchronously (optional) 46249 * @return {p5} a p5 instance 46250 */ 46251var p5 = function(sketch, node, sync) { 46252 if (typeof node === 'boolean' && typeof sync === 'undefined') { 46253 sync = node; 46254 node = undefined; 46255 } 46256 46257 ////////////////////////////////////////////// 46258 // PUBLIC p5 PROPERTIES AND METHODS 46259 ////////////////////////////////////////////// 46260 46261 /** 46262 * Called directly before setup(), the preload() function is used to handle 46263 * asynchronous loading of external files in a blocking way. If a preload 46264 * function is defined, setup() will wait until any load calls within have 46265 * finished. Nothing besides load calls (loadImage, loadJSON, loadFont, 46266 * loadStrings, etc.) should be inside preload function. If asynchronous 46267 * loading is preferred, the load methods can instead be called in setup() 46268 * or anywhere else with the use of a callback parameter. 46269 * <br><br> 46270 * By default the text "loading..." will be displayed. To make your own 46271 * loading page, include an HTML element with id "p5_loading" in your 46272 * page. More information <a href="http://bit.ly/2kQ6Nio">here</a>. 46273 * 46274 * @method preload 46275 * @example 46276 * <div><code> 46277 * var img; 46278 * var c; 46279 * function preload() { 46280 // preload() runs once 46281 * img = loadImage('assets/laDefense.jpg'); 46282 * } 46283 * 46284 * function setup() { 46285 // setup() waits until preload() is done 46286 * img.loadPixels(); 46287 * // get color of middle pixel 46288 * c = img.get(img.width / 2, img.height / 2); 46289 * } 46290 * 46291 * function draw() { 46292 * background(c); 46293 * image(img, 25, 25, 50, 50); 46294 * } 46295 * </code></div> 46296 * 46297 * @alt 46298 * nothing displayed 46299 * 46300 */ 46301 46302 /** 46303 * The setup() function is called once when the program starts. It's used to 46304 * define initial environment properties such as screen size and background 46305 * color and to load media such as images and fonts as the program starts. 46306 * There can only be one setup() function for each program and it shouldn't 46307 * be called again after its initial execution. 46308 * <br><br> 46309 * Note: Variables declared within setup() are not accessible within other 46310 * functions, including draw(). 46311 * 46312 * @method setup 46313 * @example 46314 * <div><code> 46315 * var a = 0; 46316 * 46317 * function setup() { 46318 * background(0); 46319 * noStroke(); 46320 * fill(102); 46321 * } 46322 * 46323 * function draw() { 46324 * rect(a++ % width, 10, 2, 80); 46325 * } 46326 * </code></div> 46327 * 46328 * @alt 46329 * nothing displayed 46330 * 46331 */ 46332 46333 /** 46334 * Called directly after setup(), the draw() function continuously executes 46335 * the lines of code contained inside its block until the program is stopped
46336 * or noLoop() is called. Note if noLoop() is called in setup(), draw() will 46337 * still be executed once before stopping. draw() is called automatically and 46338 * should never be called explicitly. 46339 * <br><br> 46340 * It should always be controlled with noLoop(), redraw() and loop(). After 46341 * noLoop() stops the code in draw() from executing, redraw() causes the 46342 * code inside draw() to execute once, and loop() will cause the code 46343 * inside draw() to resume executing continuously. 46344 * <br><br> 46345 * The number of times draw() executes in each second may be controlled with 46346 * the frameRate() function. 46347 * <br><br> 46348 * There can only be one draw() function for each sketch, and draw() must 46349 * exist if you want the code to run continuously, or to process events such 46350 * as mousePressed(). Sometimes, you might have an empty call to draw() in 46351 * your program, as shown in the above example. 46352 * <br><br> 46353 * It is important to note that the drawing coordinate system will be reset 46354 * at the beginning of each draw() call. If any transformations are performed 46355 * within draw() (ex: scale, rotate, translate), their effects will be 46356 * undone at the beginning of draw(), so transformations will not accumulate 46357 * over time. On the other hand, styling applied (ex: fill, stroke, etc) will 46358 * remain in effect. 46359 * 46360 * @method draw 46361 * @example 46362 * <div><code> 46363 * var yPos = 0; 46364 * function setup() { 46365 // setup() runs once 46366 * frameRate(30); 46367 * } 46368 * function draw() { 46369 // draw() loops forever, until stopped 46370 * background(204); 46371 * yPos = yPos - 1; 46372 * if (yPos < 0) { 46373 * yPos = height; 46374 * } 46375 * line(0, yPos, width, yPos); 46376 * } 46377 * </code></div> 46378 * 46379 * @alt 46380 * nothing displayed 46381 * 46382 */ 46383 46384 ////////////////////////////////////////////// 46385 // PRIVATE p5 PROPERTIES AND METHODS 46386 ////////////////////////////////////////////// 46387 46388 this._setupDone = false; 46389 // for handling hidpi 46390 this._pixelDensity = Math.ceil(window.devicePixelRatio) || 1; 46391 this._userNode = node; 46392 this._curElement = null; 46393 this._elements = []; 46394 this._requestAnimId = 0; 46395 this._preloadCount = 0; 46396 this._isGlobal = false; 46397 this._loop = true; 46398 this._initializeInstanceVariables(); 46399 this._defaultCanvasSize = { 46400 width: 100, 46401 height: 100 46402 }; 46403 this._events = { 46404 // keep track of user-events for unregistering later 46405 mousemove: null, 46406 mousedown: null, 46407 mouseup: null, 46408 dragend: null, 46409 dragover: null, 46410 click: null, 46411 dblclick: null, 46412 mouseover: null, 46413 mouseout: null, 46414 keydown: null, 46415 keyup: null, 46416 keypress: null, 46417 touchstart: null, 46418 touchmove: null, 46419 touchend: null, 46420 resize: null, 46421 blur: null 46422 }; 46423 46424 this._events.wheel = null; 46425 this._loadingScreenId = 'p5_loading'; 46426 46427 // Allows methods to be registered on an instance that 46428 // are instance-specific. 46429 this._registeredMethods = {}; 46430 var methods = Object.getOwnPropertyNames(p5.prototype._registeredMethods); 46431 for (var i = 0; i < methods.length; i++) { 46432 var prop = methods[i]; 46433 this._registeredMethods[prop] = p5.prototype._registeredMethods[ 46434 prop 46435 ].slice(); 46436 } 46437 46438 if (window.DeviceOrientationEvent) { 46439 this._events.deviceorientation = null; 46440 } 46441 if (window.DeviceMotionEvent && !window._isNodeWebkit) { 46442 this._events.devicemotion = null; 46443 } 46444 46445 this._start = function() { 46446 // Find node if id given 46447 if (this._userNode) { 46448 if (typeof this._userNode === 'string') { 46449 this._userNode = document.getElementById(this._userNode); 46450 } 46451 } 46452 46453 var userPreload = this.preload || window.preload; // look for "preload" 46454 if (userPreload) { 46455 // Setup loading screen 46456 // Set loading screen into dom if not present 46457 // Otherwise displays and removes user provided loading screen 46458 var loadingScreen = document.getElementById(this._loadingScreenId); 46459 if (!loadingScreen) { 46460 loadingScreen = document.createElement('div'); 46461 loadingScreen.innerHTML = 'Loading...'; 46462 loadingScreen.style.position = 'absolute'; 46463 loadingScreen.id = this._loadingScreenId; 46464 var node = this._userNode || document.body; 46465 node.appendChild(loadingScreen); 46466 } 46467 // var methods = this._preloadMethods; 46468 for (var method in this._preloadMethods) { 46469 // default to p5 if no object defined 46470 this._preloadMethods[method] = this._preloadMethods[method] || p5; 46471 var obj = this._preloadMethods[method]; 46472 //it's p5, check if it's global or instance 46473 if (obj === p5.prototype || obj === p5) { 46474 if (this._isGlobal) { 46475 window[method] = this._wrapPreload(this, method); 46476 } 46477 obj = this; 46478 } 46479 this._registeredPreloadMethods[method] = obj[method]; 46480 obj[method] = this._wrapPreload(obj, method); 46481 } 46482 46483 userPreload(); 46484 this._runIfPreloadsAreDone(); 46485 } else { 46486 this._setup(); 46487 this._runFrames(); 46488 this._draw(); 46489 } 46490 }.bind(this); 46491 46492 this._runIfPreloadsAreDone = function() { 46493 var context = this._isGlobal ? window : this; 46494 if (context._preloadCount === 0) { 46495 var loadingScreen = document.getElementById(context._loadingScreenId); 46496 if (loadingScreen) { 46497 loadingScreen.parentNode.removeChild(loadingScreen); 46498 } 46499 context._setup(); 46500 context._runFrames(); 46501 context._draw(); 46502 } 46503 }; 46504 46505 this._decrementPreload = function() { 46506 var context = this._isGlobal ? window : this; 46507 if (typeof context.preload === 'function') { 46508 context._setProperty('_preloadCount', context._preloadCount - 1); 46509 context._runIfPreloadsAreDone(); 46510 } 46511 }; 46512 46513 this._wrapPreload = function(obj, fnName) { 46514 return function() { 46515 //increment counter 46516 this._incrementPreload(); 46517 //call original function 46518 return this._registeredPreloadMethods[fnName].apply(obj, arguments); 46519 }.bind(this); 46520 }; 46521 46522 this._incrementPreload = function() { 46523 var context = this._isGlobal ? window : this; 46524 context._setProperty('_preloadCount', context._preloadCount + 1); 46525 }; 46526 46527 this._setup = function() { 46528 // Always create a default canvas. 46529 // Later on if the user calls createCanvas, this default one 46530 // will be replaced 46531 this.createCanvas( 46532 this._defaultCanvasSize.width, 46533 this._defaultCanvasSize.height, 46534 'p2d' 46535 ); 46536 46537 // return preload functions to their normal vals if switched by preload 46538 var context = this._isGlobal ? window : this; 46539 if (typeof context.preload === 'function') { 46540 for (var f in this._preloadMethods) { 46541 context[f] = this._preloadMethods[f][f]; 46542 if (context[f] && this) { 46543 context[f] = context[f].bind(this); 46544 } 46545 } 46546 } 46547 46548 // Short-circuit on this, in case someone used the library in "global" 46549 // mode earlier 46550 if (typeof context.setup === 'function') { 46551 context.setup(); 46552 } 46553 46554 // unhide any hidden canvases that were created
46555 var canvases = document.getElementsByTagName('canvas'); 46556 for (var i = 0; i < canvases.length; i++) { 46557 var k = canvases[i]; 46558 if (k.dataset.hidden === 'true') { 46559 k.style.visibility = ''; 46560 delete k.dataset.hidden; 46561 } 46562 } 46563 this._setupDone = true; 46564 }.bind(this); 46565 46566 this._draw = function() { 46567 var now = window.performance.now(); 46568 var time_since_last = now - this._lastFrameTime; 46569 var target_time_between_frames = 1000 / this._targetFrameRate; 46570 46571 // only draw if we really need to; don't overextend the browser. 46572 // draw if we're within 5ms of when our next frame should paint 46573 // (this will prevent us from giving up opportunities to draw 46574 // again when it's really about time for us to do so). fixes an 46575 // issue where the frameRate is too low if our refresh loop isn't 46576 // in sync with the browser. note that we have to draw once even 46577 // if looping is off, so we bypass the time delay if that 46578 // is the case. 46579 var epsilon = 5; 46580 if ( 46581 !this._loop || 46582 time_since_last >= target_time_between_frames - epsilon 46583 ) { 46584 //mandatory update values(matrixs and stack) 46585 46586 this.redraw(); 46587 this._frameRate = 1000.0 / (now - this._lastFrameTime); 46588 this._lastFrameTime = now; 46589 46590 // If the user is actually using mouse module, then update 46591 // coordinates, otherwise skip. We can test this by simply 46592 // checking if any of the mouse functions are available or not. 46593 // NOTE : This reflects only in complete build or modular build. 46594 if (typeof this._updateMouseCoords !== 'undefined') { 46595 this._updateMouseCoords(); 46596 } 46597 } 46598 46599 // get notified the next time the browser gives us 46600 // an opportunity to draw. 46601 if (this._loop) { 46602 this._requestAnimId = window.requestAnimationFrame(this._draw); 46603 } 46604 }.bind(this); 46605 46606 this._runFrames = function() { 46607 if (this._updateInterval) { 46608 clearInterval(this._updateInterval); 46609 } 46610 }.bind(this); 46611 46612 this._setProperty = function(prop, value) { 46613 this[prop] = value; 46614 if (this._isGlobal) { 46615 window[prop] = value; 46616 } 46617 }.bind(this); 46618 46619 /** 46620 * Removes the entire p5 sketch. This will remove the canvas and any 46621 * elements created by p5.js. It will also stop the draw loop and unbind 46622 * any properties or methods from the window global scope. It will 46623 * leave a variable p5 in case you wanted to create a new p5 sketch. 46624 * If you like, you can set p5 = null to erase it. While all functions and 46625 * variables and objects created by the p5 library will be removed, any 46626 * other global variables created by your code will remain. 46627 * 46628 * @method remove 46629 * @example 46630 * <div class='norender'><code> 46631 * function draw() { 46632 * ellipse(50, 50, 10, 10); 46633 * } 46634 * 46635 * function mousePressed() { 46636 * remove(); // remove whole sketch on mouse press 46637 * } 46638 * </code></div> 46639 * 46640 * @alt 46641 * nothing displayed 46642 * 46643 */ 46644 this.remove = function() { 46645 var loadingScreen = document.getElementById(this._loadingScreenId); 46646 if (loadingScreen) { 46647 loadingScreen.parentNode.removeChild(loadingScreen); 46648 // Add 1 to preload counter to prevent the sketch ever executing setup() 46649 this._incrementPreload(); 46650 } 46651 if (this._curElement) { 46652 // stop draw 46653 this._loop = false; 46654 if (this._requestAnimId) { 46655 window.cancelAnimationFrame(this._requestAnimId); 46656 } 46657 46658 // unregister events sketch-wide 46659 for (var ev in this._events) { 46660 window.removeEventListener(ev, this._events[ev]); 46661 } 46662 46663 // remove DOM elements created by p5, and listeners 46664 for (var i = 0; i < this._elements.length; i++) { 46665 var e = this._elements[i]; 46666 if (e.elt.parentNode) { 46667 e.elt.parentNode.removeChild(e.elt); 46668 } 46669 for (var elt_ev in e._events) { 46670 e.elt.removeEventListener(elt_ev, e._events[elt_ev]); 46671 } 46672 } 46673 46674 // call any registered remove functions 46675 var self = this; 46676 this._registeredMethods.remove.forEach(function(f) { 46677 if (typeof f !== 'undefined') { 46678 f.call(self); 46679 } 46680 }); 46681 } 46682 // remove window bound properties and methods 46683 if (this._isGlobal) { 46684 for (var p in p5.prototype) { 46685 try { 46686 delete window[p]; 46687 } catch (x) { 46688 window[p] = undefined; 46689 } 46690 } 46691 for (var p2 in this) { 46692 if (this.hasOwnProperty(p2)) { 46693 try { 46694 delete window[p2]; 46695 } catch (x) { 46696 window[p2] = undefined; 46697 } 46698 } 46699 } 46700 p5.instance = null; 46701 } 46702 }.bind(this); 46703 46704 // call any registered init functions 46705 this._registeredMethods.init.forEach(function(f) { 46706 if (typeof f !== 'undefined') { 46707 f.call(this); 46708 } 46709 }, this); 46710 46711 var friendlyBindGlobal = this._createFriendlyGlobalFunctionBinder(); 46712 46713 // If the user has created a global setup or draw function, 46714 // assume "global" mode and make everything global (i.e. on the window) 46715 if (!sketch) { 46716 this._isGlobal = true; 46717 p5.instance = this; 46718 // Loop through methods on the prototype and attach them to the window 46719 for (var p in p5.prototype) { 46720 if (typeof p5.prototype[p] === 'function') { 46721 var ev = p.substring(2); 46722 if (!this._events.hasOwnProperty(ev)) { 46723 if (Math.hasOwnProperty(p) && Math[p] === p5.prototype[p]) { 46724 // Multiple p5 methods are just native Math functions. These can be 46725 // called without any binding. 46726 friendlyBindGlobal(p, p5.prototype[p]); 46727 } else { 46728 friendlyBindGlobal(p, p5.prototype[p].bind(this)); 46729 } 46730 } 46731 } else { 46732 friendlyBindGlobal(p, p5.prototype[p]); 46733 } 46734 } 46735 // Attach its properties to the window 46736 for (var p2 in this) { 46737 if (this.hasOwnProperty(p2)) { 46738 friendlyBindGlobal(p2, this[p2]); 46739 } 46740 } 46741 } else { 46742 // Else, the user has passed in a sketch closure that may set
46743 // user-provided 'setup', 'draw', etc. properties on this instance of p5 46744 sketch(this); 46745 } 46746 46747 // Bind events to window (not using container div bc key events don't work) 46748 46749 for (var e in this._events) { 46750 var f = this['_on' + e]; 46751 if (f) { 46752 var m = f.bind(this); 46753 window.addEventListener(e, m, { passive: false }); 46754 this._events[e] = m; 46755 } 46756 } 46757 46758 var focusHandler = function() { 46759 this._setProperty('focused', true); 46760 }.bind(this); 46761 var blurHandler = function() { 46762 this._setProperty('focused', false); 46763 }.bind(this); 46764 window.addEventListener('focus', focusHandler); 46765 window.addEventListener('blur', blurHandler); 46766 this.registerMethod('remove', function() { 46767 window.removeEventListener('focus', focusHandler); 46768 window.removeEventListener('blur', blurHandler); 46769 }); 46770 46771 if (sync) { 46772 this._start(); 46773 } else { 46774 if (document.readyState === 'complete') { 46775 this._start(); 46776 } else { 46777 window.addEventListener('load', this._start.bind(this), false); 46778 } 46779 } 46780}; 46781 46782p5.prototype._initializeInstanceVariables = function() { 46783 this._styles = []; 46784 46785 this._bezierDetail = 20; 46786 this._curveDetail = 20; 46787 46788 this._colorMode = constants.RGB; 46789 this._colorMaxes = { 46790 rgb: [255, 255, 255, 255], 46791 hsb: [360, 100, 100, 1], 46792 hsl: [360, 100, 100, 1] 46793 }; 46794}; 46795 46796// This is a pointer to our global mode p5 instance, if we're in 46797// global mode. 46798p5.instance = null; 46799 46800// Allows for the friendly error system to be turned off when creating a sketch, 46801// which can give a significant boost to performance when needed. 46802p5.disableFriendlyErrors = false; 46803 46804// attach constants to p5 prototype 46805for (var k in constants) { 46806 p5.prototype[k] = constants[k]; 46807} 46808 46809// functions that cause preload to wait 46810// more can be added by using registerPreloadMethod(func) 46811p5.prototype._preloadMethods = { 46812 loadJSON: p5.prototype, 46813 loadImage: p5.prototype, 46814 loadStrings: p5.prototype, 46815 loadXML: p5.prototype, 46816 loadBytes: p5.prototype, 46817 loadShape: p5.prototype, 46818 loadTable: p5.prototype, 46819 loadFont: p5.prototype, 46820 loadModel: p5.prototype, 46821 loadShader: p5.prototype 46822}; 46823 46824p5.prototype._registeredMethods = { init: [], pre: [], post: [], remove: [] }; 46825 46826p5.prototype._registeredPreloadMethods = {}; 46827 46828p5.prototype.registerPreloadMethod = function(fnString, obj) { 46829 // obj = obj || p5.prototype; 46830 if (!p5.prototype._preloadMethods.hasOwnProperty(fnString)) { 46831 p5.prototype._preloadMethods[fnString] = obj; 46832 } 46833}; 46834 46835p5.prototype.registerMethod = function(name, m) { 46836 var target = this || p5.prototype; 46837 if (!target._registeredMethods.hasOwnProperty(name)) { 46838 target._registeredMethods[name] = []; 46839 } 46840 target._registeredMethods[name].push(m); 46841}; 46842 46843p5.prototype._createFriendlyGlobalFunctionBinder = function(options) { 46844 options = options || {}; 46845 46846 var globalObject = options.globalObject || window; 46847 var log = options.log || console.log.bind(console); 46848 var propsToForciblyOverwrite = { 46849 // p5.print actually always overwrites an existing global function, 46850 // albeit one that is very unlikely to be used: 46851 // 46852 // https://developer.mozilla.org/en-US/docs/Web/API/Window/print 46853 print: true 46854 }; 46855 46856 return function(prop, value) { 46857 if ( 46858 !p5.disableFriendlyErrors && 46859 typeof IS_MINIFIED === 'undefined' && 46860 typeof value === 'function' && 46861 !(prop in p5.prototype._preloadMethods) 46862 ) { 46863 try { 46864 // Because p5 has so many common function names, it's likely 46865 // that users may accidentally overwrite global p5 functions with 46866 // their own variables. Let's allow this but log a warning to 46867 // help users who may be doing this unintentionally. 46868 // 46869 // For more information, see: 46870 // 46871 // https://github.com/processing/p5.js/issues/1317 46872 46873 if (prop in globalObject && !(prop in propsToForciblyOverwrite)) { 46874 throw new Error('global "' + prop + '" already exists'); 46875 } 46876 46877 // It's possible that this might throw an error because there 46878 // are a lot of edge-cases in which `Object.defineProperty` might 46879 // not succeed; since this functionality is only intended to 46880 // help beginners anyways, we'll just catch such an exception 46881 // if it occurs, and fall back to legacy behavior. 46882 Object.defineProperty(globalObject, prop, { 46883 configurable: true, 46884 enumerable: true, 46885 get: function() { 46886 return value; 46887 }, 46888 set: function(newValue) { 46889 Object.defineProperty(globalObject, prop, { 46890 configurable: true, 46891 enumerable: true, 46892 value: newValue, 46893 writable: true 46894 }); 46895 log( 46896 'You just changed the value of "' + 46897 prop + 46898 '", which was ' + 46899 "a p5 function. This could cause problems later if you're " + 46900 'not careful.' 46901 ); 46902 } 46903 }); 46904 } catch (e) { 46905 log( 46906 'p5 had problems creating the global function "' + 46907 prop + 46908 '", ' +
46909 'possibly because your code is already using that name as ' + 46910 'a variable. You may want to rename your variable to something ' + 46911 'else.' 46912 ); 46913 globalObject[prop] = value; 46914 } 46915 } else { 46916 globalObject[prop] = value; 46917 } 46918 }; 46919}; 46920 46921module.exports = p5; 46922 46923},{"./constants":21,"./shim":32}],23:[function(_dereq_,module,exports){ 46924/** 46925 * @module Shape 46926 * @submodule Curves 46927 * @for p5 46928 * @requires core 46929 */ 46930 46931'use strict'; 46932 46933var p5 = _dereq_('./core'); 46934_dereq_('./error_helpers'); 46935 46936/** 46937 * Draws a cubic Bezier curve on the screen. These curves are defined by a 46938 * series of anchor and control points. The first two parameters specify 46939 * the first anchor point and the last two parameters specify the other 46940 * anchor point, which become the first and last points on the curve. The 46941 * middle parameters specify the two control points which define the shape 46942 * of the curve. Approximately speaking, control points "pull" the curve 46943 * towards them.<br /><br />Bezier curves were developed by French 46944 * automotive engineer Pierre Bezier, and are commonly used in computer 46945 * graphics to define gently sloping curves. See also curve(). 46946 * 46947 * @method bezier 46948 * @param {Number} x1 x-coordinate for the first anchor point 46949 * @param {Number} y1 y-coordinate for the first anchor point 46950 * @param {Number} x2 x-coordinate for the first control point 46951 * @param {Number} y2 y-coordinate for the first control point 46952 * @param {Number} x3 x-coordinate for the second control point 46953 * @param {Number} y3 y-coordinate for the second control point 46954 * @param {Number} x4 x-coordinate for the second anchor point 46955 * @param {Number} y4 y-coordinate for the second anchor point 46956 * @chainable 46957 * @example 46958 * <div> 46959 * <code> 46960 * noFill(); 46961 * stroke(255, 102, 0); 46962 * line(85, 20, 10, 10); 46963 * line(90, 90, 15, 80); 46964 * stroke(0, 0, 0); 46965 * bezier(85, 20, 10, 10, 90, 90, 15, 80); 46966 * </code> 46967 * </div> 46968 * 46969 * <div> 46970 * <code> 46971 * background(0, 0, 0); 46972 * noFill(); 46973 * stroke(255); 46974 * bezier(250, 250, 0, 100, 100, 0, 100, 0, 0, 0, 100, 0); 46975 * </code> 46976 * </div> 46977 * 46978 * @alt 46979 * stretched black s-shape in center with orange lines extending from end points. 46980 * stretched black s-shape with 10 5x5 white ellipses along the shape. 46981 * stretched black s-shape with 7 5x5 ellipses and orange lines along the shape. 46982 * stretched black s-shape with 17 small orange lines extending from under shape. 46983 * horseshoe shape with orange ends facing left and black curved center. 46984 * horseshoe shape with orange ends facing left and black curved center. 46985 * Line shaped like right-facing arrow,points move with mouse-x and warp shape. 46986 * horizontal line that hooks downward on the right and 13 5x5 ellipses along it. 46987 * right curving line mid-right of canvas with 7 short lines radiating from it. 46988 */ 46989/** 46990 * @method bezier 46991 * @param {Number} x1 46992 * @param {Number} y1 46993 * @param {Number} z1 z-coordinate for the first anchor point 46994 * @param {Number} x2 46995 * @param {Number} y2 46996 * @param {Number} z2 z-coordinate for the first control point 46997 * @param {Number} x3 46998 * @param {Number} y3 46999 * @param {Number} z3 z-coordinate for the second control point 47000 * @param {Number} x4 47001 * @param {Number} y4 47002 * @param {Number} z4 z-coordinate for the second anchor point 47003 * @chainable 47004 */ 47005p5.prototype.bezier = function() { 47006 p5._validateParameters('bezier', arguments); 47007 47008 if (this._renderer._doStroke || this._renderer._doFill) { 47009 this._renderer.bezier.apply(this._renderer, arguments); 47010 } 47011 47012 return this; 47013}; 47014 47015/** 47016 * Sets the resolution at which Beziers display. 47017 * 47018 * The default value is 20. 47019 * 47020 * This function is only useful when using the WEBGL renderer 47021 * as the default canvas renderer does not use this information. 47022 * 47023 * @method bezierDetail 47024 * @param {Number} detail resolution of the curves 47025 * @chainable 47026 * @example 47027 * <div modernizr='webgl'> 47028 * <code> 47029 * function setup() { 47030 * createCanvas(100, 100, WEBGL); 47031 * noFill(); 47032 * 47033 * bezierDetail(5); 47034 * } 47035 * 47036 * function draw() { 47037 * background(200); 47038 * 47039 * // prettier-ignore 47040 * bezier(-40, -40, 0, 47041 * 90, -40, 0, 47042 * -90, 40, 0, 47043 * 40, 40, 0); 47044 * } 47045 * </code> 47046 * </div> 47047 * 47048 * @alt 47049 * stretched black s-shape with a low level of bezier detail 47050 * 47051 */ 47052p5.prototype.bezierDetail = function(d) { 47053 p5._validateParameters('bezierDetail', arguments); 47054 this._bezierDetail = d; 47055 return this; 47056}; 47057 47058/** 47059 * Evaluates the Bezier at position t for points a, b, c, d. 47060 * The parameters a and d are the first and last points 47061 * on the curve, and b and c are the control points. 47062 * The final parameter t varies between 0 and 1. 47063 * This can be done once with the x coordinates and a second time 47064 * with the y coordinates to get the location of a bezier curve at t. 47065 * 47066 * @method bezierPoint 47067 * @param {Number} a coordinate of first point on the curve 47068 * @param {Number} b coordinate of first control point 47069 * @param {Number} c coordinate of second control point 47070 * @param {Number} d coordinate of second point on the curve 47071 * @param {Number} t value between 0 and 1 47072 * @return {Number} the value of the Bezier at position t 47073 * @example 47074 * <div> 47075 * <code> 47076 * noFill(); 47077 * var x1 = 85, 47078 x2 = 10, 47079 x3 = 90, 47080 x4 = 15; 47081 * var y1 = 20, 47082 y2 = 10, 47083 y3 = 90, 47084 y4 = 80; 47085 * bezier(x1, y1, x2, y2, x3, y3, x4, y4); 47086 * fill(255); 47087 * var steps = 10; 47088 * for (var i = 0; i <= steps; i++) { 47089 * var t = i / steps; 47090 * var x = bezierPoint(x1, x2, x3, x4, t); 47091 * var y = bezierPoint(y1, y2, y3, y4, t); 47092 * ellipse(x, y, 5, 5); 47093 * } 47094 * </code> 47095 * </div> 47096 * 47097 * @alt 47098 * stretched black s-shape with 17 small orange lines extending from under shape. 47099 * 47100 */ 47101p5.prototype.bezierPoint = function(a, b, c, d, t) { 47102 p5._validateParameters('bezierPoint', arguments); 47103 47104 var adjustedT = 1 - t; 47105 return ( 47106 Math.pow(adjustedT, 3) * a + 47107 3 * Math.pow(adjustedT, 2) * t * b + 47108 3 * adjustedT * Math.pow(t, 2) * c + 47109 Math.pow(t, 3) * d 47110 ); 47111}; 47112 47113/** 47114 * Evaluates the tangent to the Bezier at position t for points a, b, c, d. 47115 * The parameters a and d are the first and last points 47116 * on the curve, and b and c are the control points. 47117 * The final parameter t varies between 0 and 1. 47118 * 47119 * @method bezierTangent 47120 * @param {Number} a coordinate of first point on the curve 47121 * @param {Number} b coordinate of first control point 47122 * @param {Number} c coordinate of second control point 47123 * @param {Number} d coordinate of second point on the curve 47124 * @param {Number} t value between 0 and 1 47125 * @return {Number} the tangent at position t 47126 * @example 47127 * <div> 47128 * <code> 47129 * noFill(); 47130 * bezier(85, 20, 10, 10, 90, 90, 15, 80); 47131 * var steps = 6; 47132 * fill(255); 47133 * for (var i = 0; i <= steps; i++) { 47134 * var t = i / steps; 47135 * // Get the location of the point 47136 * var x = bezierPoint(85, 10, 90, 15, t); 47137 * var y = bezierPoint(20, 10, 90, 80, t); 47138 * // Get the tangent points 47139 * var tx = bezierTangent(85, 10, 90, 15, t); 47140 * var ty = bezierTangent(20, 10, 90, 80, t); 47141 * // Calculate an angle from the tangent points 47142 * var a = atan2(ty, tx); 47143 * a += PI; 47144 * stroke(255, 102, 0); 47145 * line(x, y, cos(a) * 30 + x, sin(a) * 30 + y); 47146 * // The following line of code makes a line 47147 * // inverse of the above line 47148 * //line(x, y, cos(a)*-30 + x, sin(a)*-30 + y); 47149 * stroke(0); 47150 * ellipse(x, y, 5, 5); 47151 * } 47152 * </code> 47153 * </div> 47154 * 47155 * <div> 47156 * <code> 47157 * noFill(); 47158 * bezier(85, 20, 10, 10, 90, 90, 15, 80); 47159 * stroke(255, 102, 0); 47160 * var steps = 16; 47161 * for (var i = 0; i <= steps; i++) { 47162 * var t = i / steps; 47163 * var x = bezierPoint(85, 10, 90, 15, t); 47164 * var y = bezierPoint(20, 10, 90, 80, t); 47165 * var tx = bezierTangent(85, 10, 90, 15, t); 47166 * var ty = bezierTangent(20, 10, 90, 80, t); 47167 * var a = atan2(ty, tx); 47168 * a -= HALF_PI; 47169 * line(x, y, cos(a) * 8 + x, sin(a) * 8 + y); 47170 * } 47171 * </code> 47172 * </div> 47173 * 47174 * @alt 47175 * s-shaped line with 17 short orange lines extending from underside of shape 47176 * 47177 */ 47178p5.prototype.bezierTangent = function(a, b, c, d, t) { 47179 p5._validateParameters('bezierTangent', arguments); 47180 47181 var adjustedT = 1 - t; 47182 return ( 47183 3 * d * Math.pow(t, 2) - 47184 3 * c * Math.pow(t, 2) + 47185 6 * c * adjustedT * t - 47186 6 * b * adjustedT * t + 47187 3 * b * Math.pow(adjustedT, 2) - 47188 3 * a * Math.pow(adjustedT, 2) 47189 ); 47190}; 47191 47192/** 47193 * Draws a curved line on the screen between two points, given as the 47194 * middle four parameters. The first two parameters are a control point, as 47195 * if the curve came from this point even though it's not drawn. The last 47196 * two parameters similarly describe the other control point. <br /><br /> 47197 * Longer curves can be created by putting a series of curve() functions 47198 * together or using curveVertex(). An additional function called 47199 * curveTightness() provides control for the visual quality of the curve. 47200 * The curve() function is an implementation of Catmull-Rom splines. 47201 * 47202 * @method curve 47203 * @param {Number} x1 x-coordinate for the beginning control point 47204 * @param {Number} y1 y-coordinate for the beginning control point 47205 * @param {Number} x2 x-coordinate for the first point 47206 * @param {Number} y2 y-coordinate for the first point 47207 * @param {Number} x3 x-coordinate for the second point 47208 * @param {Number} y3 y-coordinate for the second point 47209 * @param {Number} x4 x-coordinate for the ending control point 47210 * @param {Number} y4 y-coordinate for the ending control point 47211 * @chainable 47212 * @example 47213 * <div> 47214 * <code> 47215 * noFill(); 47216 * stroke(255, 102, 0); 47217 * curve(5, 26, 5, 26, 73, 24, 73, 61); 47218 * stroke(0); 47219 * curve(5, 26, 73, 24, 73, 61, 15, 65);
47220 * stroke(255, 102, 0); 47221 * curve(73, 24, 73, 61, 15, 65, 15, 65); 47222 * </code> 47223 * </div> 47224 * <div> 47225 * <code> 47226 * // Define the curve points as JavaScript objects 47227 * var p1 = { x: 5, y: 26 }, 47228 p2 = { x: 73, y: 24 }; 47229 * var p3 = { x: 73, y: 61 }, 47230 p4 = { x: 15, y: 65 }; 47231 * noFill(); 47232 * stroke(255, 102, 0); 47233 * curve(p1.x, p1.y, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y); 47234 * stroke(0); 47235 * curve(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y); 47236 * stroke(255, 102, 0); 47237 * curve(p2.x, p2.y, p3.x, p3.y, p4.x, p4.y, p4.x, p4.y); 47238 * </code> 47239 * </div> 47240 * <div> 47241 * <code> 47242 * noFill(); 47243 * stroke(255, 102, 0); 47244 * curve(5, 26, 0, 5, 26, 0, 73, 24, 0, 73, 61, 0); 47245 * stroke(0); 47246 * curve(5, 26, 0, 73, 24, 0, 73, 61, 0, 15, 65, 0); 47247 * stroke(255, 102, 0); 47248 * curve(73, 24, 0, 73, 61, 0, 15, 65, 0, 15, 65, 0); 47249 * </code> 47250 * </div> 47251 * 47252 * @alt 47253 * horseshoe shape with orange ends facing left and black curved center. 47254 * horseshoe shape with orange ends facing left and black curved center. 47255 * curving black and orange lines. 47256 */ 47257/** 47258 * @method curve 47259 * @param {Number} x1 47260 * @param {Number} y1 47261 * @param {Number} z1 z-coordinate for the beginning control point 47262 * @param {Number} x2 47263 * @param {Number} y2 47264 * @param {Number} z2 z-coordinate for the first point 47265 * @param {Number} x3 47266 * @param {Number} y3 47267 * @param {Number} z3 z-coordinate for the second point 47268 * @param {Number} x4 47269 * @param {Number} y4 47270 * @param {Number} z4 z-coordinate for the ending control point 47271 * @chainable 47272 */ 47273p5.prototype.curve = function() { 47274 p5._validateParameters('curve', arguments); 47275 47276 if (this._renderer._doStroke) { 47277 this._renderer.curve.apply(this._renderer, arguments); 47278 } 47279 47280 return this; 47281}; 47282 47283/** 47284 * Sets the resolution at which curves display. 47285 * 47286 * The default value is 20. 47287 * 47288 * This function is only useful when using the WEBGL renderer 47289 * as the default canvas renderer does not use this 47290 * information. 47291 * 47292 * @method curveDetail 47293 * @param {Number} resolution of the curves 47294 * @chainable 47295 * @example 47296 * <div modernizr='webgl'> 47297 * <code> 47298 * function setup() { 47299 * createCanvas(100, 100, WEBGL); 47300 * 47301 * curveDetail(5); 47302 * } 47303 * function draw() { 47304 * background(200); 47305 * 47306 * // prettier-ignore 47307 * curve( 250, 600, 0, 47308 * -30, 40, 0, 47309 * 30, 30, 0, 47310 * -250, 600, 0); 47311 * } 47312 * </code> 47313 * </div> 47314 * 47315 * @alt 47316 * white arch shape with a low level of curve detail. 47317 * 47318 */ 47319p5.prototype.curveDetail = function(d) { 47320 p5._validateParameters('curveDetail', arguments); 47321 this._curveDetail = d; 47322 return this; 47323}; 47324 47325/** 47326 * Modifies the quality of forms created with curve() and curveVertex(). 47327 * The parameter tightness determines how the curve fits to the vertex 47328 * points. The value 0.0 is the default value for tightness (this value 47329 * defines the curves to be Catmull-Rom splines) and the value 1.0 connects 47330 * all the points with straight lines. Values within the range -5.0 and 5.0 47331 * will deform the curves but will leave them recognizable and as values 47332 * increase in magnitude, they will continue to deform. 47333 * 47334 * @method curveTightness 47335 * @param {Number} amount of deformation from the original vertices 47336 * @chainable 47337 * @example 47338 * <div> 47339 * <code> 47340 * // Move the mouse left and right to see the curve change 47341 * 47342 * function setup() { 47343 * createCanvas(100, 100); 47344 * noFill(); 47345 * } 47346 * 47347 * function draw() { 47348 * background(204); 47349 * var t = map(mouseX, 0, width, -5, 5); 47350 * curveTightness(t); 47351 * beginShape(); 47352 * curveVertex(10, 26); 47353 * curveVertex(10, 26); 47354 * curveVertex(83, 24); 47355 * curveVertex(83, 61); 47356 * curveVertex(25, 65); 47357 * curveVertex(25, 65); 47358 * endShape(); 47359 * } 47360 * </code> 47361 * </div> 47362 * 47363 * @alt 47364 * Line shaped like right-facing arrow,points move with mouse-x and warp shape. 47365 */ 47366p5.prototype.curveTightness = function(t) { 47367 p5._validateParameters('curveTightness', arguments); 47368 this._renderer._curveTightness = t; 47369}; 47370 47371/** 47372 * Evaluates the curve at position t for points a, b, c, d. 47373 * The parameter t varies between 0 and 1, a and d are points 47374 * on the curve, and b and c are the control points. 47375 * This can be done once with the x coordinates and a second time 47376 * with the y coordinates to get the location of a curve at t. 47377 * 47378 * @method curvePoint 47379 * @param {Number} a coordinate of first point on the curve 47380 * @param {Number} b coordinate of first control point 47381 * @param {Number} c coordinate of second control point 47382 * @param {Number} d coordinate of second point on the curve 47383 * @param {Number} t value between 0 and 1 47384 * @return {Number} bezier value at position t 47385 * @example 47386 * <div> 47387 * <code> 47388 * noFill(); 47389 * curve(5, 26, 5, 26, 73, 24, 73, 61); 47390 * curve(5, 26, 73, 24, 73, 61, 15, 65); 47391 * fill(255); 47392 * ellipseMode(CENTER); 47393 * var steps = 6; 47394 * for (var i = 0; i <= steps; i++) { 47395 * var t = i / steps; 47396 * var x = curvePoint(5, 5, 73, 73, t); 47397 * var y = curvePoint(26, 26, 24, 61, t); 47398 * ellipse(x, y, 5, 5); 47399 * x = curvePoint(5, 73, 73, 15, t); 47400 * y = curvePoint(26, 24, 61, 65, t); 47401 * ellipse(x, y, 5, 5); 47402 * } 47403 * </code> 47404 * </div> 47405 * 47406 *line hooking down to right-bottom with 13 5x5 white ellipse points 47407 */ 47408p5.prototype.curvePoint = function(a, b, c, d, t) { 47409 p5._validateParameters('curvePoint', arguments); 47410 47411 var t3 = t * t * t, 47412 t2 = t * t, 47413 f1 = -0.5 * t3 + t2 - 0.5 * t, 47414 f2 = 1.5 * t3 - 2.5 * t2 + 1.0, 47415 f3 = -1.5 * t3 + 2.0 * t2 + 0.5 * t, 47416 f4 = 0.5 * t3 - 0.5 * t2; 47417 return a * f1 + b * f2 + c * f3 + d * f4; 47418}; 47419 47420/** 47421 * Evaluates the tangent to the curve at position t for points a, b, c, d. 47422 * The parameter t varies between 0 and 1, a and d are points on the curve, 47423 * and b and c are the control points. 47424 * 47425 * @method curveTangent 47426 * @param {Number} a coordinate of first point on the curve 47427 * @param {Number} b coordinate of first control point 47428 * @param {Number} c coordinate of second control point 47429 * @param {Number} d coordinate of second point on the curve 47430 * @param {Number} t value between 0 and 1 47431 * @return {Number} the tangent at position t 47432 * @example 47433 * <div> 47434 * <code> 47435 * noFill(); 47436 * curve(5, 26, 73, 24, 73, 61, 15, 65); 47437 * var steps = 6; 47438 * for (var i = 0; i <= steps; i++) { 47439 * var t = i / steps; 47440 * var x = curvePoint(5, 73, 73, 15, t); 47441 * var y = curvePoint(26, 24, 61, 65, t); 47442 * //ellipse(x, y, 5, 5); 47443 * var tx = curveTangent(5, 73, 73, 15, t); 47444 * var ty = curveTangent(26, 24, 61, 65, t); 47445 * var a = atan2(ty, tx); 47446 * a -= PI / 2.0; 47447 * line(x, y, cos(a) * 8 + x, sin(a) * 8 + y); 47448 * } 47449 * </code> 47450 * </div> 47451 * 47452 * @alt 47453 *right curving line mid-right of canvas with 7 short lines radiating from it. 47454 */ 47455p5.prototype.curveTangent = function(a, b, c, d, t) { 47456 p5._validateParameters('curveTangent', arguments); 47457 47458 var t2 = t * t, 47459 f1 = -3 * t2 / 2 + 2 * t - 0.5, 47460 f2 = 9 * t2 / 2 - 5 * t, 47461 f3 = -9 * t2 / 2 + 4 * t + 0.5, 47462 f4 = 3 * t2 / 2 - t; 47463 return a * f1 + b * f2 + c * f3 + d * f4; 47464}; 47465 47466module.exports = p5; 47467 47468},{"./core":22,"./error_helpers":25}],24:[function(_dereq_,module,exports){ 47469/** 47470 * @module Environment 47471 * @submodule Environment 47472 * @for p5 47473 * @requires core 47474 * @requires constants 47475 */ 47476 47477'use strict'; 47478 47479var p5 = _dereq_('./core'); 47480var C = _dereq_('./constants'); 47481 47482var standardCursors = [C.ARROW, C.CROSS, C.HAND, C.MOVE, C.TEXT, C.WAIT]; 47483 47484p5.prototype._frameRate = 0; 47485p5.prototype._lastFrameTime = window.performance.now(); 47486p5.prototype._targetFrameRate = 60; 47487 47488var _windowPrint = window.print; 47489 47490/** 47491 * The print() function writes to the console area of your browser. 47492 * This function is often helpful for looking at the data a program is 47493 * producing. This function creates a new line of text for each call to 47494 * the function. Individual elements can be 47495 * separated with quotes ("") and joined with the addition operator (+). 47496 * 47497 * @method print 47498 * @param {Any} contents any combination of Number, String, Object, Boolean, 47499 * Array to print 47500 * @example 47501 * <div><code class='norender'> 47502 * var x = 10; 47503 * print('The value of x is ' + x); 47504 * // prints "The value of x is 10" 47505 * </code></div> 47506 * @alt 47507 * default grey canvas 47508 */ 47509p5.prototype.print = function() { 47510 if (!arguments.length) { 47511 _windowPrint(); 47512 } else { 47513 console.log.apply(console, arguments); 47514 } 47515}; 47516 47517/** 47518 * The system variable frameCount contains the number of frames that have 47519 * been displayed since the program started. Inside setup() the value is 0, 47520 * after the first iteration of draw it is 1, etc. 47521 * 47522 * @property {Integer} frameCount 47523 * @readOnly 47524 * @example 47525 * <div><code> 47526 * function setup() { 47527 * frameRate(30); 47528 * textSize(20); 47529 * textSize(30); 47530 * textAlign(CENTER); 47531 * } 47532 * 47533 * function draw() { 47534 * background(200); 47535 * text(frameCount, width / 2, height / 2); 47536 * } 47537</code></div> 47538 * 47539 * @alt 47540 * numbers rapidly counting upward with frame count set to 30. 47541 * 47542 */ 47543p5.prototype.frameCount = 0; 47544 47545/** 47546 * Confirms if the window a p5.js program is in is "focused," meaning that 47547 * the sketch will accept mouse or keyboard input. This variable is 47548 * "true" if the window is focused and "false" if not. 47549 * 47550 * @property {Boolean}
47550 focused 47551 * @readOnly 47552 * @example 47553 * <div><code> 47554 * // To demonstrate, put two windows side by side. 47555 * // Click on the window that the p5 sketch isn't in! 47556 * function draw() { 47557 * background(200); 47558 * noStroke(); 47559 * fill(0, 200, 0); 47560 * ellipse(25, 25, 50, 50); 47561 * 47562 * if (!focused) { 47563 // or "if (focused === false)" 47564 * stroke(200, 0, 0); 47565 * line(0, 0, 100, 100); 47566 * line(100, 0, 0, 100); 47567 * } 47568 * } 47569 * </code></div> 47570 * 47571 * @alt 47572 * green 50x50 ellipse at top left. Red X covers canvas when page focus changes 47573 * 47574 */ 47575p5.prototype.focused = document.hasFocus(); 47576 47577/** 47578 * Sets the cursor to a predefined symbol or an image, or makes it visible 47579 * if already hidden. If you are trying to set an image as the cursor, the 47580 * recommended size is 16x16 or 32x32 pixels. It is not possible to load an 47581 * image as the cursor if you are exporting your program for the Web, and not 47582 * all MODES work with all browsers. The values for parameters x and y must 47583 * be less than the dimensions of the image. 47584 * 47585 * @method cursor 47586 * @param {String|Constant} type either ARROW, CROSS, HAND, MOVE, TEXT, or 47587 * WAIT, or path for image 47588 * @param {Number} [x] the horizontal active spot of the cursor 47589 * @param {Number} [y] the vertical active spot of the cursor 47590 * @example 47591 * <div><code> 47592 * // Move the mouse left and right across the image 47593 * // to see the cursor change from a cross to a hand 47594 * function draw() { 47595 * line(width / 2, 0, width / 2, height); 47596 * if (mouseX < 50) { 47597 * cursor(CROSS); 47598 * } else { 47599 * cursor(HAND); 47600 * } 47601 * } 47602 * </code></div> 47603 * 47604 * @alt 47605 * horizontal line divides canvas. cursor on left is a cross, right is hand. 47606 * 47607 */ 47608p5.prototype.cursor = function(type, x, y) { 47609 var cursor = 'auto'; 47610 var canvas = this._curElement.elt; 47611 if (standardCursors.indexOf(type) > -1) { 47612 // Standard css cursor 47613 cursor = type; 47614 } else if (typeof type === 'string') { 47615 var coords = ''; 47616 if (x && y && (typeof x === 'number' && typeof y === 'number')) { 47617 // Note that x and y values must be unit-less positive integers < 32 47618 // https://developer.mozilla.org/en-US/docs/Web/CSS/cursor 47619 coords = x + ' ' + y; 47620 } 47621 if ( 47622 type.substring(0, 7) === 'http://' || 47623 type.substring(0, 8) === 'https://' 47624 ) { 47625 // Image (absolute url) 47626 cursor = 'url(' + type + ') ' + coords + ', auto'; 47627 } else if (/\.(cur|jpg|jpeg|gif|png|CUR|JPG|JPEG|GIF|PNG)$/.test(type)) { 47628 // Image file (relative path) - Separated for performance reasons 47629 cursor = 'url(' + type + ') ' + coords + ', auto'; 47630 } else { 47631 // Any valid string for the css cursor property 47632 cursor = type; 47633 } 47634 } 47635 canvas.style.cursor = cursor; 47636}; 47637 47638/** 47639 * Specifies the number of frames to be displayed every second. For example, 47640 * the function call frameRate(30) will attempt to refresh 30 times a second. 47641 * If the processor is not fast enough to maintain the specified rate, the 47642 * frame rate will not be achieved. Setting the frame rate within setup() is 47643 * recommended. The default rate is 60 frames per second. This is the same as 47644 * setFrameRate(val). 47645 * <br><br> 47646 * Calling frameRate() with no arguments returns the current framerate. The 47647 * draw function must run at least once before it will return a value. This 47648 * is the same as getFrameRate(). 47649 * <br><br> 47650 * Calling frameRate() with arguments that are not of the type numbers 47651 * or are non positive also returns current framerate. 47652 * 47653 * @method frameRate 47654 * @param {Number} fps number of frames to be displayed every second 47655 * @chainable 47656 * 47657 * @example 47658 * 47659 * <div><code> 47660 * var rectX = 0; 47661 * var fr = 30; //starting FPS 47662 * var clr; 47663 * 47664 * function setup() { 47665 * background(200); 47666 * frameRate(fr); // Attempt to refresh at starting FPS 47667 * clr = color(255, 0, 0); 47668 * } 47669 * 47670 * function draw() { 47671 * background(200); 47672 * rectX = rectX += 1; // Move Rectangle 47673 * 47674 * if (rectX >= width) { 47675 // If you go off screen. 47676 * if (fr === 30) { 47677 * clr = color(0, 0, 255); 47678 * fr = 10; 47679 * frameRate(fr); // make frameRate 10 FPS 47680 * } else { 47681 * clr = color(255, 0, 0); 47682 * fr = 30; 47683 * frameRate(fr); // make frameRate 30 FPS 47684 * } 47685 * rectX = 0; 47686 * } 47687 * fill(clr);
47688 * rect(rectX, 40, 20, 20); 47689 * } 47690 * </code></div> 47691 * 47692 * @alt 47693 * blue rect moves left to right, followed by red rect moving faster. Loops. 47694 * 47695 */ 47696/** 47697 * @method frameRate 47698 * @return {Number} current frameRate 47699 */ 47700p5.prototype.frameRate = function(fps) { 47701 p5._validateParameters('frameRate', arguments); 47702 if (typeof fps !== 'number' || fps < 0) { 47703 return this._frameRate; 47704 } else { 47705 this._setProperty('_targetFrameRate', fps); 47706 this._runFrames(); 47707 return this; 47708 } 47709}; 47710/** 47711 * Returns the current framerate. 47712 * 47713 * @private 47714 * @return {Number} current frameRate 47715 */ 47716p5.prototype.getFrameRate = function() { 47717 return this.frameRate(); 47718}; 47719 47720/** 47721 * Specifies the number of frames to be displayed every second. For example, 47722 * the function call frameRate(30) will attempt to refresh 30 times a second. 47723 * If the processor is not fast enough to maintain the specified rate, the 47724 * frame rate will not be achieved. Setting the frame rate within setup() is 47725 * recommended. The default rate is 60 frames per second. 47726 * 47727 * Calling frameRate() with no arguments returns the current framerate. 47728 * 47729 * @private 47730 * @param {Number} [fps] number of frames to be displayed every second 47731 */ 47732p5.prototype.setFrameRate = function(fps) { 47733 return this.frameRate(fps); 47734}; 47735 47736/** 47737 * Hides the cursor from view. 47738 * 47739 * @method noCursor 47740 * @example 47741 * <div><code> 47742 * function setup() { 47743 * noCursor(); 47744 * } 47745 * 47746 * function draw() { 47747 * background(200); 47748 * ellipse(mouseX, mouseY, 10, 10); 47749 * } 47750 * </code></div> 47751 * 47752 * 47753 * @alt 47754 * cursor becomes 10x 10 white ellipse the moves with mouse x and y. 47755 * 47756 */ 47757p5.prototype.noCursor = function() { 47758 this._curElement.elt.style.cursor = 'none'; 47759}; 47760 47761/** 47762 * System variable that stores the width of the entire screen display. This 47763 * is used to run a full-screen program on any display size. 47764 * 47765 * @property {Number} displayWidth 47766 * @readOnly 47767 * @example 47768 * <div class="norender"><code> 47769 * createCanvas(displayWidth, displayHeight); 47770 * </code></div> 47771 * 47772 * @alt 47773 * cursor becomes 10x 10 white ellipse the moves with mouse x and y. 47774 * 47775 */ 47776p5.prototype.displayWidth = screen.width; 47777 47778/** 47779 * System variable that stores the height of the entire screen display. This 47780 * is used to run a full-screen program on any display size. 47781 * 47782 * @property {Number} displayHeight 47783 * @readOnly 47784 * @example 47785 * <div class="norender"><code> 47786 * createCanvas(displayWidth, displayHeight); 47787 * </code></div> 47788 * 47789 * @alt 47790 * no display. 47791 * 47792 */ 47793p5.prototype.displayHeight = screen.height; 47794 47795/** 47796 * System variable that stores the width of the inner window, it maps to 47797 * window.innerWidth. 47798 * 47799 * @property {Number} windowWidth 47800 * @readOnly 47801 * @example 47802 * <div class="norender"><code> 47803 * createCanvas(windowWidth, windowHeight); 47804 * </code></div> 47805 * 47806 * @alt 47807 * no display. 47808 * 47809 */ 47810p5.prototype.windowWidth = getWindowWidth(); 47811/** 47812 * System variable that stores the height of the inner window, it maps to 47813 * window.innerHeight. 47814 * 47815 * @property {Number} windowHeight 47816 * @readOnly 47817 * @example 47818 * <div class="norender"><code> 47819 * createCanvas(windowWidth, windowHeight); 47820 * </code></div> 47821 *@alt 47822 * no display. 47823 * 47824 */ 47825p5.prototype.windowHeight = getWindowHeight(); 47826 47827/** 47828 * The windowResized() function is called once every time the browser window 47829 * is resized. This is a good place to resize the canvas or do any other 47830 * adjustments to accommodate the new window size. 47831 * 47832 * @method windowResized 47833 * @example 47834 * <div class="norender"><code> 47835 * function setup() { 47836 * createCanvas(windowWidth, windowHeight); 47837 * } 47838 * 47839 * function draw() { 47840 * background(0, 100, 200); 47841 * } 47842 * 47843 * function windowResized() { 47844 * resizeCanvas(windowWidth, windowHeight); 47845 * } 47846 * </code></div> 47847 * @alt 47848 * no display. 47849 */ 47850p5.prototype._onresize = function(e) { 47851 this._setProperty('windowWidth', getWindowWidth()); 47852 this._setProperty('windowHeight', getWindowHeight()); 47853 var context = this._isGlobal ? window : this; 47854 var executeDefault; 47855 if (typeof context.windowResized === 'function') { 47856 executeDefault = context.windowResized(e); 47857 if (executeDefault !== undefined && !executeDefault) { 47858 e.preventDefault(); 47859 } 47860 } 47861}; 47862 47863function getWindowWidth() { 47864 return ( 47865 window.innerWidth || 47866 (document.documentElement && document.documentElement.clientWidth) || 47867 (document.body && document.body.clientWidth) || 47868 0 47869 ); 47870} 47871 47872function getWindowHeight() { 47873 return ( 47874 window.innerHeight || 47875 (document.documentElement && document.documentElement.clientHeight) || 47876 (document.body && document.body.clientHeight) || 47877 0 47878 ); 47879} 47880 47881/** 47882 * System variable that stores the width of the drawing canvas. This value 47883 * is set by the first parameter of the createCanvas() function. 47884 * For example, the function call createCanvas(320, 240) sets the width 47885 * variable to the value 320. The value of width defaults to 100 if 47886 * createCanvas() is not used in a program. 47887 * 47888 * @property {Number} width 47889 * @readOnly 47890 */ 47891p5.prototype.width = 0; 47892 47893/** 47894 * System variable that stores the height of the drawing canvas. This value 47895 * is set by the second parameter of the createCanvas() function. For 47896 * example, the function call createCanvas(320, 240) sets the height 47897 * variable to the value 240. The value of height defaults to 100 if 47898 * createCanvas() is not used in a program. 47899 * 47900 * @property {Number} height 47901 * @readOnly 47902 */ 47903p5.prototype.height = 0; 47904 47905/** 47906 * If argument is given, sets the sketch to fullscreen or not based on the 47907 * value of the argument. If no argument is given, returns the current 47908 * fullscreen state. Note that due to browser restrictions this can only 47909 * be called on user input, for example, on mouse press like the example 47910 * below. 47911 * 47912 * @method fullscreen 47913 * @param {Boolean} [val] whether the sketch should be in fullscreen mode 47914 * or not 47915 * @return {Boolean} current fullscreen state 47916 * @example 47917 * <div> 47918 * <code> 47919 * // Clicking in the box toggles fullscreen on and off. 47920 * function setup() { 47921 * background(200); 47922 * } 47923 * function mousePressed() { 47924 * if (mouseX > 0 && mouseX < 100 && mouseY > 0 && mouseY < 100) { 47925 * var fs = fullscreen(); 47926 * fullscreen(!fs); 47927 * } 47928 * } 47929 * </code> 47930 * </div> 47931 * 47932 * @alt
47933 * no display. 47934 * 47935 */ 47936p5.prototype.fullscreen = function(val) { 47937 p5._validateParameters('fullscreen', arguments); 47938 // no arguments, return fullscreen or not 47939 if (typeof val === 'undefined') { 47940 return ( 47941 document.fullscreenElement || 47942 document.webkitFullscreenElement || 47943 document.mozFullScreenElement || 47944 document.msFullscreenElement 47945 ); 47946 } else { 47947 // otherwise set to fullscreen or not 47948 if (val) { 47949 launchFullscreen(document.documentElement); 47950 } else { 47951 exitFullscreen(); 47952 } 47953 } 47954}; 47955 47956/** 47957 * Sets the pixel scaling for high pixel density displays. By default 47958 * pixel density is set to match display density, call pixelDensity(1) 47959 * to turn this off. Calling pixelDensity() with no arguments returns 47960 * the current pixel density of the sketch. 47961 * 47962 * 47963 * @method pixelDensity 47964 * @param {Number} [val] whether or how much the sketch should scale 47965 * @returns {Number} current pixel density of the sketch 47966 * @example 47967 * <div> 47968 * <code> 47969 * function setup() { 47970 * pixelDensity(1); 47971 * createCanvas(100, 100); 47972 * background(200); 47973 * ellipse(width / 2, height / 2, 50, 50); 47974 * } 47975 * </code> 47976 * </div> 47977 * <div> 47978 * <code> 47979 * function setup() { 47980 * pixelDensity(3.0); 47981 * createCanvas(100, 100); 47982 * background(200); 47983 * ellipse(width / 2, height / 2, 50, 50); 47984 * } 47985 * </code> 47986 * </div> 47987 * 47988 * @alt 47989 * fuzzy 50x50 white ellipse with black outline in center of canvas. 47990 * sharp 50x50 white ellipse with black outline in center of canvas. 47991 */ 47992p5.prototype.pixelDensity = function(val) { 47993 p5._validateParameters('pixelDensity', arguments); 47994 if (typeof val === 'number') { 47995 this._pixelDensity = val; 47996 } else { 47997 return this._pixelDensity; 47998 } 47999 this.resizeCanvas(this.width, this.height, true); 48000}; 48001 48002/** 48003 * Returns the pixel density of the current display the sketch is running on. 48004 * 48005 * @method displayDensity 48006 * @returns {Number} current pixel density of the display 48007 * @example 48008 * <div> 48009 * <code> 48010 * function setup() { 48011 * var density = displayDensity(); 48012 * pixelDensity(density); 48013 * createCanvas(100, 100); 48014 * background(200); 48015 * ellipse(width / 2, height / 2, 50, 50); 48016 * } 48017 * </code> 48018 * </div> 48019 * 48020 * @alt 48021 * 50x50 white ellipse with black outline in center of canvas. 48022 */ 48023p5.prototype.displayDensity = function() { 48024 return window.devicePixelRatio; 48025}; 48026 48027function launchFullscreen(element) { 48028 var enabled = 48029 document.fullscreenEnabled || 48030 document.webkitFullscreenEnabled || 48031 document.mozFullScreenEnabled || 48032 document.msFullscreenEnabled; 48033 if (!enabled) { 48034 throw new Error('Fullscreen not enabled in this browser.'); 48035 } 48036 if (element.requestFullscreen) { 48037 element.requestFullscreen(); 48038 } else if (element.mozRequestFullScreen) { 48039 element.mozRequestFullScreen(); 48040 } else if (element.webkitRequestFullscreen) { 48041 element.webkitRequestFullscreen(); 48042 } else if (element.msRequestFullscreen) { 48043 element.msRequestFullscreen(); 48044 } 48045} 48046 48047function exitFullscreen() { 48048 if (document.exitFullscreen) { 48049 document.exitFullscreen(); 48050 } else if (document.mozCancelFullScreen) { 48051 document.mozCancelFullScreen(); 48052 } else if (document.webkitExitFullscreen) { 48053 document.webkitExitFullscreen(); 48054 } else if (document.msExitFullscreen) { 48055 document.msExitFullscreen(); 48056 } 48057} 48058 48059/** 48060 * Gets the current URL. 48061 * @method getURL 48062 * @return {String} url 48063 * @example 48064 * <div> 48065 * <code> 48066 * var url; 48067 * var x = 100; 48068 * 48069 * function setup() { 48070 * fill(0); 48071 * noStroke(); 48072 * url = getURL(); 48073 * } 48074 * 48075 * function draw() { 48076 * background(200); 48077 * text(url, x, height / 2); 48078 * x--; 48079 * } 48080 * </code> 48081 * </div> 48082 * 48083 * @alt 48084 * current url (http://p5js.org/reference/#/p5/getURL) moves right to left. 48085 * 48086 */ 48087p5.prototype.getURL = function() { 48088 return location.href; 48089}; 48090/** 48091 * Gets the current URL path as an array. 48092 * @method getURLPath 48093 * @return {String[]} path components 48094 * @example 48095 * <div class='norender'><code> 48096 * function setup() { 48097 * var urlPath = getURLPath(); 48098 * for (var i = 0; i < urlPath.length; i++) { 48099 * text(urlPath[i], 10, i * 20 + 20); 48100 * } 48101 * } 48102 * </code></div> 48103 * 48104 * @alt 48105 *no display 48106 * 48107 */ 48108p5.prototype.getURLPath = function() { 48109 return location.pathname.split('/').filter(function(v) { 48110 return v !== ''; 48111 }); 48112}; 48113/** 48114 * Gets the current URL params as an Object. 48115 * @method getURLParams 48116 * @return {Object} URL params 48117 * @example 48118 * <div class='norender notest'> 48119 * <code> 48120 * // Example: http://p5js.org?year=2014&month=May&day=15 48121 * 48122 * function setup() { 48123 * var params = getURLParams(); 48124 * text(params.day, 10, 20); 48125 * text(params.month, 10, 40); 48126 * text(params.year, 10, 60); 48127 * } 48128 * </code> 48129 * </div> 48130 * @alt
48131 * no display. 48132 * 48133 */ 48134p5.prototype.getURLParams = function() { 48135 var re = /[?&]([^&=]+)(?:[&=])([^&=]+)/gim; 48136 var m; 48137 var v = {}; 48138 while ((m = re.exec(location.search)) != null) { 48139 if (m.index === re.lastIndex) { 48140 re.lastIndex++; 48141 } 48142 v[m[1]] = m[2]; 48143 } 48144 return v; 48145}; 48146 48147module.exports = p5; 48148 48149},{"./constants":21,"./core":22}],25:[function(_dereq_,module,exports){ 48150/** 48151 * @for p5 48152 * @requires core 48153 */ 48154 48155'use strict'; 48156 48157var p5 = _dereq_('./core'); 48158var constants = _dereq_('./constants'); 48159 48160if (typeof IS_MINIFIED !== 'undefined') { 48161 p5._validateParameters = p5._friendlyFileLoadError = function() {}; 48162} else { 48163 var doFriendlyWelcome = false; // TEMP until we get it all working LM 48164 // for parameter validation 48165 var dataDoc = _dereq_('../../docs/reference/data.json'); 48166 var arrDoc = JSON.parse(JSON.stringify(dataDoc)); 48167 48168 // -- Borrowed from jQuery 1.11.3 -- 48169 var class2type = {}; 48170 var toString = class2type.toString; 48171 var names = [ 48172 'Boolean', 48173 'Number', 48174 'String', 48175 'Function', 48176 'Array', 48177 'Date', 48178 'RegExp', 48179 'Object', 48180 'Error' 48181 ]; 48182 for (var n = 0; n < names.length; n++) { 48183 class2type['[object ' + names[n] + ']'] = names[n].toLowerCase(); 48184 } 48185 var getType = function(obj) { 48186 if (obj == null) { 48187 return obj + ''; 48188 } 48189 return typeof obj === 'object' || typeof obj === 'function' 48190 ? class2type[toString.call(obj)] || 'object' 48191 : typeof obj; 48192 }; 48193 48194 // -- End borrow -- 48195 48196 var friendlyWelcome = function() { 48197 // p5.js brand - magenta: #ED225D 48198 //var astrixBgColor = 'transparent'; 48199 //var astrixTxtColor = '#ED225D'; 48200 //var welcomeBgColor = '#ED225D'; 48201 //var welcomeTextColor = 'white'; 48202 console.log( 48203 ' _ \n' + 48204 ' /\\| |/\\ \n' + 48205 " \\ ` ' / \n" + 48206 ' / , . \\ \n' + 48207 ' \\/|_|\\/ ' + 48208 '\n\n> p5.js says: Welcome! ' + 48209 'This is your friendly debugger. ' + 48210 'To turn me off switch to using âp5.min.jsâ.' 48211 ); 48212 }; 48213 48214 /** 48215 * Prints out a fancy, colorful message to the console log 48216 * 48217 * @private 48218 * @param {String} message the words to be said 48219 * @param {String} func the name of the function to link 48220 * @param {Number|String} color CSS color string or error type 48221 * 48222 * @return console logs 48223 */ 48224 // Wrong number of params, undefined param, wrong type 48225 var FILE_LOAD = 3; 48226 var ERR_PARAMS = 3; 48227 // p5.js blue, p5.js orange, auto dark green; fallback p5.js darkened magenta 48228 // See testColors below for all the color codes and names 48229 var typeColors = ['#2D7BB6', '#EE9900', '#4DB200', '#C83C00']; 48230 var report = function(message, func, color) { 48231 if (doFriendlyWelcome) { 48232 friendlyWelcome(); 48233 doFriendlyWelcome = false; 48234 } 48235 if ('undefined' === getType(color)) { 48236 color = '#B40033'; // dark magenta 48237 } else if (getType(color) === 'number') { 48238 // Type to color 48239 color = typeColors[color]; 48240 } 48241 if (func.substring(0, 4) === 'load') { 48242 console.log( 48243 '> p5.js says: ' + 48244 message + 48245 '[https://github.com/processing/p5.js/wiki/Local-server]' 48246 ); 48247 } else { 48248 console.log( 48249 '> p5.js says: ' + 48250 message + 48251 ' [http://p5js.org/reference/#p5/' + 48252 func + 48253 ']' 48254 ); 48255 } 48256 }; 48257 48258 var errorCases = { 48259 '0': { 48260 fileType: 'image', 48261 method: 'loadImage', 48262 message: ' hosting the image online,' 48263 }, 48264 '1': { 48265 fileType: 'XML file', 48266 method: 'loadXML' 48267 }, 48268 '2': { 48269 fileType: 'table file', 48270 method: 'loadTable' 48271 }, 48272 '3': { 48273 fileType: 'text file', 48274 method: 'loadStrings' 48275 }, 48276 '4': { 48277 fileType: 'font', 48278 method: 'loadFont', 48279 message: ' hosting the font online,' 48280 } 48281 }; 48282 p5._friendlyFileLoadError = function(errorType, filePath) { 48283 var errorInfo = errorCases[errorType]; 48284 var message = 48285 'It looks like there was a problem' + 48286 ' loading your ' + 48287 errorInfo.fileType + 48288 '.' + 48289 ' Try checking if the file path [' + 48290 filePath + 48291 '] is correct,' + 48292 (errorInfo.message || '') + 48293 ' or running a local server.'; 48294 report(message, errorInfo.method, FILE_LOAD); 48295 }; 48296 48297 var docCache = {}; 48298 var builtinTypes = [ 48299 'number', 48300 'string', 48301 'boolean', 48302 'constant', 48303 'function', 48304 'any', 48305 'integer' 48306 ]; 48307 48308 // validateParameters() helper functions: 48309 // lookupParamDoc() for querying data.json 48310 var lookupParamDoc = function(func) { 48311 var queryResult = arrDoc.classitems.filter(function(x) { 48312 return x.name === func; 48313 }); 48314 // different JSON structure for funct with multi-format 48315 var overloads = []; 48316 if (queryResult[0].hasOwnProperty('overloads')) { 48317 for (var i = 0; i < queryResult[0].overloads.length; i++) { 48318 overloads.push(queryResult[0].overloads[i].params); 48319 } 48320 } else { 48321 overloads.push(queryResult[0].params || []); 48322 } 48323 48324 var mapConstants = {}; 48325 var maxParams = 0; 48326 overloads.forEach(function(formats) { 48327 if (maxParams < formats.length) { 48328 maxParams = formats.length; 48329 }
48330 formats.forEach(function(format) { 48331 format.types = format.type.split('|').map(function ct(type) { 48332 // array 48333 if (type.substr(type.length - 2, 2) === '[]') { 48334 return { 48335 name: type, 48336 array: ct(type.substr(0, type.length - 2)) 48337 }; 48338 } 48339 48340 var lowerType = type.toLowerCase(); 48341 48342 // contant 48343 if (lowerType === 'constant') { 48344 var constant; 48345 if (mapConstants.hasOwnProperty(format.name)) { 48346 constant = mapConstants[format.name]; 48347 } else { 48348 // parse possible constant values from description 48349 var myRe = /either\s+(?:[A-Z0-9_]+\s*,?\s*(?:or)?\s*)+/g; 48350 var values = {}; 48351 var names = []; 48352 48353 constant = mapConstants[format.name] = { 48354 values: values, 48355 names: names 48356 }; 48357 48358 var myArray = myRe.exec(format.description); 48359 if (func === 'endShape' && format.name === 'mode') { 48360 values[constants.CLOSE] = true; 48361 names.push('CLOSE'); 48362 } else { 48363 var match = myArray[0]; 48364 var reConst = /[A-Z0-9_]+/g; 48365 var matchConst; 48366 while ((matchConst = reConst.exec(match)) !== null) { 48367 var name = matchConst[0]; 48368 if (constants.hasOwnProperty(name)) { 48369 values[constants[name]] = true; 48370 names.push(name); 48371 } 48372 } 48373 } 48374 } 48375 return { 48376 name: type, 48377 builtin: lowerType, 48378 names: constant.names, 48379 values: constant.values 48380 }; 48381 } 48382 48383 // function 48384 if (lowerType.substr(0, 'function'.length) === 'function') { 48385 lowerType = 'function'; 48386 } 48387 // builtin 48388 if (builtinTypes.indexOf(lowerType) >= 0) { 48389 return { name: type, builtin: lowerType }; 48390 } 48391 48392 // find type's prototype 48393 var t = window; 48394 var typeParts = type.split('.'); 48395 48396 // special-case 'p5' since it may be non-global 48397 if (typeParts[0] === 'p5') { 48398 t = p5; 48399 typeParts.shift(); 48400 } 48401 48402 typeParts.forEach(function(p) { 48403 t = t && t[p]; 48404 }); 48405 if (t) { 48406 return { name: type, prototype: t }; 48407 } 48408 48409 return { name: type, type: lowerType }; 48410 }); 48411 }); 48412 }); 48413 return { 48414 overloads: overloads, 48415 maxParams: maxParams 48416 }; 48417 }; 48418 48419 var testParamType = function(param, type) { 48420 var isArray = param instanceof Array; 48421 if (type.array && isArray) { 48422 for (var i = 0; i < param.length; i++) { 48423 if (!testParamType(param[i], type.array)) { 48424 return false; 48425 } 48426 } 48427 return true; 48428 } else if (type.prototype) { 48429 return param instanceof type.prototype; 48430 } else if (type.builtin) { 48431 switch (type.builtin) { 48432 case 'number': 48433 return typeof param === 'number' || (!!param && !isNaN(param)); 48434 case 'integer': 48435 return ( 48436 (typeof param === 'number' || (!!param && !isNaN(param))) && 48437 Number(param) === Math.floor(param) 48438 ); 48439 case 'boolean': 48440 case 'any': 48441 return true; 48442 case 'array': 48443 return isArray; 48444 case 'string': 48445 return typeof param === 'number' || typeof param === 'string'; 48446 case 'constant': 48447 return type.values.hasOwnProperty(param); 48448 case 'function': 48449 return param instanceof Function; 48450 } 48451 } 48452 48453 return typeof param === type.t; 48454 }; 48455 48456 // testType() for non-object type parameter validation 48457 // Returns true if PASS, false if FAIL 48458 var testParamTypes = function(param, types) { 48459 for (var i = 0; i < types.length; i++) { 48460 if (testParamType(param, types[i])) { 48461 return true; 48462 } 48463 } 48464 return false; 48465 }; 48466 48467 var testParamFormat = function(args, formats) { 48468 var errorArray = []; 48469 for (var p = 0; p < formats.length; p++) { 48470 var arg = args[p]; 48471 var format = formats[p]; 48472 var argType = typeof arg; 48473 if ('undefined' === argType || null === arg) { 48474 if (format.optional !== true) { 48475 errorArray.push({ 48476 type: 'EMPTY_VAR', 48477 position: p, 48478 format: format 48479 }); 48480 } 48481 } else if (!testParamTypes(arg, format.types)) { 48482 errorArray.push({ 48483 type: 'WRONG_TYPE', 48484 position: p, 48485 format: format, 48486 arg: arg 48487 }); 48488 } 48489 } 48490 return errorArray; 48491 }; 48492 48493 // function for generating console.log() msg 48494 p5._friendlyParamError = function(errorObj, func) { 48495 var message; 48496 48497 function formatType() { 48498 var format = errorObj.format; 48499 return format.types 48500 .map(function(type) {
48501 return type.names ? type.names.join('|') : type.name; 48502 }) 48503 .join('|'); 48504 } 48505 48506 switch (errorObj.type) { 48507 case 'EMPTY_VAR': 48508 message = 48509 func + 48510 '() was expecting ' + 48511 formatType() + 48512 ' for parameter #' + 48513 errorObj.position + 48514 ' (zero-based index), received an empty variable instead.' + 48515 ' If not intentional, this is often a problem with scope:' + 48516 ' [https://p5js.org/examples/data-variable-scope.html]'; 48517 break; 48518 case 'WRONG_TYPE': 48519 var arg = errorObj.arg; 48520 var argType = arg instanceof Array ? 'array' : arg.name || typeof arg; 48521 message = 48522 func + 48523 '() was expecting ' + 48524 formatType() + 48525 ' for parameter #' + 48526 errorObj.position + 48527 ' (zero-based index), received ' + 48528 argType + 48529 ' instead'; 48530 break; 48531 case 'WRONG_ARGUMENT_COUNT': 48532 message = 48533 func + 48534 '() was expecting ' + 48535 errorObj.maxParams + 48536 ' arguments, but received ' + 48537 errorObj.argCount; 48538 break; 48539 } 48540 48541 if (message) { 48542 try { 48543 var re = /Function\.validateParameters.*[\r\n].*[\r\n].*\(([^)]*)/; 48544 var location = re.exec(new Error().stack)[1]; 48545 if (location) { 48546 message += ' at ' + location; 48547 } 48548 } catch (err) {} 48549 48550 report(message + '.', func, ERR_PARAMS); 48551 } 48552 }; 48553 48554 /** 48555 * Validates parameters 48556 * param {String} func the name of the function 48557 * param {Array} args user input arguments 48558 * 48559 * example: 48560 * var a; 48561 * ellipse(10,10,a,5); 48562 * console ouput: 48563 * "It looks like ellipse received an empty variable in spot #2." 48564 * 48565 * example: 48566 * ellipse(10,"foo",5,5); 48567 * console output: 48568 * "ellipse was expecting a number for parameter #1, 48569 * received "foo" instead." 48570 */ 48571 p5._validateParameters = function validateParameters(func, args) { 48572 if (p5.disableFriendlyErrors) { 48573 return; // skip FES 48574 } 48575 48576 var docs = docCache[func] || (docCache[func] = lookupParamDoc(func)); 48577 var errorArray = []; 48578 var minErrCount = 999999; 48579 var overloads = docs.overloads; 48580 for (var i = 0; i < overloads.length; i++) { 48581 var arrError = testParamFormat(args, overloads[i]); 48582 // see if this is the format with min number of err 48583 if (minErrCount > arrError.length) { 48584 minErrCount = arrError.length; 48585 errorArray = arrError; 48586 } 48587 if (arrError.length === 0) { 48588 break; // no error 48589 } 48590 } 48591 48592 if (!errorArray.length && args.length > docs.maxParams) { 48593 errorArray.push({ 48594 type: 'WRONG_ARGUMENT_COUNT', 48595 argCount: args.length, 48596 maxParams: docs.maxParams 48597 }); 48598 } 48599 48600 // generate err msg 48601 for (var n = 0; n < errorArray.length; n++) { 48602 p5._friendlyParamError(errorArray[n], func); 48603 } 48604 }; 48605 48606 /** 48607 * Prints out all the colors in the color pallete with white text. 48608 * For color blindness testing. 48609 */ 48610 /* function testColors() { 48611 var str = 'A box of biscuits, a box of mixed biscuits and a biscuit mixer'; 48612 report(str, 'print', '#ED225D'); // p5.js magenta 48613 report(str, 'print', '#2D7BB6'); // p5.js blue 48614 report(str, 'print', '#EE9900'); // p5.js orange 48615 report(str, 'print', '#A67F59'); // p5.js light brown 48616 report(str, 'print', '#704F21'); // p5.js gold 48617 report(str, 'print', '#1CC581'); // auto cyan 48618 report(str, 'print', '#FF6625'); // auto orange 48619 report(str, 'print', '#79EB22'); // auto green 48620 report(str, 'print', '#B40033'); // p5.js darkened magenta 48621 report(str, 'print', '#084B7F'); // p5.js darkened blue 48622 report(str, 'print', '#945F00'); // p5.js darkened orange 48623 report(str, 'print', '#6B441D'); // p5.js darkened brown 48624 report(str, 'print', '#2E1B00'); // p5.js darkened gold 48625 report(str, 'print', '#008851'); // auto dark cyan 48626 report(str, 'print', '#C83C00'); // auto dark orange 48627 report(str, 'print', '#4DB200'); // auto dark green 48628 } */ 48629 48630 p5.prototype._validateParameters = p5.validateParameters; 48631} 48632 48633// This is a lazily-defined list of p5 symbols that may be 48634// misused by beginners at top-level code, outside of setup/draw. We'd like 48635// to detect these errors and help the user by suggesting they move them 48636// into setup/draw. 48637// 48638// For more details, see https://github.com/processing/p5.js/issues/1121. 48639var misusedAtTopLevelCode = null; 48640var FAQ_URL = 48641 'https://github.com/processing/p5.js/wiki/' + 48642 'Frequently-Asked-Questions' + 48643 '#why-cant-i-assign-variables-using-p5-functions-and-' + 48644 'variables-before-setup'; 48645 48646var defineMisusedAtTopLevelCode = function() { 48647 var uniqueNamesFound = {}; 48648 48649 var getSymbols = function(obj) { 48650 return Object.getOwnPropertyNames(obj) 48651 .filter(function(name) { 48652 if (name[0] === '_') { 48653 return false;
48654 } 48655 if (name in uniqueNamesFound) { 48656 return false; 48657 } 48658 48659 uniqueNamesFound[name] = true; 48660 48661 return true; 48662 }) 48663 .map(function(name) { 48664 var type; 48665 48666 if (typeof obj[name] === 'function') { 48667 type = 'function'; 48668 } else if (name === name.toUpperCase()) { 48669 type = 'constant'; 48670 } else { 48671 type = 'variable'; 48672 } 48673 48674 return { name: name, type: type }; 48675 }); 48676 }; 48677 48678 misusedAtTopLevelCode = [].concat( 48679 getSymbols(p5.prototype), 48680 // At present, p5 only adds its constants to p5.prototype during 48681 // construction, which may not have happened at the time a 48682 // ReferenceError is thrown, so we'll manually add them to our list. 48683 getSymbols(_dereq_('./constants')) 48684 ); 48685 48686 // This will ultimately ensure that we report the most specific error 48687 // possible to the user, e.g. advising them about HALF_PI instead of PI 48688 // when their code misuses the former. 48689 misusedAtTopLevelCode.sort(function(a, b) { 48690 return b.name.length - a.name.length; 48691 }); 48692}; 48693 48694var helpForMisusedAtTopLevelCode = function(e, log) { 48695 if (!log) { 48696 log = console.log.bind(console); 48697 } 48698 48699 if (!misusedAtTopLevelCode) { 48700 defineMisusedAtTopLevelCode(); 48701 } 48702 48703 // If we find that we're logging lots of false positives, we can 48704 // uncomment the following code to avoid displaying anything if the 48705 // user's code isn't likely to be using p5's global mode. (Note that 48706 // setup/draw are more likely to be defined due to JS function hoisting.) 48707 // 48708 //if (!('setup' in window || 'draw' in window)) { 48709 // return; 48710 //} 48711 48712 misusedAtTopLevelCode.some(function(symbol) { 48713 // Note that while just checking for the occurrence of the 48714 // symbol name in the error message could result in false positives, 48715 // a more rigorous test is difficult because different browsers 48716 // log different messages, and the format of those messages may 48717 // change over time. 48718 // 48719 // For example, if the user uses 'PI' in their code, it may result 48720 // in any one of the following messages: 48721 // 48722 // * 'PI' is undefined (Microsoft Edge) 48723 // * ReferenceError: PI is undefined (Firefox) 48724 // * Uncaught ReferenceError: PI is not defined (Chrome) 48725 48726 if (e.message && e.message.match('\\W?' + symbol.name + '\\W') !== null) { 48727 log( 48728 "Did you just try to use p5.js's " + 48729 symbol.name + 48730 (symbol.type === 'function' ? '() ' : ' ') + 48731 symbol.type + 48732 '? If so, you may want to ' + 48733 "move it into your sketch's setup() function.\n\n" + 48734 'For more details, see: ' + 48735 FAQ_URL 48736 ); 48737 return true; 48738 } 48739 }); 48740}; 48741 48742// Exposing this primarily for unit testing. 48743p5.prototype._helpForMisusedAtTopLevelCode = helpForMisusedAtTopLevelCode; 48744 48745if (document.readyState !== 'complete') { 48746 window.addEventListener('error', helpForMisusedAtTopLevelCode, false); 48747 48748 // Our job is only to catch ReferenceErrors that are thrown when 48749 // global (non-instance mode) p5 APIs are used at the top-level 48750 // scope of a file, so we'll unbind our error listener now to make 48751 // sure we don't log false positives later. 48752 window.addEventListener('load', function() { 48753 window.removeEventListener('error', helpForMisusedAtTopLevelCode, false); 48754 }); 48755} 48756 48757module.exports = p5; 48758 48759},{"../../docs/reference/data.json":1,"./constants":21,"./core":22}],26:[function(_dereq_,module,exports){ 48760'use strict'; 48761 48762var p5 = _dereq_('../core/core'); 48763 48764/** 48765 * _globalInit 48766 * 48767 * TODO: ??? 48768 * if sketch is on window 48769 * assume "global" mode 48770 * and instantiate p5 automatically 48771 * otherwise do nothing 48772 * 48773 * @private 48774 * @return {Undefined} 48775 */ 48776var _globalInit = function() { 48777 if (!window.PHANTOMJS && !window.mocha) { 48778 // If there is a setup or draw function on the window 48779 // then instantiate p5 in "global" mode 48780 if ( 48781 ((window.setup && typeof window.setup === 'function') || 48782 (window.draw && typeof window.draw === 'function')) && 48783 !p5.instance 48784 ) { 48785 new p5(); 48786 } 48787 } 48788}; 48789 48790// TODO: ??? 48791if (document.readyState === 'complete') { 48792 _globalInit(); 48793} else { 48794 window.addEventListener('load', _globalInit, false); 48795} 48796 48797},{"../core/core":22}],27:[function(_dereq_,module,exports){ 48798/** 48799 * @module DOM 48800 * @submodule DOM 48801 * @for p5.Element 48802 */ 48803 48804'use strict'; 48805 48806var p5 = _dereq_('./core'); 48807 48808/** 48809 * Base class for all elements added to a sketch, including canvas, 48810 * graphics buffers, and other HTML elements. Methods in blue are 48811 * included in the core functionality, methods in brown are added 48812 * with the <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom 48813 * library</a>. 48814 * It is not called directly, but p5.Element 48815 * objects are created by calling createCanvas, createGraphics, 48816 * or in the p5.dom library, createDiv, createImg, createInput, etc. 48817 * 48818 * @class p5.Element 48819 * @param {String} elt DOM node that is wrapped 48820 * @param {p5} [pInst] pointer to p5 instance 48821 */ 48822p5.Element = function(elt, pInst) { 48823 /** 48824 * Underlying HTML element. All normal HTML methods can be called on this. 48825 * @example 48826 * <div> 48827 * <code> 48828 * createCanvas(300, 500); 48829 * background(0, 0, 0, 0); 48830 * var input = createInput(); 48831 * input.position(20, 225); 48832 * var inputElem = new p5.Element(input.elt); 48833 * inputElem.style('width:450px;'); 48834 * inputElem.value('some string'); 48835 * </code> 48836 * </div> 48837 * 48838 * @property elt 48839 * @readOnly 48840 */ 48841 this.elt = elt; 48842 this._pInst = pInst; 48843 this._events = {}; 48844 this.width = this.elt.offsetWidth; 48845 this.height = this.elt.offsetHeight; 48846}; 48847 48848/** 48849 * 48850 * Attaches the element to the parent specified. A way of setting 48851 * the container for the element. Accepts either a string ID, DOM 48852 * node, or p5.Element. If no arguments given, parent node is returned. 48853 * For more ways to position the canvas, see the 48854 * <a href='https://github.com/processing/p5.js/wiki/Positioning-your-canvas'> 48855 * positioning the canvas</a> wiki page. 48856 * 48857 * @method parent
48858 * @param {String|p5.Element|Object} parent the ID, DOM node, or p5.Element 48859 * of desired parent element 48860 * @chainable 48861 * 48862 * @example 48863 * <div class="norender notest"><code> 48864 * // in the html file: 48865 * // <div id="myContainer"></div> 48866 * 48867 * // in the js file: 48868 * var cnv = createCanvas(100, 100); 48869 * cnv.parent('myContainer'); 48870 * </code></div> 48871 * <div class='norender'><code> 48872 * var div0 = createDiv('this is the parent'); 48873 * var div1 = createDiv('this is the child'); 48874 * div1.parent(div0); // use p5.Element 48875 * </code></div> 48876 * <div class='norender'><code> 48877 * var div0 = createDiv('this is the parent'); 48878 * div0.id('apples'); 48879 * var div1 = createDiv('this is the child'); 48880 * div1.parent('apples'); // use id 48881 * </code></div> 48882 * <div class='norender notest'><code> 48883 * var elt = document.getElementById('myParentDiv'); 48884 * var div1 = createDiv('this is the child'); 48885 * div1.parent(elt); // use element from page 48886 * </code></div> 48887 * 48888 * @alt 48889 * no display. 48890 */ 48891/** 48892 * @method parent 48893 * @return {p5.Element} 48894 * 48895 */ 48896p5.Element.prototype.parent = function(p) { 48897 if (typeof p === 'undefined') { 48898 return this.elt.parentNode; 48899 } 48900 48901 if (typeof p === 'string') { 48902 if (p[0] === '#') { 48903 p = p.substring(1); 48904 } 48905 p = document.getElementById(p); 48906 } else if (p instanceof p5.Element) { 48907 p = p.elt; 48908 } 48909 p.appendChild(this.elt); 48910 return this; 48911}; 48912 48913/** 48914 * 48915 * Sets the ID of the element. If no ID argument is passed in, it instead 48916 * returns the current ID of the element. 48917 * 48918 * @method id 48919 * @param {String} id ID of the element 48920 * @chainable 48921 * 48922 * @example 48923 * <div class='norender'><code> 48924 * function setup() { 48925 * var cnv = createCanvas(100, 100); 48926 * // Assigns a CSS selector ID to 48927 * // the canvas element. 48928 * cnv.id('mycanvas'); 48929 * } 48930 * </code></div> 48931 * 48932 * @alt 48933 * no display. 48934 */ 48935/** 48936 * @method id 48937 * @return {String} the id of the element 48938 */ 48939p5.Element.prototype.id = function(id) { 48940 if (typeof id === 'undefined') { 48941 return this.elt.id; 48942 } 48943 48944 this.elt.id = id; 48945 this.width = this.elt.offsetWidth; 48946 this.height = this.elt.offsetHeight; 48947 return this; 48948}; 48949 48950/** 48951 * 48952 * Adds given class to the element. If no class argument is passed in, it 48953 * instead returns a string containing the current class(es) of the element. 48954 * 48955 * @method class 48956 * @param {String} class class to add 48957 * @chainable 48958 * 48959 * @example 48960 * <div class='norender'><code> 48961 * function setup() { 48962 * var cnv = createCanvas(100, 100); 48963 * // Assigns a CSS selector class 'small' 48964 * // to the canvas element. 48965 * cnv.class('small'); 48966 * } 48967 * </code></div> 48968 * 48969 * @alt 48970 * no display. 48971 */ 48972/** 48973 * @method class 48974 * @return {String} the class of the element 48975 */ 48976p5.Element.prototype.class = function(c) { 48977 if (typeof c === 'undefined') { 48978 return this.elt.className; 48979 } 48980 48981 this.elt.className = c; 48982 return this; 48983}; 48984 48985/** 48986 * The .mousePressed() function is called once after every time a 48987 * mouse button is pressed over the element. This can be used to 48988 * attach element specific event listeners. 48989 * 48990 * @method mousePressed 48991 * @param {Function|Boolean} fxn function to be fired when mouse is 48992 * pressed over the element. 48993 * if `false` is passed instead, the previously 48994 * firing function will no longer fire. 48995 * @chainable 48996 * @example 48997 * <div class='norender'><code> 48998 * var cnv; 48999 * var d; 49000 * var g; 49001 * function setup() { 49002 * cnv = createCanvas(100, 100); 49003 * cnv.mousePressed(changeGray); // attach listener for 49004 * // canvas click only 49005 * d = 10; 49006 * g = 100; 49007 * } 49008 * 49009 * function draw() { 49010 * background(g); 49011 * ellipse(width / 2, height / 2, d, d); 49012 * } 49013 * 49014 * // this function fires with any click anywhere 49015 * function mousePressed() { 49016 * d = d + 10; 49017 * } 49018 * 49019 * // this function fires only when cnv is clicked 49020 * function changeGray() { 49021 * g = random(0, 255); 49022 * } 49023 * </code></div> 49024 * 49025 * @alt 49026 * no display. 49027 * 49028 */ 49029p5.Element.prototype.mousePressed = function(fxn) { 49030 adjustListener('mousedown', fxn, this); 49031 adjustListener('touchstart', fxn, this); 49032 return this; 49033}; 49034 49035/** 49036 * The .doubleClicked() function is called once after every time a 49037 * mouse button is pressed twice over the element. This can be used to 49038 * attach element and action specific event listeners. 49039 * 49040 * @method doubleClicked 49041 * @param {Function|Boolean} fxn function to be fired when mouse is 49042 * double clicked over the element. 49043 * if `false` is passed instead, the previously 49044 * firing function will no longer fire. 49045 * @return {p5.Element} 49046 * @example 49047 * <div class='norender'><code> 49048 * var cnv; 49049 * var d; 49050 * var g; 49051 * function setup() { 49052 * cnv = createCanvas(100, 100); 49053 * cnv.doubleClicked(changeGray); // attach listener for 49054 * // canvas double click only 49055 * d = 10; 49056 * g = 100; 49057 * } 49058 * 49059 * function draw() { 49060 * background(g); 49061 * ellipse(width / 2, height / 2, d, d); 49062 * } 49063 *
49064 * // this function fires with any double click anywhere 49065 * function doubleClicked() { 49066 * d = d + 10; 49067 * } 49068 * 49069 * // this function fires only when cnv is double clicked 49070 * function changeGray() { 49071 * g = random(0, 255); 49072 * } 49073 * </code></div> 49074 * 49075 * @alt 49076 * no display. 49077 * 49078 */ 49079p5.Element.prototype.doubleClicked = function(fxn) { 49080 adjustListener('dblclick', fxn, this); 49081 return this; 49082}; 49083 49084/** 49085 * The .mouseWheel() function is called once after every time a 49086 * mouse wheel is scrolled over the element. This can be used to 49087 * attach element specific event listeners. 49088 * <br><br> 49089 * The function accepts a callback function as argument which will be executed 49090 * when the `wheel` event is triggered on the element, the callback function is 49091 * passed one argument `event`. The `event.deltaY` property returns negative 49092 * values if the mouse wheel is rotated up or away from the user and positive 49093 * in the other direction. The `event.deltaX` does the same as `event.deltaY` 49094 * except it reads the horizontal wheel scroll of the mouse wheel. 49095 * <br><br> 49096 * On OS X with "natural" scrolling enabled, the `event.deltaY` values are 49097 * reversed. 49098 * 49099 * @method mouseWheel 49100 * @param {Function|Boolean} fxn function to be fired when mouse is 49101 * scrolled over the element. 49102 * if `false` is passed instead, the previously 49103 * firing function will no longer fire. 49104 * @chainable 49105 * @example 49106 * <div class='norender'><code> 49107 * var cnv; 49108 * var d; 49109 * var g; 49110 * function setup() { 49111 * cnv = createCanvas(100, 100); 49112 * cnv.mouseWheel(changeSize); // attach listener for 49113 * // activity on canvas only 49114 * d = 10; 49115 * g = 100; 49116 * } 49117 * 49118 * function draw() { 49119 * background(g); 49120 * ellipse(width / 2, height / 2, d, d); 49121 * } 49122 * 49123 * // this function fires with mousewheel movement 49124 * // anywhere on screen 49125 * function mouseWheel() { 49126 * g = g + 10; 49127 * } 49128 * 49129 * // this function fires with mousewheel movement 49130 * // over canvas only 49131 * function changeSize(event) { 49132 * if (event.deltaY > 0) { 49133 * d = d + 10; 49134 * } else { 49135 * d = d - 10; 49136 * } 49137 * } 49138 * </code></div> 49139 * 49140 * 49141 * @alt 49142 * no display. 49143 * 49144 */ 49145p5.Element.prototype.mouseWheel = function(fxn) { 49146 adjustListener('wheel', fxn, this); 49147 return this; 49148}; 49149 49150/** 49151 * The .mouseReleased() function is called once after every time a 49152 * mouse button is released over the element. This can be used to 49153 * attach element specific event listeners. 49154 * 49155 * @method mouseReleased 49156 * @param {Function|Boolean} fxn function to be fired when mouse is 49157 * released over the element. 49158 * if `false` is passed instead, the previously 49159 * firing function will no longer fire. 49160 * @chainable 49161 * @example 49162 * <div class='norender'><code> 49163 * var cnv; 49164 * var d; 49165 * var g; 49166 * function setup() { 49167 * cnv = createCanvas(100, 100); 49168 * cnv.mouseReleased(changeGray); // attach listener for 49169 * // activity on canvas only 49170 * d = 10; 49171 * g = 100; 49172 * } 49173 * 49174 * function draw() { 49175 * background(g); 49176 * ellipse(width / 2, height / 2, d, d); 49177 * } 49178 * 49179 * // this function fires after the mouse has been 49180 * // released 49181 * function mouseReleased() { 49182 * d = d + 10; 49183 * } 49184 * 49185 * // this function fires after the mouse has been 49186 * // released while on canvas 49187 * function changeGray() { 49188 * g = random(0, 255); 49189 * } 49190 * </code></div> 49191 * 49192 * 49193 * @alt 49194 * no display. 49195 * 49196 */ 49197p5.Element.prototype.mouseReleased = function(fxn) { 49198 adjustListener('mouseup', fxn, this); 49199 adjustListener('touchend', fxn, this); 49200 return this; 49201}; 49202 49203/** 49204 * The .mouseClicked() function is called once after a mouse button is 49205 * pressed and released over the element. This can be used to 49206 * attach element specific event listeners. 49207 * 49208 * @method mouseClicked 49209 * @param {Function|Boolean} fxn function to be fired when mouse is 49210 * clicked over the element. 49211 * if `false` is passed instead, the previously 49212 * firing function will no longer fire. 49213 * @chainable 49214 * @example 49215 * <div class="norender"> 49216 * <code> 49217 * var cnv; 49218 * var d; 49219 * var g; 49220 * 49221 * function setup() { 49222 * cnv = createCanvas(100, 100); 49223 * cnv.mouseClicked(changeGray); // attach listener for 49224 * // activity on canvas only 49225 * d = 10; 49226 * g = 100; 49227 * } 49228 * 49229 * function draw() { 49230 * background(g); 49231 * ellipse(width / 2, height / 2, d, d); 49232 * } 49233 * 49234 * // this function fires after the mouse has been 49235 * // clicked anywhere 49236 * function mouseClicked() { 49237 * d = d + 10; 49238 * } 49239 * 49240 * // this function fires after the mouse has been 49241 * // clicked on canvas 49242 * function changeGray() { 49243 * g = random(0, 255); 49244 * } 49245 * </code> 49246 * </div> 49247 * 49248 * @alt
49249 * no display. 49250 * 49251 */ 49252p5.Element.prototype.mouseClicked = function(fxn) { 49253 adjustListener('click', fxn, this); 49254 return this; 49255}; 49256 49257/** 49258 * The .mouseMoved() function is called once every time a 49259 * mouse moves over the element. This can be used to attach an 49260 * element specific event listener. 49261 * 49262 * @method mouseMoved 49263 * @param {Function|Boolean} fxn function to be fired when a mouse moves 49264 * over the element. 49265 * if `false` is passed instead, the previously 49266 * firing function will no longer fire. 49267 * @chainable 49268 * @example 49269 * <div class='norender'><code> 49270 * var cnv; 49271 * var d = 30; 49272 * var g; 49273 * function setup() { 49274 * cnv = createCanvas(100, 100); 49275 * cnv.mouseMoved(changeSize); // attach listener for 49276 * // activity on canvas only 49277 * d = 10; 49278 * g = 100; 49279 * } 49280 * 49281 * function draw() { 49282 * background(g); 49283 * fill(200); 49284 * ellipse(width / 2, height / 2, d, d); 49285 * } 49286 * 49287 * // this function fires when mouse moves anywhere on 49288 * // page 49289 * function mouseMoved() { 49290 * g = g + 5; 49291 * if (g > 255) { 49292 * g = 0; 49293 * } 49294 * } 49295 * 49296 * // this function fires when mouse moves over canvas 49297 * function changeSize() { 49298 * d = d + 2; 49299 * if (d > 100) { 49300 * d = 0; 49301 * } 49302 * } 49303 * </code></div> 49304 * 49305 * 49306 * @alt 49307 * no display. 49308 * 49309 */ 49310p5.Element.prototype.mouseMoved = function(fxn) { 49311 adjustListener('mousemove', fxn, this); 49312 adjustListener('touchmove', fxn, this); 49313 return this; 49314}; 49315 49316/** 49317 * The .mouseOver() function is called once after every time a 49318 * mouse moves onto the element. This can be used to attach an 49319 * element specific event listener. 49320 * 49321 * @method mouseOver 49322 * @param {Function|Boolean} fxn function to be fired when a mouse moves 49323 * onto the element. 49324 * if `false` is passed instead, the previously 49325 * firing function will no longer fire. 49326 * @chainable 49327 * @example 49328 * <div class='norender'><code> 49329 * var cnv; 49330 * var d; 49331 * function setup() { 49332 * cnv = createCanvas(100, 100); 49333 * cnv.mouseOver(changeGray); 49334 * d = 10; 49335 * } 49336 * 49337 * function draw() { 49338 * ellipse(width / 2, height / 2, d, d); 49339 * } 49340 * 49341 * function changeGray() { 49342 * d = d + 10; 49343 * if (d > 100) { 49344 * d = 0; 49345 * } 49346 * } 49347 * </code></div> 49348 * 49349 * 49350 * @alt 49351 * no display. 49352 * 49353 */ 49354p5.Element.prototype.mouseOver = function(fxn) { 49355 adjustListener('mouseover', fxn, this); 49356 return this; 49357}; 49358 49359/** 49360 * The .changed() function is called when the value of an 49361 * element changes. 49362 * This can be used to attach an element specific event listener. 49363 * 49364 * @method changed 49365 * @param {Function|Boolean} fxn function to be fired when the value of 49366 * an element changes. 49367 * if `false` is passed instead, the previously 49368 * firing function will no longer fire. 49369 * @chainable 49370 * @example 49371 * <div><code> 49372 * var sel; 49373 * 49374 * function setup() { 49375 * textAlign(CENTER); 49376 * background(200); 49377 * sel = createSelect(); 49378 * sel.position(10, 10); 49379 * sel.option('pear'); 49380 * sel.option('kiwi'); 49381 * sel.option('grape'); 49382 * sel.changed(mySelectEvent); 49383 * } 49384 * 49385 * function mySelectEvent() { 49386 * var item = sel.value(); 49387 * background(200); 49388 * text("it's a " + item + '!', 50, 50); 49389 * } 49390 * </code></div> 49391 * <div><code> 49392 * var checkbox; 49393 * var cnv; 49394 * 49395 * function setup() { 49396 * checkbox = createCheckbox(' fill'); 49397 * checkbox.changed(changeFill); 49398 * cnv = createCanvas(100, 100); 49399 * cnv.position(0, 30); 49400 * noFill(); 49401 * } 49402 * 49403 * function draw() { 49404 * background(200); 49405 * ellipse(50, 50, 50, 50); 49406 * } 49407 * 49408 * function changeFill() { 49409 * if (checkbox.checked()) { 49410 * fill(0); 49411 * } else { 49412 * noFill(); 49413 * } 49414 * } 49415 * </code></div> 49416 * 49417 * @alt 49418 * dropdown: pear, kiwi, grape. When selected text "its a" + selection shown. 49419 * 49420 */ 49421p5.Element.prototype.changed = function(fxn) { 49422 adjustListener('change', fxn, this); 49423 return this; 49424}; 49425 49426/** 49427 * The .input() function is called when any user input is 49428 * detected with an element. The input event is often used 49429 * to detect keystrokes in a input element, or changes on a 49430 * slider element. This can be used to attach an element specific 49431 * event listener. 49432 * 49433 * @method input 49434 * @param {Function|Boolean} fxn function to be fired when any user input is 49435 * detected within the element. 49436 * if `false` is passed instead, the previously 49437 * firing function will no longer fire. 49438 * @chainable 49439 * @example 49440 * <div class='norender'><code> 49441 * // Open your console to see the output 49442 * function setup() { 49443 * var inp = createInput(''); 49444 * inp.input(myInputEvent); 49445 * } 49446 * 49447 * function myInputEvent() { 49448 * console.log('you are typing: ', this.value()); 49449 * } 49450 * </code></div> 49451 * 49452 * @alt
49453 * no display. 49454 * 49455 */ 49456p5.Element.prototype.input = function(fxn) { 49457 adjustListener('input', fxn, this); 49458 return this; 49459}; 49460 49461/** 49462 * The .mouseOut() function is called once after every time a 49463 * mouse moves off the element. This can be used to attach an 49464 * element specific event listener. 49465 * 49466 * @method mouseOut 49467 * @param {Function|Boolean} fxn function to be fired when a mouse 49468 * moves off of an element. 49469 * if `false` is passed instead, the previously 49470 * firing function will no longer fire. 49471 * @chainable 49472 * @example 49473 * <div class='norender'><code> 49474 * var cnv; 49475 * var d; 49476 * function setup() { 49477 * cnv = createCanvas(100, 100); 49478 * cnv.mouseOut(changeGray); 49479 * d = 10; 49480 * } 49481 * 49482 * function draw() { 49483 * ellipse(width / 2, height / 2, d, d); 49484 * } 49485 * 49486 * function changeGray() { 49487 * d = d + 10; 49488 * if (d > 100) { 49489 * d = 0; 49490 * } 49491 * } 49492 * </code></div> 49493 * 49494 * @alt 49495 * no display. 49496 * 49497 */ 49498p5.Element.prototype.mouseOut = function(fxn) { 49499 adjustListener('mouseout', fxn, this); 49500 return this; 49501}; 49502 49503/** 49504 * The .touchStarted() function is called once after every time a touch is 49505 * registered. This can be used to attach element specific event listeners. 49506 * 49507 * @method touchStarted 49508 * @param {Function|Boolean} fxn function to be fired when a touch 49509 * starts over the element. 49510 * if `false` is passed instead, the previously 49511 * firing function will no longer fire. 49512 * @chainable 49513 * @example 49514 * <div class='norender'><code> 49515 * var cnv; 49516 * var d; 49517 * var g; 49518 * function setup() { 49519 * cnv = createCanvas(100, 100); 49520 * cnv.touchStarted(changeGray); // attach listener for 49521 * // canvas click only 49522 * d = 10; 49523 * g = 100; 49524 * } 49525 * 49526 * function draw() { 49527 * background(g); 49528 * ellipse(width / 2, height / 2, d, d); 49529 * } 49530 * 49531 * // this function fires with any touch anywhere 49532 * function touchStarted() { 49533 * d = d + 10; 49534 * } 49535 * 49536 * // this function fires only when cnv is clicked 49537 * function changeGray() { 49538 * g = random(0, 255); 49539 * } 49540 * </code></div> 49541 * 49542 * @alt 49543 * no display. 49544 * 49545 */ 49546p5.Element.prototype.touchStarted = function(fxn) { 49547 adjustListener('touchstart', fxn, this); 49548 adjustListener('mousedown', fxn, this); 49549 return this; 49550}; 49551 49552/** 49553 * The .touchMoved() function is called once after every time a touch move is 49554 * registered. This can be used to attach element specific event listeners. 49555 * 49556 * @method touchMoved 49557 * @param {Function|Boolean} fxn function to be fired when a touch moves over 49558 * the element. 49559 * if `false` is passed instead, the previously 49560 * firing function will no longer fire. 49561 * @chainable 49562 * @example 49563 * <div class='norender'><code> 49564 * var cnv; 49565 * var g; 49566 * function setup() { 49567 * cnv = createCanvas(100, 100); 49568 * cnv.touchMoved(changeGray); // attach listener for 49569 * // canvas click only 49570 * g = 100; 49571 * } 49572 * 49573 * function draw() { 49574 * background(g); 49575 * } 49576 * 49577 * // this function fires only when cnv is clicked 49578 * function changeGray() { 49579 * g = random(0, 255); 49580 * } 49581 * </code></div> 49582 * 49583 * @alt 49584 * no display. 49585 * 49586 */ 49587p5.Element.prototype.touchMoved = function(fxn) { 49588 adjustListener('touchmove', fxn, this); 49589 adjustListener('mousemove', fxn, this); 49590 return this; 49591}; 49592 49593/** 49594 * The .touchEnded() function is called once after every time a touch is 49595 * registered. This can be used to attach element specific event listeners. 49596 * 49597 * @method touchEnded 49598 * @param {Function|Boolean} fxn function to be fired when a touch ends 49599 * over the element. 49600 * if `false` is passed instead, the previously 49601 * firing function will no longer fire. 49602 * @chainable 49603 * @example 49604 * <div class='norender'><code> 49605 * var cnv; 49606 * var d; 49607 * var g; 49608 * function setup() { 49609 * cnv = createCanvas(100, 100); 49610 * cnv.touchEnded(changeGray); // attach listener for 49611 * // canvas click only 49612 * d = 10; 49613 * g = 100; 49614 * } 49615 * 49616 * function draw() { 49617 * background(g); 49618 * ellipse(width / 2, height / 2, d, d); 49619 * } 49620 * 49621 * // this function fires with any touch anywhere 49622 * function touchEnded() { 49623 * d = d + 10; 49624 * } 49625 * 49626 * // this function fires only when cnv is clicked 49627 * function changeGray() { 49628 * g = random(0, 255); 49629 * } 49630 * </code></div> 49631 * 49632 * 49633 * @alt
49634 * no display. 49635 * 49636 */ 49637p5.Element.prototype.touchEnded = function(fxn) { 49638 adjustListener('touchend', fxn, this); 49639 adjustListener('mouseup', fxn, this); 49640 return this; 49641}; 49642 49643/** 49644 * The .dragOver() function is called once after every time a 49645 * file is dragged over the element. This can be used to attach an 49646 * element specific event listener. 49647 * 49648 * @method dragOver 49649 * @param {Function|Boolean} fxn function to be fired when a file is 49650 * dragged over the element. 49651 * if `false` is passed instead, the previously 49652 * firing function will no longer fire. 49653 * @chainable 49654 * @example 49655 * <div><code> 49656 * // To test this sketch, simply drag a 49657 * // file over the canvas 49658 * function setup() { 49659 * var c = createCanvas(100, 100); 49660 * background(200); 49661 * textAlign(CENTER); 49662 * text('Drag file', width / 2, height / 2); 49663 * c.dragOver(dragOverCallback); 49664 * } 49665 * 49666 * // This function will be called whenever 49667 * // a file is dragged over the canvas 49668 * function dragOverCallback() { 49669 * background(240); 49670 * text('Dragged over', width / 2, height / 2); 49671 * } 49672 * </code></div> 49673 * @alt 49674 * nothing displayed 49675 */ 49676p5.Element.prototype.dragOver = function(fxn) { 49677 adjustListener('dragover', fxn, this); 49678 return this; 49679}; 49680 49681/** 49682 * The .dragLeave() function is called once after every time a 49683 * dragged file leaves the element area. This can be used to attach an 49684 * element specific event listener. 49685 * 49686 * @method dragLeave 49687 * @param {Function|Boolean} fxn function to be fired when a file is 49688 * dragged off the element. 49689 * if `false` is passed instead, the previously 49690 * firing function will no longer fire. 49691 * @chainable 49692 * @example 49693 * <div><code> 49694 * // To test this sketch, simply drag a file 49695 * // over and then out of the canvas area 49696 * function setup() { 49697 * var c = createCanvas(100, 100); 49698 * background(200); 49699 * textAlign(CENTER); 49700 * text('Drag file', width / 2, height / 2); 49701 * c.dragLeave(dragLeaveCallback); 49702 * } 49703 * 49704 * // This function will be called whenever 49705 * // a file is dragged out of the canvas 49706 * function dragLeaveCallback() { 49707 * background(240); 49708 * text('Dragged off', width / 2, height / 2); 49709 * } 49710 * </code></div> 49711 * @alt 49712 * nothing displayed 49713 */ 49714p5.Element.prototype.dragLeave = function(fxn) { 49715 adjustListener('dragleave', fxn, this); 49716 return this; 49717}; 49718 49719/** 49720 * The .drop() function is called for each file dropped on the element. 49721 * It requires a callback that is passed a p5.File object. You can 49722 * optionally pass two callbacks, the first one (required) is triggered 49723 * for each file dropped when the file is loaded. The second (optional) 49724 * is triggered just once when a file (or files) are dropped. 49725 * 49726 * @method drop 49727 * @param {Function} callback callback triggered when files are dropped. 49728 * @param {Function} [fxn] callback to receive loaded file. 49729 * @chainable 49730 * @example 49731 * <div><code> 49732 * function setup() { 49733 * var c = createCanvas(100, 100); 49734 * background(200); 49735 * textAlign(CENTER); 49736 * text('drop image', width / 2, height / 2); 49737 * c.drop(gotFile); 49738 * } 49739 * 49740 * function gotFile(file) { 49741 * var img = createImg(file.data).hide(); 49742 * // Draw the image onto the canvas 49743 * image(img, 0, 0, width, height); 49744 * } 49745 * </code></div> 49746 * 49747 * @alt 49748 * Canvas turns into whatever image is dragged/dropped onto it. 49749 * 49750 */ 49751p5.Element.prototype.drop = function(callback, fxn) { 49752 // Make a file loader callback and trigger user's callback 49753 function makeLoader(theFile) { 49754 // Making a p5.File object 49755 var p5file = new p5.File(theFile); 49756 return function(e) { 49757 p5file.data = e.target.result; 49758 callback(p5file); 49759 }; 49760 } 49761 49762 // Is the file stuff supported? 49763 if (window.File && window.FileReader && window.FileList && window.Blob) { 49764 // If you want to be able to drop you've got to turn off 49765 // a lot of default behavior 49766 attachListener( 49767 'dragover', 49768 function(evt) { 49769 evt.stopPropagation(); 49770 evt.preventDefault(); 49771 }, 49772 this 49773 ); 49774 49775 // If this is a drag area we need to turn off the default behavior 49776 attachListener( 49777 'dragleave', 49778 function(evt) { 49779 evt.stopPropagation(); 49780 evt.preventDefault(); 49781 }, 49782 this 49783 ); 49784 49785 // If just one argument it's the callback for the files 49786 if (typeof fxn !== 'undefined') { 49787 attachListener('drop', fxn, this); 49788 } 49789 49790 // Deal with the files 49791 attachListener( 49792 'drop', 49793 function(evt) { 49794 evt.stopPropagation(); 49795 evt.preventDefault(); 49796 49797 // A FileList 49798 var files = evt.dataTransfer.files; 49799 49800 // Load each one and trigger the callback 49801 for (var i = 0; i < files.length; i++) { 49802 var f = files[i]; 49803 var reader = new FileReader(); 49804 reader.onload = makeLoader(f); 49805 49806 // Text or data? 49807 // This should likely be improved 49808 if (f.type.indexOf('text') > -1) { 49809 reader.readAsText(f); 49810 } else {
49811 reader.readAsDataURL(f); 49812 } 49813 } 49814 }, 49815 this 49816 ); 49817 } else { 49818 console.log('The File APIs are not fully supported in this browser.'); 49819 } 49820 49821 return this; 49822}; 49823 49824// General handler for event attaching and detaching 49825function adjustListener(ev, fxn, ctx) { 49826 if (fxn === false) { 49827 detachListener(ev, ctx); 49828 } else { 49829 attachListener(ev, fxn, ctx); 49830 } 49831 return this; 49832} 49833 49834function attachListener(ev, fxn, ctx) { 49835 // LM removing, not sure why we had this? 49836 // var _this = ctx; 49837 // var f = function (e) { fxn(e, _this); }; 49838 49839 // detach the old listener if there was one 49840 if (ctx._events[ev]) { 49841 detachListener(ev, ctx); 49842 } 49843 var f = fxn.bind(ctx); 49844 ctx.elt.addEventListener(ev, f, false); 49845 ctx._events[ev] = f; 49846} 49847 49848function detachListener(ev, ctx) { 49849 var f = ctx._events[ev]; 49850 ctx.elt.removeEventListener(ev, f, false); 49851 ctx._events[ev] = null; 49852} 49853 49854/** 49855 * Helper fxn for sharing pixel methods 49856 * 49857 */ 49858p5.Element.prototype._setProperty = function(prop, value) { 49859 this[prop] = value; 49860}; 49861 49862module.exports = p5.Element; 49863 49864},{"./core":22}],28:[function(_dereq_,module,exports){ 49865/** 49866 * @module Rendering 49867 * @submodule Rendering 49868 * @for p5 49869 */ 49870 49871'use strict'; 49872 49873var p5 = _dereq_('./core'); 49874var constants = _dereq_('./constants'); 49875 49876/** 49877 * Thin wrapper around a renderer, to be used for creating a 49878 * graphics buffer object. Use this class if you need 49879 * to draw into an off-screen graphics buffer. The two parameters define the 49880 * width and height in pixels. The fields and methods for this class are 49881 * extensive, but mirror the normal drawing API for p5. 49882 * 49883 * @class p5.Graphics 49884 * @extends p5.Element 49885 * @param {Number} w width 49886 * @param {Number} h height 49887 * @param {Constant} renderer the renderer to use, either P2D or WEBGL 49888 * @param {p5} [pInst] pointer to p5 instance 49889 */ 49890p5.Graphics = function(w, h, renderer, pInst) { 49891 var r = renderer || constants.P2D; 49892 49893 this.canvas = document.createElement('canvas'); 49894 var node = pInst._userNode || document.body; 49895 node.appendChild(this.canvas); 49896 49897 p5.Element.call(this, this.canvas, pInst, false); 49898 49899 // bind methods and props of p5 to the new object 49900 for (var p in p5.prototype) { 49901 if (!this[p]) { 49902 if (typeof p5.prototype[p] === 'function') { 49903 this[p] = p5.prototype[p].bind(this); 49904 } else { 49905 this[p] = p5.prototype[p]; 49906 } 49907 } 49908 } 49909 49910 p5.prototype._initializeInstanceVariables.apply(this); 49911 this.width = w; 49912 this.height = h; 49913 this._pixelDensity = pInst._pixelDensity; 49914 49915 if (r === constants.WEBGL) { 49916 this._renderer = new p5.RendererGL(this.canvas, this, false); 49917 } else { 49918 this._renderer = new p5.Renderer2D(this.canvas, this, false); 49919 } 49920 pInst._elements.push(this); 49921 49922 this._renderer.resize(w, h); 49923 this._renderer._applyDefaults(); 49924 return this; 49925}; 49926 49927p5.Graphics.prototype = Object.create(p5.Element.prototype); 49928 49929/** 49930 * Removes a Graphics object from the page and frees any resources 49931 * associated with it. 49932 * 49933 * @method remove 49934 * 49935 * @example 49936 * <div class='norender'><code> 49937 * var bg; 49938 * function setup() { 49939 * bg = createCanvas(100, 100); 49940 * bg.background(0); 49941 * image(bg, 0, 0); 49942 * bg.remove(); 49943 * } 49944 * </code></div> 49945 * 49946 * <div><code> 49947 * var bg; 49948 * function setup() { 49949 * pixelDensity(1); 49950 * createCanvas(100, 100); 49951 * stroke(255); 49952 * fill(0); 49953 * 49954 * // create and draw the background image 49955 * bg = createGraphics(100, 100); 49956 * bg.background(200); 49957 * bg.ellipse(50, 50, 80, 80); 49958 * } 49959 * function draw() { 49960 * var t = millis() / 1000; 49961 * // draw the background 49962 * if (bg) { 49963 * image(bg, frameCount % 100, 0); 49964 * image(bg, frameCount % 100 - 100, 0); 49965 * } 49966 * // draw the foreground 49967 * var p = p5.Vector.fromAngle(t, 35).add(50, 50); 49968 * ellipse(p.x, p.y, 30); 49969 * } 49970 * function mouseClicked() { 49971 * // remove the background 49972 * if (bg) { 49973 * bg.remove(); 49974 * bg = null; 49975 * } 49976 * } 49977 * </code></div> 49978 * 49979 * @alt 49980 * no image 49981 * a multi-colored circle moving back and forth over a scrolling background. 49982 * 49983 */ 49984p5.Graphics.prototype.remove = function() { 49985 if (this.elt.parentNode) { 49986 this.elt.parentNode.removeChild(this.elt); 49987 } 49988 var idx = this._pInst._elements.indexOf(this); 49989 if (idx !== -1) { 49990 this._pInst._elements.splice(idx, 1); 49991 } 49992 for (var elt_ev in this._events) { 49993 this.elt.removeEventListener(elt_ev, this._events[elt_ev]); 49994 } 49995}; 49996 49997module.exports = p5.Graphics; 49998 49999},{"./constants":21,"./core":22}],29:[function(_dereq_,module,exports){ 50000/** 50001 * @module Rendering 50002 * @submodule Rendering 50003 * @for p5 50004 */ 50005 50006'use strict'; 50007 50008var p5 = _dereq_('./core'); 50009var constants = _dereq_('../core/constants'); 50010 50011/** 50012 * Main graphics and rendering context, as well as the base API 50013 * implementation for p5.js "core". To be used as the superclass for 50014 * Renderer2D and Renderer3D classes, respecitvely. 50015 * 50016 * @class p5.Renderer 50017 * @constructor 50018 * @extends p5.Element 50019 * @param {String} elt DOM node that is wrapped 50020 * @param {p5} [pInst] pointer to p5 instance 50021 * @param {Boolean} [isMainCanvas] whether we're using it as main canvas 50022 */ 50023p5.Renderer = function(elt, pInst, isMainCanvas) { 50024 p5.Element.call(this, elt, pInst); 50025 this.canvas = elt; 50026 this._pInst = pInst; 50027 if (isMainCanvas) { 50028 this._isMainCanvas = true; 50029 // for pixel method sharing with pimage 50030 this._pInst._setProperty('_curElement', this); 50031 this._pInst._setProperty('canvas', this.canvas); 50032 this._pInst._setProperty('width', this.width); 50033 this._pInst._setProperty('height', this.height); 50034 } else { 50035 // hide if offscreen buffer by default 50036 this.canvas.style.display = 'none'; 50037 this._styles = []; // non-main elt styles stored in p5.Renderer 50038 } 50039 50040 this._textSize = 12; 50041 this._textLeading = 15; 50042 this._textFont = 'sans-serif'; 50043 this._textStyle = constants.NORMAL; 50044 this._textAscent = null; 50045 this._textDescent = null; 50046 50047 this._rectMode = constants.CORNER; 50048 this._ellipseMode = constants.CENTER; 50049 this._curveTightness = 0; 50050 this._imageMode = constants.CORNER; 50051 50052 this._tint = null; 50053 this._doStroke = true; 50054 this._doFill = true; 50055 this._strokeSet = false;
50056 this._fillSet = false; 50057}; 50058 50059p5.Renderer.prototype = Object.create(p5.Element.prototype); 50060 50061// the renderer should return a 'style' object that it wishes to 50062// store on the push stack. 50063p5.Renderer.prototype.push = function() { 50064 return { 50065 properties: { 50066 _doStroke: this._doStroke, 50067 _strokeSet: this._strokeSet, 50068 _doFill: this._doFill, 50069 _fillSet: this._fillSet, 50070 _tint: this._tint, 50071 _imageMode: this._imageMode, 50072 _rectMode: this._rectMode, 50073 _ellipseMode: this._ellipseMode, 50074 _textFont: this._textFont, 50075 _textLeading: this._textLeading, 50076 _textSize: this._textSize, 50077 _textStyle: this._textStyle 50078 } 50079 }; 50080}; 50081 50082// this is implementation of Object.assign() which is unavailable in 50083// IE11 and (non-Chrome) Android browsers. 50084// The assign() method is used to copy the values of all enumerable 50085// own properties from one or more source objects to a target object. 50086// It will return the target object. 50087function assign(to, firstSource) { 50088 for (var i = 1; i < arguments.length; i++) { 50089 var nextSource = arguments[i]; 50090 if (nextSource === undefined || nextSource === null) { 50091 continue; 50092 } 50093 50094 for (var nextKey in nextSource) 50095 if (nextSource.hasOwnProperty(nextKey)) { 50096 to[nextKey] = nextSource[nextKey]; 50097 } 50098 } 50099 return to; 50100} 50101 50102// a pop() operation is in progress 50103// the renderer is passed the 'style' object that it returned 50104// from its push() method. 50105p5.Renderer.prototype.pop = function(style) { 50106 if (style.properties) { 50107 // copy the style properties back into the renderer 50108 assign(this, style.properties); 50109 } 50110}; 50111 50112/** 50113 * Resize our canvas element. 50114 */ 50115p5.Renderer.prototype.resize = function(w, h) { 50116 this.width = w; 50117 this.height = h; 50118 this.elt.width = w * this._pInst._pixelDensity; 50119 this.elt.height = h * this._pInst._pixelDensity; 50120 this.elt.style.width = w + 'px'; 50121 this.elt.style.height = h + 'px'; 50122 if (this._isMainCanvas) { 50123 this._pInst._setProperty('width', this.width); 50124 this._pInst._setProperty('height', this.height); 50125 } 50126}; 50127 50128p5.Renderer.prototype.textLeading = function(l) { 50129 if (typeof l === 'number') { 50130 this._setProperty('_textLeading', l); 50131 return this; 50132 } 50133 50134 return this._textLeading; 50135}; 50136 50137p5.Renderer.prototype.textSize = function(s) { 50138 if (typeof s === 'number') { 50139 this._setProperty('_textSize', s); 50140 this._setProperty('_textLeading', s * constants._DEFAULT_LEADMULT); 50141 return this._applyTextProperties(); 50142 } 50143 50144 return this._textSize; 50145}; 50146 50147p5.Renderer.prototype.textStyle = function(s) { 50148 if (s) { 50149 if ( 50150 s === constants.NORMAL || 50151 s === constants.ITALIC || 50152 s === constants.BOLD 50153 ) { 50154 this._setProperty('_textStyle', s); 50155 } 50156 50157 return this._applyTextProperties(); 50158 } 50159 50160 return this._textStyle; 50161}; 50162 50163p5.Renderer.prototype.textAscent = function() { 50164 if (this._textAscent === null) { 50165 this._updateTextMetrics(); 50166 } 50167 return this._textAscent; 50168}; 50169 50170p5.Renderer.prototype.textDescent = function() { 50171 if (this._textDescent === null) { 50172 this._updateTextMetrics(); 50173 } 50174 return this._textDescent; 50175}; 50176 50177p5.Renderer.prototype._applyDefaults = function() { 50178 return this; 50179}; 50180 50181/** 50182 * Helper fxn to check font type (system or otf) 50183 */ 50184p5.Renderer.prototype._isOpenType = function(f) { 50185 f = f || this._textFont; 50186 return typeof f === 'object' && f.font && f.font.supported; 50187}; 50188 50189p5.Renderer.prototype._updateTextMetrics = function() { 50190 if (this._isOpenType()) { 50191 this._setProperty('_textAscent', this._textFont._textAscent()); 50192 this._setProperty('_textDescent', this._textFont._textDescent()); 50193 return this; 50194 } 50195 50196 // Adapted from http://stackoverflow.com/a/25355178 50197 var text = document.createElement('span'); 50198 text.style.fontFamily = this._textFont; 50199 text.style.fontSize = this._textSize + 'px'; 50200 text.innerHTML = 'ABCjgq|'; 50201 50202 var block = document.createElement('div'); 50203 block.style.display = 'inline-block'; 50204 block.style.width = '1px'; 50205 block.style.height = '0px'; 50206 50207 var container = document.createElement('div'); 50208 container.appendChild(text); 50209 container.appendChild(block); 50210 50211 container.style.height = '0px'; 50212 container.style.overflow = 'hidden'; 50213 document.body.appendChild(container); 50214 50215 block.style.verticalAlign = 'baseline'; 50216 var blockOffset = calculateOffset(block); 50217 var textOffset = calculateOffset(text); 50218 var ascent = blockOffset[1] - textOffset[1]; 50219 50220 block.style.verticalAlign = 'bottom'; 50221 blockOffset = calculateOffset(block); 50222 textOffset = calculateOffset(text); 50223 var height = blockOffset[1] - textOffset[1]; 50224 var descent = height - ascent; 50225 50226 document.body.removeChild(container); 50227 50228 this._setProperty('_textAscent', ascent); 50229 this._setProperty('_textDescent', descent); 50230 50231 return this; 50232}; 50233 50234/**
50235 * Helper fxn to measure ascent and descent. 50236 * Adapted from http://stackoverflow.com/a/25355178 50237 */ 50238function calculateOffset(object) { 50239 var currentLeft = 0, 50240 currentTop = 0; 50241 if (object.offsetParent) { 50242 do { 50243 currentLeft += object.offsetLeft; 50244 currentTop += object.offsetTop; 50245 } while ((object = object.offsetParent)); 50246 } else { 50247 currentLeft += object.offsetLeft; 50248 currentTop += object.offsetTop; 50249 } 50250 return [currentLeft, currentTop]; 50251} 50252 50253module.exports = p5.Renderer; 50254 50255},{"../core/constants":21,"./core":22}],30:[function(_dereq_,module,exports){ 50256'use strict'; 50257 50258var p5 = _dereq_('./core'); 50259var canvas = _dereq_('./canvas'); 50260var constants = _dereq_('./constants'); 50261var filters = _dereq_('../image/filters'); 50262 50263_dereq_('./p5.Renderer'); 50264 50265/** 50266 * p5.Renderer2D 50267 * The 2D graphics canvas renderer class. 50268 * extends p5.Renderer 50269 */ 50270var styleEmpty = 'rgba(0,0,0,0)'; 50271// var alphaThreshold = 0.00125; // minimum visible 50272 50273p5.Renderer2D = function(elt, pInst, isMainCanvas) { 50274 p5.Renderer.call(this, elt, pInst, isMainCanvas); 50275 this.drawingContext = this.canvas.getContext('2d'); 50276 this._pInst._setProperty('drawingContext', this.drawingContext); 50277 return this; 50278}; 50279 50280p5.Renderer2D.prototype = Object.create(p5.Renderer.prototype); 50281 50282p5.Renderer2D.prototype._applyDefaults = function() { 50283 this._cachedFillStyle = this._cachedStrokeStyle = undefined; 50284 this._setFill(constants._DEFAULT_FILL); 50285 this._setStroke(constants._DEFAULT_STROKE); 50286 this.drawingContext.lineCap = constants.ROUND; 50287 this.drawingContext.font = 'normal 12px sans-serif'; 50288}; 50289 50290p5.Renderer2D.prototype.resize = function(w, h) { 50291 p5.Renderer.prototype.resize.call(this, w, h); 50292 this.drawingContext.scale( 50293 this._pInst._pixelDensity, 50294 this._pInst._pixelDensity 50295 ); 50296}; 50297 50298////////////////////////////////////////////// 50299// COLOR | Setting 50300////////////////////////////////////////////// 50301 50302p5.Renderer2D.prototype.background = function() { 50303 this.drawingContext.save(); 50304 this.drawingContext.setTransform(1, 0, 0, 1, 0, 0); 50305 this.drawingContext.scale( 50306 this._pInst._pixelDensity, 50307 this._pInst._pixelDensity 50308 ); 50309 50310 if (arguments[0] instanceof p5.Image) { 50311 this._pInst.image(arguments[0], 0, 0, this.width, this.height); 50312 } else { 50313 var curFill = this._getFill(); 50314 // create background rect 50315 var color = this._pInst.color.apply(this._pInst, arguments); 50316 var newFill = color.toString(); 50317 this._setFill(newFill); 50318 this.drawingContext.fillRect(0, 0, this.width, this.height); 50319 // reset fill 50320 this._setFill(curFill); 50321 } 50322 this.drawingContext.restore(); 50323}; 50324 50325p5.Renderer2D.prototype.clear = function() { 50326 this.drawingContext.save(); 50327 this.drawingContext.setTransform(1, 0, 0, 1, 0, 0); 50328 this.drawingContext.clearRect(0, 0, this.width, this.height); 50329 this.drawingContext.restore(); 50330}; 50331 50332p5.Renderer2D.prototype.fill = function() { 50333 var color = this._pInst.color.apply(this._pInst, arguments); 50334 this._setFill(color.toString()); 50335}; 50336 50337p5.Renderer2D.prototype.stroke = function() { 50338 var color = this._pInst.color.apply(this._pInst, arguments); 50339 this._setStroke(color.toString()); 50340}; 50341 50342////////////////////////////////////////////// 50343// IMAGE | Loading & Displaying 50344////////////////////////////////////////////// 50345 50346p5.Renderer2D.prototype.image = function( 50347 img, 50348 sx, 50349 sy, 50350 sWidth, 50351 sHeight, 50352 dx, 50353 dy, 50354 dWidth, 50355 dHeight 50356) { 50357 var cnv; 50358 try { 50359 if (this._tint) { 50360 if (p5.MediaElement && img instanceof p5.MediaElement) { 50361 img.loadPixels(); 50362 } 50363 if (img.canvas) { 50364 cnv = this._getTintedImageCanvas(img); 50365 } 50366 } 50367 if (!cnv) { 50368 cnv = img.canvas || img.elt; 50369 } 50370 this.drawingContext.drawImage( 50371 cnv, 50372 sx, 50373 sy, 50374 sWidth, 50375 sHeight, 50376 dx, 50377 dy, 50378 dWidth, 50379 dHeight 50380 ); 50381 } catch (e) { 50382 if (e.name !== 'NS_ERROR_NOT_AVAILABLE') { 50383 throw e; 50384 } 50385 } 50386}; 50387 50388p5.Renderer2D.prototype._getTintedImageCanvas = function(img) { 50389 if (!img.canvas) { 50390 return img; 50391 } 50392 var pixels = filters._toPixels(img.canvas); 50393 var tmpCanvas = document.createElement('canvas'); 50394 tmpCanvas.width = img.canvas.width; 50395 tmpCanvas.height = img.canvas.height; 50396 var tmpCtx = tmpCanvas.getContext('2d'); 50397 var id = tmpCtx.createImageData(img.canvas.width, img.canvas.height); 50398 var newPixels = id.data; 50399 for (var i = 0; i < pixels.length; i += 4) { 50400 var r = pixels[i]; 50401 var g = pixels[i + 1]; 50402 var b = pixels[i + 2]; 50403 var a = pixels[i + 3];
50404 newPixels[i] = r * this._tint[0] / 255; 50405 newPixels[i + 1] = g * this._tint[1] / 255; 50406 newPixels[i + 2] = b * this._tint[2] / 255; 50407 newPixels[i + 3] = a * this._tint[3] / 255; 50408 } 50409 tmpCtx.putImageData(id, 0, 0); 50410 return tmpCanvas; 50411}; 50412 50413////////////////////////////////////////////// 50414// IMAGE | Pixels 50415////////////////////////////////////////////// 50416 50417p5.Renderer2D.prototype.blendMode = function(mode) { 50418 this.drawingContext.globalCompositeOperation = mode; 50419}; 50420p5.Renderer2D.prototype.blend = function() { 50421 var currBlend = this.drawingContext.globalCompositeOperation; 50422 var blendMode = arguments[arguments.length - 1]; 50423 50424 var copyArgs = Array.prototype.slice.call(arguments, 0, arguments.length - 1); 50425 50426 this.drawingContext.globalCompositeOperation = blendMode; 50427 if (this._pInst) { 50428 this._pInst.copy.apply(this._pInst, copyArgs); 50429 } else { 50430 this.copy.apply(this, copyArgs); 50431 } 50432 this.drawingContext.globalCompositeOperation = currBlend; 50433}; 50434 50435p5.Renderer2D.prototype.copy = function() { 50436 var srcImage, sx, sy, sw, sh, dx, dy, dw, dh; 50437 if (arguments.length === 9) { 50438 srcImage = arguments[0]; 50439 sx = arguments[1]; 50440 sy = arguments[2]; 50441 sw = arguments[3]; 50442 sh = arguments[4]; 50443 dx = arguments[5]; 50444 dy = arguments[6]; 50445 dw = arguments[7]; 50446 dh = arguments[8]; 50447 } else if (arguments.length === 8) { 50448 srcImage = this._pInst; 50449 sx = arguments[0]; 50450 sy = arguments[1]; 50451 sw = arguments[2]; 50452 sh = arguments[3]; 50453 dx = arguments[4]; 50454 dy = arguments[5]; 50455 dw = arguments[6]; 50456 dh = arguments[7]; 50457 } else { 50458 throw new Error('Signature not supported'); 50459 } 50460 p5.Renderer2D._copyHelper(this, srcImage, sx, sy, sw, sh, dx, dy, dw, dh); 50461}; 50462 50463p5.Renderer2D._copyHelper = function( 50464 dstImage, 50465 srcImage, 50466 sx, 50467 sy, 50468 sw, 50469 sh, 50470 dx, 50471 dy, 50472 dw, 50473 dh 50474) { 50475 srcImage.loadPixels(); 50476 var s = srcImage.canvas.width / srcImage.width; 50477 dstImage.drawingContext.drawImage( 50478 srcImage.canvas, 50479 s * sx, 50480 s * sy, 50481 s * sw, 50482 s * sh, 50483 dx, 50484 dy, 50485 dw, 50486 dh 50487 ); 50488}; 50489 50490p5.Renderer2D.prototype.get = function(x, y, w, h) { 50491 if ( 50492 x === undefined && 50493 y === undefined && 50494 w === undefined && 50495 h === undefined 50496 ) { 50497 x = 0; 50498 y = 0; 50499 w = this.width; 50500 h = this.height; 50501 } else if (w === undefined && h === undefined) { 50502 w = 1; 50503 h = 1; 50504 } 50505 50506 // if the section does not overlap the canvas 50507 if (x + w < 0 || y + h < 0 || x > this.width || y > this.height) { 50508 return [0, 0, 0, 255]; 50509 } 50510 50511 var ctx = this._pInst || this; 50512 ctx.loadPixels(); 50513 50514 var pd = ctx._pixelDensity; 50515 50516 // round down to get integer numbers 50517 x = Math.floor(x); 50518 y = Math.floor(y); 50519 w = Math.floor(w); 50520 h = Math.floor(h); 50521 50522 var sx = x * pd; 50523 var sy = y * pd; 50524 if (w === 1 && h === 1 && !(this instanceof p5.RendererGL)) { 50525 var imageData = this.drawingContext.getImageData(sx, sy, 1, 1).data; 50526 //imageData = [0,0,0,0]; 50527 return [imageData[0], imageData[1], imageData[2], imageData[3]]; 50528 } else { 50529 //auto constrain the width and height to 50530 //dimensions of the source image 50531 var dw = Math.min(w, ctx.width); 50532 var dh = Math.min(h, ctx.height); 50533 var sw = dw * pd; 50534 var sh = dh * pd; 50535 50536 var region = new p5.Image(dw, dh); 50537 region.canvas 50538 .getContext('2d') 50539 .drawImage(this.canvas, sx, sy, sw, sh, 0, 0, dw, dh); 50540 50541 return region; 50542 } 50543}; 50544 50545p5.Renderer2D.prototype.loadPixels = function() { 50546 var ctx = this._pInst || this; // if called by p5.Image 50547 var pd = ctx._pixelDensity; 50548 var w = this.width * pd; 50549 var h = this.height * pd; 50550 var imageData = this.drawingContext.getImageData(0, 0, w, h); 50551 // @todo this should actually set pixels per object, so diff buffers can 50552 // have diff pixel arrays. 50553 ctx._setProperty('imageData', imageData); 50554 ctx._setProperty('pixels', imageData.data); 50555}; 50556 50557p5.Renderer2D.prototype.set = function(x, y, imgOrCol) { 50558 // round down to get integer numbers 50559 x = Math.floor(x); 50560 y = Math.floor(y); 50561 var ctx = this._pInst || this; 50562 if (imgOrCol instanceof p5.Image) { 50563 this.drawingContext.save(); 50564 this.drawingContext.setTransform(1, 0, 0, 1, 0, 0); 50565 this.drawingContext.scale(ctx._pixelDensity, ctx._pixelDensity); 50566 this.drawingContext.drawImage(imgOrCol.canvas, x, y); 50567 this.loadPixels.call(ctx);
50568 this.drawingContext.restore(); 50569 } else { 50570 var r = 0, 50571 g = 0, 50572 b = 0, 50573 a = 0; 50574 var idx = 50575 4 * 50576 (y * ctx._pixelDensity * (this.width * ctx._pixelDensity) + 50577 x * ctx._pixelDensity); 50578 if (!ctx.imageData) { 50579 ctx.loadPixels.call(ctx); 50580 } 50581 if (typeof imgOrCol === 'number') { 50582 if (idx < ctx.pixels.length) { 50583 r = imgOrCol; 50584 g = imgOrCol; 50585 b = imgOrCol; 50586 a = 255; 50587 //this.updatePixels.call(this); 50588 } 50589 } else if (imgOrCol instanceof Array) { 50590 if (imgOrCol.length < 4) { 50591 throw new Error('pixel array must be of the form [R, G, B, A]'); 50592 } 50593 if (idx < ctx.pixels.length) { 50594 r = imgOrCol[0]; 50595 g = imgOrCol[1]; 50596 b = imgOrCol[2]; 50597 a = imgOrCol[3]; 50598 //this.updatePixels.call(this); 50599 } 50600 } else if (imgOrCol instanceof p5.Color) { 50601 if (idx < ctx.pixels.length) { 50602 r = imgOrCol.levels[0]; 50603 g = imgOrCol.levels[1]; 50604 b = imgOrCol.levels[2]; 50605 a = imgOrCol.levels[3]; 50606 //this.updatePixels.call(this); 50607 } 50608 } 50609 // loop over pixelDensity * pixelDensity 50610 for (var i = 0; i < ctx._pixelDensity; i++) { 50611 for (var j = 0; j < ctx._pixelDensity; j++) { 50612 // loop over 50613 idx = 50614 4 * 50615 ((y * ctx._pixelDensity + j) * this.width * ctx._pixelDensity + 50616 (x * ctx._pixelDensity + i)); 50617 ctx.pixels[idx] = r; 50618 ctx.pixels[idx + 1] = g; 50619 ctx.pixels[idx + 2] = b; 50620 ctx.pixels[idx + 3] = a; 50621 } 50622 } 50623 } 50624}; 50625 50626p5.Renderer2D.prototype.updatePixels = function(x, y, w, h) { 50627 var ctx = this._pInst || this; 50628 var pd = ctx._pixelDensity; 50629 if ( 50630 x === undefined && 50631 y === undefined && 50632 w === undefined && 50633 h === undefined 50634 ) { 50635 x = 0; 50636 y = 0; 50637 w = this.width; 50638 h = this.height; 50639 } 50640 w *= pd; 50641 h *= pd; 50642 50643 this.drawingContext.putImageData(ctx.imageData, x, y, 0, 0, w, h); 50644}; 50645 50646////////////////////////////////////////////// 50647// SHAPE | 2D Primitives 50648////////////////////////////////////////////// 50649 50650/** 50651 * Generate a cubic Bezier representing an arc on the unit circle of total 50652 * angle `size` radians, beginning `start` radians above the x-axis. Up to 50653 * four of these curves are combined to make a full arc. 50654 * 50655 * See www.joecridge.me/bezier.pdf for an explanation of the method. 50656 */ 50657p5.Renderer2D.prototype._acuteArcToBezier = function _acuteArcToBezier( 50658 start, 50659 size 50660) { 50661 // Evauate constants. 50662 var alpha = size / 2.0, 50663 cos_alpha = Math.cos(alpha), 50664 sin_alpha = Math.sin(alpha), 50665 cot_alpha = 1.0 / Math.tan(alpha), 50666 phi = start + alpha, // This is how far the arc needs to be rotated. 50667 cos_phi = Math.cos(phi), 50668 sin_phi = Math.sin(phi), 50669 lambda = (4.0 - cos_alpha) / 3.0, 50670 mu = sin_alpha + (cos_alpha - lambda) * cot_alpha; 50671 50672 // Return rotated waypoints. 50673 return { 50674 ax: Math.cos(start), 50675 ay: Math.sin(start), 50676 bx: lambda * cos_phi + mu * sin_phi,
50677 by: lambda * sin_phi - mu * cos_phi, 50678 cx: lambda * cos_phi - mu * sin_phi, 50679 cy: lambda * sin_phi + mu * cos_phi, 50680 dx: Math.cos(start + size), 50681 dy: Math.sin(start + size) 50682 }; 50683}; 50684 50685p5.Renderer2D.prototype.arc = function(x, y, w, h, start, stop, mode) { 50686 var ctx = this.drawingContext; 50687 var vals = canvas.arcModeAdjust(x, y, w, h, this._ellipseMode); 50688 var rx = vals.w / 2.0; 50689 var ry = vals.h / 2.0; 50690 var epsilon = 0.00001; // Smallest visible angle on displays up to 4K. 50691 var arcToDraw = 0; 50692 var curves = []; 50693 50694 // Create curves 50695 while (stop - start > epsilon) { 50696 arcToDraw = Math.min(stop - start, constants.HALF_PI); 50697 curves.push(this._acuteArcToBezier(start, arcToDraw)); 50698 start += arcToDraw; 50699 } 50700 50701 // Fill curves 50702 if (this._doFill) { 50703 ctx.beginPath(); 50704 curves.forEach(function(curve, index) { 50705 if (index === 0) { 50706 ctx.moveTo(vals.x + curve.ax * rx, vals.y + curve.ay * ry); 50707 } 50708 // prettier-ignore 50709 ctx.bezierCurveTo(vals.x + curve.bx * rx, vals.y + curve.by * ry, 50710 vals.x + curve.cx * rx, vals.y + curve.cy * ry, 50711 vals.x + curve.dx * rx, vals.y + curve.dy * ry); 50712 }); 50713 if (mode === constants.PIE || mode == null) { 50714 ctx.lineTo(vals.x, vals.y); 50715 } 50716 ctx.closePath(); 50717 ctx.fill(); 50718 } 50719 50720 // Stroke curves 50721 if (this._doStroke) { 50722 ctx.beginPath(); 50723 curves.forEach(function(curve, index) { 50724 if (index === 0) { 50725 ctx.moveTo(vals.x + curve.ax * rx, vals.y + curve.ay * ry); 50726 } 50727 // prettier-ignore 50728 ctx.bezierCurveTo(vals.x + curve.bx * rx, vals.y + curve.by * ry, 50729 vals.x + curve.cx * rx, vals.y + curve.cy * ry, 50730 vals.x + curve.dx * rx, vals.y + curve.dy * ry); 50731 }); 50732 if (mode === constants.PIE) { 50733 ctx.lineTo(vals.x, vals.y); 50734 ctx.closePath(); 50735 } else if (mode === constants.CHORD) { 50736 ctx.closePath(); 50737 } 50738 ctx.stroke(); 50739 } 50740 return this; 50741}; 50742 50743p5.Renderer2D.prototype.ellipse = function(args) { 50744 var ctx = this.drawingContext; 50745 var doFill = this._doFill, 50746 doStroke = this._doStroke; 50747 var x = args[0], 50748 y = args[1], 50749 w = args[2], 50750 h = args[3]; 50751 if (doFill && !doStroke) { 50752 if (this._getFill() === styleEmpty) { 50753 return this; 50754 } 50755 } else if (!doFill && doStroke) { 50756 if (this._getStroke() === styleEmpty) { 50757 return this; 50758 } 50759 } 50760 var kappa = 0.5522847498, 50761 ox = w / 2 * kappa, // control point offset horizontal 50762 oy = h / 2 * kappa, // control point offset vertical 50763 xe = x + w, // x-end 50764 ye = y + h, // y-end 50765 xm = x + w / 2, // x-middle 50766 ym = y + h / 2; // y-middle 50767 ctx.beginPath(); 50768 ctx.moveTo(x, ym); 50769 ctx.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); 50770 ctx.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); 50771 ctx.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); 50772 ctx.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); 50773 ctx.closePath(); 50774 if (doFill) { 50775 ctx.fill(); 50776 } 50777 if (doStroke) { 50778 ctx.stroke(); 50779 } 50780}; 50781 50782p5.Renderer2D.prototype.line = function(x1, y1, x2, y2) { 50783 var ctx = this.drawingContext; 50784 if (!this._doStroke) { 50785 return this; 50786 } else if (this._getStroke() === styleEmpty) { 50787 return this; 50788 } 50789 // Translate the line by (0.5, 0.5) to draw it crisp 50790 if (ctx.lineWidth % 2 === 1) { 50791 ctx.translate(0.5, 0.5); 50792 } 50793 ctx.beginPath(); 50794 ctx.moveTo(x1, y1); 50795 ctx.lineTo(x2, y2); 50796 ctx.stroke(); 50797 if (ctx.lineWidth % 2 === 1) { 50798 ctx.translate(-0.5, -0.5); 50799 } 50800 return this; 50801}; 50802 50803p5.Renderer2D.prototype.point = function(x, y) { 50804 var ctx = this.drawingContext; 50805 if (!this._doStroke) { 50806 return this; 50807 } else if (this._getStroke() === styleEmpty) { 50808 return this; 50809 } 50810 var s = this._getStroke(); 50811 var f = this._getFill(); 50812 x = Math.round(x); 50813 y = Math.round(y); 50814 // swapping fill color to stroke and back after for correct point rendering 50815 this._setFill(s); 50816 if (ctx.lineWidth > 1) { 50817 ctx.beginPath(); 50818 ctx.arc(x, y, ctx.lineWidth / 2, 0, constants.TWO_PI, false); 50819 ctx.fill(); 50820 } else { 50821 ctx.fillRect(x, y, 1, 1); 50822 } 50823 this._setFill(f); 50824}; 50825 50826p5.Renderer2D.prototype.quad = function(x1, y1, x2, y2, x3, y3, x4, y4) { 50827 var ctx = this.drawingContext; 50828 var doFill = this._doFill, 50829 doStroke = this._doStroke; 50830 if (doFill && !doStroke) { 50831 if (this._getFill() === styleEmpty) { 50832 return this; 50833 } 50834 } else if (!doFill && doStroke) { 50835 if (this._getStroke() === styleEmpty) { 50836 return this; 50837 } 50838 } 50839 ctx.beginPath(); 50840 ctx.moveTo(x1, y1); 50841 ctx.lineTo(x2, y2); 50842 ctx.lineTo(x3, y3); 50843 ctx.lineTo(x4, y4); 50844 ctx.closePath(); 50845 if (doFill) { 50846 ctx.fill(); 50847 } 50848 if (doStroke) { 50849 ctx.stroke(); 50850 } 50851 return this; 50852}; 50853 50854p5.Renderer2D.prototype.rect = function(args) { 50855 var x = args[0], 50856 y = args[1], 50857 w = args[2], 50858 h = args[3], 50859 tl = args[4], 50860 tr = args[5], 50861 br = args[6], 50862 bl = args[7]; 50863 var ctx = this.drawingContext; 50864 var doFill = this._doFill, 50865 doStroke = this._doStroke; 50866 if (doFill && !doStroke) { 50867 if (this._getFill() === styleEmpty) { 50868 return this; 50869 } 50870 } else if (!doFill && doStroke) { 50871 if (this._getStroke() === styleEmpty) { 50872 return this; 50873 } 50874 } 50875 // Translate the line by (0.5, 0.5) to draw a crisp rectangle border 50876 if (this._doStroke && ctx.lineWidth % 2 === 1) { 50877 ctx.translate(0.5, 0.5); 50878 } 50879 ctx.beginPath(); 50880 50881 if (typeof tl === 'undefined') { 50882 // No rounded corners 50883 ctx.rect(x, y, w, h); 50884 } else { 50885 // At least one rounded corner 50886 // Set defaults when not specified 50887 if (typeof tr === 'undefined') { 50888 tr = tl; 50889 } 50890 if (typeof br === 'undefined') { 50891 br = tr; 50892 } 50893 if (typeof bl === 'undefined') { 50894 bl = br; 50895 } 50896
50897 var hw = w / 2; 50898 var hh = h / 2; 50899 50900 // Clip radii 50901 if (w < 2 * tl) { 50902 tl = hw; 50903 } 50904 if (h < 2 * tl) { 50905 tl = hh; 50906 } 50907 if (w < 2 * tr) { 50908 tr = hw; 50909 } 50910 if (h < 2 * tr) { 50911 tr = hh; 50912 } 50913 if (w < 2 * br) { 50914 br = hw; 50915 } 50916 if (h < 2 * br) { 50917 br = hh; 50918 } 50919 if (w < 2 * bl) { 50920 bl = hw; 50921 } 50922 if (h < 2 * bl) { 50923 bl = hh; 50924 } 50925 50926 // Draw shape 50927 ctx.beginPath(); 50928 ctx.moveTo(x + tl, y); 50929 ctx.arcTo(x + w, y, x + w, y + h, tr); 50930 ctx.arcTo(x + w, y + h, x, y + h, br); 50931 ctx.arcTo(x, y + h, x, y, bl); 50932 ctx.arcTo(x, y, x + w, y, tl); 50933 ctx.closePath(); 50934 } 50935 if (this._doFill) { 50936 ctx.fill(); 50937 } 50938 if (this._doStroke) { 50939 ctx.stroke(); 50940 } 50941 if (this._doStroke && ctx.lineWidth % 2 === 1) { 50942 ctx.translate(-0.5, -0.5); 50943 } 50944 return this; 50945}; 50946 50947p5.Renderer2D.prototype.triangle = function(args) { 50948 var ctx = this.drawingContext; 50949 var doFill = this._doFill, 50950 doStroke = this._doStroke; 50951 var x1 = args[0], 50952 y1 = args[1]; 50953 var x2 = args[2], 50954 y2 = args[3]; 50955 var x3 = args[4], 50956 y3 = args[5]; 50957 if (doFill && !doStroke) { 50958 if (this._getFill() === styleEmpty) { 50959 return this; 50960 } 50961 } else if (!doFill && doStroke) { 50962 if (this._getStroke() === styleEmpty) { 50963 return this; 50964 } 50965 } 50966 ctx.beginPath(); 50967 ctx.moveTo(x1, y1); 50968 ctx.lineTo(x2, y2); 50969 ctx.lineTo(x3, y3); 50970 ctx.closePath(); 50971 if (doFill) { 50972 ctx.fill(); 50973 } 50974 if (doStroke) { 50975 ctx.stroke(); 50976 } 50977}; 50978 50979p5.Renderer2D.prototype.endShape = function( 50980 mode, 50981 vertices, 50982 isCurve, 50983 isBezier, 50984 isQuadratic, 50985 isContour, 50986 shapeKind 50987) { 50988 if (vertices.length === 0) { 50989 return this; 50990 } 50991 if (!this._doStroke && !this._doFill) { 50992 return this; 50993 } 50994 var closeShape = mode === constants.CLOSE; 50995 var v; 50996 if (closeShape && !isContour) { 50997 vertices.push(vertices[0]); 50998 } 50999 var i, j; 51000 var numVerts = vertices.length; 51001 if (isCurve && (shapeKind === constants.POLYGON || shapeKind === null)) { 51002 if (numVerts > 3) { 51003 var b = [], 51004 s = 1 - this._curveTightness; 51005 this.drawingContext.beginPath(); 51006 this.drawingContext.moveTo(vertices[1][0], vertices[1][1]); 51007 for (i = 1; i + 2 < numVerts; i++) { 51008 v = vertices[i]; 51009 b[0] = [v[0], v[1]]; 51010 b[1] = [ 51011 v[0] + (s * vertices[i + 1][0] - s * vertices[i - 1][0]) / 6, 51012 v[1] + (s * vertices[i + 1][1] - s * vertices[i - 1][1]) / 6 51013 ]; 51014 b[2] = [ 51015 vertices[i + 1][0] + 51016 (s * vertices[i][0] - s * vertices[i + 2][0]) / 6, 51017 vertices[i + 1][1] + (s * vertices[i][1] - s * vertices[i + 2][1]) / 6 51018 ]; 51019 b[3] = [vertices[i + 1][0], vertices[i + 1][1]]; 51020 this.drawingContext.bezierCurveTo( 51021 b[1][0], 51022 b[1][1], 51023 b[2][0], 51024 b[2][1], 51025 b[3][0], 51026 b[3][1] 51027 ); 51028 } 51029 if (closeShape) { 51030 this.drawingContext.lineTo(vertices[i + 1][0], vertices[i + 1][1]); 51031 } 51032 this._doFillStrokeClose(); 51033 } 51034 } else if ( 51035 isBezier && 51036 (shapeKind === constants.POLYGON || shapeKind === null) 51037 ) { 51038 this.drawingContext.beginPath(); 51039 for (i = 0; i < numVerts; i++) { 51040 if (vertices[i].isVert) { 51041 if (vertices[i].moveTo) { 51042 this.drawingContext.moveTo(vertices[i][0], vertices[i][1]); 51043 } else { 51044 this.drawingContext.lineTo(vertices[i][0], vertices[i][1]); 51045 } 51046 } else { 51047 this.drawingContext.bezierCurveTo( 51048 vertices[i][0], 51049 vertices[i][1], 51050 vertices[i][2], 51051 vertices[i][3], 51052 vertices[i][4], 51053 vertices[i][5] 51054 ); 51055 } 51056 } 51057 this._doFillStrokeClose(); 51058 } else if ( 51059 isQuadratic && 51060 (shapeKind === constants.POLYGON || shapeKind === null) 51061 ) { 51062 this.drawingContext.beginPath(); 51063 for (i = 0; i < numVerts; i++) { 51064 if (vertices[i].isVert) { 51065 if (vertices[i].moveTo) { 51066 this.drawingContext.moveTo([0], vertices[i][1]); 51067 } else { 51068 this.drawingContext.lineTo(vertices[i][0], vertices[i][1]); 51069 } 51070 } else { 51071 this.drawingContext.quadraticCurveTo( 51072 vertices[i][0], 51073 vertices[i][1], 51074 vertices[i][2], 51075 vertices[i][3] 51076 ); 51077 } 51078 } 51079 this._doFillStrokeClose(); 51080 } else { 51081 if (shapeKind === constants.POINTS) { 51082 for (i = 0; i < numVerts; i++) { 51083 v = vertices[i]; 51084 if (this._doStroke) { 51085 this._pInst.stroke(v[6]); 51086 } 51087 this._pInst.point(v[0], v[1]); 51088 } 51089 } else if (shapeKind === constants.LINES) { 51090 for (i = 0; i + 1 < numVerts; i += 2) { 51091 v = vertices[i]; 51092 if (this._doStroke) { 51093 this._pInst.stroke(vertices[i + 1][6]); 51094 } 51095 this._pInst.line(v[0], v[1], vertices[i + 1][0], vertices[i + 1][1]); 51096 } 51097 } else if (shapeKind === constants.TRIANGLES) { 51098 for (i = 0; i + 2 < numVerts; i += 3) { 51099 v = vertices[i]; 51100 this.drawingContext.beginPath(); 51101 this.drawingContext.moveTo(v[0], v[1]); 51102 this.drawingContext.lineTo(vertices[i + 1][0], vertices[i + 1][1]); 51103 this.drawingContext.lineTo(vertices[i + 2][0], vertices[i + 2][1]); 51104 this.drawingContext.lineTo(v[0], v[1]); 51105 if (this._doFill) { 51106 this._pInst.fill(vertices[i + 2][5]); 51107 this.drawingContext.fill(); 51108 } 51109 if (this._doStroke) { 51110 this._pInst.stroke(vertices[i + 2][6]); 51111 this.drawingContext.stroke(); 51112 } 51113 this.drawingContext.closePath(); 51114 } 51115 } else if (shapeKind === constants.TRIANGLE_STRIP) { 51116 for (i = 0; i + 1 < numVerts; i++) { 51117 v = vertices[i]; 51118 this.drawingContext.beginPath();
51119 this.drawingContext.moveTo(vertices[i + 1][0], vertices[i + 1][1]); 51120 this.drawingContext.lineTo(v[0], v[1]); 51121 if (this._doStroke) { 51122 this._pInst.stroke(vertices[i + 1][6]); 51123 } 51124 if (this._doFill) { 51125 this._pInst.fill(vertices[i + 1][5]); 51126 } 51127 if (i + 2 < numVerts) { 51128 this.drawingContext.lineTo(vertices[i + 2][0], vertices[i + 2][1]); 51129 if (this._doStroke) { 51130 this._pInst.stroke(vertices[i + 2][6]); 51131 } 51132 if (this._doFill) { 51133 this._pInst.fill(vertices[i + 2][5]); 51134 } 51135 } 51136 this._doFillStrokeClose(); 51137 } 51138 } else if (shapeKind === constants.TRIANGLE_FAN) { 51139 if (numVerts > 2) { 51140 // For performance reasons, try to batch as many of the 51141 // fill and stroke calls as possible. 51142 this.drawingContext.beginPath(); 51143 for (i = 2; i < numVerts; i++) { 51144 v = vertices[i]; 51145 this.drawingContext.moveTo(vertices[0][0], vertices[0][1]); 51146 this.drawingContext.lineTo(vertices[i - 1][0], vertices[i - 1][1]); 51147 this.drawingContext.lineTo(v[0], v[1]); 51148 this.drawingContext.lineTo(vertices[0][0], vertices[0][1]); 51149 // If the next colour is going to be different, stroke / fill now 51150 if (i < numVerts - 1) { 51151 if ( 51152 (this._doFill && v[5] !== vertices[i + 1][5]) || 51153 (this._doStroke && v[6] !== vertices[i + 1][6]) 51154 ) { 51155 if (this._doFill) { 51156 this._pInst.fill(v[5]); 51157 this.drawingContext.fill(); 51158 this._pInst.fill(vertices[i + 1][5]); 51159 } 51160 if (this._doStroke) { 51161 this._pInst.stroke(v[6]); 51162 this.drawingContext.stroke(); 51163 this._pInst.stroke(vertices[i + 1][6]); 51164 } 51165 this.drawingContext.closePath(); 51166 this.drawingContext.beginPath(); // Begin the next one 51167 } 51168 } 51169 } 51170 this._doFillStrokeClose(); 51171 } 51172 } else if (shapeKind === constants.QUADS) { 51173 for (i = 0; i + 3 < numVerts; i += 4) { 51174 v = vertices[i]; 51175 this.drawingContext.beginPath(); 51176 this.drawingContext.moveTo(v[0], v[1]); 51177 for (j = 1; j < 4; j++) { 51178 this.drawingContext.lineTo(vertices[i + j][0], vertices[i + j][1]); 51179 } 51180 this.drawingContext.lineTo(v[0], v[1]); 51181 if (this._doFill) { 51182 this._pInst.fill(vertices[i + 3][5]); 51183 } 51184 if (this._doStroke) { 51185 this._pInst.stroke(vertices[i + 3][6]); 51186 } 51187 this._doFillStrokeClose(); 51188 } 51189 } else if (shapeKind === constants.QUAD_STRIP) { 51190 if (numVerts > 3) { 51191 for (i = 0; i + 1 < numVerts; i += 2) { 51192 v = vertices[i]; 51193 this.drawingContext.beginPath(); 51194 if (i + 3 < numVerts) { 51195 this.drawingContext.moveTo(vertices[i + 2][0], vertices[i + 2][1]); 51196 this.drawingContext.lineTo(v[0], v[1]); 51197 this.drawingContext.lineTo(vertices[i + 1][0], vertices[i + 1][1]); 51198 this.drawingContext.lineTo(vertices[i + 3][0], vertices[i + 3][1]); 51199 if (this._doFill) { 51200 this._pInst.fill(vertices[i + 3][5]); 51201 } 51202 if (this._doStroke) { 51203 this._pInst.stroke(vertices[i + 3][6]); 51204 } 51205 } else { 51206 this.drawingContext.moveTo(v[0], v[1]); 51207 this.drawingContext.lineTo(vertices[i + 1][0], vertices[i + 1][1]); 51208 } 51209 this._doFillStrokeClose(); 51210 } 51211 } 51212 } else { 51213 this.drawingContext.beginPath(); 51214 this.drawingContext.moveTo(vertices[0][0], vertices[0][1]); 51215 for (i = 1; i < numVerts; i++) { 51216 v = vertices[i]; 51217 if (v.isVert) { 51218 if (v.moveTo) { 51219 this.drawingContext.moveTo(v[0], v[1]); 51220 } else { 51221 this.drawingContext.lineTo(v[0], v[1]); 51222 } 51223 } 51224 } 51225 this._doFillStrokeClose(); 51226 } 51227 } 51228 isCurve = false; 51229 isBezier = false;
51230 isQuadratic = false; 51231 isContour = false; 51232 if (closeShape) { 51233 vertices.pop(); 51234 } 51235 return this; 51236}; 51237////////////////////////////////////////////// 51238// SHAPE | Attributes 51239////////////////////////////////////////////// 51240 51241p5.Renderer2D.prototype.noSmooth = function() { 51242 if ('imageSmoothingEnabled' in this.drawingContext) { 51243 this.drawingContext.imageSmoothingEnabled = false; 51244 } 51245 return this; 51246}; 51247 51248p5.Renderer2D.prototype.smooth = function() { 51249 if ('imageSmoothingEnabled' in this.drawingContext) { 51250 this.drawingContext.imageSmoothingEnabled = true; 51251 } 51252 return this; 51253}; 51254 51255p5.Renderer2D.prototype.strokeCap = function(cap) { 51256 if ( 51257 cap === constants.ROUND || 51258 cap === constants.SQUARE || 51259 cap === constants.PROJECT 51260 ) { 51261 this.drawingContext.lineCap = cap; 51262 } 51263 return this; 51264}; 51265 51266p5.Renderer2D.prototype.strokeJoin = function(join) { 51267 if ( 51268 join === constants.ROUND || 51269 join === constants.BEVEL || 51270 join === constants.MITER 51271 ) { 51272 this.drawingContext.lineJoin = join; 51273 } 51274 return this; 51275}; 51276 51277p5.Renderer2D.prototype.strokeWeight = function(w) { 51278 if (typeof w === 'undefined' || w === 0) { 51279 // hack because lineWidth 0 doesn't work 51280 this.drawingContext.lineWidth = 0.0001; 51281 } else { 51282 this.drawingContext.lineWidth = w; 51283 } 51284 return this; 51285}; 51286 51287p5.Renderer2D.prototype._getFill = function() { 51288 if (!this._cachedFillStyle) { 51289 this._cachedFillStyle = this.drawingContext.fillStyle; 51290 } 51291 return this._cachedFillStyle; 51292}; 51293 51294p5.Renderer2D.prototype._setFill = function(fillStyle) { 51295 if (fillStyle !== this._cachedFillStyle) { 51296 this.drawingContext.fillStyle = fillStyle; 51297 this._cachedFillStyle = fillStyle; 51298 } 51299}; 51300 51301p5.Renderer2D.prototype._getStroke = function() { 51302 if (!this._cachedStrokeStyle) { 51303 this._cachedStrokeStyle = this.drawingContext.strokeStyle; 51304 } 51305 return this._cachedStrokeStyle; 51306}; 51307 51308p5.Renderer2D.prototype._setStroke = function(strokeStyle) { 51309 if (strokeStyle !== this._cachedStrokeStyle) { 51310 this.drawingContext.strokeStyle = strokeStyle; 51311 this._cachedStrokeStyle = strokeStyle; 51312 } 51313}; 51314 51315////////////////////////////////////////////// 51316// SHAPE | Curves 51317////////////////////////////////////////////// 51318p5.Renderer2D.prototype.bezier = function(x1, y1, x2, y2, x3, y3, x4, y4) { 51319 this._pInst.beginShape(); 51320 this._pInst.vertex(x1, y1); 51321 this._pInst.bezierVertex(x2, y2, x3, y3, x4, y4); 51322 this._pInst.endShape(); 51323 return this; 51324}; 51325 51326p5.Renderer2D.prototype.curve = function(x1, y1, x2, y2, x3, y3, x4, y4) { 51327 this._pInst.beginShape(); 51328 this._pInst.curveVertex(x1, y1); 51329 this._pInst.curveVertex(x2, y2); 51330 this._pInst.curveVertex(x3, y3); 51331 this._pInst.curveVertex(x4, y4); 51332 this._pInst.endShape(); 51333 return this; 51334}; 51335 51336////////////////////////////////////////////// 51337// SHAPE | Vertex 51338////////////////////////////////////////////// 51339 51340p5.Renderer2D.prototype._doFillStrokeClose = function() { 51341 if (this._doFill) { 51342 this.drawingContext.fill(); 51343 } 51344 if (this._doStroke) { 51345 this.drawingContext.stroke(); 51346 } 51347 this.drawingContext.closePath(); 51348}; 51349 51350////////////////////////////////////////////// 51351// TRANSFORM 51352////////////////////////////////////////////// 51353 51354p5.Renderer2D.prototype.applyMatrix = function(a, b, c, d, e, f) { 51355 this.drawingContext.transform(a, b, c, d, e, f); 51356}; 51357 51358p5.Renderer2D.prototype.resetMatrix = function() { 51359 this.drawingContext.setTransform(1, 0, 0, 1, 0, 0); 51360 this.drawingContext.scale( 51361 this._pInst._pixelDensity, 51362 this._pInst._pixelDensity 51363 ); 51364 return this; 51365}; 51366 51367p5.Renderer2D.prototype.rotate = function(rad) { 51368 this.drawingContext.rotate(rad); 51369}; 51370 51371p5.Renderer2D.prototype.scale = function(x, y) { 51372 this.drawingContext.scale(x, y); 51373 return this; 51374}; 51375 51376p5.Renderer2D.prototype.shearX = function(rad) { 51377 this.drawingContext.transform(1, 0, Math.tan(rad), 1, 0, 0); 51378 return this; 51379}; 51380 51381p5.Renderer2D.prototype.shearY = function(rad) { 51382 this.drawingContext.transform(1, Math.tan(rad), 0, 1, 0, 0); 51383 return this; 51384}; 51385 51386p5.Renderer2D.prototype.translate = function(x, y) { 51387 // support passing a vector as the 1st parameter 51388 if (x instanceof p5.Vector) { 51389 y = x.y; 51390 x = x.x; 51391 } 51392 this.drawingContext.translate(x, y); 51393 return this; 51394}; 51395 51396////////////////////////////////////////////// 51397// TYPOGRAPHY 51398// 51399////////////////////////////////////////////// 51400 51401p5.Renderer2D.prototype.text = function(str, x, y, maxWidth, maxHeight) { 51402 var p = this._pInst, 51403 cars, 51404 n, 51405 ii, 51406 jj, 51407 line, 51408 testLine, 51409 testWidth, 51410 words, 51411 totalHeight, 51412 baselineHacked, 51413 finalMaxHeight = Number.MAX_VALUE; 51414 51415 // baselineHacked: (HACK) 51416 // A temporary fix to conform to Processing's implementation 51417 // of BASELINE vertical alignment in a bounding box 51418 51419 if (!(this._doFill || this._doStroke)) { 51420 return; 51421 } 51422 51423 if (typeof str === 'undefined') { 51424 return; 51425 } else if (typeof str !== 'string') { 51426 str = str.toString(); 51427 } 51428 51429 str = str.replace(/(\t)/g, ' '); 51430 cars = str.split('\n'); 51431 51432 if (typeof maxWidth !== 'undefined') { 51433 totalHeight = 0; 51434 for (ii = 0; ii < cars.length; ii++) { 51435 line = ''; 51436 words = cars[ii].split(' '); 51437 for (n = 0; n < words.length; n++) { 51438 testLine = line + words[n] + ' '; 51439 testWidth = this.textWidth(testLine); 51440 if (testWidth > maxWidth) { 51441 line = words[n] + ' '; 51442 totalHeight += p.textLeading(); 51443 } else { 51444 line = testLine; 51445 } 51446 } 51447 } 51448 51449 if (this._rectMode === constants.CENTER) { 51450 x -= maxWidth / 2; 51451 y -= maxHeight / 2; 51452 } 51453 51454 switch (this.drawingContext.textAlign) { 51455 case constants.CENTER: 51456 x += maxWidth / 2; 51457 break; 51458 case constants.RIGHT: 51459 x += maxWidth; 51460 break; 51461 } 51462 51463 if (typeof maxHeight !== 'undefined') { 51464 switch (this.drawingContext.textBaseline) { 51465 case constants.BOTTOM: 51466 y += maxHeight - totalHeight; 51467 break; 51468 case constants._CTX_MIDDLE: // CENTER? 51469 y += (maxHeight - totalHeight) / 2; 51470 break; 51471 case constants.BASELINE: 51472 baselineHacked = true; 51473 this.drawingContext.textBaseline = constants.TOP; 51474 break; 51475 } 51476 51477 // remember the max-allowed y-position for any line (fix to #928) 51478 finalMaxHeight = y + maxHeight - p.textAscent(); 51479 } 51480 51481 for (ii = 0; ii < cars.length; ii++) { 51482 line = ''; 51483 words = cars[ii].split(' '); 51484 for (n = 0; n < words.length; n++) { 51485 testLine = line + words[n] + ' '; 51486 testWidth = this.textWidth(testLine); 51487 if (testWidth > maxWidth && line.length > 0) { 51488 this._renderText(p, line, x, y, finalMaxHeight); 51489 line = words[n] + ' '; 51490 y += p.textLeading(); 51491 } else { 51492 line = testLine; 51493 } 51494 } 51495 51496 this._renderText(p, line, x, y, finalMaxHeight); 51497 y += p.textLeading(); 51498 } 51499 } else { 51500 // Offset to account for vertically centering multiple lines of text - no 51501 // need to adjust anything for vertical align top or baseline 51502 var offset = 0, 51503 vAlign = p.textAlign().vertical; 51504 if (vAlign === constants.CENTER) { 51505 offset = (cars.length - 1) * p.textLeading() / 2; 51506 } else if (vAlign === constants.BOTTOM) { 51507 offset = (cars.length - 1) * p.textLeading(); 51508 } 51509 51510 for (jj = 0; jj < cars.length; jj++) { 51511 this._renderText(p, cars[jj], x, y - offset, finalMaxHeight); 51512 y += p.textLeading(); 51513 } 51514 } 51515 51516 if (baselineHacked) { 51517 this.drawingContext.textBaseline = constants.BASELINE; 51518 } 51519 51520 return p; 51521}; 51522 51523p5.Renderer2D.prototype._renderText = function(p, line, x, y, maxY) { 51524 if (y >= maxY) { 51525 return; // don't render lines beyond our maxY position 51526 } 51527 51528 p.push(); // fix to #803 51529 51530 if (!this._isOpenType()) { 51531 // a system/browser font 51532 51533 // no stroke unless specified by user 51534 if (this._doStroke && this._strokeSet) { 51535 this.drawingContext.strokeText(line, x, y); 51536 } 51537 51538 if (this._doFill) { 51539 // if fill hasn't been set by user, use default text fill 51540 if (!this._fillSet) { 51541 this._setFill(constants._DEFAULT_TEXT_FILL); 51542 } 51543 51544 this.drawingContext.fillText(line, x, y); 51545 } 51546 } else { 51547 // an opentype font, let it handle the rendering 51548 51549 this._textFont._renderPath(line, x, y, { renderer: this }); 51550 } 51551 51552 p.pop(); 51553 51554 return p; 51555}; 51556 51557p5.Renderer2D.prototype.textWidth = function(s) { 51558 if (this._isOpenType()) { 51559 return this._textFont._textWidth(s, this._textSize); 51560 } 51561 51562 return this.drawingContext.measureText(s).width; 51563}; 51564 51565p5.Renderer2D.prototype.textAlign = function(h, v) { 51566 if (typeof h !== 'undefined') { 51567 if ( 51568 h === constants.LEFT || 51569 h === constants.RIGHT || 51570 h === constants.CENTER 51571 ) { 51572 this.drawingContext.textAlign = h; 51573 } 51574 51575 if ( 51576 v === constants.TOP || 51577 v === constants.BOTTOM || 51578 v === constants.CENTER || 51579 v === constants.BASELINE 51580 ) { 51581 if (v === constants.CENTER) { 51582 this.drawingContext.textBaseline = constants._CTX_MIDDLE; 51583 } else { 51584 this.drawingContext.textBaseline = v; 51585 } 51586 } 51587 51588 return this._pInst; 51589 } else {
51590 var valign = this.drawingContext.textBaseline; 51591 51592 if (valign === constants._CTX_MIDDLE) { 51593 valign = constants.CENTER; 51594 } 51595 51596 return { 51597 horizontal: this.drawingContext.textAlign, 51598 vertical: valign 51599 }; 51600 } 51601}; 51602 51603p5.Renderer2D.prototype._applyTextProperties = function() { 51604 var font, 51605 p = this._pInst; 51606 51607 this._setProperty('_textAscent', null); 51608 this._setProperty('_textDescent', null); 51609 51610 font = this._textFont; 51611 51612 if (this._isOpenType()) { 51613 font = this._textFont.font.familyName; 51614 this._setProperty('_textStyle', this._textFont.font.styleName); 51615 } 51616 51617 this.drawingContext.font = 51618 (this._textStyle || 'normal') + 51619 ' ' + 51620 (this._textSize || 12) + 51621 'px ' + 51622 (font || 'sans-serif'); 51623 51624 return p; 51625}; 51626 51627////////////////////////////////////////////// 51628// STRUCTURE 51629////////////////////////////////////////////// 51630 51631// a push() operation is in progress. 51632// the renderer should return a 'style' object that it wishes to 51633// store on the push stack. 51634// derived renderers should call the base class' push() method 51635// to fetch the base style object. 51636p5.Renderer2D.prototype.push = function() { 51637 this.drawingContext.save(); 51638 51639 // get the base renderer style 51640 return p5.Renderer.prototype.push.apply(this); 51641}; 51642 51643// a pop() operation is in progress 51644// the renderer is passed the 'style' object that it returned 51645// from its push() method. 51646// derived renderers should pass this object to their base 51647// class' pop method 51648p5.Renderer2D.prototype.pop = function(style) { 51649 this.drawingContext.restore(); 51650 // Re-cache the fill / stroke state 51651 this._cachedFillStyle = this.drawingContext.fillStyle; 51652 this._cachedStrokeStyle = this.drawingContext.strokeStyle; 51653 51654 p5.Renderer.prototype.pop.call(this, style); 51655}; 51656 51657module.exports = p5.Renderer2D; 51658 51659},{"../image/filters":41,"./canvas":20,"./constants":21,"./core":22,"./p5.Renderer":29}],31:[function(_dereq_,module,exports){ 51660/** 51661 * @module Rendering 51662 * @submodule Rendering 51663 * @for p5 51664 */ 51665 51666'use strict'; 51667 51668var p5 = _dereq_('./core'); 51669var constants = _dereq_('./constants'); 51670_dereq_('./p5.Graphics'); 51671_dereq_('./p5.Renderer2D'); 51672_dereq_('../webgl/p5.RendererGL'); 51673var defaultId = 'defaultCanvas0'; // this gets set again in createCanvas 51674var defaultClass = 'p5Canvas'; 51675 51676/** 51677 * Creates a canvas element in the document, and sets the dimensions of it 51678 * in pixels. This method should be called only once at the start of setup. 51679 * Calling createCanvas more than once in a sketch will result in very 51680 * unpredictable behavior. If you want more than one drawing canvas 51681 * you could use createGraphics (hidden by default but it can be shown). 51682 * <br><br> 51683 * The system variables width and height are set by the parameters passed 51684 * to this function. If createCanvas() is not used, the window will be 51685 * given a default size of 100x100 pixels. 51686 * <br><br> 51687 * For more ways to position the canvas, see the 51688 * <a href='https://github.com/processing/p5.js/wiki/Positioning-your-canvas'> 51689 * positioning the canvas</a> wiki page. 51690 * 51691 * @method createCanvas 51692 * @param {Number} w width of the canvas 51693 * @param {Number} h height of the canvas 51694 * @param {Constant} [renderer] either P2D or WEBGL 51695 * @return {p5.Renderer} 51696 * @example 51697 * <div> 51698 * <code> 51699 * function setup() { 51700 * createCanvas(100, 50); 51701 * background(153); 51702 * line(0, 0, width, height); 51703 * } 51704 * </code> 51705 * </div> 51706 * 51707 * @alt 51708 * Black line extending from top-left of canvas to bottom right. 51709 * 51710 */ 51711 51712p5.prototype.createCanvas = function(w, h, renderer) { 51713 p5._validateParameters('createCanvas', arguments); 51714 //optional: renderer, otherwise defaults to p2d 51715 var r = renderer || constants.P2D; 51716 var c; 51717 51718 if (r === constants.WEBGL) { 51719 c = document.getElementById(defaultId); 51720 if (c) { 51721 //if defaultCanvas already exists 51722 c.parentNode.removeChild(c); //replace the existing defaultCanvas 51723 var thisRenderer = this._renderer; 51724 this._elements = this._elements.filter(function(e) { 51725 return e !== thisRenderer; 51726 }); 51727 } 51728 c = document.createElement('canvas'); 51729 c.id = defaultId; 51730 c.classList.add(defaultClass); 51731 } else { 51732 if (!this._defaultGraphicsCreated) { 51733 c = document.createElement('canvas'); 51734 var i = 0; 51735 while (document.getElementById('defaultCanvas' + i)) { 51736 i++; 51737 } 51738 defaultId = 'defaultCanvas' + i; 51739 c.id = defaultId; 51740 c.classList.add(defaultClass); 51741 } else { 51742 // resize the default canvas if new one is created 51743 c = this.canvas; 51744 } 51745 } 51746 51747 // set to invisible if still in setup (to prevent flashing with manipulate) 51748 if (!this._setupDone) { 51749 c.dataset.hidden = true; // tag to show later 51750 c.style.visibility = 'hidden'; 51751 } 51752 51753 if (this._userNode) { 51754 // user input node case 51755 this._userNode.appendChild(c); 51756 } else { 51757 document.body.appendChild(c); 51758 } 51759 51760 // Init our graphics renderer 51761 //webgl mode 51762 if (r === constants.WEBGL) { 51763 this._setProperty('_renderer', new p5.RendererGL(c, this, true)); 51764 this._elements.push(this._renderer); 51765 } else { 51766 //P2D mode 51767 if (!this._defaultGraphicsCreated) { 51768 this._setProperty('_renderer', new p5.Renderer2D(c, this, true)); 51769 this._defaultGraphicsCreated = true; 51770 this._elements.push(this._renderer); 51771 } 51772 } 51773 this._renderer.resize(w, h); 51774 this._renderer._applyDefaults(); 51775 return this._renderer; 51776}; 51777 51778/** 51779 * Resizes the canvas to given width and height. The canvas will be cleared 51780 * and draw will be called immediately, allowing the sketch to re-render itself 51781 * in the resized canvas. 51782 * @method resizeCanvas 51783 * @param {Number} w width of the canvas 51784 * @param {Number} h height of the canvas 51785 * @param {Boolean} [noRedraw] don't redraw the canvas immediately 51786 * @example 51787 * <div class="norender"><code> 51788 * function setup() { 51789 * createCanvas(windowWidth, windowHeight); 51790 * } 51791 * 51792 * function draw() { 51793 * background(0, 100, 200); 51794 * } 51795 * 51796 * function windowResized() { 51797 * resizeCanvas(windowWidth, windowHeight); 51798 * } 51799 * </code></div> 51800 * 51801 * @alt 51802 * No image displayed. 51803 * 51804 */ 51805p5.prototype.resizeCanvas = function(w, h, noRedraw) { 51806 p5._validateParameters('resizeCanvas', arguments); 51807 if (this._renderer) { 51808 // save canvas properties 51809 var props = {}; 51810 for (var key in this.drawingContext) { 51811 var val = this.drawingContext[key]; 51812 if (typeof val !== 'object' && typeof val !== 'function') { 51813 props[key] = val; 51814 } 51815 } 51816 this._renderer.resize(w, h); 51817 // reset canvas properties 51818 for (var savedKey in props) {
51819 try { 51820 this.drawingContext[savedKey] = props[savedKey]; 51821 } catch (err) { 51822 // ignore read-only property errors 51823 } 51824 } 51825 if (!noRedraw) { 51826 this.redraw(); 51827 } 51828 } 51829}; 51830 51831/** 51832 * Removes the default canvas for a p5 sketch that doesn't 51833 * require a canvas 51834 * @method noCanvas 51835 * @example 51836 * <div> 51837 * <code> 51838 * function setup() { 51839 * noCanvas(); 51840 * } 51841 * </code> 51842 * </div> 51843 * 51844 * @alt 51845 * no image displayed 51846 * 51847 */ 51848p5.prototype.noCanvas = function() { 51849 if (this.canvas) { 51850 this.canvas.parentNode.removeChild(this.canvas); 51851 } 51852}; 51853 51854/** 51855 * Creates and returns a new p5.Renderer object. Use this class if you need 51856 * to draw into an off-screen graphics buffer. The two parameters define the 51857 * width and height in pixels. 51858 * 51859 * @method createGraphics 51860 * @param {Number} w width of the offscreen graphics buffer 51861 * @param {Number} h height of the offscreen graphics buffer 51862 * @param {Constant} [renderer] either P2D or WEBGL 51863 * undefined defaults to p2d 51864 * @return {p5.Graphics} offscreen graphics buffer 51865 * @example 51866 * <div> 51867 * <code> 51868 * var pg; 51869 * function setup() { 51870 * createCanvas(100, 100); 51871 * pg = createGraphics(100, 100); 51872 * } 51873 * function draw() { 51874 * background(200); 51875 * pg.background(100); 51876 * pg.noStroke(); 51877 * pg.ellipse(pg.width / 2, pg.height / 2, 50, 50); 51878 * image(pg, 50, 50); 51879 * image(pg, 0, 0, 50, 50); 51880 * } 51881 * </code> 51882 * </div> 51883 * 51884 * @alt 51885 * 4 grey squares alternating light and dark grey. White quarter circle mid-left. 51886 * 51887 */ 51888p5.prototype.createGraphics = function(w, h, renderer) { 51889 p5._validateParameters('createGraphics', arguments); 51890 return new p5.Graphics(w, h, renderer, this); 51891}; 51892 51893/** 51894 * Blends the pixels in the display window according to the defined mode. 51895 * There is a choice of the following modes to blend the source pixels (A) 51896 * with the ones of pixels already in the display window (B): 51897 * <ul> 51898 * <li><code>BLEND</code> - linear interpolation of colours: C = 51899 * A\*factor + B. This is the default blending mode.</li> 51900 * <li><code>ADD</code> - sum of A and B</li> 51901 * <li><code>DARKEST</code> - only the darkest colour succeeds: C = 51902 * min(A\*factor, B).</li> 51903 * <li><code>LIGHTEST</code> - only the lightest colour succeeds: C = 51904 * max(A\*factor, B).</li> 51905 * <li><code>DIFFERENCE</code> - subtract colors from underlying image.</li> 51906 * <li><code>EXCLUSION</code> - similar to <code>DIFFERENCE</code>, but less 51907 * extreme.</li> 51908 * <li><code>MULTIPLY</code> - multiply the colors, result will always be 51909 * darker.</li> 51910 * <li><code>SCREEN</code> - opposite multiply, uses inverse values of the 51911 * colors.</li> 51912 * <li><code>REPLACE</code> - the pixels entirely replace the others and 51913 * don't utilize alpha (transparency) values.</li> 51914 * <li><code>OVERLAY</code> - mix of <code>MULTIPLY</code> and <code>SCREEN 51915 * </code>. Multiplies dark values, and screens light values.</li> 51916 * <li><code>HARD_LIGHT</code> - <code>SCREEN</code> when greater than 50% 51917 * gray, <code>MULTIPLY</code> when lower.</li> 51918 * <li><code>SOFT_LIGHT</code> - mix of <code>DARKEST</code> and 51919 * <code>LIGHTEST</code>. Works like <code>OVERLAY</code>, but not as harsh. 51920 * </li> 51921 * <li><code>DODGE</code> - lightens light tones and increases contrast, 51922 * ignores darks.</li> 51923 * <li><code>BURN</code> - darker areas are applied, increasing contrast, 51924 * ignores lights.</li> 51925 * </ul> 51926 * 51927 * @method blendMode 51928 * @param {Constant} mode blend mode to set for canvas. 51929 * either BLEND, DARKEST, LIGHTEST, DIFFERENCE, MULTIPLY, 51930 * EXCLUSION, SCREEN, REPLACE, OVERLAY, HARD_LIGHT, 51931 * SOFT_LIGHT, DODGE, BURN, ADD or NORMAL 51932 * @example 51933 * <div> 51934 * <code> 51935 * blendMode(LIGHTEST); 51936 * strokeWeight(30); 51937 * stroke(80, 150, 255); 51938 * line(25, 25, 75, 75); 51939 * stroke(255, 50, 50); 51940 * line(75, 25, 25, 75); 51941 * </code> 51942 * </div> 51943 * <div> 51944 * <code> 51945 * blendMode(MULTIPLY); 51946 * strokeWeight(30); 51947 * stroke(80, 150, 255); 51948 * line(25, 25, 75, 75); 51949 * stroke(255, 50, 50); 51950 * line(75, 25, 25, 75); 51951 * </code> 51952 * </div> 51953 * @alt 51954 * translucent image thick red & blue diagonal rounded lines intersecting center 51955 * Thick red & blue diagonal rounded lines intersecting center. dark at overlap 51956 * 51957 */ 51958p5.prototype.blendMode = function(mode) { 51959 p5._validateParameters('blendMode', arguments); 51960 if ( 51961 mode === constants.BLEND || 51962 mode === constants.DARKEST || 51963 mode === constants.LIGHTEST || 51964 mode === constants.DIFFERENCE || 51965 mode === constants.MULTIPLY || 51966 mode === constants.EXCLUSION || 51967 mode === constants.SCREEN || 51968 mode === constants.REPLACE || 51969 mode === constants.OVERLAY || 51970 mode === constants.HARD_LIGHT || 51971 mode === constants.SOFT_LIGHT || 51972 mode === constants.DODGE || 51973 mode === constants.BURN || 51974 mode === constants.ADD || 51975 mode === constants.NORMAL 51976 ) { 51977 this._renderer.blendMode(mode); 51978 } else { 51979 throw new Error('Mode ' + mode + ' not recognized.'); 51980 } 51981}; 51982 51983module.exports = p5; 51984 51985},{"../webgl/p5.RendererGL":72,"./constants":21,"./core":22,"./p5.Graphics":28,"./p5.Renderer2D":30}],32:[function(_dereq_,module,exports){ 51986'use strict'; 51987 51988// requestAnim shim layer by Paul Irish 51989window.requestAnimationFrame = (function() { 51990 return ( 51991 window.requestAnimationFrame || 51992 window.webkitRequestAnimationFrame || 51993 window.mozRequestAnimationFrame || 51994 window.oRequestAnimationFrame || 51995 window.msRequestAnimationFrame || 51996 function(callback, element) { 51997 // should '60' here be framerate? 51998 window.setTimeout(callback, 1000 / 60); 51999 } 52000 ); 52001})(); 52002 52003// use window.performance() to get max fast and accurate time in milliseconds 52004window.performance = window.performance || {}; 52005window.performance.now = (function() { 52006 var load_date = Date.now(); 52007 return ( 52008 window.performance.now || 52009 window.performance.mozNow || 52010 window.performance.msNow || 52011 window.performance.oNow || 52012 window.performance.webkitNow || 52013 function() { 52014 return Date.now() - load_date; 52015 } 52016 ); 52017})(); 52018 52019/* 52020// http://paulirish.com/2011/requestanimationframe-for-smart-animating/ 52021// http://my.opera.com/emoller/blog/2011/12/20/ 52022// requestanimationframe-for-smart-er-animating 52023// requestAnimationFrame polyfill by Erik Möller 52024// fixes from Paul Irish and Tino Zijdel 52025(function() { 52026 var lastTime = 0; 52027 var vendors = ['ms', 'moz', 'webkit', 'o']; 52028 for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { 52029 window.requestAnimationFrame = 52030 window[vendors[x]+'RequestAnimationFrame']; 52031 window.cancelAnimationFrame = 52032 window[vendors[x]+'CancelAnimationFrame'] || 52033 window[vendors[x]+'CancelRequestAnimationFrame']; 52034 } 52035 52036 if (!window.requestAnimationFrame) { 52037 window.requestAnimationFrame = function(callback, element) { 52038 var currTime = new Date().getTime(); 52039 var timeToCall = Math.max(0, 16 - (currTime - lastTime)); 52040 var id = window.setTimeout(function() 52041 { callback(currTime + timeToCall); }, timeToCall); 52042 lastTime = currTime + timeToCall; 52043 return id; 52044 }; 52045 } 52046 52047 if (!window.cancelAnimationFrame) { 52048 window.cancelAnimationFrame = function(id) { 52049 clearTimeout(id); 52050 }; 52051 } 52052}()); 52053*/ 52054 52055/** 52056 * shim for Uint8ClampedArray.slice 52057 * (allows arrayCopy to work with pixels[]) 52058 * with thanks to http://halfpapstudios.com/blog/tag/html5-canvas/ 52059 * Enumerable set to false to protect for...in from 52060 * Uint8ClampedArray.prototype pollution. 52061 */ 52062(function() { 52063 'use strict'; 52064 if ( 52065 typeof Uint8ClampedArray !== 'undefined' && 52066 !Uint8ClampedArray.prototype.slice 52067 ) { 52068 Object.defineProperty(Uint8ClampedArray.prototype, 'slice', { 52069 value: Array.prototype.slice, 52070 writable: true, 52071 configurable: true, 52072 enumerable: false 52073 }); 52074 } 52075})(); 52076 52077},{}],33:[function(_dereq_,module,exports){ 52078/** 52079 * @module Structure 52080 * @submodule Structure 52081 * @for p5 52082 * @requires core 52083 */ 52084 52085'use strict'; 52086 52087var p5 = _dereq_('./core'); 52088 52089p5.prototype.exit = function() { 52090 throw 'exit() not implemented, see remove()'; 52091}; 52092/** 52093 * Stops p5.js from continuously executing the code within draw(). 52094 * If loop() is called, the code in draw() begins to run continuously again. 52095 * If using noLoop() in setup(), it should be the last line inside the block. 52096 * <br><br> 52097 * When noLoop() is used, it's not possible to manipulate or access the 52098 * screen inside event handling functions such as mousePressed() or 52099 * keyPressed(). Instead, use those functions to call redraw() or loop(), 52100 * which will run draw(), which can update the screen properly. This means 52101 * that when noLoop() has been called, no drawing can happen, and functions 52102 * like saveFrame() or loadPixels() may not be used. 52103 * <br><br> 52104 * Note that if the sketch is resized, redraw() will be called to update 52105 * the sketch, even after noLoop() has been specified. Otherwise, the sketch 52106 * would enter an odd state until loop() was called. 52107 * 52108 * @method noLoop 52109 * @example 52110 * <div><code> 52111 * function setup() { 52112 * createCanvas(100, 100); 52113 * background(200); 52114 * noLoop(); 52115 * } 52116 52117 * function draw() { 52118 * line(10, 10, 90, 90); 52119 * } 52120 * </code></div> 52121 * 52122 * <div><code> 52123 * var x = 0; 52124 * function setup() { 52125 * createCanvas(100, 100); 52126 * } 52127 * 52128 * function draw() { 52129 * background(204); 52130 * x = x + 0.1; 52131 * if (x > width) { 52132 * x = 0; 52133 * } 52134 * line(x, 0, x, height); 52135 * } 52136 * 52137 * function mousePressed() { 52138 * noLoop(); 52139 * } 52140 * 52141 * function mouseReleased() { 52142 * loop(); 52143 * } 52144 * </code></div> 52145 * 52146 * @alt 52147 * 113 pixel long line extending from top-left to bottom right of canvas. 52148 * horizontal line moves slowly from left. Loops but stops on mouse press. 52149 * 52150 */ 52151p5.prototype.noLoop = function() { 52152 this._loop = false;
52153}; 52154/** 52155 * By default, p5.js loops through draw() continuously, executing the code 52156 * within it. However, the draw() loop may be stopped by calling noLoop(). 52157 * In that case, the draw() loop can be resumed with loop(). 52158 * 52159 * @method loop 52160 * @example 52161 * <div><code> 52162 * var x = 0; 52163 * function setup() { 52164 * createCanvas(100, 100); 52165 * noLoop(); 52166 * } 52167 * 52168 * function draw() { 52169 * background(204); 52170 * x = x + 0.1; 52171 * if (x > width) { 52172 * x = 0; 52173 * } 52174 * line(x, 0, x, height); 52175 * } 52176 * 52177 * function mousePressed() { 52178 * loop(); 52179 * } 52180 * 52181 * function mouseReleased() { 52182 * noLoop(); 52183 * } 52184 * </code></div> 52185 * 52186 * @alt 52187 * horizontal line moves slowly from left. Loops but stops on mouse press. 52188 * 52189 */ 52190 52191p5.prototype.loop = function() { 52192 this._loop = true; 52193 this._draw(); 52194}; 52195 52196function assign(dest, varArgs) { 52197 for (var index = 1; index < arguments.length; index++) { 52198 var src = arguments[index]; 52199 if (src != null) { 52200 for (var key in src) { 52201 if (src.hasOwnProperty(key)) { 52202 dest[key] = src[key]; 52203 } 52204 } 52205 } 52206 } 52207} 52208 52209/** 52210 * The push() function saves the current drawing style settings and 52211 * transformations, while pop() restores these settings. Note that these 52212 * functions are always used together. They allow you to change the style 52213 * and transformation settings and later return to what you had. When a new 52214 * state is started with push(), it builds on the current style and transform 52215 * information. The push() and pop() functions can be embedded to provide 52216 * more control. (See the second example for a demonstration.) 52217 * <br><br> 52218 * push() stores information related to the current transformation state 52219 * and style settings controlled by the following functions: fill(),
52220 * stroke(), tint(), strokeWeight(), strokeCap(), strokeJoin(), 52221 * imageMode(), rectMode(), ellipseMode(), colorMode(), textAlign(), 52222 * textFont(), textMode(), textSize(), textLeading(). 52223 * 52224 * @method push 52225 * @example 52226 * <div> 52227 * <code> 52228 * ellipse(0, 50, 33, 33); // Left circle 52229 * 52230 * push(); // Start a new drawing state 52231 * strokeWeight(10); 52232 * fill(204, 153, 0); 52233 * translate(50, 0); 52234 * ellipse(0, 50, 33, 33); // Middle circle 52235 * pop(); // Restore original state 52236 * 52237 * ellipse(100, 50, 33, 33); // Right circle 52238 * </code> 52239 * </div> 52240 * <div> 52241 * <code> 52242 * ellipse(0, 50, 33, 33); // Left circle 52243 * 52244 * push(); // Start a new drawing state 52245 * strokeWeight(10); 52246 * fill(204, 153, 0); 52247 * ellipse(33, 50, 33, 33); // Left-middle circle 52248 * 52249 * push(); // Start another new drawing state 52250 * stroke(0, 102, 153); 52251 * ellipse(66, 50, 33, 33); // Right-middle circle 52252 * pop(); // Restore previous state 52253 * 52254 * pop(); // Restore original state 52255 * 52256 * ellipse(100, 50, 33, 33); // Right circle 52257 * </code> 52258 * </div> 52259 * 52260 * @alt 52261 * Gold ellipse + thick black outline @center 2 white ellipses on left and right. 52262 * 2 Gold ellipses left black right blue stroke. 2 white ellipses on left+right. 52263 * 52264 */ 52265p5.prototype.push = function() { 52266 this._styles.push({ 52267 props: { 52268 _colorMode: this._colorMode 52269 }, 52270 renderer: this._renderer.push() 52271 }); 52272}; 52273 52274/** 52275 * The push() function saves the current drawing style settings and 52276 * transformations, while pop() restores these settings. Note that these 52277 * functions are always used together. They allow you to change the style 52278 * and transformation settings and later return to what you had. When a new 52279 * state is started with push(), it builds on the current style and transform 52280 * information. The push() and pop() functions can be embedded to provide 52281 * more control. (See the second example for a demonstration.) 52282 * <br><br> 52283 * push() stores information related to the current transformation state 52284 * and style settings controlled by the following functions: fill(),
52285 * stroke(), tint(), strokeWeight(), strokeCap(), strokeJoin(), 52286 * imageMode(), rectMode(), ellipseMode(), colorMode(), textAlign(), 52287 * textFont(), textMode(), textSize(), textLeading(). 52288 * 52289 * @method pop 52290 * @example 52291 * <div> 52292 * <code> 52293 * ellipse(0, 50, 33, 33); // Left circle 52294 * 52295 * push(); // Start a new drawing state 52296 * translate(50, 0); 52297 * strokeWeight(10); 52298 * fill(204, 153, 0); 52299 * ellipse(0, 50, 33, 33); // Middle circle 52300 * pop(); // Restore original state 52301 * 52302 * ellipse(100, 50, 33, 33); // Right circle 52303 * </code> 52304 * </div> 52305 * <div> 52306 * <code> 52307 * ellipse(0, 50, 33, 33); // Left circle 52308 * 52309 * push(); // Start a new drawing state 52310 * strokeWeight(10); 52311 * fill(204, 153, 0); 52312 * ellipse(33, 50, 33, 33); // Left-middle circle 52313 * 52314 * push(); // Start another new drawing state 52315 * stroke(0, 102, 153); 52316 * ellipse(66, 50, 33, 33); // Right-middle circle 52317 * pop(); // Restore previous state 52318 * 52319 * pop(); // Restore original state 52320 * 52321 * ellipse(100, 50, 33, 33); // Right circle 52322 * </code> 52323 * </div> 52324 * 52325 * @alt 52326 * Gold ellipse + thick black outline @center 2 white ellipses on left and right. 52327 * 2 Gold ellipses left black right blue stroke. 2 white ellipses on left+right. 52328 * 52329 */ 52330p5.prototype.pop = function() { 52331 var style = this._styles.pop(); 52332 if (style) { 52333 this._renderer.pop(style.renderer); 52334 assign(this, style.props); 52335 } else { 52336 console.warn('pop() was called without matching push()'); 52337 } 52338}; 52339 52340p5.prototype.pushStyle = function() { 52341 throw new Error('pushStyle() not used, see push()'); 52342}; 52343 52344p5.prototype.popStyle = function() { 52345 throw new Error('popStyle() not used, see pop()'); 52346}; 52347 52348/** 52349 * 52350 * Executes the code within draw() one time. This functions allows the 52351 * program to update the display window only when necessary, for example 52352 * when an event registered by mousePressed() or keyPressed() occurs. 52353 * <br><br> 52354 * In structuring a program, it only makes sense to call redraw() within 52355 * events such as mousePressed(). This is because redraw() does not run 52356 * draw() immediately (it only sets a flag that indicates an update is 52357 * needed). 52358 * <br><br> 52359 * The redraw() function does not work properly when called inside draw(). 52360 * To enable/disable animations, use loop() and noLoop(). 52361 * <br><br> 52362 * In addition you can set the number of redraws per method call. Just 52363 * add an integer as single parameter for the number of redraws. 52364 * 52365 * @method redraw 52366 * @param {Integer} [n] Redraw for n-times. The default value is 1. 52367 * @example 52368 * <div><code> 52369 * var x = 0; 52370 * 52371 * function setup() { 52372 * createCanvas(100, 100); 52373 * noLoop(); 52374 * } 52375 * 52376 * function draw() { 52377 * background(204); 52378 * line(x, 0, x, height); 52379 * } 52380 * 52381 * function mousePressed() { 52382 * x += 1; 52383 * redraw(); 52384 * } 52385 * </code></div> 52386 * 52387 * <div class='norender'><code> 52388 * var x = 0; 52389 * 52390 * function setup() { 52391 * createCanvas(100, 100); 52392 * noLoop(); 52393 * } 52394 * 52395 * function draw() { 52396 * background(204); 52397 * x += 1; 52398 * line(x, 0, x, height); 52399 * } 52400 * 52401 * function mousePressed() { 52402 * redraw(5); 52403 * } 52404 * </code></div> 52405 * 52406 * @alt 52407 * black line on far left of canvas 52408 * black line on far left of canvas 52409 * 52410 */ 52411p5.prototype.redraw = function(n) { 52412 this.resetMatrix(); 52413 if (this._renderer.isP3D) { 52414 this._renderer._update(); 52415 } 52416 52417 var numberOfRedraws = parseInt(n); 52418 if (isNaN(numberOfRedraws) || numberOfRedraws < 1) { 52419 numberOfRedraws = 1; 52420 } 52421 52422 var userSetup = this.setup || window.setup; 52423 var userDraw = this.draw || window.draw; 52424 if (typeof userDraw === 'function') { 52425 if (typeof userSetup === 'undefined') { 52426 this.scale(this._pixelDensity, this._pixelDensity); 52427 } 52428 var self = this; 52429 var callMethod = function(f) { 52430 f.call(self); 52431 }; 52432 for (var idxRedraw = 0; idxRedraw < numberOfRedraws; idxRedraw++) { 52433 this._setProperty('frameCount', this.frameCount + 1); 52434 this._registeredMethods.pre.forEach(callMethod); 52435 userDraw(); 52436 this._registeredMethods.post.forEach(callMethod); 52437 } 52438 } 52439}; 52440 52441p5.prototype.size = function() { 52442 var s = 'size() is not a valid p5 function, to set the size of the '; 52443 s += 'drawing canvas, please use createCanvas() instead'; 52444 throw s; 52445}; 52446 52447module.exports = p5; 52448 52449},{"./core":22}],34:[function(_dereq_,module,exports){ 52450/** 52451 * @module Transform
52452 * @submodule Transform 52453 * @for p5 52454 * @requires core 52455 * @requires constants 52456 */ 52457 52458'use strict'; 52459 52460var p5 = _dereq_('./core'); 52461 52462/** 52463 * Multiplies the current matrix by the one specified through the parameters. 52464 * This is a powerful operation that can perform the equivalent of translate, 52465 * scale, shear and rotate all at once. You can learn more about transformation 52466 * matrices on <a href="https://en.wikipedia.org/wiki/Transformation_matrix"> 52467 * Wikipedia</a>. 52468 * 52469 * The naming of the arguments here follows the naming of the <a href= 52470 * "https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-transform"> 52471 * WHATWG specification</a> and corresponds to a 52472 * transformation matrix of the 52473 * form: 52474 * 52475 * > <img style="max-width: 150px" src="assets/transformation-matrix.png" 52476 * alt="The transformation matrix used when applyMatrix is called"/> 52477 * 52478 * @method applyMatrix 52479 * @param {Number} a numbers which define the 2x3 matrix to be multiplied 52480 * @param {Number} b numbers which define the 2x3 matrix to be multiplied 52481 * @param {Number} c numbers which define the 2x3 matrix to be multiplied 52482 * @param {Number} d numbers which define the 2x3 matrix to be multiplied 52483 * @param {Number} e numbers which define the 2x3 matrix to be multiplied 52484 * @param {Number} f numbers which define the 2x3 matrix to be multiplied 52485 * @chainable 52486 * @example 52487 * <div> 52488 * <code> 52489 * function setup() { 52490 * frameRate(10); 52491 * rectMode(CENTER); 52492 * } 52493 * 52494 * function draw() { 52495 * var step = frameCount % 20; 52496 * background(200); 52497 * // Equivalent to translate(x, y); 52498 * applyMatrix(1, 0, 0, 1, 40 + step, 50); 52499 * rect(0, 0, 50, 50); 52500 * } 52501 * </code> 52502 * </div> 52503 * <div> 52504 * <code> 52505 * function setup() { 52506 * frameRate(10); 52507 * rectMode(CENTER); 52508 * } 52509 * 52510 * function draw() { 52511 * var step = frameCount % 20; 52512 * background(200); 52513 * translate(50, 50); 52514 * // Equivalent to scale(x, y); 52515 * applyMatrix(1 / step, 0, 0, 1 / step, 0, 0); 52516 * rect(0, 0, 50, 50); 52517 * } 52518 * </code> 52519 * </div> 52520 * <div> 52521 * <code> 52522 * function setup() { 52523 * frameRate(10); 52524 * rectMode(CENTER); 52525 * } 52526 * 52527 * function draw() { 52528 * var step = frameCount % 20; 52529 * var angle = map(step, 0, 20, 0, TWO_PI); 52530 * var cos_a = cos(angle); 52531 * var sin_a = sin(angle); 52532 * background(200); 52533 * translate(50, 50); 52534 * // Equivalent to rotate(angle); 52535 * applyMatrix(cos_a, sin_a, -sin_a, cos_a, 0, 0); 52536 * rect(0, 0, 50, 50); 52537 * } 52538 * </code> 52539 * </div> 52540 * <div> 52541 * <code> 52542 * function setup() { 52543 * frameRate(10); 52544 * rectMode(CENTER); 52545 * } 52546 * 52547 * function draw() { 52548 * var step = frameCount % 20; 52549 * var angle = map(step, 0, 20, -PI / 4, PI / 4); 52550 * background(200); 52551 * translate(50, 50); 52552 * // equivalent to shearX(angle); 52553 * var shear_factor = 1 / tan(PI / 2 - angle); 52554 * applyMatrix(1, 0, shear_factor, 1, 0, 0); 52555 * rect(0, 0, 50, 50); 52556 * } 52557 * </code> 52558 * </div> 52559 * 52560 * @alt 52561 * A rectangle translating to the right 52562 * A rectangle shrinking to the center 52563 * A rectangle rotating clockwise about the center 52564 * A rectangle shearing 52565 * 52566 */ 52567p5.prototype.applyMatrix = function(a, b, c, d, e, f) { 52568 this._renderer.applyMatrix(a, b, c, d, e, f); 52569 return this; 52570}; 52571 52572p5.prototype.popMatrix = function() { 52573 throw new Error('popMatrix() not used, see pop()'); 52574}; 52575 52576p5.prototype.printMatrix = function() { 52577 throw new Error('printMatrix() not implemented'); 52578}; 52579 52580p5.prototype.pushMatrix = function() { 52581 throw new Error('pushMatrix() not used, see push()'); 52582}; 52583 52584/** 52585 * Replaces the current matrix with the identity matrix. 52586 * 52587 * @method resetMatrix 52588 * @chainable 52589 * @example 52590 * <div> 52591 * <code> 52592 * translate(50, 50); 52593 * applyMatrix(0.5, 0.5, -0.5, 0.5, 0, 0); 52594 * rect(0, 0, 20, 20); 52595 * // Note that the translate is also reset. 52596 * resetMatrix(); 52597 * rect(0, 0, 20, 20); 52598 * </code> 52599 * </div> 52600 * 52601 * @alt 52602 * A rotated retangle in the center with another at the top left corner 52603 * 52604 */ 52605p5.prototype.resetMatrix = function() { 52606 this._renderer.resetMatrix(); 52607 return this; 52608}; 52609 52610/** 52611 * Rotates a shape the amount specified by the angle parameter. This 52612 * function accounts for angleMode, so angles can be entered in either 52613 * RADIANS or DEGREES.
52614 * <br><br> 52615 * Objects are always rotated around their relative position to the 52616 * origin and positive numbers rotate objects in a clockwise direction. 52617 * Transformations apply to everything that happens after and subsequent 52618 * calls to the function accumulates the effect. For example, calling 52619 * rotate(HALF_PI) and then rotate(HALF_PI) is the same as rotate(PI). 52620 * All tranformations are reset when draw() begins again. 52621 * <br><br> 52622 * Technically, rotate() multiplies the current transformation matrix 52623 * by a rotation matrix. This function can be further controlled by 52624 * the push() and pop(). 52625 * 52626 * @method rotate 52627 * @param {Number} angle the angle of rotation, specified in radians 52628 * or degrees, depending on current angleMode 52629 * @param {p5.Vector|Number[]} [axis] (in 3d) the axis to rotate around 52630 * @chainable 52631 * @example 52632 * <div> 52633 * <code> 52634 * translate(width / 2, height / 2); 52635 * rotate(PI / 3.0); 52636 * rect(-26, -26, 52, 52); 52637 * </code> 52638 * </div> 52639 * 52640 * @alt 52641 * white 52x52 rect with black outline at center rotated counter 45 degrees 52642 * 52643 */ 52644p5.prototype.rotate = function(angle, axis) { 52645 p5._validateParameters('rotate', arguments); 52646 this._renderer.rotate(this._toRadians(angle), axis); 52647 return this; 52648}; 52649 52650/** 52651 * Rotates around X axis. 52652 * @method rotateX 52653 * @param {Number} angle the angle of rotation, specified in radians 52654 * or degrees, depending on current angleMode 52655 * @chainable 52656 * @example 52657 * <div modernizr='webgl'> 52658 * <code> 52659 * function setup() { 52660 * createCanvas(100, 100, WEBGL); 52661 * } 52662 * function draw() { 52663 * background(255); 52664 * rotateX(millis() / 1000); 52665 * box(); 52666 * } 52667 * </code> 52668 * </div> 52669 * 52670 * @alt 52671 * 3d box rotating around the x axis. 52672 */ 52673p5.prototype.rotateX = function(angle) { 52674 this._assert3d('rotateX'); 52675 p5._validateParameters('rotateX', arguments); 52676 this._renderer.rotateX(this._toRadians(angle)); 52677 return this; 52678}; 52679 52680/** 52681 * Rotates around Y axis. 52682 * @method rotateY 52683 * @param {Number} angle the angle of rotation, specified in radians 52684 * or degrees, depending on current angleMode 52685 * @chainable 52686 * @example 52687 * <div modernizr='webgl'> 52688 * <code> 52689 * function setup() { 52690 * createCanvas(100, 100, WEBGL); 52691 * } 52692 * function draw() { 52693 * background(255); 52694 * rotateY(millis() / 1000); 52695 * box(); 52696 * } 52697 * </code> 52698 * </div> 52699 * 52700 * @alt 52701 * 3d box rotating around the y axis. 52702 */ 52703p5.prototype.rotateY = function(angle) { 52704 this._assert3d('rotateY'); 52705 p5._validateParameters('rotateY', arguments); 52706 this._renderer.rotateY(this._toRadians(angle)); 52707 return this; 52708}; 52709 52710/** 52711 * Rotates around Z axis. Webgl mode only. 52712 * @method rotateZ 52713 * @param {Number} angle the angle of rotation, specified in radians 52714 * or degrees, depending on current angleMode 52715 * @chainable 52716 * @example 52717 * <div modernizr='webgl'> 52718 * <code> 52719 * function setup() { 52720 * createCanvas(100, 100, WEBGL); 52721 * } 52722 * function draw() { 52723 * background(255); 52724 * rotateZ(millis() / 1000); 52725 * box(); 52726 * } 52727 * </code> 52728 * </div> 52729 * 52730 * @alt 52731 * 3d box rotating around the z axis. 52732 */ 52733p5.prototype.rotateZ = function(angle) { 52734 this._assert3d('rotateZ'); 52735 p5._validateParameters('rotateZ', arguments); 52736 this._renderer.rotateZ(this._toRadians(angle)); 52737 return this; 52738}; 52739 52740/** 52741 * Increases or decreases the size of a shape by expanding and contracting 52742 * vertices. Objects always scale from their relative origin to the 52743 * coordinate system. Scale values are specified as decimal percentages. 52744 * For example, the function call scale(2.0) increases the dimension of a 52745 * shape by 200%. 52746 * <br><br> 52747 * Transformations apply to everything that happens after and subsequent 52748 * calls to the function multiply the effect. For example, calling scale(2.0) 52749 * and then scale(1.5) is the same as scale(3.0). If scale() is called 52750 * within draw(), the transformation is reset when the loop begins again. 52751 * <br><br> 52752 * Using this function with the z parameter is only available in WEBGL mode. 52753 * This function can be further controlled with push() and pop(). 52754 * 52755 * @method scale 52756 * @param {Number|p5.Vector|Number[]} s 52757 * percent to scale the object, or percentage to 52758 * scale the object in the x-axis if multiple arguments 52759 * are given 52760 * @param {Number} [y] percent to scale the object in the y-axis 52761 * @param {Number} [z] percent to scale the object in the z-axis (webgl only) 52762 * @chainable 52763 * @example 52764 * <div> 52765 * <code> 52766 * translate(width / 2, height / 2); 52767 * rotate(PI / 3.0); 52768 * rect(-26, -26, 52, 52); 52769 * </code> 52770 * </div> 52771 * 52772 * <div> 52773 * <code> 52774 * rect(30, 20, 50, 50); 52775 * scale(0.5, 1.3); 52776 * rect(30, 20, 50, 50); 52777 * </code> 52778 * </div> 52779 * 52780 * @alt 52781 * white 52x52 rect with black outline at center rotated counter 45 degrees 52782 * 2 white rects with black outline- 1 50x50 at center. other 25x65 bottom left 52783 * 52784 */ 52785/** 52786 * @method scale 52787 * @param {p5.Vector|Number[]} scales per-axis percents to scale the object 52788 * @chainable 52789 */ 52790p5.prototype.scale = function(x, y, z) { 52791 p5._validateParameters('scale', arguments); 52792 // Only check for Vector argument type if Vector is available 52793 if (x instanceof p5.Vector) { 52794 var v = x; 52795 x = v.x; 52796 y = v.y; 52797 z = v.z; 52798 } else if (x instanceof Array) { 52799 var rg = x; 52800 x = rg[0]; 52801 y = rg[1]; 52802 z = rg[2] || 1; 52803 } 52804 if (isNaN(y)) { 52805 y = z = x; 52806 } else if (isNaN(z)) { 52807 z = 1; 52808 } 52809 52810 this._renderer.scale.call(this._renderer, x, y, z); 52811 52812 return this; 52813}; 52814 52815/** 52816 * Shears a shape around the x-axis the amount specified by the angle 52817 * parameter. Angles should be specified in the current angleMode. 52818 * Objects are always sheared around their relative position to the origin 52819 * and positive numbers shear objects in a clockwise direction. 52820 * <br><br> 52821 * Transformations apply to everything that happens after and subsequent 52822 * calls to the function accumulates the effect. For example, calling 52823 * shearX(PI/2) and then shearX(PI/2) is the same as shearX(PI). 52824 * If shearX() is called within the draw(), the transformation is reset when 52825 * the loop begins again. 52826 * <br><br> 52827 * Technically, shearX() multiplies the current transformation matrix by a 52828 * rotation matrix. This function can be further controlled by the 52829 * push() and pop() functions. 52830 * 52831 * @method shearX 52832 * @param {Number} angle angle of shear specified in radians or degrees, 52833 * depending on current angleMode 52834 * @chainable 52835 * @example 52836 * <div> 52837 * <code> 52838 * translate(width / 4, height / 4); 52839 * shearX(PI / 4.0); 52840 * rect(0, 0, 30, 30); 52841 * </code> 52842 * </div> 52843 * 52844 * @alt 52845 * white irregular quadrilateral with black outline at top middle. 52846 * 52847 */ 52848p5.prototype.shearX = function(angle) { 52849 p5._validateParameters('shearX', arguments); 52850 this._renderer.shearX(this._toRadians(angle)); 52851 return this; 52852}; 52853 52854/** 52855 * Shears a shape around the y-axis the amount specified by the angle 52856 * parameter. Angles should be specified in the current angleMode. Objects 52857 * are always sheared around their relative position to the origin and 52858 * positive numbers shear objects in a clockwise direction. 52859 * <br><br> 52860 * Transformations apply to everything that happens after and subsequent 52861 * calls to the function accumulates the effect. For example, calling 52862 * shearY(PI/2) and then shearY(PI/2) is the same as shearY(PI). If 52863 * shearY() is called within the draw(), the transformation is reset when 52864 * the loop begins again. 52865 * <br><br> 52866 * Technically, shearY() multiplies the current transformation matrix by a 52867 * rotation matrix. This function can be further controlled by the 52868 * push() and pop() functions. 52869 * 52870 * @method shearY 52871 * @param {Number} angle angle of shear specified in radians or degrees, 52872 * depending on current angleMode 52873 * @chainable 52874 * @example 52875 * <div> 52876 * <code> 52877 * translate(width / 4, height / 4); 52878 * shearY(PI / 4.0); 52879 * rect(0, 0, 30, 30); 52880 * </code> 52881 * </div> 52882 * 52883 * @alt 52884 * white irregular quadrilateral with black outline at middle bottom. 52885 * 52886 */ 52887p5.prototype.shearY = function(angle) { 52888 p5._validateParameters('shearY', arguments); 52889 this._renderer.shearY(this._toRadians(angle)); 52890 return this; 52891}; 52892 52893/** 52894 * Specifies an amount to displace objects within the display window. 52895 * The x parameter specifies left/right translation, the y parameter 52896 * specifies up/down translation. 52897 * <br><br> 52898 * Transformations are cumulative and apply to everything that happens after 52899 * and subsequent calls to the function accumulates the effect. For example, 52900 * calling translate(50, 0) and then translate(20, 0) is the same as 52901 * translate(70, 0). If translate() is called within draw(), the 52902 * transformation is reset when the loop begins again. This function can be 52903 * further controlled by using push() and pop(). 52904 * 52905 * @method translate 52906 * @param {Number} x left/right translation 52907 * @param {Number} y up/down translation 52908 * @param {Number} [z] forward/backward translation (webgl only) 52909 * @chainable 52910 * @example 52911 * <div> 52912 * <code> 52913 * translate(30, 20); 52914 * rect(0, 0, 55, 55); 52915 * </code> 52916 * </div> 52917 * 52918 * <div> 52919 * <code> 52920 * rect(0, 0, 55, 55); // Draw rect at original 0,0 52921 * translate(30, 20); 52922 * rect(0, 0, 55, 55); // Draw rect at new 0,0 52923 * translate(14, 14); 52924 * rect(0, 0, 55, 55); // Draw rect at new 0,0 52925 * </code> 52926 * </div> 52927 * 52928 52929 * <div> 52930 * <code> 52931 * function draw() { 52932 * background(200); 52933 * rectMode(CENTER); 52934 * translate(width / 2, height / 2); 52935 * translate(p5.Vector.fromAngle(millis() / 1000, 40)); 52936 * rect(0, 0, 20, 20); 52937 * } 52938 * </code> 52939 * </div> 52940 * 52941 * @alt 52942 * white 55x55 rect with black outline at center right. 52943 * 3 white 55x55 rects with black outlines at top-l, center-r and bottom-r.
52944 * a 20x20 white rect moving in a circle around the canvas 52945 * 52946 */ 52947/** 52948 * @method translate 52949 * @param {p5.Vector} vector the vector to translate by 52950 * @chainable 52951 */ 52952p5.prototype.translate = function(x, y, z) { 52953 p5._validateParameters('translate', arguments); 52954 if (this._renderer.isP3D) { 52955 this._renderer.translate(x, y, z); 52956 } else { 52957 this._renderer.translate(x, y); 52958 } 52959 return this; 52960}; 52961 52962module.exports = p5; 52963 52964},{"./core":22}],35:[function(_dereq_,module,exports){ 52965/** 52966 * @module Shape 52967 * @submodule Vertex 52968 * @for p5 52969 * @requires core 52970 * @requires constants 52971 */ 52972 52973'use strict'; 52974 52975var p5 = _dereq_('./core'); 52976var constants = _dereq_('./constants'); 52977var shapeKind = null; 52978var vertices = []; 52979var contourVertices = []; 52980var isBezier = false; 52981var isCurve = false; 52982var isQuadratic = false; 52983var isContour = false; 52984var isFirstContour = true; 52985 52986/** 52987 * Use the beginContour() and endContour() functions to create negative 52988 * shapes within shapes such as the center of the letter 'O'. beginContour() 52989 * begins recording vertices for the shape and endContour() stops recording. 52990 * The vertices that define a negative shape must "wind" in the opposite 52991 * direction from the exterior shape. First draw vertices for the exterior 52992 * clockwise order, then for internal shapes, draw vertices 52993 * shape in counter-clockwise. 52994 * <br><br> 52995 * These functions can only be used within a beginShape()/endShape() pair and 52996 * transformations such as translate(), rotate(), and scale() do not work 52997 * within a beginContour()/endContour() pair. It is also not possible to use 52998 * other shapes, such as ellipse() or rect() within. 52999 * 53000 * @method beginContour 53001 * @chainable 53002 * @example 53003 * <div> 53004 * <code> 53005 * translate(50, 50); 53006 * stroke(255, 0, 0); 53007 * beginShape(); 53008 * // Exterior part of shape, clockwise winding 53009 * vertex(-40, -40); 53010 * vertex(40, -40); 53011 * vertex(40, 40); 53012 * vertex(-40, 40); 53013 * // Interior part of shape, counter-clockwise winding 53014 * beginContour(); 53015 * vertex(-20, -20); 53016 * vertex(-20, 20); 53017 * vertex(20, 20); 53018 * vertex(20, -20); 53019 * endContour(); 53020 * endShape(CLOSE); 53021 * </code> 53022 * </div> 53023 * 53024 * @alt 53025 * white rect and smaller grey rect with red outlines in center of canvas. 53026 * 53027 */ 53028p5.prototype.beginContour = function() { 53029 contourVertices = []; 53030 isContour = true; 53031 return this; 53032}; 53033 53034/** 53035 * Using the beginShape() and endShape() functions allow creating more 53036 * complex forms. beginShape() begins recording vertices for a shape and 53037 * endShape() stops recording. The value of the kind parameter tells it which 53038 * types of shapes to create from the provided vertices. With no mode 53039 * specified, the shape can be any irregular polygon. 53040 * <br><br> 53041 * The parameters available for beginShape() are POINTS, LINES, TRIANGLES, 53042 * TRIANGLE_FAN, TRIANGLE_STRIP, QUADS, and QUAD_STRIP. After calling the 53043 * beginShape() function, a series of vertex() commands must follow. To stop 53044 * drawing the shape, call endShape(). Each shape will be outlined with the 53045 * current stroke color and filled with the fill color. 53046 * <br><br> 53047 * Transformations such as translate(), rotate(), and scale() do not work 53048 * within beginShape(). It is also not possible to use other shapes, such as 53049 * ellipse() or rect() within beginShape(). 53050 * 53051 * @method beginShape 53052 * @param {Constant} [kind] either POINTS, LINES, TRIANGLES, TRIANGLE_FAN 53053 * TRIANGLE_STRIP, QUADS, or QUAD_STRIP 53054 * @chainable 53055 * @example 53056 * <div> 53057 * <code> 53058 * beginShape(); 53059 * vertex(30, 20); 53060 * vertex(85, 20); 53061 * vertex(85, 75); 53062 * vertex(30, 75); 53063 * endShape(CLOSE); 53064 * </code> 53065 * </div> 53066 * 53067 * <div> 53068 * <code> 53069 * beginShape(POINTS); 53070 * vertex(30, 20); 53071 * vertex(85, 20); 53072 * vertex(85, 75); 53073 * vertex(30, 75); 53074 * endShape(); 53075 * </code> 53076 * </div> 53077 * 53078 * <div> 53079 * <code> 53080 * beginShape(LINES); 53081 * vertex(30, 20); 53082 * vertex(85, 20); 53083 * vertex(85, 75); 53084 * vertex(30, 75); 53085 * endShape(); 53086 * </code> 53087 * </div> 53088 * 53089 * <div> 53090 * <code> 53091 * noFill(); 53092 * beginShape(); 53093 * vertex(30, 20); 53094 * vertex(85, 20); 53095 * vertex(85, 75); 53096 * vertex(30, 75); 53097 * endShape(); 53098 * </code> 53099 * </div> 53100 * 53101 * <div> 53102 * <code> 53103 * noFill(); 53104 * beginShape(); 53105 * vertex(30, 20); 53106 * vertex(85, 20);
53107 * vertex(85, 75); 53108 * vertex(30, 75); 53109 * endShape(CLOSE); 53110 * </code> 53111 * </div> 53112 * 53113 * <div> 53114 * <code> 53115 * beginShape(TRIANGLES); 53116 * vertex(30, 75); 53117 * vertex(40, 20); 53118 * vertex(50, 75); 53119 * vertex(60, 20); 53120 * vertex(70, 75); 53121 * vertex(80, 20); 53122 * endShape(); 53123 * </code> 53124 * </div> 53125 * 53126 * <div> 53127 * <code> 53128 * beginShape(TRIANGLE_STRIP); 53129 * vertex(30, 75); 53130 * vertex(40, 20); 53131 * vertex(50, 75); 53132 * vertex(60, 20); 53133 * vertex(70, 75); 53134 * vertex(80, 20); 53135 * vertex(90, 75); 53136 * endShape(); 53137 * </code> 53138 * </div> 53139 * 53140 * <div> 53141 * <code> 53142 * beginShape(TRIANGLE_FAN); 53143 * vertex(57.5, 50); 53144 * vertex(57.5, 15); 53145 * vertex(92, 50); 53146 * vertex(57.5, 85); 53147 * vertex(22, 50); 53148 * vertex(57.5, 15); 53149 * endShape(); 53150 * </code> 53151 * </div> 53152 * 53153 * <div> 53154 * <code> 53155 * beginShape(QUADS); 53156 * vertex(30, 20); 53157 * vertex(30, 75); 53158 * vertex(50, 75); 53159 * vertex(50, 20); 53160 * vertex(65, 20); 53161 * vertex(65, 75); 53162 * vertex(85, 75); 53163 * vertex(85, 20); 53164 * endShape(); 53165 * </code> 53166 * </div> 53167 * 53168 * <div> 53169 * <code> 53170 * beginShape(QUAD_STRIP); 53171 * vertex(30, 20); 53172 * vertex(30, 75); 53173 * vertex(50, 20); 53174 * vertex(50, 75); 53175 * vertex(65, 20); 53176 * vertex(65, 75); 53177 * vertex(85, 20); 53178 * vertex(85, 75); 53179 * endShape(); 53180 * </code> 53181 * </div> 53182 * 53183 * <div> 53184 * <code> 53185 * beginShape(); 53186 * vertex(20, 20); 53187 * vertex(40, 20); 53188 * vertex(40, 40); 53189 * vertex(60, 40); 53190 * vertex(60, 60); 53191 * vertex(20, 60); 53192 * endShape(CLOSE); 53193 * </code> 53194 * </div> 53195 * @alt 53196 * white square-shape with black outline in middle-right of canvas. 53197 * 4 black points in a square shape in middle-right of canvas. 53198 * 2 horizontal black lines. In the top-right and bottom-right of canvas. 53199 * 3 line shape with horizontal on top, vertical in middle and horizontal bottom. 53200 * square line shape in middle-right of canvas. 53201 * 2 white triangle shapes mid-right canvas. left one pointing up and right down. 53202 * 5 horizontal interlocking and alternating white triangles in mid-right canvas. 53203 * 4 interlocking white triangles in 45 degree rotated square-shape. 53204 * 2 white rectangle shapes in mid-right canvas. Both 20x55. 53205 * 3 side-by-side white rectangles center rect is smaller in mid-right canvas. 53206 * Thick white l-shape with black outline mid-top-left of canvas. 53207 * 53208 */ 53209p5.prototype.beginShape = function(kind) { 53210 p5._validateParameters('beginShape', arguments); 53211 if (this._renderer.isP3D) { 53212 this._renderer.beginShape.apply(this._renderer, arguments); 53213 } else { 53214 if ( 53215 kind === constants.POINTS || 53216 kind === constants.LINES || 53217 kind === constants.TRIANGLES || 53218 kind === constants.TRIANGLE_FAN || 53219 kind === constants.TRIANGLE_STRIP || 53220 kind === constants.QUADS || 53221 kind === constants.QUAD_STRIP 53222 ) { 53223 shapeKind = kind; 53224 } else { 53225 shapeKind = null; 53226 } 53227 53228 vertices = []; 53229 contourVertices = []; 53230 } 53231 return this; 53232}; 53233 53234/** 53235 * Specifies vertex coordinates for Bezier curves. Each call to 53236 * bezierVertex() defines the position of two control points and 53237 * one anchor point of a Bezier curve, adding a new segment to a 53238 * line or shape. 53239 * <br><br> 53240 * The first time bezierVertex() is used within a 53241 * beginShape() call, it must be prefaced with a call to vertex() 53242 * to set the first anchor point. This function must be used between 53243 * beginShape() and endShape() and only when there is no MODE 53244 * parameter specified to beginShape(). 53245 * 53246 * @method bezierVertex 53247 * @param {Number} x2 x-coordinate for the first control point 53248 * @param {Number} y2 y-coordinate for the first control point 53249 * @param {Number} x3 x-coordinate for the second control point 53250 * @param {Number} y3 y-coordinate for the second control point 53251 * @param {Number} x4 x-coordinate for the anchor point 53252 * @param {Number} y4 y-coordinate for the anchor point 53253 * @chainable 53254 * @example 53255 * <div> 53256 * <code> 53257 * strokeWeight(5); 53258 * point(30, 20); 53259 * point(80, 20); 53260 * point(80, 75); 53261 * point(30, 75); 53262 * 53263 * strokeWeight(1); 53264 * noFill(); 53265 * beginShape(); 53266 * vertex(30, 20); 53267 * bezierVertex(80, 20, 80, 75, 30, 75); 53268 * endShape(); 53269 * </code> 53270 * </div> 53271 * 53272 * <div> 53273 * <code> 53274 * strokeWeight(5); 53275 * point(30, 20); 53276 * point(80, 20); 53277 * point(80, 75); 53278 * point(30, 75); 53279 * 53280 * stroke(244, 122, 158); 53281 * point(50, 80); 53282 * point(60, 25); 53283 * point(30, 20); 53284 * 53285 * stroke(0); 53286 * strokeWeight(1); 53287 * beginShape(); 53288 * vertex(30, 20); 53289 * bezierVertex(80, 20, 80, 75, 30, 75); 53290 * bezierVertex(50, 80, 60, 25, 30, 20); 53291 * endShape(); 53292 * </code> 53293 * </div> 53294 * 53295 * @alt 53296 * crescent-shaped line in middle of canvas. Points facing left. 53297 * white crescent shape in middle of canvas. Points facing left. 53298 * 53299 */ 53300p5.prototype.bezierVertex = function(x2, y2, x3, y3, x4, y4) { 53301 p5._validateParameters('bezierVertex', arguments); 53302 if (vertices.length === 0) { 53303 throw 'vertex() must be used once before calling bezierVertex()'; 53304 } else { 53305 isBezier = true; 53306 var vert = []; 53307 for (var i = 0; i < arguments.length; i++) { 53308 vert[i] = arguments[i]; 53309 } 53310 vert.isVert = false;
53311 if (isContour) { 53312 contourVertices.push(vert); 53313 } else { 53314 vertices.push(vert); 53315 } 53316 } 53317 return this; 53318}; 53319 53320/** 53321 * Specifies vertex coordinates for curves. This function may only 53322 * be used between beginShape() and endShape() and only when there 53323 * is no MODE parameter specified to beginShape(). 53324 * <br><br> 53325 * The first and last points in a series of curveVertex() lines will be used to 53326 * guide the beginning and end of a the curve. A minimum of four 53327 * points is required to draw a tiny curve between the second and 53328 * third points. Adding a fifth point with curveVertex() will draw 53329 * the curve between the second, third, and fourth points. The 53330 * curveVertex() function is an implementation of Catmull-Rom 53331 * splines. 53332 * 53333 * @method curveVertex 53334 * @param {Number} x x-coordinate of the vertex 53335 * @param {Number} y y-coordinate of the vertex 53336 * @chainable 53337 * @example 53338 * <div> 53339 * <code> 53340 * strokeWeight(5); 53341 * point(84, 91); 53342 * point(68, 19); 53343 * point(21, 17); 53344 * point(32, 91); 53345 * strokeWeight(1); 53346 * 53347 * noFill(); 53348 * beginShape(); 53349 * curveVertex(84, 91); 53350 * curveVertex(84, 91); 53351 * curveVertex(68, 19); 53352 * curveVertex(21, 17); 53353 * curveVertex(32, 91); 53354 * curveVertex(32, 91); 53355 * endShape(); 53356 * </code> 53357 * </div> 53358 * 53359 * 53360 * @alt 53361 * Upside-down u-shape line, mid canvas. left point extends beyond canvas view. 53362 * 53363 */ 53364p5.prototype.curveVertex = function(x, y) { 53365 p5._validateParameters('curveVertex', arguments); 53366 isCurve = true; 53367 this.vertex(x, y); 53368 return this; 53369}; 53370 53371/** 53372 * Use the beginContour() and endContour() functions to create negative 53373 * shapes within shapes such as the center of the letter 'O'. beginContour() 53374 * begins recording vertices for the shape and endContour() stops recording. 53375 * The vertices that define a negative shape must "wind" in the opposite 53376 * direction from the exterior shape. First draw vertices for the exterior 53377 * clockwise order, then for internal shapes, draw vertices 53378 * shape in counter-clockwise. 53379 * <br><br> 53380 * These functions can only be used within a beginShape()/endShape() pair and 53381 * transformations such as translate(), rotate(), and scale() do not work 53382 * within a beginContour()/endContour() pair. It is also not possible to use 53383 * other shapes, such as ellipse() or rect() within. 53384 * 53385 * @method endContour 53386 * @chainable 53387 * @example 53388 * <div> 53389 * <code> 53390 * translate(50, 50); 53391 * stroke(255, 0, 0); 53392 * beginShape(); 53393 * // Exterior part of shape, clockwise winding 53394 * vertex(-40, -40); 53395 * vertex(40, -40); 53396 * vertex(40, 40); 53397 * vertex(-40, 40); 53398 * // Interior part of shape, counter-clockwise winding 53399 * beginContour(); 53400 * vertex(-20, -20); 53401 * vertex(-20, 20); 53402 * vertex(20, 20); 53403 * vertex(20, -20); 53404 * endContour(); 53405 * endShape(CLOSE); 53406 * </code> 53407 * </div> 53408 * 53409 * @alt 53410 * white rect and smaller grey rect with red outlines in center of canvas. 53411 * 53412 */ 53413p5.prototype.endContour = function() { 53414 var vert = contourVertices[0].slice(); // copy all data 53415 vert.isVert = contourVertices[0].isVert; 53416 vert.moveTo = false; 53417 contourVertices.push(vert); 53418 53419 // prevent stray lines with multiple contours 53420 if (isFirstContour) { 53421 vertices.push(vertices[0]); 53422 isFirstContour = false; 53423 } 53424 53425 for (var i = 0; i < contourVertices.length; i++) { 53426 vertices.push(contourVertices[i]); 53427 } 53428 return this; 53429}; 53430 53431/** 53432 * The endShape() function is the companion to beginShape() and may only be 53433 * called after beginShape(). When endshape() is called, all of image data 53434 * defined since the previous call to beginShape() is written into the image 53435 * buffer. The constant CLOSE as the value for the MODE parameter to close 53436 * the shape (to connect the beginning and the end). 53437 * 53438 * @method endShape 53439 * @param {Constant} [mode] use CLOSE to close the shape 53440 * @chainable 53441 * @example 53442 * <div> 53443 * <code> 53444 * noFill(); 53445 * 53446 * beginShape(); 53447 * vertex(20, 20); 53448 * vertex(45, 20); 53449 * vertex(45, 80); 53450 * endShape(CLOSE); 53451 * 53452 * beginShape(); 53453 * vertex(50, 20); 53454 * vertex(75, 20); 53455 * vertex(75, 80); 53456 * endShape(); 53457 * </code> 53458 * </div> 53459 * 53460 * @alt 53461 * Triangle line shape with smallest interior angle on bottom and upside-down L. 53462 * 53463 */ 53464p5.prototype.endShape = function(mode) { 53465 p5._validateParameters('endShape', arguments); 53466 if (this._renderer.isP3D) { 53467 this._renderer.endShape( 53468 mode, 53469 isCurve, 53470 isBezier, 53471 isQuadratic, 53472 isContour, 53473 shapeKind 53474 ); 53475 } else { 53476 if (vertices.length === 0) { 53477 return this; 53478 } 53479 if (!this._renderer._doStroke && !this._renderer._doFill) { 53480 return this; 53481 } 53482 53483 var closeShape = mode === constants.CLOSE; 53484 53485 // if the shape is closed, the first element is also the last element 53486 if (closeShape && !isContour) { 53487 vertices.push(vertices[0]); 53488 } 53489 53490 this._renderer.endShape( 53491 mode, 53492 vertices, 53493 isCurve, 53494 isBezier, 53495 isQuadratic, 53496 isContour, 53497 shapeKind 53498 ); 53499 53500 // Reset some settings 53501 isCurve = false;
53502 isBezier = false; 53503 isQuadratic = false; 53504 isContour = false; 53505 isFirstContour = true; 53506 53507 // If the shape is closed, the first element was added as last element. 53508 // We must remove it again to prevent the list of vertices from growing 53509 // over successive calls to endShape(CLOSE) 53510 if (closeShape) { 53511 vertices.pop(); 53512 } 53513 } 53514 return this; 53515}; 53516 53517/** 53518 * Specifies vertex coordinates for quadratic Bezier curves. Each call to 53519 * quadraticVertex() defines the position of one control points and one 53520 * anchor point of a Bezier curve, adding a new segment to a line or shape. 53521 * The first time quadraticVertex() is used within a beginShape() call, it 53522 * must be prefaced with a call to vertex() to set the first anchor point. 53523 * This function must be used between beginShape() and endShape() and only 53524 * when there is no MODE parameter specified to beginShape(). 53525 * 53526 * @method quadraticVertex 53527 * @param {Number} cx x-coordinate for the control point 53528 * @param {Number} cy y-coordinate for the control point 53529 * @param {Number} x3 x-coordinate for the anchor point 53530 * @param {Number} y3 y-coordinate for the anchor point 53531 * @chainable 53532 * @example 53533 * <div> 53534 * <code> 53535 * strokeWeight(5); 53536 * point(20, 20); 53537 * point(80, 20); 53538 * point(50, 50); 53539 * 53540 * noFill(); 53541 * strokeWeight(1); 53542 * beginShape(); 53543 * vertex(20, 20); 53544 * quadraticVertex(80, 20, 50, 50); 53545 * endShape(); 53546 * </code> 53547 * </div> 53548 * 53549 * <div> 53550 * <code> 53551 * strokeWeight(5); 53552 * point(20, 20); 53553 * point(80, 20); 53554 * point(50, 50); 53555 * 53556 * point(20, 80); 53557 * point(80, 80); 53558 * point(80, 60); 53559 * 53560 * noFill(); 53561 * strokeWeight(1); 53562 * beginShape(); 53563 * vertex(20, 20); 53564 * quadraticVertex(80, 20, 50, 50); 53565 * quadraticVertex(20, 80, 80, 80); 53566 * vertex(80, 60); 53567 * endShape(); 53568 * </code> 53569 * </div> 53570 * 53571 * @alt 53572 * arched-shaped black line with 4 pixel thick stroke weight. 53573 * backwards s-shaped black line with 4 pixel thick stroke weight. 53574 * 53575 */ 53576p5.prototype.quadraticVertex = function(cx, cy, x3, y3) { 53577 p5._validateParameters('quadraticVertex', arguments); 53578 //if we're drawing a contour, put the points into an 53579 // array for inside drawing 53580 if (this._contourInited) { 53581 var pt = {}; 53582 pt.x = cx; 53583 pt.y = cy; 53584 pt.x3 = x3; 53585 pt.y3 = y3; 53586 pt.type = constants.QUADRATIC; 53587 this._contourVertices.push(pt); 53588 53589 return this; 53590 } 53591 if (vertices.length > 0) { 53592 isQuadratic = true; 53593 var vert = []; 53594 for (var i = 0; i < arguments.length; i++) { 53595 vert[i] = arguments[i]; 53596 } 53597 vert.isVert = false; 53598 if (isContour) { 53599 contourVertices.push(vert); 53600 } else { 53601 vertices.push(vert); 53602 } 53603 } else { 53604 throw 'vertex() must be used once before calling quadraticVertex()'; 53605 } 53606 return this; 53607}; 53608 53609/** 53610 * All shapes are constructed by connecting a series of vertices. vertex() 53611 * is used to specify the vertex coordinates for points, lines, triangles, 53612 * quads, and polygons. It is used exclusively within the beginShape() and 53613 * endShape() functions. 53614 * 53615 * @method vertex 53616 * @param {Number} x x-coordinate of the vertex 53617 * @param {Number} y y-coordinate of the vertex 53618 * @chainable 53619 * @example 53620 * <div> 53621 * <code> 53622 * strokeWeight(3); 53623 * beginShape(POINTS); 53624 * vertex(30, 20); 53625 * vertex(85, 20); 53626 * vertex(85, 75); 53627 * vertex(30, 75); 53628 * endShape(); 53629 * </code> 53630 * </div> 53631 * 53632 * @alt 53633 * 4 black points in a square shape in middle-right of canvas. 53634 * 53635 * <div> 53636 * <code> 53637 * createCanvas(100, 100, WEBGL); 53638 * background(240, 240, 240); 53639 * fill(237, 34, 93); 53640 * noStroke(); 53641 * beginShape(); 53642 * vertex(0, 35); 53643 * vertex(35, 0); 53644 * vertex(0, -35); 53645 * vertex(-35, 0); 53646 * endShape(); 53647 * </code> 53648 * </div> 53649 * 53650 * @alt 53651 * 4 points making a diamond shape 53652 * 53653 * <div> 53654 * <code> 53655 * createCanvas(100, 100, WEBGL); 53656 * background(240, 240, 240); 53657 * fill(237, 34, 93); 53658 * noStroke(); 53659 * beginShape(); 53660 * vertex(-10, 10); 53661 * vertex(0, 35); 53662 * vertex(10, 10); 53663 * vertex(35, 0); 53664 * vertex(10, -8); 53665 * vertex(0, -35); 53666 * vertex(-10, -8); 53667 * vertex(-35, 0); 53668 * endShape(); 53669 * </code> 53670 * </div> 53671 * 53672 * @alt 53673 * 8 points making a star 53674 * 53675 * <div> 53676 * <code> 53677 * strokeWeight(3); 53678 * stroke(237, 34, 93); 53679 * beginShape(LINES); 53680 * vertex(10, 35); 53681 * vertex(90, 35); 53682 * vertex(10, 65); 53683 * vertex(90, 65); 53684 * vertex(35, 10); 53685 * vertex(35, 90); 53686 * vertex(65, 10); 53687 * vertex(65, 90); 53688 * endShape(); 53689 * </code> 53690 * </div> 53691 * 53692 * @alt 53693 * 8 points making 4 lines 53694 * 53695 */ 53696/** 53697 * @method vertex 53698 * @param {Number} x 53699 * @param {Number} y 53700 * @param {Number} [z] z-coordinate of the vertex 53701 * @param {Number} [u] the vertex's texture u-coordinate 53702 * @param {Number} [v] the vertex's texture v-coordinate 53703 */ 53704p5.prototype.vertex = function(x, y, moveTo, u, v) { 53705 if (this._renderer.isP3D) { 53706 this._renderer.vertex.apply(this._renderer, arguments); 53707 } else { 53708 var vert = []; 53709 vert.isVert = true; 53710 vert[0] = x; 53711 vert[1] = y; 53712 vert[2] = 0; 53713 vert[3] = 0; 53714 vert[4] = 0; 53715 vert[5] = this._renderer._getFill(); 53716 vert[6] = this._renderer._getStroke(); 53717 53718 if (moveTo) { 53719 vert.moveTo = moveTo; 53720 } 53721 if (isContour) { 53722 if (contourVertices.length === 0) { 53723 vert.moveTo = true; 53724 } 53725 contourVertices.push(vert); 53726 } else { 53727 vertices.push(vert); 53728 } 53729 } 53730 return this; 53731}; 53732 53733module.exports = p5; 53734 53735},{"./constants":21,"./core":22}],36:[function(_dereq_,module,exports){ 53736/** 53737 * @module Data 53738 * @submodule Dictionary 53739 * @for p5.TypedDict 53740 * @requires core 53741 * 53742 * This module defines the p5 methods for the p5 Dictionary classes 53743 * these classes StringDict and NumberDict are for storing and working 53744 * with key, value pairs 53745 */ 53746 53747'use strict'; 53748 53749var p5 = _dereq_('../core/core'); 53750 53751/** 53752 * 53753 * Creates a new instance of p5.StringDict using the key, value pair 53754 * or object you provide. 53755 * 53756 * @method createStringDict 53757 * @for p5 53758 * @param {String} key 53759 * @param {String} value 53760 * @return {p5.StringDict} 53761 * 53762 * @example 53763 * <div class="norender"> 53764 * <code> 53765 * function setup() { 53766 * var myDictionary = createStringDict('p5', 'js'); 53767 * print(myDictionary.hasKey('p5')); // logs true to console 53768 * } 53769 * </code></div> 53770 */ 53771/** 53772 * @method createStringDict 53773 * @param {Object} object object 53774 * @return {p5.StringDict} 53775 */ 53776 53777p5.prototype.createStringDict = function(key, value) { 53778 p5._validateParameters('createStringDict', arguments); 53779 return new p5.StringDict(key, value); 53780}; 53781 53782/** 53783 * 53784 * Creates a new instance of p5.NumberDict using the key, value pair 53785 * or object you provide. 53786 * 53787 * @method createNumberDict 53788 * @for p5 53789 * @param {Number} key 53790 * @param {Number} value 53791 * @return {p5.NumberDict} 53792 * 53793 * @example 53794 * <div class="norender"> 53795 * <code> 53796 * function setup() { 53797 * var myDictionary = createNumberDict(100, 42); 53798 * print(myDictionary.hasKey(100)); // logs true to console 53799 * } 53800 * </code></div> 53801 */ 53802/** 53803 * @method createNumberDict 53804 * @param {Object} object object 53805 * @return {p5.NumberDict} 53806 */ 53807 53808p5.prototype.createNumberDict = function(key, value) { 53809 p5._validateParameters('createNumberDict', arguments); 53810 return new p5.NumberDict(key, value); 53811}; 53812 53813/** 53814 * 53815 * Base class for all p5.Dictionary types. More specifically 53816 * typed Dictionary objects inherit from this 53817 * 53818 * @class p5.TypedDict 53819 * 53820 */ 53821 53822p5.TypedDict = function(key, value) { 53823 if (key instanceof Object) { 53824 this.data = key; 53825 } else { 53826 this.data = {}; 53827 this.data[key] = value; 53828 } 53829 return this; 53830}; 53831 53832/** 53833 * Returns the number of key-value pairs currently in Dictionary object 53834 * 53835 * @method size 53836 * @return {Integer} the number of key-value pairs in Dictionary object 53837 * 53838 * @example 53839 * <div class="norender"> 53840 * <code> 53841 * function setup() { 53842 * var myDictionary = createNumberDict(1, 10); 53843 * myDictionary.create(2, 20); 53844 * myDictionary.create(3, 30); 53845 * print(myDictionary.size()); // value of amt is 3 53846 * } 53847 * </code></div> 53848 * 53849 */ 53850p5.TypedDict.prototype.size = function() { 53851 return Object.keys(this.data).length; 53852}; 53853 53854/** 53855 * Returns true if key exists in Dictionary 53856 * otherwise returns false 53857 * 53858 * @method hasKey 53859 * @param {Number|String} key that you want to access 53860 * @return {Boolean} whether that key exists in Dictionary 53861 * 53862 * @example 53863 * <div class="norender"> 53864 * <code> 53865 * function setup() { 53866 * var myDictionary = createStringDict('p5', 'js'); 53867 * print(myDictionary.hasKey('p5')); // logs true to console 53868 * } 53869 * </code></div> 53870 * 53871 */ 53872 53873p5.TypedDict.prototype.hasKey = function(key) { 53874 return this.data.hasOwnProperty(key); 53875}; 53876 53877/** 53878 * Returns value stored at supplied key. 53879 * 53880 * @method get 53881 * @param {Number|String} key that you want to access 53882 * @return {Number|String} the value stored at that key 53883 * 53884 * @example 53885 * <div class="norender"> 53886 * <code> 53887 * function setup() { 53888 * var myDictionary = createStringDict('p5', 'js'); 53889 * var myValue = myDictionary.get('p5'); 53890 * print(myValue === 'js'); // logs true to console 53891 * } 53892 * </code></div> 53893 * 53894 */ 53895 53896p5.TypedDict.prototype.get = function(key) { 53897 if (this.data.hasOwnProperty(key)) { 53898 return this.data[key]; 53899 } else { 53900 console.log(key + ' does not exist in this Dictionary'); 53901 } 53902}; 53903 53904/** 53905 * Changes the value of key if in it already exists in 53906 * in the Dictionary otherwise makes a new key-value pair 53907 * 53908 * @method set 53909 * @param {Number|String} key 53910 * @param {Number|String} value 53911 * 53912 * @example 53913 * <div class="norender"> 53914 * <code> 53915 * function setup() { 53916 * var myDictionary = createStringDict('p5', 'js'); 53917 * myDictionary.set('p5', 'JS'); 53918 * myDictionary.print(); 53919 * // above logs "key: p5 - value: JS" to console 53920 * } 53921 * </code></div> 53922 * 53923 */ 53924 53925p5.TypedDict.prototype.set = function(key, value) {
53926 if (this._validate(value)) { 53927 this.data[key] = value; 53928 } else { 53929 console.log('Those values dont work for this dictionary type.'); 53930 } 53931}; 53932 53933/** 53934 * private helper function to handle the user passing objects in 53935 * during construction or calls to create() 53936 */ 53937 53938p5.TypedDict.prototype._addObj = function(obj) { 53939 for (var key in obj) { 53940 this.set(key, obj[key]); 53941 } 53942}; 53943 53944/** 53945 * Creates a key-value pair in the Dictionary 53946 * 53947 * @method create 53948 * @param {Number|String} key 53949 * @param {Number|String} value 53950 * 53951 * @example 53952 * <div class="norender"> 53953 * <code> 53954 * function setup() { 53955 * var myDictionary = createStringDict('p5', 'js'); 53956 * myDictionary.create('happy', 'coding'); 53957 * myDictionary.print(); 53958 * // above logs "key: p5 - value: js, key: happy - value: coding" to console 53959 * } 53960 * </code></div> 53961 */ 53962/** 53963 * @method create 53964 * @param {Object} obj key/value pair 53965 */ 53966 53967p5.TypedDict.prototype.create = function(key, value) { 53968 if (key instanceof Object && typeof value === 'undefined') { 53969 this._addObj(key); 53970 } else if (typeof key !== 'undefined') { 53971 this.set(key, value); 53972 } else { 53973 console.log( 53974 'In order to create a new Dictionary entry you must pass ' + 53975 'an object or a key, value pair' 53976 ); 53977 } 53978}; 53979 53980/** 53981 * Empties Dictionary of all key-value pairs 53982 * @method clear 53983 * @example 53984 * <div class="norender"> 53985 * <code> 53986 * function setup() { 53987 * var myDictionary = createStringDict('p5', 'js'); 53988 * print(myDictionary.hasKey('p5')); // prints 'true' 53989 * myDictionary.clear(); 53990 * print(myDictionary.hasKey('p5')); // prints 'false' 53991 * } 53992 * </code> 53993 * </div> 53994 */ 53995 53996p5.TypedDict.prototype.clear = function() { 53997 this.data = {}; 53998}; 53999 54000/** 54001 * Removes a key-value pair in the Dictionary 54002 * 54003 * @method remove 54004 * @param {Number|String} key for the pair to remove 54005 * 54006 * @example 54007 * <div class="norender"> 54008 * <code> 54009 * function setup() { 54010 * var myDictionary = createStringDict('p5', 'js'); 54011 * myDictionary.create('happy', 'coding'); 54012 * myDictionary.print(); 54013 * // above logs "key: p5 - value: js, key: happy - value: coding" to console 54014 * myDictionary.remove('p5'); 54015 * myDictionary.print(); 54016 * // above logs "key: happy value: coding" to console 54017 * } 54018 * </code></div> 54019 * 54020 */ 54021 54022p5.TypedDict.prototype.remove = function(key) { 54023 if (this.data.hasOwnProperty(key)) { 54024 delete this.data[key]; 54025 } else { 54026 throw key + ' does not exist in this Dictionary'; 54027 } 54028}; 54029 54030/** 54031 * Logs the list of items currently in the Dictionary to the console 54032 * 54033 * @method print 54034 * 54035 * @example 54036 * <div class="norender"> 54037 * <code> 54038 * function setup() { 54039 * var myDictionary = createStringDict('p5', 'js'); 54040 * myDictionary.create('happy', 'coding'); 54041 * myDictionary.print(); 54042 * // above logs "key: p5 - value: js, key: happy - value: coding" to console 54043 * } 54044 * </code> 54045 * </div> 54046 */ 54047 54048p5.TypedDict.prototype.print = function() { 54049 for (var item in this.data) { 54050 console.log('key:' + item + ' value:' + this.data[item]); 54051 } 54052}; 54053 54054/** 54055 * Converts the Dictionary into a CSV file for local 54056 * storage. 54057 * 54058 * @method saveTable 54059 * @example 54060 * <div> 54061 * <code> 54062 * createButton('save') 54063 * .position(10, 10) 54064 * .mousePressed(function() { 54065 * createStringDict({ 54066 * john: 1940, 54067 paul: 1942, 54068 george: 1943, 54069 ringo: 1940 54070 * }).saveTable('beatles'); 54071 * }); 54072 * </code> 54073 * </div> 54074 */ 54075 54076p5.TypedDict.prototype.saveTable = function(filename) { 54077 var output = ''; 54078 54079 for (var key in this.data) { 54080 output += key + ',' + this.data[key] + '\n'; 54081 } 54082 54083 var blob = new Blob([output], { type: 'text/csv' }); 54084 p5.prototype.downloadFile(blob, filename || 'mycsv', 'csv'); 54085}; 54086 54087/** 54088 * Converts the Dictionary into a JSON file for local 54089 * storage. 54090 * 54091 * @method saveJSON 54092 * @example 54093 * <div> 54094 * <code> 54095 * createButton('save') 54096 * .position(10, 10) 54097 * .mousePressed(function() { 54098 * createStringDict({ 54099 * john: 1940, 54100 paul: 1942, 54101 george: 1943, 54102 ringo: 1940 54103 * }).saveJSON('beatles'); 54104 * }); 54105 * </code> 54106 * </div> 54107 */ 54108 54109p5.TypedDict.prototype.saveJSON = function(filename, opt) { 54110 p5.prototype.saveJSON(this.data, filename, opt); 54111}; 54112 54113/** 54114 * private helper function to ensure that the user passed in valid 54115 * values for the Dictionary type 54116 */ 54117 54118p5.TypedDict.prototype._validate = function(value) { 54119 return true; 54120}; 54121 54122/** 54123 * 54124 * A Dictionary class for Strings. 54125 * 54126 * 54127 * @class p5.StringDict 54128 * @extends p5.TypedDict 54129 * 54130 */ 54131 54132p5.StringDict = function() { 54133 p5.TypedDict.apply(this, arguments); 54134}; 54135 54136p5.StringDict.prototype = Object.create(p5.TypedDict.prototype); 54137 54138p5.StringDict.prototype._validate = function(value) { 54139 return typeof value === 'string'; 54140}; 54141 54142/** 54143 * 54144 * A simple Dictionary class for Numbers. 54145 * 54146 * 54147 * @class p5.NumberDict 54148 * @extends p5.TypedDict 54149 * 54150 */ 54151 54152p5.NumberDict = function() { 54153 p5.TypedDict.apply(this, arguments); 54154}; 54155 54156p5.NumberDict.prototype = Object.create(p5.TypedDict.prototype); 54157 54158/** 54159 * private helper function to ensure that the user passed in valid 54160 * values for the Dictionary type 54161 */ 54162 54163p5.NumberDict.prototype._validate = function(value) { 54164 return typeof value === 'number'; 54165}; 54166 54167/** 54168 * Add to a value stored at a certain key 54169 * The sum is stored in that location in the Dictionary. 54170 * 54171 * @method add 54172 * @param {Number} Key for value you wish to add to 54173 * @param {Number} Amount to add to the value 54174 * @example 54175 * <div class='norender'> 54176 * <code> 54177 * function setup() { 54178 * var myDictionary = createNumberDict(2, 5); 54179 * myDictionary.add(2, 2); 54180 * console.log(myDictionary.get(2)); // logs 7 to console. 54181 * } 54182 * </code></div> 54183 * 54184 * 54185 */ 54186 54187p5.NumberDict.prototype.add = function(key, amount) { 54188 if (this.data.hasOwnProperty(key)) { 54189 this.data[key] += amount; 54190 } else { 54191 console.log('The key - ' + key + ' does not exist in this dictionary.'); 54192 } 54193}; 54194 54195/** 54196 * Subtract from a value stored at a certain key 54197 * The difference is stored in that location in the Dictionary. 54198 * 54199 * @method sub 54200 * @param {Number}
54200 Key for value you wish to subtract from 54201 * @param {Number} Amount to subtract from the value 54202 * @example 54203 * <div class='norender'> 54204 * <code> 54205 * function setup() { 54206 * var myDictionary = createNumberDict(2, 5); 54207 * myDictionary.sub(2, 2); 54208 * console.log(myDictionary.get(2)); // logs 3 to console. 54209 * } 54210 * </code></div> 54211 * 54212 * 54213 */ 54214 54215p5.NumberDict.prototype.sub = function(key, amount) { 54216 this.add(key, -amount); 54217}; 54218 54219/** 54220 * Multiply a value stored at a certain key 54221 * The product is stored in that location in the Dictionary. 54222 * 54223 * @method mult 54224 * @param {Number} Key for value you wish to multiply 54225 * @param {Number} Amount to multiply the value by 54226 * @example 54227 * <div class='norender'> 54228 * <code> 54229 * function setup() { 54230 * var myDictionary = createNumberDict(2, 4); 54231 * myDictionary.mult(2, 2); 54232 * console.log(myDictionary.get(2)); // logs 8 to console. 54233 * } 54234 * </code></div> 54235 * 54236 * 54237 */ 54238 54239p5.NumberDict.prototype.mult = function(key, amount) { 54240 if (this.data.hasOwnProperty(key)) { 54241 this.data[key] *= amount; 54242 } else { 54243 console.log('The key - ' + key + ' does not exist in this dictionary.'); 54244 } 54245}; 54246 54247/** 54248 * Divide a value stored at a certain key 54249 * The quotient is stored in that location in the Dictionary. 54250 * 54251 * @method div 54252 * @param {Number} Key for value you wish to divide 54253 * @param {Number} Amount to divide the value by 54254 * @example 54255 * <div class='norender'> 54256 * <code> 54257 * function setup() { 54258 * var myDictionary = createNumberDict(2, 8); 54259 * myDictionary.div(2, 2); 54260 * console.log(myDictionary.get(2)); // logs 4 to console. 54261 * } 54262 * </code></div> 54263 * 54264 * 54265 */ 54266 54267p5.NumberDict.prototype.div = function(key, amount) { 54268 if (this.data.hasOwnProperty(key)) { 54269 this.data[key] /= amount; 54270 } else { 54271 console.log('The key - ' + key + ' does not exist in this dictionary.'); 54272 } 54273}; 54274 54275/** 54276 * private helper function for finding lowest or highest value 54277 * the argument 'flip' is used to flip the comparison arrow 54278 * from 'less than' to 'greater than' 54279 * 54280 */ 54281 54282p5.NumberDict.prototype._valueTest = function(flip) { 54283 if (Object.keys(this.data).length === 0) { 54284 throw 'Unable to search for a minimum or maximum value on an empty NumberDict'; 54285 } else if (Object.keys(this.data).length === 1) { 54286 return this.data[Object.keys(this.data)[0]]; 54287 } else { 54288 var result = this.data[Object.keys(this.data)[0]]; 54289 for (var key in this.data) { 54290 if (this.data[key] * flip < result * flip) { 54291 result = this.data[key]; 54292 } 54293 } 54294 return result; 54295 } 54296}; 54297 54298/** 54299 * Return the lowest value. 54300 * 54301 * @method minValue 54302 * @return {Number} 54303 * @example 54304 * <div class='norender'> 54305 * <code> 54306 * function setup() { 54307 * var myDictionary = createNumberDict({ 2: -10, 4: 0.65, 1.2: 3 }); 54308 * var lowestValue = myDictionary.minValue(); // value is -10 54309 * print(lowestValue); 54310 * } 54311 * </code></div> 54312 * 54313 */ 54314 54315p5.NumberDict.prototype.minValue = function() { 54316 return this._valueTest(1); 54317}; 54318 54319/** 54320 * Return the highest value. 54321 * 54322 * @method maxValue 54323 * @return {Number} 54324 * @example 54325 * <div class='norender'> 54326 * <code> 54327 * function setup() { 54328 * var myDictionary = createNumberDict({ 2: -10, 4: 0.65, 1.2: 3 }); 54329 * var highestValue = myDictionary.maxValue(); // value is 3 54330 * print(highestValue); 54331 * } 54332 * </code></div> 54333 * 54334 */ 54335 54336p5.NumberDict.prototype.maxValue = function() { 54337 return this._valueTest(-1); 54338}; 54339 54340/** 54341 * private helper function for finding lowest or highest key 54342 * the argument 'flip' is used to flip the comparison arrow 54343 * from 'less than' to 'greater than' 54344 * 54345 */ 54346 54347p5.NumberDict.prototype._keyTest = function(flip) { 54348 if (Object.keys(this.data).length === 0) { 54349 throw 'Unable to use minValue on an empty NumberDict'; 54350 } else if (Object.keys(this.data).length === 1) { 54351 return Object.keys(this.data)[0]; 54352 } else { 54353 var result = Object.keys(this.data)[0]; 54354 for (var i = 1; i < Object.keys(this.data).length; i++) { 54355 if (Object.keys(this.data)[i] * flip < result * flip) { 54356 result = Object.keys(this.data)[i]; 54357 } 54358 } 54359 return result; 54360 } 54361}; 54362 54363/** 54364 * Return the lowest key. 54365 * 54366 * @method minKey 54367 * @return {Number} 54368 * @example 54369 * <div class='norender'> 54370 * <code> 54371 * function setup() { 54372 * var myDictionary = createNumberDict({ 2: 4, 4: 6, 1.2: 3 }); 54373 * var lowestKey = myDictionary.minKey(); // value is 1.2 54374 * print(lowestKey); 54375 * } 54376 * </code></div> 54377 * 54378 */ 54379 54380p5.NumberDict.prototype.minKey = function() { 54381 return this._keyTest(1); 54382}; 54383 54384/** 54385 * Return the highest key. 54386 * 54387 * @method maxKey 54388 * @return {Number} 54389 * @example 54390 * <div class='norender'> 54391 * <code> 54392 * function setup() { 54393 * var myDictionary = createNumberDict({ 2: 4, 4: 6, 1.2: 3 }); 54394 * var highestKey = myDictionary.maxKey(); // value is 4 54395 * print(highestKey); 54396 * } 54397 * </code></div> 54398 * 54399 */ 54400 54401p5.NumberDict.prototype.maxKey = function() { 54402 return this._keyTest(-1); 54403}; 54404 54405module.exports = p5.TypedDict; 54406 54407},{"../core/core":22}],37:[function(_dereq_,module,exports){ 54408/** 54409 * @module Events 54410 * @submodule Acceleration 54411 * @for p5 54412 * @requires core 54413 */ 54414 54415'use strict'; 54416 54417var p5 = _dereq_('../core/core'); 54418 54419/** 54420 * The system variable deviceOrientation always contains the orientation of 54421 * the device. The value of this variable will either be set 'landscape' 54422 * or 'portrait'. If no data is available it will be set to 'undefined'. 54423 * either LANDSCAPE or PORTRAIT. 54424 * 54425 * @property {Constant} deviceOrientation 54426 * @readOnly 54427 */ 54428p5.prototype.deviceOrientation = undefined; 54429 54430/** 54431 * The system variable accelerationX always contains the acceleration of the
54432 * device along the x axis. Value is represented as meters per second squared. 54433 * 54434 * @property {Number} accelerationX 54435 * @readOnly 54436 */ 54437p5.prototype.accelerationX = 0; 54438 54439/** 54440 * The system variable accelerationY always contains the acceleration of the 54441 * device along the y axis. Value is represented as meters per second squared. 54442 * 54443 * @property {Number} accelerationY 54444 * @readOnly 54445 */ 54446p5.prototype.accelerationY = 0; 54447 54448/** 54449 * The system variable accelerationZ always contains the acceleration of the 54450 * device along the z axis. Value is represented as meters per second squared. 54451 * 54452 * @property {Number} accelerationZ 54453 * @readOnly 54454 */ 54455p5.prototype.accelerationZ = 0; 54456 54457/** 54458 * The system variable pAccelerationX always contains the acceleration of the 54459 * device along the x axis in the frame previous to the current frame. Value 54460 * is represented as meters per second squared. 54461 * 54462 * @property {Number} pAccelerationX 54463 * @readOnly 54464 */ 54465p5.prototype.pAccelerationX = 0; 54466 54467/** 54468 * The system variable pAccelerationY always contains the acceleration of the 54469 * device along the y axis in the frame previous to the current frame. Value 54470 * is represented as meters per second squared. 54471 * 54472 * @property {Number} pAccelerationY 54473 * @readOnly 54474 */ 54475p5.prototype.pAccelerationY = 0; 54476 54477/** 54478 * The system variable pAccelerationZ always contains the acceleration of the 54479 * device along the z axis in the frame previous to the current frame. Value 54480 * is represented as meters per second squared. 54481 * 54482 * @property {Number} pAccelerationZ 54483 * @readOnly 54484 */ 54485p5.prototype.pAccelerationZ = 0; 54486 54487/** 54488 * _updatePAccelerations updates the pAcceleration values 54489 * 54490 * @private 54491 */ 54492p5.prototype._updatePAccelerations = function() { 54493 this._setProperty('pAccelerationX', this.accelerationX); 54494 this._setProperty('pAccelerationY', this.accelerationY); 54495 this._setProperty('pAccelerationZ', this.accelerationZ); 54496}; 54497 54498/** 54499 * The system variable rotationX always contains the rotation of the 54500 * device along the x axis. Value is represented as 0 to +/-180 degrees. 54501 * <br><br> 54502 * Note: The order the rotations are called is important, ie. if used 54503 * together, it must be called in the order Z-X-Y or there might be 54504 * unexpected behaviour. 54505 * 54506 * @example 54507 * <div> 54508 * <code> 54509 * function setup() { 54510 * createCanvas(100, 100, WEBGL); 54511 * } 54512 * 54513 * function draw() { 54514 * background(200); 54515 * //rotateZ(radians(rotationZ)); 54516 * rotateX(radians(rotationX)); 54517 * //rotateY(radians(rotationY)); 54518 * box(200, 200, 200); 54519 * } 54520 * </code> 54521 * </div> 54522 * 54523 * @property {Number} rotationX 54524 * @readOnly 54525 * 54526 * @alt 54527 * red horizontal line right, green vertical line bottom. black background. 54528 * 54529 */ 54530p5.prototype.rotationX = 0; 54531 54532/** 54533 * The system variable rotationY always contains the rotation of the 54534 * device along the y axis. Value is represented as 0 to +/-90 degrees. 54535 * <br><br> 54536 * Note: The order the rotations are called is important, ie. if used 54537 * together, it must be called in the order Z-X-Y or there might be 54538 * unexpected behaviour. 54539 * 54540 * @example 54541 * <div> 54542 * <code> 54543 * function setup() { 54544 * createCanvas(100, 100, WEBGL); 54545 * } 54546 * 54547 * function draw() { 54548 * background(200); 54549 * //rotateZ(radians(rotationZ)); 54550 * //rotateX(radians(rotationX)); 54551 * rotateY(radians(rotationY)); 54552 * box(200, 200, 200); 54553 * } 54554 * </code> 54555 * </div> 54556 * 54557 * @property {Number} rotationY 54558 * @readOnly 54559 * 54560 * @alt 54561 * red horizontal line right, green vertical line bottom. black background. 54562 */ 54563p5.prototype.rotationY = 0; 54564 54565/** 54566 * The system variable rotationZ always contains the rotation of the 54567 * device along the z axis. Value is represented as 0 to 359 degrees. 54568 * <br><br> 54569 * Unlike rotationX and rotationY, this variable is available for devices 54570 * with a built-in compass only. 54571 * <br><br> 54572 * Note: The order the rotations are called is important, ie. if used 54573 * together, it must be called in the order Z-X-Y or there might be 54574 * unexpected behaviour. 54575 * 54576 * @example 54577 * <div> 54578 * <code> 54579 * function setup() { 54580 * createCanvas(100, 100, WEBGL); 54581 * } 54582 * 54583 * function draw() { 54584 * background(200); 54585 * rotateZ(radians(rotationZ)); 54586 * //rotateX(radians(rotationX)); 54587 * //rotateY(radians(rotationY)); 54588 * box(200, 200, 200); 54589 * } 54590 * </code> 54591 * </div> 54592 * 54593 * @property {Number} rotationZ 54594 * @readOnly 54595 * 54596 * @alt 54597 * red horizontal line right, green vertical line bottom. black background. 54598 */ 54599p5.prototype.rotationZ = 0; 54600 54601/** 54602 * The system variable pRotationX always contains the rotation of the 54603 * device along the x axis in the frame previous to the current frame. Value 54604 * is represented as 0 to +/-180 degrees. 54605 * <br><br> 54606 * pRotationX can also be used with rotationX to determine the rotate 54607 * direction of the device along the X-axis. 54608 * @example 54609 * <div class='norender'> 54610 * <code> 54611 * // A simple if statement looking at whether 54612 * // rotationX - pRotationX < 0 is true or not will be 54613 * // sufficient for determining the rotate direction 54614 * // in most cases. 54615 * 54616 * // Some extra logic is needed to account for cases where 54617 * // the angles wrap around. 54618 * var rotateDirection = 'clockwise'; 54619 * 54620 * // Simple range conversion to make things simpler. 54621 * // This is not absolutely necessary but the logic 54622 * // will be different in that case. 54623 * 54624 * var rX = rotationX + 180; 54625 * var pRX = pRotationX + 180; 54626 * 54627 * if ((rX - pRX > 0 && rX - pRX < 270) || rX - pRX < -270) { 54628 * rotateDirection = 'clockwise'; 54629 * } else if (rX - pRX < 0 || rX - pRX > 270) { 54630 * rotateDirection = 'counter-clockwise'; 54631 * } 54632 * 54633 * print(rotateDirection); 54634 * </code> 54635 * </div> 54636 * 54637 * @alt 54638 * no image to display. 54639 * 54640 * 54641 * @property {Number} pRotationX 54642 * @readOnly 54643 */ 54644p5.prototype.pRotationX = 0; 54645 54646/** 54647 * The system variable pRotationY always contains the rotation of the 54648 * device along the y axis in the frame previous to the current frame. Value 54649 * is represented as 0 to +/-90 degrees. 54650 * <br><br> 54651 * pRotationY can also be used with rotationY to determine the rotate 54652 * direction of the device along the Y-axis. 54653 * @example 54654 * <div class='norender'> 54655 * <code> 54656 * // A simple if statement looking at whether 54657 * // rotationY - pRotationY < 0 is true or not will be 54658 * // sufficient for determining the rotate direction 54659 * // in most cases. 54660 * 54661 * // Some extra logic is needed to account for cases where 54662 * // the angles wrap around. 54663 * var rotateDirection = 'clockwise'; 54664 * 54665 * // Simple range conversion to make things simpler. 54666 * // This is not absolutely necessary but the logic 54667 * // will be different in that case. 54668 * 54669 * var rY = rotationY + 180; 54670 * var pRY = pRotationY + 180; 54671 * 54672 * if ((rY - pRY > 0 && rY - pRY < 270) || rY - pRY < -270) { 54673 * rotateDirection = 'clockwise'; 54674 * } else if (rY - pRY < 0 || rY - pRY > 270) { 54675 * rotateDirection = 'counter-clockwise'; 54676 * } 54677 * print(rotateDirection); 54678 * </code> 54679 * </div> 54680 * 54681 * @alt 54682 * no image to display. 54683 * 54684 * 54685 * @property {Number} pRotationY 54686 * @readOnly 54687 */ 54688p5.prototype.pRotationY = 0; 54689 54690/** 54691 * The system variable pRotationZ always contains the rotation of the 54692 * device along the z axis in the frame previous to the current frame. Value 54693 * is represented as 0 to 359 degrees. 54694 * <br><br> 54695 * pRotationZ can also be used with rotationZ to determine the rotate 54696 * direction of the device along the Z-axis. 54697 * @example 54698 * <div class='norender'> 54699 * <code> 54700 * // A simple if statement looking at whether 54701 * // rotationZ - pRotationZ < 0 is true or not will be 54702 * // sufficient for determining the rotate direction 54703 * // in most cases. 54704 * 54705 * // Some extra logic is needed to account for cases where 54706 * // the angles wrap around. 54707 * var rotateDirection = 'clockwise'; 54708 * 54709 * if ( 54710 * (rotationZ - pRotationZ > 0 && rotationZ - pRotationZ < 270) || 54711 * rotationZ - pRotationZ < -270 54712 * ) { 54713 * rotateDirection = 'clockwise'; 54714 * } else if (rotationZ - pRotationZ < 0 || rotationZ - pRotationZ > 270) { 54715 * rotateDirection = 'counter-clockwise'; 54716 * } 54717 * print(rotateDirection); 54718 * </code> 54719 * </div> 54720 * 54721 * @alt 54722 * no image to display. 54723 * 54724 * 54725 * @property {Number} pRotationZ 54726 * @readOnly 54727 */ 54728p5.prototype.pRotationZ = 0; 54729 54730var startAngleX = 0; 54731var startAngleY = 0; 54732var startAngleZ = 0; 54733 54734var rotateDirectionX = 'clockwise'; 54735var rotateDirectionY = 'clockwise'; 54736var rotateDirectionZ = 'clockwise'; 54737 54738var pRotateDirectionX; 54739var pRotateDirectionY; 54740var pRotateDirectionZ; 54741 54742p5.prototype._updatePRotations = function() { 54743 this._setProperty('pRotationX', this.rotationX); 54744 this._setProperty('pRotationY', this.rotationY); 54745 this._setProperty('pRotationZ', this.rotationZ); 54746}; 54747 54748/** 54749 * @property {String} turnAxis 54750 * @readOnly 54751 */ 54752p5.prototype.turnAxis = undefined; 54753 54754var move_threshold = 0.5; 54755var shake_threshold = 30; 54756 54757/** 54758 * The setMoveThreshold() function is used to set the movement threshold for 54759 * the deviceMoved() function. The default threshold is set to 0.5. 54760 * 54761 * @method setMoveThreshold 54762 * @param {number} value The threshold value 54763 */ 54764p5.prototype.setMoveThreshold = function(val) { 54765 p5._validateParameters('setMoveThreshold', arguments); 54766 move_threshold = val; 54767}; 54768 54769/** 54770 * The setShakeThreshold() function is used to set the movement threshold for 54771 * the deviceShaken() function. The default threshold is set to 30. 54772 * 54773 * @method setShakeThreshold 54774 * @param {number} value The threshold value 54775 */ 54776p5.prototype.setShakeThreshold = function(val) { 54777 p5._validateParameters('setShakeThreshold', arguments); 54778 shake_threshold = val; 54779}; 54780 54781/** 54782 * The deviceMoved() function is called when the device is moved by more than 54783 * the threshold value along X, Y or Z axis. The default threshold is set to 54784 * 0.5. 54785 * @method deviceMoved 54786 * @example 54787 * <div class="norender"> 54788 * <code> 54789 * // Run this example on a mobile device 54790 * // Move the device around 54791 * // to change the value. 54792 * 54793 * var value = 0; 54794 * function draw() { 54795 * fill(value); 54796 * rect(25, 25, 50, 50); 54797 * } 54798 * function deviceMoved() { 54799 * value = value + 5; 54800 * if (value > 255) { 54801 * value = 0; 54802 * } 54803 * } 54804 * </code> 54805 * </div> 54806 * 54807 * @alt 54808 * 50x50 black rect in center of canvas. turns white on mobile when device moves 54809 * 54810 */ 54811 54812/** 54813 * The deviceTurned() function is called when the device rotates by 54814 * more than 90 degrees continuously. 54815 * <br><br> 54816 * The axis that triggers the deviceTurned() method is stored in the turnAxis 54817 * variable. The deviceTurned() method can be locked to trigger on any axis: 54818 * X, Y or Z by comparing the turnAxis variable to 'X', 'Y' or 'Z'. 54819 * 54820 * @method deviceTurned 54821 * @example 54822 * <div class="norender"> 54823 * <code> 54824 * // Run this example on a mobile device 54825 * // Rotate the device by 90 degrees 54826 * // to change the value. 54827 * 54828 * var value = 0; 54829 * function draw() { 54830 * fill(value); 54831 * rect(25, 25, 50, 50); 54832 * } 54833 * function deviceTurned() { 54834 * if (value === 0) { 54835 * value = 255; 54836 * }
54836 else if (value === 255) { 54837 * value = 0; 54838 * } 54839 * } 54840 * </code> 54841 * </div> 54842 * <div> 54843 * <code> 54844 * // Run this example on a mobile device 54845 * // Rotate the device by 90 degrees in the 54846 * // X-axis to change the value. 54847 * 54848 * var value = 0; 54849 * function draw() { 54850 * fill(value); 54851 * rect(25, 25, 50, 50); 54852 * } 54853 * function deviceTurned() { 54854 * if (turnAxis === 'X') { 54855 * if (value === 0) { 54856 * value = 255; 54857 * } else if (value === 255) { 54858 * value = 0; 54859 * } 54860 * } 54861 * } 54862 * </code> 54863 * </div> 54864 * 54865 * @alt 54866 * 50x50 black rect in center of canvas. turns white on mobile when device turns 54867 * 50x50 black rect in center of canvas. turns white on mobile when x-axis turns 54868 * 54869 */ 54870 54871/** 54872 * The deviceShaken() function is called when the device total acceleration 54873 * changes of accelerationX and accelerationY values is more than 54874 * the threshold value. The default threshold is set to 30. 54875 * @method deviceShaken 54876 * @example 54877 * <div class="norender"> 54878 * <code> 54879 * // Run this example on a mobile device 54880 * // Shake the device to change the value. 54881 * 54882 * var value = 0; 54883 * function draw() { 54884 * fill(value); 54885 * rect(25, 25, 50, 50); 54886 * } 54887 * function deviceShaken() { 54888 * value = value + 5; 54889 * if (value > 255) { 54890 * value = 0; 54891 * } 54892 * } 54893 * </code> 54894 * </div> 54895 * 54896 * @alt 54897 * 50x50 black rect in center of canvas. turns white on mobile when device shakes 54898 * 54899 */ 54900 54901p5.prototype._ondeviceorientation = function(e) { 54902 this._updatePRotations(); 54903 this._setProperty('rotationX', e.beta); 54904 this._setProperty('rotationY', e.gamma); 54905 this._setProperty('rotationZ', e.alpha); 54906 this._handleMotion(); 54907}; 54908p5.prototype._ondevicemotion = function(e) { 54909 this._updatePAccelerations(); 54910 this._setProperty('accelerationX', e.acceleration.x * 2); 54911 this._setProperty('accelerationY', e.acceleration.y * 2); 54912 this._setProperty('accelerationZ', e.acceleration.z * 2); 54913 this._handleMotion(); 54914}; 54915p5.prototype._handleMotion = function() { 54916 if (window.orientation === 90 || window.orientation === -90) { 54917 this._setProperty('deviceOrientation', 'landscape'); 54918 } else if (window.orientation === 0) { 54919 this._setProperty('deviceOrientation', 'portrait'); 54920 } else if (window.orientation === undefined) { 54921 this._setProperty('deviceOrientation', 'undefined'); 54922 } 54923 var deviceMoved = this.deviceMoved || window.deviceMoved; 54924 if (typeof deviceMoved === 'function') { 54925 if ( 54926 Math.abs(this.accelerationX - this.pAccelerationX) > move_threshold || 54927 Math.abs(this.accelerationY - this.pAccelerationY) > move_threshold || 54928 Math.abs(this.accelerationZ - this.pAccelerationZ) > move_threshold 54929 ) { 54930 deviceMoved(); 54931 } 54932 } 54933 var deviceTurned = this.deviceTurned || window.deviceTurned; 54934 if (typeof deviceTurned === 'function') { 54935 // The angles given by rotationX etc is from range -180 to 180. 54936 // The following will convert them to 0 to 360 for ease of calculation 54937 // of cases when the angles wrapped around. 54938 // _startAngleX will be converted back at the end and updated. 54939 var wRX = this.rotationX + 180; 54940 var wPRX = this.pRotationX + 180; 54941 var wSAX = startAngleX + 180; 54942 if ((wRX - wPRX > 0 && wRX - wPRX < 270) || wRX - wPRX < -270) { 54943 rotateDirectionX = 'clockwise'; 54944 } else if (wRX - wPRX < 0 || wRX - wPRX > 270) { 54945 rotateDirectionX = 'counter-clockwise'; 54946 } 54947 if (rotateDirectionX !== pRotateDirectionX) { 54948 wSAX = wRX; 54949 } 54950 if (Math.abs(wRX - wSAX) > 90 && Math.abs(wRX - wSAX) < 270) { 54951 wSAX = wRX; 54952 this._setProperty('turnAxis', 'X'); 54953 deviceTurned(); 54954 } 54955 pRotateDirectionX = rotateDirectionX; 54956 startAngleX = wSAX - 180; 54957 54958 // Y-axis is identical to X-axis except for changing some names. 54959 var wRY = this.rotationY + 180; 54960 var wPRY = this.pRotationY + 180; 54961 var wSAY = startAngleY + 180; 54962 if ((wRY - wPRY > 0 && wRY - wPRY < 270) || wRY - wPRY < -270) { 54963 rotateDirectionY = 'clockwise'; 54964 } else if (wRY - wPRY < 0 || wRY - this.pRotationY > 270) { 54965 rotateDirectionY = 'counter-clockwise'; 54966 } 54967 if (rotateDirectionY !== pRotateDirectionY) { 54968 wSAY = wRY; 54969 } 54970 if (Math.abs(wRY - wSAY) > 90 && Math.abs(wRY - wSAY) < 270) { 54971 wSAY = wRY; 54972 this._setProperty('turnAxis', 'Y'); 54973 deviceTurned(); 54974 } 54975 pRotateDirectionY = rotateDirectionY; 54976 startAngleY = wSAY - 180; 54977 54978 // Z-axis is already in the range 0 to 360 54979 // so no conversion is needed. 54980 if ( 54981 (this.rotationZ - this.pRotationZ > 0 && 54982 this.rotationZ - this.pRotationZ < 270) || 54983 this.rotationZ - this.pRotationZ < -270 54984 ) { 54985 rotateDirectionZ = 'clockwise'; 54986 } else if ( 54987 this.rotationZ - this.pRotationZ < 0 || 54988 this.rotationZ - this.pRotationZ > 270 54989 ) { 54990 rotateDirectionZ = 'counter-clockwise'; 54991 } 54992 if (rotateDirectionZ !== pRotateDirectionZ) { 54993 startAngleZ = this.rotationZ; 54994 } 54995 if ( 54996 Math.abs(this.rotationZ - startAngleZ) > 90 && 54997 Math.abs(this.rotationZ - startAngleZ) < 270 54998 ) { 54999 startAngleZ = this.rotationZ; 55000 this._setProperty('turnAxis', 'Z'); 55001 deviceTurned(); 55002 } 55003 pRotateDirectionZ = rotateDirectionZ; 55004 this._setProperty('turnAxis', undefined); 55005 } 55006 var deviceShaken = this.deviceShaken || window.deviceShaken; 55007 if (typeof deviceShaken === 'function') { 55008 var accelerationChangeX; 55009 var accelerationChangeY; 55010 // Add accelerationChangeZ if acceleration change on Z is needed 55011 if (this.pAccelerationX !== null) { 55012 accelerationChangeX = Math.abs(this.accelerationX - this.pAccelerationX); 55013 accelerationChangeY = Math.abs(this.accelerationY - this.pAccelerationY); 55014 } 55015 if (accelerationChangeX + accelerationChangeY > shake_threshold) { 55016 deviceShaken(); 55017 } 55018 } 55019}; 55020 55021module.exports = p5; 55022 55023},{"../core/core":22}],38:[function(_dereq_,module,exports){ 55024/** 55025 * @module Events 55026 * @submodule Keyboard 55027 * @for p5 55028 * @requires core 55029 */ 55030 55031'use strict'; 55032 55033var p5 = _dereq_('../core/core'); 55034 55035/** 55036 * Holds the key codes of currently pressed keys. 55037 * @private 55038 */ 55039var downKeys = {}; 55040 55041/** 55042 * The boolean system variable keyIsPressed is true if any key is pressed 55043 * and false if no keys are pressed. 55044 * 55045 * @property {Boolean} keyIsPressed 55046 * @readOnly 55047 * @example 55048 * <div> 55049 * <code> 55050 * function draw() { 55051 * if (keyIsPressed === true) { 55052 * fill(0); 55053 * } else { 55054 * fill(255); 55055 * } 55056 * rect(25, 25, 50, 50); 55057 * } 55058 * </code> 55059 * </div> 55060 * 55061 * @alt 55062 * 50x50 white rect that turns black on keypress. 55063 * 55064 */ 55065p5.prototype.isKeyPressed = false;
55066p5.prototype.keyIsPressed = false; // khan 55067 55068/** 55069 * The system variable key always contains the value of the most recent 55070 * key on the keyboard that was typed. To get the proper capitalization, it 55071 * is best to use it within keyTyped(). For non-ASCII keys, use the keyCode 55072 * variable. 55073 * 55074 * @property {String} key 55075 * @readOnly 55076 * @example 55077 * <div><code> 55078 * // Click any key to display it! 55079 * // (Not Guaranteed to be Case Sensitive) 55080 * function setup() { 55081 * fill(245, 123, 158); 55082 * textSize(50); 55083 * } 55084 * 55085 * function draw() { 55086 * background(200); 55087 * text(key, 33, 65); // Display last key pressed. 55088 * } 55089 * </code></div> 55090 * 55091 * @alt 55092 * canvas displays any key value that is pressed in pink font. 55093 * 55094 */ 55095p5.prototype.key = ''; 55096 55097/** 55098 * The variable keyCode is used to detect special keys such as BACKSPACE, 55099 * DELETE, ENTER, RETURN, TAB, ESCAPE, SHIFT, CONTROL, OPTION, ALT, UP_ARROW, 55100 * DOWN_ARROW, LEFT_ARROW, RIGHT_ARROW. 55101 * You can also check for custom keys by looking up the keyCode of any key 55102 * on a site like this: <a href="http://keycode.info/">keycode.info</a>. 55103 * 55104 * @property {Integer} keyCode 55105 * @readOnly 55106 * @example 55107 * <div><code> 55108 * var fillVal = 126; 55109 * function draw() { 55110 * fill(fillVal); 55111 * rect(25, 25, 50, 50); 55112 * } 55113 * 55114 * function keyPressed() { 55115 * if (keyCode === UP_ARROW) { 55116 * fillVal = 255; 55117 * } else if (keyCode === DOWN_ARROW) { 55118 * fillVal = 0; 55119 * } 55120 * return false; // prevent default 55121 * } 55122 * </code></div> 55123 * 55124 * @alt 55125 * Grey rect center. turns white when up arrow pressed and black when down 55126 * 55127 */ 55128p5.prototype.keyCode = 0; 55129 55130/** 55131 * The keyPressed() function is called once every time a key is pressed. The 55132 * keyCode for the key that was pressed is stored in the keyCode variable. 55133 * <br><br> 55134 * For non-ASCII keys, use the keyCode variable. You can check if the keyCode 55135 * equals BACKSPACE, DELETE, ENTER, RETURN, TAB, ESCAPE, SHIFT, CONTROL, 55136 * OPTION, ALT, UP_ARROW, DOWN_ARROW, LEFT_ARROW, RIGHT_ARROW. 55137 * <br><br> 55138 * For ASCII keys that was pressed is stored in the key variable. However, it 55139 * does not distinguish between uppercase and lowercase. For this reason, it 55140 * is recommended to use keyTyped() to read the key variable, in which the 55141 * case of the variable will be distinguished.
55142 * <br><br> 55143 * Because of how operating systems handle key repeats, holding down a key 55144 * may cause multiple calls to keyTyped() (and keyReleased() as well). The 55145 * rate of repeat is set by the operating system and how each computer is 55146 * configured.<br><br> 55147 * Browsers may have different default 55148 * behaviors attached to various key events. To prevent any default 55149 * behavior for this event, add "return false" to the end of the method. 55150 * 55151 * @method keyPressed 55152 * @example 55153 * <div> 55154 * <code> 55155 * var value = 0; 55156 * function draw() { 55157 * fill(value); 55158 * rect(25, 25, 50, 50); 55159 * } 55160 * function keyPressed() { 55161 * if (value === 0) { 55162 * value = 255; 55163 * } else { 55164 * value = 0; 55165 * } 55166 * } 55167 * </code> 55168 * </div> 55169 * <div> 55170 * <code> 55171 * var value = 0; 55172 * function draw() { 55173 * fill(value); 55174 * rect(25, 25, 50, 50); 55175 * } 55176 * function keyPressed() { 55177 * if (keyCode === LEFT_ARROW) { 55178 * value = 255; 55179 * } else if (keyCode === RIGHT_ARROW) { 55180 * value = 0; 55181 * } 55182 * } 55183 * </code> 55184 * </div> 55185 * <div class="norender"> 55186 * <code> 55187 * function keyPressed() { 55188 * // Do something 55189 * return false; // prevent any default behaviour 55190 * } 55191 * </code> 55192 * </div> 55193 * 55194 * @alt 55195 * black rect center. turns white when key pressed and black when released 55196 * black rect center. turns white when left arrow pressed and black when right. 55197 * 55198 */ 55199p5.prototype._onkeydown = function(e) {
55200 if (downKeys[e.which]) { 55201 // prevent multiple firings 55202 return; 55203 } 55204 this._setProperty('isKeyPressed', true); 55205 this._setProperty('keyIsPressed', true); 55206 this._setProperty('keyCode', e.which); 55207 downKeys[e.which] = true; 55208 var key = String.fromCharCode(e.which); 55209 if (!key) { 55210 key = e.which; 55211 } 55212 this._setProperty('key', key); 55213 var keyPressed = this.keyPressed || window.keyPressed; 55214 if (typeof keyPressed === 'function' && !e.charCode) { 55215 var executeDefault = keyPressed(e); 55216 if (executeDefault === false) { 55217 e.preventDefault(); 55218 } 55219 } 55220}; 55221/** 55222 * The keyReleased() function is called once every time a key is released. 55223 * See key and keyCode for more information.<br><br> 55224 * Browsers may have different default 55225 * behaviors attached to various key events. To prevent any default 55226 * behavior for this event, add "return false" to the end of the method. 55227 * 55228 * @method keyReleased 55229 * @example 55230 * <div> 55231 * <code> 55232 * var value = 0; 55233 * function draw() { 55234 * fill(value); 55235 * rect(25, 25, 50, 50); 55236 * } 55237 * function keyReleased() { 55238 * if (value === 0) { 55239 * value = 255; 55240 * } else { 55241 * value = 0; 55242 * } 55243 * return false; // prevent any default behavior 55244 * } 55245 * </code> 55246 * </div> 55247 * 55248 * @alt 55249 * black rect center. turns white when key pressed and black when pressed again 55250 * 55251 */ 55252p5.prototype._onkeyup = function(e) { 55253 var keyReleased = this.keyReleased || window.keyReleased; 55254 downKeys[e.which] = false; 55255 55256 if (!areDownKeys()) { 55257 this._setProperty('isKeyPressed', false); 55258 this._setProperty('keyIsPressed', false); 55259 } 55260 55261 this._setProperty('_lastKeyCodeTyped', null); 55262 55263 var key = String.fromCharCode(e.which); 55264 if (!key) { 55265 key = e.which; 55266 } 55267 this._setProperty('key', key); 55268 this._setProperty('keyCode', e.which); 55269 if (typeof keyReleased === 'function') { 55270 var executeDefault = keyReleased(e); 55271 if (executeDefault === false) { 55272 e.preventDefault(); 55273 } 55274 } 55275}; 55276 55277/** 55278 * The keyTyped() function is called once every time a key is pressed, but 55279 * action keys such as Ctrl, Shift, and Alt are ignored. The most recent 55280 * key pressed will be stored in the key variable. 55281 * <br><br> 55282 * Because of how operating systems handle key repeats, holding down a key 55283 * will cause multiple calls to keyTyped() (and keyReleased() as well). The 55284 * rate of repeat is set by the operating system and how each computer is 55285 * configured.<br><br> 55286 * Browsers may have different default behaviors attached to various key 55287 * events. To prevent any default behavior for this event, add "return false" 55288 * to the end of the method. 55289 * 55290 * @method keyTyped 55291 * @example 55292 * <div> 55293 * <code> 55294 * var value = 0; 55295 * function draw() { 55296 * fill(value); 55297 * rect(25, 25, 50, 50); 55298 * } 55299 * function keyTyped() { 55300 * if (key === 'a') { 55301 * value = 255; 55302 * } else if (key === 'b') { 55303 * value = 0; 55304 * } 55305 * // uncomment to prevent any default behavior 55306 * // return false; 55307 * } 55308 * </code> 55309 * </div> 55310 * 55311 * @alt 55312 * black rect center. turns white when 'a' key typed and black when 'b' pressed 55313 * 55314 */ 55315p5.prototype._onkeypress = function(e) { 55316 if (e.which === this._lastKeyCodeTyped) { 55317 // prevent multiple firings 55318 return; 55319 } 55320 this._setProperty('keyCode', e.which); 55321 this._setProperty('_lastKeyCodeTyped', e.which); // track last keyCode 55322 this._setProperty('key', String.fromCharCode(e.which)); 55323 var keyTyped = this.keyTyped || window.keyTyped; 55324 if (typeof keyTyped === 'function') { 55325 var executeDefault = keyTyped(e); 55326 if (executeDefault === false) { 55327 e.preventDefault(); 55328 } 55329 } 55330}; 55331/** 55332 * The onblur function is called when the user is no longer focused 55333 * on the p5 element. Because the keyup events will not fire if the user is 55334 * not focused on the element we must assume all keys currently down have 55335 * been released. 55336 */ 55337p5.prototype._onblur = function(e) { 55338 downKeys = {}; 55339}; 55340 55341/** 55342 * The keyIsDown() function checks if the key is currently down, i.e. pressed. 55343 * It can be used if you have an object that moves, and you want several keys 55344 * to be able to affect its behaviour simultaneously, such as moving a 55345 * sprite diagonally. You can put in any number representing the keyCode of 55346 * the key, or use any of the variable keyCode names listed 55347 * <a href="http://p5js.org/reference/#p5/keyCode">here</a>. 55348 * 55349 * @method keyIsDown 55350 * @param {Number} code The key to check for. 55351 * @return {Boolean} whether key is down or not 55352 * @example 55353 * <div><code> 55354 * var x = 100; 55355 * var y = 100; 55356 * 55357 * function setup() { 55358 * createCanvas(512, 512); 55359 * } 55360 * 55361 * function draw() { 55362 * if (keyIsDown(LEFT_ARROW)) { 55363 * x -= 5; 55364 * } 55365 * 55366 * if (keyIsDown(RIGHT_ARROW)) { 55367 * x += 5; 55368 * } 55369 * 55370 * if (keyIsDown(UP_ARROW)) { 55371 * y -= 5; 55372 * } 55373 * 55374 * if (keyIsDown(DOWN_ARROW)) { 55375 * y += 5; 55376 * } 55377 * 55378 * clear(); 55379 * fill(255, 0, 0); 55380 * ellipse(x, y, 50, 50); 55381 * } 55382 * </code></div> 55383 * 55384 * @alt 55385 * 50x50 red ellipse moves left, right, up and down with arrow presses. 55386 * 55387 */ 55388p5.prototype.keyIsDown = function(code) { 55389 p5._validateParameters('keyIsDown', arguments); 55390 return downKeys[code]; 55391}; 55392 55393/** 55394 * The checkDownKeys function returns a boolean true if any keys pressed 55395 * and a false if no keys are currently pressed. 55396 55397 * Helps avoid instances where a multiple keys are pressed simultaneously and 55398 * releasing a single key will then switch the 55399 * keyIsPressed property to true. 55400 * @private 55401**/ 55402function areDownKeys() { 55403 for (var key in downKeys) { 55404 if (downKeys.hasOwnProperty(key) && downKeys[key] === true) { 55405 return true; 55406 } 55407 } 55408 return false;
55409} 55410 55411module.exports = p5; 55412 55413},{"../core/core":22}],39:[function(_dereq_,module,exports){ 55414/** 55415 * @module Events 55416 * @submodule Mouse 55417 * @for p5 55418 * @requires core 55419 * @requires constants 55420 */ 55421 55422'use strict'; 55423 55424var p5 = _dereq_('../core/core'); 55425var constants = _dereq_('../core/constants'); 55426 55427/* 55428 * This is a flag which is false until the first time 55429 * we receive a mouse event. The pmouseX and pmouseY 55430 * values will match the mouseX and mouseY values until 55431 * this interaction takes place. 55432 */ 55433p5.prototype._hasMouseInteracted = false; 55434 55435/** 55436 * The system variable mouseX always contains the current horizontal 55437 * position of the mouse, relative to (0, 0) of the canvas. If touch is 55438 * used instead of mouse input, mouseX will hold the x value of the most 55439 * recent touch point. 55440 * 55441 * @property {Number} mouseX 55442 * @readOnly 55443 * 55444 * @example 55445 * <div> 55446 * <code> 55447 * // Move the mouse across the canvas 55448 * function draw() { 55449 * background(244, 248, 252); 55450 * line(mouseX, 0, mouseX, 100); 55451 * } 55452 * </code> 55453 * </div> 55454 * 55455 * @alt 55456 * horizontal black line moves left and right with mouse x-position 55457 * 55458 */ 55459p5.prototype.mouseX = 0; 55460 55461/** 55462 * The system variable mouseY always contains the current vertical position 55463 * of the mouse, relative to (0, 0) of the canvas. If touch is 55464 * used instead of mouse input, mouseY will hold the y value of the most 55465 * recent touch point. 55466 * 55467 * @property {Number} mouseY 55468 * @readOnly 55469 * 55470 * @example 55471 * <div> 55472 * <code> 55473 * // Move the mouse across the canvas 55474 * function draw() { 55475 * background(244, 248, 252); 55476 * line(0, mouseY, 100, mouseY); 55477 * } 55478 * </code> 55479 * </div> 55480 * 55481 * @alt 55482 * vertical black line moves up and down with mouse y-position 55483 * 55484 */ 55485p5.prototype.mouseY = 0; 55486 55487/** 55488 * The system variable pmouseX always contains the horizontal position of 55489 * the mouse or finger in the frame previous to the current frame, relative to 55490 * (0, 0) of the canvas. 55491 * 55492 * @property {Number} pmouseX 55493 * @readOnly 55494 * 55495 * @example 55496 * <div> 55497 * <code> 55498 * // Move the mouse across the canvas to leave a trail 55499 * function setup() { 55500 * //slow down the frameRate to make it more visible 55501 * frameRate(10); 55502 * } 55503 * 55504 * function draw() { 55505 * background(244, 248, 252); 55506 * line(mouseX, mouseY, pmouseX, pmouseY); 55507 * print(pmouseX + ' -> ' + mouseX); 55508 * } 55509 * </code> 55510 * </div> 55511 * 55512 * @alt 55513 * line trail is created from cursor movements. faster movement make longer line. 55514 * 55515 */ 55516p5.prototype.pmouseX = 0; 55517 55518/** 55519 * The system variable pmouseY always contains the vertical position of the 55520 * mouse or finger in the frame previous to the current frame, relative to 55521 * (0, 0) of the canvas. 55522 * 55523 * @property {Number} pmouseY 55524 * @readOnly 55525 * 55526 * @example 55527 * <div> 55528 * <code> 55529 * function draw() { 55530 * background(237, 34, 93); 55531 * fill(0); 55532 * //draw a square only if the mouse is not moving 55533 * if (mouseY === pmouseY && mouseX === pmouseX) { 55534 * rect(20, 20, 60, 60); 55535 * } 55536 * 55537 * print(pmouseY + ' -> ' + mouseY); 55538 * } 55539 * </code> 55540 * </div> 55541 * 55542 * @alt 55543 * 60x60 black rect center, fuschia background. rect flickers on mouse movement 55544 * 55545 */ 55546p5.prototype.pmouseY = 0; 55547 55548/** 55549 * The system variable winMouseX always contains the current horizontal 55550 * position of the mouse, relative to (0, 0) of the window. 55551 * 55552 * @property {Number} winMouseX 55553 * @readOnly 55554 * 55555 * @example 55556 * <div> 55557 * <code> 55558 * var myCanvas; 55559 * 55560 * function setup() { 55561 * //use a variable to store a pointer to the canvas 55562 * myCanvas = createCanvas(100, 100); 55563 * } 55564 * 55565 * function draw() { 55566 * background(237, 34, 93); 55567 * fill(0); 55568 * 55569 * //move the canvas to the horizontal mouse position 55570 * //rela tive to the window 55571 * myCanvas.position(winMouseX + 1, windowHeight / 2); 55572 * 55573 * //the y of the square is relative to the canvas 55574 * rect(20, mouseY, 60, 60); 55575 * } 55576 * </code> 55577 * </div> 55578 * 55579 * @alt 55580 * 60x60 black rect y moves with mouse y and fuschia canvas moves with mouse x 55581 * 55582 */ 55583p5.prototype.winMouseX = 0; 55584 55585/** 55586 * The system variable winMouseY always contains the current vertical 55587 * position of the mouse, relative to (0, 0) of the window. 55588 * 55589 * @property {Number} winMouseY 55590 * @readOnly 55591 * 55592 * @example 55593 * <div> 55594 * <code> 55595 * var myCanvas; 55596 * 55597 * function setup() { 55598 * //use a variable to store a pointer to the canvas 55599 * myCanvas = createCanvas(100, 100); 55600 * } 55601 * 55602 * function draw() { 55603 * background(237, 34, 93); 55604 * fill(0); 55605 * 55606 * //move the canvas to the vertical mouse position 55607 * //rel ative to the window
55608 * myCanvas.position(windowWidth / 2, winMouseY + 1); 55609 * 55610 * //the x of the square is relative to the canvas 55611 * rect(mouseX, 20, 60, 60); 55612 * } 55613 * </code> 55614 * </div> 55615 * 55616 * @alt 55617 * 60x60 black rect x moves with mouse x and fuschia canvas y moves with mouse y 55618 * 55619 */ 55620p5.prototype.winMouseY = 0; 55621 55622/** 55623 * The system variable pwinMouseX always contains the horizontal position 55624 * of the mouse in the frame previous to the current frame, relative to 55625 * (0, 0) of the window. 55626 * 55627 * @property {Number} pwinMouseX 55628 * @readOnly 55629 * 55630 * @example 55631 * <div> 55632 * <code> 55633 * var myCanvas; 55634 * 55635 * function setup() { 55636 * //use a variable to store a pointer to the canvas 55637 * myCanvas = createCanvas(100, 100); 55638 * noStroke(); 55639 * fill(237, 34, 93); 55640 * } 55641 * 55642 * function draw() { 55643 * clear(); 55644 * //the difference between previous and 55645 * //current x position is the horizontal mouse speed 55646 * var speed = abs(winMouseX - pwinMouseX); 55647 * //change the size of the circle 55648 * //according to the horizontal speed 55649 * ellipse(50, 50, 10 + speed * 5, 10 + speed * 5); 55650 * //move the canvas to the mouse position 55651 * myCanvas.position(winMouseX + 1, winMouseY + 1); 55652 * } 55653 * </code> 55654 * </div> 55655 * 55656 * @alt 55657 * fuschia ellipse moves with mouse x and y. Grows and shrinks with mouse speed 55658 * 55659 */ 55660p5.prototype.pwinMouseX = 0; 55661 55662/** 55663 * The system variable pwinMouseY always contains the vertical position of 55664 * the mouse in the frame previous to the current frame, relative to (0, 0) 55665 * of the window. 55666 * 55667 * @property {Number} pwinMouseY 55668 * @readOnly 55669 * 55670 * 55671 * @example 55672 * <div> 55673 * <code> 55674 * var myCanvas; 55675 * 55676 * function setup() { 55677 * //use a variable to store a pointer to the canvas 55678 * myCanvas = createCanvas(100, 100); 55679 * noStroke(); 55680 * fill(237, 34, 93); 55681 * } 55682 * 55683 * function draw() { 55684 * clear(); 55685 * //the difference between previous and 55686 * //current y position is the vertical mouse speed 55687 * var speed = abs(winMouseY - pwinMouseY); 55688 * //change the size of the circle 55689 * //according to the vertical speed 55690 * ellipse(50, 50, 10 + speed * 5, 10 + speed * 5); 55691 * //move the canvas to the mouse position 55692 * myCanvas.position(winMouseX + 1, winMouseY + 1); 55693 * } 55694 * </code> 55695 * </div> 55696 * 55697 * @alt 55698 * fuschia ellipse moves with mouse x and y. Grows and shrinks with mouse speed 55699 * 55700 */ 55701p5.prototype.pwinMouseY = 0; 55702 55703/** 55704 * Processing automatically tracks if the mouse button is pressed and which 55705 * button is pressed. The value of the system variable mouseButton is either 55706 * LEFT, RIGHT, or CENTER depending on which button was pressed last. 55707 * Warning: different browsers may track mouseButton differently. 55708 * 55709 * @property {Constant} mouseButton 55710 * @readOnly 55711 * 55712 * @example 55713 * <div> 55714 * <code> 55715 * function draw() { 55716 * background(237, 34, 93); 55717 * fill(0); 55718 * 55719 * if (mouseIsPressed) { 55720 * if (mouseButton === LEFT) { 55721 * ellipse(50, 50, 50, 50); 55722 * } 55723 * if (mouseButton === RIGHT) { 55724 * rect(25, 25, 50, 50); 55725 * } 55726 * if (mouseButton === CENTER) { 55727 * triangle(23, 75, 50, 20, 78, 75); 55728 * } 55729 * } 55730 * 55731 * print(mouseButton); 55732 * } 55733 * </code> 55734 * </div> 55735 * 55736 * @alt 55737 * 50x50 black ellipse appears on center of fuschia canvas on mouse click/press. 55738 * 55739 */ 55740p5.prototype.mouseButton = 0; 55741 55742/** 55743 * The boolean system variable mouseIsPressed is true if the mouse is pressed 55744 * and false if not. 55745 * 55746 * @property {Boolean} mouseIsPressed 55747 * @readOnly 55748 * 55749 * @example 55750 * <div> 55751 * <code> 55752 * function draw() { 55753 * background(237, 34, 93); 55754 * fill(0); 55755 * 55756 * if (mouseIsPressed) { 55757 * ellipse(50, 50, 50, 50); 55758 * } else { 55759 * rect(25, 25, 50, 50); 55760 * } 55761 * 55762 * print(mouseIsPressed); 55763 * } 55764 * </code> 55765 * </div> 55766 * 55767 * @alt 55768 * black 50x50 rect becomes ellipse with mouse click/press. fuschia background. 55769 * 55770 */ 55771p5.prototype.mouseIsPressed = false; 55772 55773p5.prototype._updateNextMouseCoords = function(e) { 55774 if (this._curElement !== null && (!e.touches || e.touches.length > 0)) { 55775 var mousePos = getMousePos( 55776 this._curElement.elt, 55777 this.width, 55778 this.height, 55779 e 55780 ); 55781 this._setProperty('mouseX', mousePos.x); 55782 this._setProperty('mouseY', mousePos.y); 55783 this._setProperty('winMouseX', mousePos.winX); 55784 this._setProperty('winMouseY', mousePos.winY); 55785 } 55786 if (!this._hasMouseInteracted) { 55787 // For first draw, make previous and next equal 55788 this._updateMouseCoords(); 55789 this._setProperty('_hasMouseInteracted', true); 55790 } 55791}; 55792 55793p5.prototype._updateMouseCoords = function() { 55794 this._setProperty('pmouseX', this.mouseX); 55795 this._setProperty('pmouseY', this.mouseY); 55796 this._setProperty('pwinMouseX', this.winMouseX); 55797 this._setProperty('pwinMouseY', this.winMouseY); 55798}; 55799 55800function getMousePos(canvas, w, h, evt) { 55801 if (evt && !evt.clientX) { 55802 // use touches if touch and not mouse 55803 if (evt.touches) { 55804 evt = evt.touches[0]; 55805 } else if (evt.changedTouches) { 55806 evt = evt.changedTouches[0]; 55807 } 55808 } 55809 var rect = canvas.getBoundingClientRect(); 55810 var sx = canvas.scrollWidth / w; 55811 var sy = canvas.scrollHeight / h; 55812 return { 55813 x: (evt.clientX - rect.left) / sx, 55814 y: (evt.clientY - rect.top) / sy, 55815 winX: evt.clientX, 55816 winY: evt.clientY, 55817 id: evt.identifier 55818 }; 55819} 55820 55821p5.prototype._setMouseButton = function(e) { 55822 if (e.button === 1) { 55823 this._setProperty('mouseButton', constants.CENTER); 55824 } else if (e.button === 2) { 55825 this._setProperty('mouseButton', constants.RIGHT); 55826 } else { 55827 this._setProperty('mouseButton', constants.LEFT); 55828 } 55829}; 55830 55831/** 55832 * The mouseMoved() function is called every time the mouse moves and a mouse 55833 * button is not pressed.<br><br> 55834 * Browsers may have different default 55835 * behaviors attached to various mouse events. To prevent any default 55836 * behavior for this event, add "return false" to the end of the method. 55837 * 55838 * @method mouseMoved 55839 * @example 55840 * <div> 55841 * <code> 55842 * // Move the mouse across the page 55843 * // to change its value 55844 * 55845 * var value = 0; 55846 * function draw() { 55847 * fill(value); 55848 * rect(25, 25, 50, 50); 55849 * } 55850 * function mouseMoved() { 55851 * value = value + 5; 55852 * if (value > 255) { 55853 * value = 0; 55854 * } 55855 * } 55856 * </code> 55857 * </div> 55858 * 55859 * <div class="norender"> 55860 * <code> 55861 * function mouseMoved() { 55862 * ellipse(mouseX, mouseY, 5, 5); 55863 * // prevent default 55864 * return false;
55865 * } 55866 * </code> 55867 * </div> 55868 * 55869 * @alt 55870 * black 50x50 rect becomes lighter with mouse movements until white then resets 55871 * no image displayed 55872 * 55873 */ 55874 55875/** 55876 * The mouseDragged() function is called once every time the mouse moves and 55877 * a mouse button is pressed. If no mouseDragged() function is defined, the 55878 * touchMoved() function will be called instead if it is defined.<br><br> 55879 * Browsers may have different default 55880 * behaviors attached to various mouse events. To prevent any default 55881 * behavior for this event, add "return false" to the end of the method. 55882 * 55883 * @method mouseDragged 55884 * @example 55885 * <div> 55886 * <code> 55887 * // Drag the mouse across the page 55888 * // to change its value 55889 * 55890 * var value = 0; 55891 * function draw() { 55892 * fill(value); 55893 * rect(25, 25, 50, 50); 55894 * } 55895 * function mouseDragged() { 55896 * value = value + 5; 55897 * if (value > 255) { 55898 * value = 0; 55899 * } 55900 * } 55901 * </code> 55902 * </div> 55903 * 55904 * <div class="norender"> 55905 * <code> 55906 * function mouseDragged() { 55907 * ellipse(mouseX, mouseY, 5, 5); 55908 * // prevent default 55909 * return false; 55910 * } 55911 * </code> 55912 * </div> 55913 * 55914 * @alt 55915 * black 50x50 rect turns lighter with mouse click and drag until white, resets 55916 * no image displayed 55917 * 55918 */ 55919p5.prototype._onmousemove = function(e) { 55920 var context = this._isGlobal ? window : this; 55921 var executeDefault; 55922 this._updateNextMouseCoords(e); 55923 if (!this.mouseIsPressed) { 55924 if (typeof context.mouseMoved === 'function') { 55925 executeDefault = context.mouseMoved(e); 55926 if (executeDefault === false) { 55927 e.preventDefault(); 55928 } 55929 } 55930 } else { 55931 if (typeof context.mouseDragged === 'function') { 55932 executeDefault = context.mouseDragged(e); 55933 if (executeDefault === false) { 55934 e.preventDefault(); 55935 } 55936 } else if (typeof context.touchMoved === 'function') { 55937 executeDefault = context.touchMoved(e); 55938 if (executeDefault === false) { 55939 e.preventDefault(); 55940 } 55941 } 55942 } 55943}; 55944 55945/** 55946 * The mousePressed() function is called once after every time a mouse button 55947 * is pressed. The mouseButton variable (see the related reference entry) 55948 * can be used to determine which button has been pressed. If no 55949 * mousePressed() function is defined, the touchStarted() function will be 55950 * called instead if it is defined.<br><br> 55951 * Browsers may have different default 55952 * behaviors attached to various mouse events. To prevent any default 55953 * behavior for this event, add "return false" to the end of the method. 55954 * 55955 * @method mousePressed 55956 * @example 55957 * <div> 55958 * <code> 55959 * // Click within the image to change 55960 * // the value of the rectangle 55961 * 55962 * var value = 0; 55963 * function draw() { 55964 * fill(value); 55965 * rect(25, 25, 50, 50); 55966 * } 55967 * function mousePressed() { 55968 * if (value === 0) { 55969 * value = 255; 55970 * } else { 55971 * value = 0; 55972 * } 55973 * } 55974 * </code> 55975 * </div> 55976 * 55977 * <div class="norender"> 55978 * <code> 55979 * function mousePressed() { 55980 * ellipse(mouseX, mouseY, 5, 5); 55981 * // prevent default 55982 * return false; 55983 * } 55984 * </code> 55985 * </div> 55986 * 55987 * @alt 55988 * black 50x50 rect turns white with mouse click/press. 55989 * no image displayed 55990 * 55991 */ 55992p5.prototype._onmousedown = function(e) { 55993 var context = this._isGlobal ? window : this; 55994 var executeDefault; 55995 this._setProperty('mouseIsPressed', true); 55996 this._setMouseButton(e); 55997 this._updateNextMouseCoords(e); 55998 if (typeof context.mousePressed === 'function') { 55999 executeDefault = context.mousePressed(e); 56000 if (executeDefault === false) { 56001 e.preventDefault(); 56002 } 56003 } else if (typeof context.touchStarted === 'function') { 56004 executeDefault = context.touchStarted(e); 56005 if (executeDefault === false) { 56006 e.preventDefault(); 56007 } 56008 } 56009}; 56010 56011/** 56012 * The mouseReleased() function is called every time a mouse button is 56013 * released. If no mouseReleased() function is defined, the touchEnded() 56014 * function will be called instead if it is defined.<br><br> 56015 * Browsers may have different default 56016 * behaviors attached to various mouse events. To prevent any default 56017 * behavior for this event, add "return false" to the end of the method. 56018 * 56019 * 56020 * @method mouseReleased 56021 * @example 56022 * <div> 56023 * <code> 56024 * // Click within the image to change 56025 * // the value of the rectangle 56026 * // after the mouse has been clicked 56027 * 56028 * var value = 0; 56029 * function draw() { 56030 * fill(value); 56031 * rect(25, 25, 50, 50); 56032 * } 56033 * function mouseReleased() { 56034 * if (value === 0) { 56035 * value = 255; 56036 * } else { 56037 * value = 0; 56038 * } 56039 * } 56040 * </code> 56041 * </div> 56042 * 56043 * <div class="norender"> 56044 * <code> 56045 * function mouseReleased() { 56046 * ellipse(mouseX, mouseY, 5, 5); 56047 * // prevent default 56048 * return false;
56049 * } 56050 * </code> 56051 * </div> 56052 * 56053 * @alt 56054 * black 50x50 rect turns white with mouse click/press. 56055 * no image displayed 56056 * 56057 */ 56058p5.prototype._onmouseup = function(e) { 56059 var context = this._isGlobal ? window : this; 56060 var executeDefault; 56061 this._setProperty('mouseIsPressed', false); 56062 if (typeof context.mouseReleased === 'function') { 56063 executeDefault = context.mouseReleased(e); 56064 if (executeDefault === false) { 56065 e.preventDefault(); 56066 } 56067 } else if (typeof context.touchEnded === 'function') { 56068 executeDefault = context.touchEnded(e); 56069 if (executeDefault === false) { 56070 e.preventDefault(); 56071 } 56072 } 56073}; 56074 56075p5.prototype._ondragend = p5.prototype._onmouseup; 56076p5.prototype._ondragover = p5.prototype._onmousemove; 56077 56078/** 56079 * The mouseClicked() function is called once after a mouse button has been 56080 * pressed and then released.<br><br> 56081 * Browsers handle clicks differently, so this function is only guaranteed to be 56082 * run when the left mouse button is clicked. To handle other mouse buttons 56083 * being pressed or released, see mousePressed() or mouseReleased().<br><br> 56084 * Browsers may have different default 56085 * behaviors attached to various mouse events. To prevent any default 56086 * behavior for this event, add "return false" to the end of the method. 56087 * 56088 * @method mouseClicked 56089 * @example 56090 * <div> 56091 * <code> 56092 * // Click within the image to change 56093 * // the value of the rectangle 56094 * // after the mouse has been clicked 56095 * 56096 * var value = 0; 56097 * function draw() { 56098 * fill(value); 56099 * rect(25, 25, 50, 50); 56100 * } 56101 * 56102 * function mouseClicked() { 56103 * if (value === 0) { 56104 * value = 255; 56105 * } else { 56106 * value = 0; 56107 * } 56108 * } 56109 * </code> 56110 * </div> 56111 * 56112 * <div class="norender"> 56113 * <code> 56114 * function mouseClicked() { 56115 * ellipse(mouseX, mouseY, 5, 5); 56116 * // prevent default 56117 * return false; 56118 * } 56119 * </code> 56120 * </div> 56121 * 56122 * @alt 56123 * black 50x50 rect turns white with mouse click/press. 56124 * no image displayed 56125 * 56126 */ 56127p5.prototype._onclick = function(e) { 56128 var context = this._isGlobal ? window : this; 56129 if (typeof context.mouseClicked === 'function') { 56130 var executeDefault = context.mouseClicked(e); 56131 if (executeDefault === false) { 56132 e.preventDefault(); 56133 } 56134 } 56135}; 56136 56137/** 56138 * The doubleClicked() function is executed every time a event 56139 * listener has detected a dblclick event which is a part of the 56140 * DOM L3 specification. The doubleClicked event is fired when a 56141 * pointing device button (usually a mouse's primary button) 56142 * is clicked twice on a single element. For more info on the 56143 * dblclick event refer to mozilla's documentation here: 56144 * https://developer.mozilla.org/en-US/docs/Web/Events/dblclick 56145 * 56146 * @method doubleClicked 56147 * @example 56148 * <div> 56149 * <code> 56150 * // Click within the image to change 56151 * // the value of the rectangle 56152 * // after the mouse has been double clicked 56153 * 56154 * var value = 0; 56155 * function draw() { 56156 * fill(value); 56157 * rect(25, 25, 50, 50); 56158 * } 56159 * 56160 * function doubleClicked() { 56161 * if (value === 0) { 56162 * value = 255; 56163 * } else { 56164 * value = 0; 56165 * } 56166 * } 56167 * </code> 56168 * </div> 56169 * 56170 * <div class="norender"> 56171 * <code> 56172 * function doubleClicked() { 56173 * ellipse(mouseX, mouseY, 5, 5); 56174 * // prevent default 56175 * return false; 56176 * } 56177 * </code> 56178 * </div> 56179 * 56180 * @alt 56181 * black 50x50 rect turns white with mouse doubleClick/press. 56182 * no image displayed 56183 */ 56184 56185p5.prototype._ondblclick = function(e) { 56186 var context = this._isGlobal ? window : this; 56187 if (typeof context.doubleClicked === 'function') { 56188 var executeDefault = context.doubleClicked(e); 56189 if (executeDefault === false) { 56190 e.preventDefault(); 56191 } 56192 } 56193}; 56194 56195/** 56196 * The function mouseWheel() is executed every time a vertical mouse wheel 56197 * event is detected either triggered by an actual mouse wheel or by a 56198 * touchpad.<br><br> 56199 * The event.delta property returns the amount the mouse wheel 56200 * have scrolled. The values can be positive or negative depending on the 56201 * scroll direction (on OS X with "natural" scrolling enabled, the signs 56202 * are inverted).<br><br> 56203 * Browsers may have different default behaviors attached to various 56204 * mouse events. To prevent any default behavior for this event, add 56205 * "return false" to the end of the method.<br><br> 56206 * Due to the current support of the "wheel" event on Safari, the function 56207 * may only work as expected if "return false" is included while using Safari. 56208 * 56209 * @method mouseWheel 56210 * 56211 * @example 56212 * <div> 56213 * <code> 56214 * var pos = 25; 56215 * 56216 * function draw() { 56217 * background(237, 34, 93); 56218 * fill(0); 56219 * rect(25, pos, 50, 50); 56220 * } 56221 * 56222 * function mouseWheel(event) { 56223 * print(event.delta); 56224 * //move the square according to the vertical scroll amount 56225 * pos += event.delta; 56226 * //uncomment to block page scrolling 56227 * //return false;
56228 * } 56229 * </code> 56230 * </div> 56231 * 56232 * @alt 56233 * black 50x50 rect moves up and down with vertical scroll. fuschia background 56234 * 56235 */ 56236p5.prototype._onwheel = function(e) { 56237 var context = this._isGlobal ? window : this; 56238 if (typeof context.mouseWheel === 'function') { 56239 e.delta = e.deltaY; 56240 var executeDefault = context.mouseWheel(e); 56241 if (executeDefault === false) { 56242 e.preventDefault(); 56243 } 56244 } 56245}; 56246 56247module.exports = p5; 56248 56249},{"../core/constants":21,"../core/core":22}],40:[function(_dereq_,module,exports){ 56250/** 56251 * @module Events 56252 * @submodule Touch 56253 * @for p5 56254 * @requires core 56255 */ 56256 56257'use strict'; 56258 56259var p5 = _dereq_('../core/core'); 56260 56261/** 56262 * The system variable touches[] contains an array of the positions of all 56263 * current touch points, relative to (0, 0) of the canvas, and IDs identifying a 56264 * unique touch as it moves. Each element in the array is an object with x, y, 56265 * and id properties. 56266 * 56267 * The touches[] array is not supported on Safari and IE on touch-based 56268 * desktops (laptops). 56269 * 56270 * @property {Object[]} touches 56271 * @readOnly 56272 */ 56273p5.prototype.touches = []; 56274 56275p5.prototype._updateTouchCoords = function(e) { 56276 if (this._curElement !== null) { 56277 var touches = []; 56278 for (var i = 0; i < e.touches.length; i++) { 56279 touches[i] = getTouchInfo( 56280 this._curElement.elt, 56281 this.width, 56282 this.height, 56283 e, 56284 i 56285 ); 56286 } 56287 this._setProperty('touches', touches); 56288 } 56289}; 56290 56291function getTouchInfo(canvas, w, h, e, i) { 56292 i = i || 0; 56293 var rect = canvas.getBoundingClientRect(); 56294 var sx = canvas.scrollWidth / w; 56295 var sy = canvas.scrollHeight / h; 56296 var touch = e.touches[i] || e.changedTouches[i]; 56297 return { 56298 x: (touch.clientX - rect.left) / sx, 56299 y: (touch.clientY - rect.top) / sy, 56300 winX: touch.clientX, 56301 winY: touch.clientY, 56302 id: touch.identifier 56303 }; 56304} 56305 56306/** 56307 * The touchStarted() function is called once after every time a touch is 56308 * registered. If no touchStarted() function is defined, the mousePressed() 56309 * function will be called instead if it is defined.<br><br> 56310 * Browsers may have different default behaviors attached to various touch 56311 * events. To prevent any default behavior for this event, add "return false" 56312 * to the end of the method. 56313 * 56314 * @method touchStarted 56315 * @example 56316 * <div> 56317 * <code> 56318 * // Touch within the image to change 56319 * // the value of the rectangle 56320 * 56321 * var value = 0; 56322 * function draw() { 56323 * fill(value); 56324 * rect(25, 25, 50, 50); 56325 * } 56326 * function touchStarted() { 56327 * if (value === 0) { 56328 * value = 255; 56329 * } else { 56330 * value = 0; 56331 * } 56332 * } 56333 * </code> 56334 * </div> 56335 * 56336 * <div class="norender"> 56337 * <code> 56338 * function touchStarted() { 56339 * ellipse(mouseX, mouseY, 5, 5); 56340 * // prevent default 56341 * return false; 56342 * } 56343 * </code> 56344 * </div> 56345 * 56346 * @alt 56347 * 50x50 black rect turns white with touch event. 56348 * no image displayed 56349 */ 56350p5.prototype._ontouchstart = function(e) { 56351 var context = this._isGlobal ? window : this; 56352 var executeDefault; 56353 this._setProperty('mouseIsPressed', true); 56354 this._updateTouchCoords(e); 56355 this._updateNextMouseCoords(e); 56356 if (typeof context.touchStarted === 'function') { 56357 executeDefault = context.touchStarted(e); 56358 if (executeDefault === false) { 56359 e.preventDefault(); 56360 } 56361 } else if (typeof context.mousePressed === 'function') { 56362 executeDefault = context.mousePressed(e); 56363 if (executeDefault === false) { 56364 e.preventDefault(); 56365 } 56366 } 56367}; 56368 56369/** 56370 * The touchMoved() function is called every time a touch move is registered. 56371 * If no touchMoved() function is defined, the mouseDragged() function will 56372 * be called instead if it is defined.<br><br> 56373 * Browsers may have different default behaviors attached to various touch 56374 * events. To prevent any default behavior for this event, add "return false" 56375 * to the end of the method. 56376 * 56377 * @method touchMoved 56378 * @example 56379 * <div> 56380 * <code> 56381 * // Move your finger across the page 56382 * // to change its value 56383 * 56384 * var value = 0; 56385 * function draw() { 56386 * fill(value); 56387 * rect(25, 25, 50, 50); 56388 * } 56389 * function touchMoved() { 56390 * value = value + 5; 56391 * if (value > 255) { 56392 * value = 0; 56393 * } 56394 * } 56395 * </code> 56396 * </div> 56397 * 56398 * <div class="norender"> 56399 * <code> 56400 * function touchMoved() { 56401 * ellipse(mouseX, mouseY, 5, 5); 56402 * // prevent default 56403 * return false;
56404 * } 56405 * </code> 56406 * </div> 56407 * 56408 * @alt 56409 * 50x50 black rect turns lighter with touch until white. resets 56410 * no image displayed 56411 * 56412 */ 56413p5.prototype._ontouchmove = function(e) { 56414 var context = this._isGlobal ? window : this; 56415 var executeDefault; 56416 this._updateTouchCoords(e); 56417 this._updateNextMouseCoords(e); 56418 if (typeof context.touchMoved === 'function') { 56419 executeDefault = context.touchMoved(e); 56420 if (executeDefault === false) { 56421 e.preventDefault(); 56422 } 56423 } else if (typeof context.mouseDragged === 'function') { 56424 executeDefault = context.mouseDragged(e); 56425 if (executeDefault === false) { 56426 e.preventDefault(); 56427 } 56428 } 56429}; 56430 56431/** 56432 * The touchEnded() function is called every time a touch ends. If no 56433 * touchEnded() function is defined, the mouseReleased() function will be 56434 * called instead if it is defined.<br><br> 56435 * Browsers may have different default behaviors attached to various touch 56436 * events. To prevent any default behavior for this event, add "return false" 56437 * to the end of the method. 56438 * 56439 * @method touchEnded 56440 * @example 56441 * <div> 56442 * <code> 56443 * // Release touch within the image to 56444 * // change the value of the rectangle 56445 * 56446 * var value = 0; 56447 * function draw() { 56448 * fill(value); 56449 * rect(25, 25, 50, 50); 56450 * } 56451 * function touchEnded() { 56452 * if (value === 0) { 56453 * value = 255; 56454 * } else { 56455 * value = 0; 56456 * } 56457 * } 56458 * </code> 56459 * </div> 56460 * 56461 * <div class="norender"> 56462 * <code> 56463 * function touchEnded() { 56464 * ellipse(mouseX, mouseY, 5, 5); 56465 * // prevent default 56466 * return false; 56467 * } 56468 * </code> 56469 * </div> 56470 * 56471 * @alt 56472 * 50x50 black rect turns white with touch. 56473 * no image displayed 56474 * 56475 */ 56476p5.prototype._ontouchend = function(e) { 56477 this._setProperty('mouseIsPressed', false); 56478 this._updateTouchCoords(e); 56479 this._updateNextMouseCoords(e); 56480 var context = this._isGlobal ? window : this; 56481 var executeDefault; 56482 if (typeof context.touchEnded === 'function') { 56483 executeDefault = context.touchEnded(e); 56484 if (executeDefault === false) { 56485 e.preventDefault(); 56486 } 56487 } else if (typeof context.mouseReleased === 'function') { 56488 executeDefault = context.mouseReleased(e); 56489 if (executeDefault === false) { 56490 e.preventDefault(); 56491 } 56492 } 56493}; 56494 56495module.exports = p5; 56496 56497},{"../core/core":22}],41:[function(_dereq_,module,exports){ 56498/*global ImageData:false */ 56499 56500/** 56501 * This module defines the filters for use with image buffers. 56502 * 56503 * This module is basically a collection of functions stored in an object 56504 * as opposed to modules. The functions are destructive, modifying 56505 * the passed in canvas rather than creating a copy. 56506 * 56507 * Generally speaking users of this module will use the Filters.apply method 56508 * on a canvas to create an effect. 56509 * 56510 * A number of functions are borrowed/adapted from 56511 * http://www.html5rocks.com/en/tutorials/canvas/imagefilters/ 56512 * or the java processing implementation. 56513 */ 56514 56515'use strict'; 56516 56517var Filters = {}; 56518 56519/* 56520 * Helper functions 56521 */ 56522 56523/** 56524 * Returns the pixel buffer for a canvas 56525 * 56526 * @private 56527 * 56528 * @param {Canvas|ImageData} canvas the canvas to get pixels from 56529 * @return {Uint8ClampedArray} a one-dimensional array containing 56530 * the data in thc RGBA order, with integer 56531 * values between 0 and 255 56532 */ 56533Filters._toPixels = function(canvas) { 56534 if (canvas instanceof ImageData) { 56535 return canvas.data; 56536 } else { 56537 return canvas 56538 .getContext('2d') 56539 .getImageData(0, 0, canvas.width, canvas.height).data; 56540 } 56541}; 56542 56543/** 56544 * Returns a 32 bit number containing ARGB data at ith pixel in the 56545 * 1D array containing pixels data. 56546 * 56547 * @private 56548 * 56549 * @param {Uint8ClampedArray} data array returned by _toPixels() 56550 * @param {Integer} i index of a 1D Image Array 56551 * @return {Integer} 32 bit integer value representing 56552 * ARGB value. 56553 */ 56554Filters._getARGB = function(data, i) { 56555 var offset = i * 4; 56556 return ( 56557 ((data[offset + 3] << 24) & 0xff000000) | 56558 ((data[offset] << 16) & 0x00ff0000) | 56559 ((data[offset + 1] << 8) & 0x0000ff00) | 56560 (data[offset + 2] & 0x000000ff) 56561 ); 56562}; 56563 56564/** 56565 * Modifies pixels RGBA values to values contained in the data object. 56566 * 56567 * @private 56568 * 56569 * @param {Uint8ClampedArray} pixels array returned by _toPixels() 56570 * @param {Int32Array} data source 1D array where each value 56571 * represents ARGB values 56572 */ 56573Filters._setPixels = function(pixels, data) { 56574 var offset = 0; 56575 for (var i = 0, al = pixels.length; i < al; i++) { 56576 offset = i * 4; 56577 pixels[offset + 0] = (data[i] & 0x00ff0000) >>> 16; 56578 pixels[offset + 1] = (data[i] & 0x0000ff00) >>> 8; 56579 pixels[offset + 2] = data[i] & 0x000000ff; 56580 pixels[offset + 3] = (data[i] & 0xff000000) >>> 24; 56581 } 56582}; 56583 56584/** 56585 * Returns the ImageData object for a canvas 56586 * https://developer.mozilla.org/en-US/docs/Web/API/ImageData 56587 * 56588 * @private 56589 *
56590 * @param {Canvas|ImageData} canvas canvas to get image data from 56591 * @return {ImageData} Holder of pixel data (and width and 56592 * height) for a canvas 56593 */ 56594Filters._toImageData = function(canvas) { 56595 if (canvas instanceof ImageData) { 56596 return canvas; 56597 } else { 56598 return canvas 56599 .getContext('2d') 56600 .getImageData(0, 0, canvas.width, canvas.height); 56601 } 56602}; 56603 56604/** 56605 * Returns a blank ImageData object. 56606 * 56607 * @private 56608 * 56609 * @param {Integer} width 56610 * @param {Integer} height 56611 * @return {ImageData} 56612 */ 56613Filters._createImageData = function(width, height) { 56614 Filters._tmpCanvas = document.createElement('canvas'); 56615 Filters._tmpCtx = Filters._tmpCanvas.getContext('2d'); 56616 return this._tmpCtx.createImageData(width, height); 56617}; 56618 56619/** 56620 * Applys a filter function to a canvas. 56621 * 56622 * The difference between this and the actual filter functions defined below 56623 * is that the filter functions generally modify the pixel buffer but do 56624 * not actually put that data back to the canvas (where it would actually 56625 * update what is visible). By contrast this method does make the changes 56626 * actually visible in the canvas. 56627 * 56628 * The apply method is the method that callers of this module would generally 56629 * use. It has been separated from the actual filters to support an advanced 56630 * use case of creating a filter chain that executes without actually updating 56631 * the canvas in between everystep. 56632 * 56633 * @private 56634 * @param {HTMLCanvasElement} canvas [description] 56635 * @param {function(ImageData,Object)} func [description] 56636 * @param {Object} filterParam [description] 56637 */ 56638Filters.apply = function(canvas, func, filterParam) { 56639 var ctx = canvas.getContext('2d'); 56640 var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); 56641 56642 //Filters can either return a new ImageData object, or just modify 56643 //the one they received. 56644 var newImageData = func(imageData, filterParam); 56645 if (newImageData instanceof ImageData) { 56646 ctx.putImageData(newImageData, 0, 0, 0, 0, canvas.width, canvas.height); 56647 } else { 56648 ctx.putImageData(imageData, 0, 0, 0, 0, canvas.width, canvas.height); 56649 } 56650}; 56651 56652/* 56653 * Filters 56654 */ 56655 56656/** 56657 * Converts the image to black and white pixels depending if they are above or 56658 * below the threshold defined by the level parameter. The parameter must be 56659 * between 0.0 (black) and 1.0 (white). If no level is specified, 0.5 is used. 56660 * 56661 * Borrowed from http://www.html5rocks.com/en/tutorials/canvas/imagefilters/ 56662 * 56663 * @private 56664 * @param {Canvas} canvas 56665 * @param {Float} level 56666 */ 56667Filters.threshold = function(canvas, level) { 56668 var pixels = Filters._toPixels(canvas); 56669 56670 if (level === undefined) { 56671 level = 0.5; 56672 } 56673 var thresh = Math.floor(level * 255); 56674 56675 for (var i = 0; i < pixels.length; i += 4) { 56676 var r = pixels[i]; 56677 var g = pixels[i + 1]; 56678 var b = pixels[i + 2]; 56679 var gray = 0.2126 * r + 0.7152 * g + 0.0722 * b; 56680 var val; 56681 if (gray >= thresh) { 56682 val = 255; 56683 } else { 56684 val = 0; 56685 } 56686 pixels[i] = pixels[i + 1] = pixels[i + 2] = val; 56687 } 56688}; 56689 56690/** 56691 * Converts any colors in the image to grayscale equivalents. 56692 * No parameter is used. 56693 * 56694 * Borrowed from http://www.html5rocks.com/en/tutorials/canvas/imagefilters/ 56695 * 56696 * @private 56697 * @param {Canvas} canvas 56698 */ 56699Filters.gray = function(canvas) { 56700 var pixels = Filters._toPixels(canvas); 56701 56702 for (var i = 0; i < pixels.length; i += 4) { 56703 var r = pixels[i]; 56704 var g = pixels[i + 1]; 56705 var b = pixels[i + 2]; 56706 56707 // CIE luminance for RGB 56708 var gray = 0.2126 * r + 0.7152 * g + 0.0722 * b; 56709 pixels[i] = pixels[i + 1] = pixels[i + 2] = gray; 56710 } 56711}; 56712 56713/** 56714 * Sets the alpha channel to entirely opaque. No parameter is used. 56715 * 56716 * @private 56717 * @param {Canvas} canvas 56718 */ 56719Filters.opaque = function(canvas) { 56720 var pixels = Filters._toPixels(canvas); 56721 56722 for (var i = 0; i < pixels.length; i += 4) { 56723 pixels[i + 3] = 255; 56724 } 56725 56726 return pixels; 56727}; 56728 56729/** 56730 * Sets each pixel to its inverse value. No parameter is used. 56731 * @private 56732 * @param {Canvas} canvas 56733 */ 56734Filters.invert = function(canvas) { 56735 var pixels = Filters._toPixels(canvas); 56736 56737 for (var i = 0; i < pixels.length; i += 4) { 56738 pixels[i] = 255 - pixels[i]; 56739 pixels[i + 1] = 255 - pixels[i + 1]; 56740 pixels[i + 2] = 255 - pixels[i + 2]; 56741 } 56742}; 56743 56744/** 56745 * Limits each channel of the image to the number of colors specified as 56746 * the parameter. The parameter can be set to values between 2 and 255, but 56747 * results are most noticeable in the lower ranges. 56748 * 56749 * Adapted from java based processing implementation 56750 * 56751 * @private
56752 * @param {Canvas} canvas 56753 * @param {Integer} level 56754 */ 56755Filters.posterize = function(canvas, level) { 56756 var pixels = Filters._toPixels(canvas); 56757 56758 if (level < 2 || level > 255) { 56759 throw new Error( 56760 'Level must be greater than 2 and less than 255 for posterize' 56761 ); 56762 } 56763 56764 var levels1 = level - 1; 56765 for (var i = 0; i < pixels.length; i += 4) { 56766 var rlevel = pixels[i]; 56767 var glevel = pixels[i + 1]; 56768 var blevel = pixels[i + 2]; 56769 56770 pixels[i] = ((rlevel * level) >> 8) * 255 / levels1; 56771 pixels[i + 1] = ((glevel * level) >> 8) * 255 / levels1; 56772 pixels[i + 2] = ((blevel * level) >> 8) * 255 / levels1; 56773 } 56774}; 56775 56776/** 56777 * reduces the bright areas in an image 56778 * @private 56779 * @param {Canvas} canvas 56780 * 56781 */ 56782Filters.dilate = function(canvas) { 56783 var pixels = Filters._toPixels(canvas); 56784 var currIdx = 0; 56785 var maxIdx = pixels.length ? pixels.length / 4 : 0; 56786 var out = new Int32Array(maxIdx); 56787 var currRowIdx, maxRowIdx, colOrig, colOut, currLum; 56788 56789 var idxRight, idxLeft, idxUp, idxDown; 56790 var colRight, colLeft, colUp, colDown; 56791 var lumRight, lumLeft, lumUp, lumDown; 56792 56793 while (currIdx < maxIdx) { 56794 currRowIdx = currIdx; 56795 maxRowIdx = currIdx + canvas.width; 56796 while (currIdx < maxRowIdx) { 56797 colOrig = colOut = Filters._getARGB(pixels, currIdx); 56798 idxLeft = currIdx - 1; 56799 idxRight = currIdx + 1; 56800 idxUp = currIdx - canvas.width; 56801 idxDown = currIdx + canvas.width; 56802 56803 if (idxLeft < currRowIdx) { 56804 idxLeft = currIdx; 56805 } 56806 if (idxRight >= maxRowIdx) { 56807 idxRight = currIdx; 56808 } 56809 if (idxUp < 0) { 56810 idxUp = 0; 56811 } 56812 if (idxDown >= maxIdx) { 56813 idxDown = currIdx; 56814 } 56815 colUp = Filters._getARGB(pixels, idxUp); 56816 colLeft = Filters._getARGB(pixels, idxLeft); 56817 colDown = Filters._getARGB(pixels, idxDown); 56818 colRight = Filters._getARGB(pixels, idxRight); 56819 56820 //compute luminance 56821 currLum = 56822 77 * ((colOrig >> 16) & 0xff) + 56823 151 * ((colOrig >> 8) & 0xff) + 56824 28 * (colOrig & 0xff); 56825 lumLeft = 56826 77 * ((colLeft >> 16) & 0xff) + 56827 151 * ((colLeft >> 8) & 0xff) + 56828 28 * (colLeft & 0xff); 56829 lumRight = 56830 77 * ((colRight >>
56830 16) & 0xff) + 56831 151 * ((colRight >> 8) & 0xff) + 56832 28 * (colRight & 0xff); 56833 lumUp = 56834 77 * ((colUp >> 16) & 0xff) + 56835 151 * ((colUp >> 8) & 0xff) + 56836 28 * (colUp & 0xff); 56837 lumDown = 56838 77 * ((colDown >> 16) & 0xff) + 56839 151 * ((colDown >> 8) & 0xff) + 56840 28 * (colDown & 0xff); 56841 56842 if (lumLeft > currLum) { 56843 colOut = colLeft; 56844 currLum = lumLeft; 56845 } 56846 if (lumRight > currLum) { 56847 colOut = colRight; 56848 currLum = lumRight; 56849 } 56850 if (lumUp > currLum) { 56851 colOut = colUp; 56852 currLum = lumUp; 56853 } 56854 if (lumDown > currLum) { 56855 colOut = colDown; 56856 currLum = lumDown; 56857 } 56858 out[currIdx++] = colOut; 56859 } 56860 } 56861 Filters._setPixels(pixels, out); 56862}; 56863 56864/** 56865 * increases the bright areas in an image 56866 * @private 56867 * @param {Canvas} canvas 56868 * 56869 */ 56870Filters.erode = function(canvas) { 56871 var pixels = Filters._toPixels(canvas); 56872 var currIdx = 0; 56873 var maxIdx = pixels.length ? pixels.length / 4 : 0; 56874 var out = new Int32Array(maxIdx); 56875 var currRowIdx, maxRowIdx, colOrig, colOut, currLum; 56876 var idxRight, idxLeft, idxUp, idxDown; 56877 var colRight, colLeft, colUp, colDown; 56878 var lumRight, lumLeft, lumUp, lumDown; 56879 56880 while (currIdx < maxIdx) { 56881 currRowIdx = currIdx; 56882 maxRowIdx = currIdx + canvas.width; 56883 while (currIdx < maxRowIdx) { 56884 colOrig = colOut = Filters._getARGB(pixels, currIdx); 56885 idxLeft = currIdx - 1; 56886 idxRight = currIdx + 1; 56887 idxUp = currIdx - canvas.width; 56888 idxDown = currIdx + canvas.width; 56889 56890 if (idxLeft < currRowIdx) { 56891 idxLeft = currIdx; 56892 } 56893 if (idxRight >= maxRowIdx) { 56894 idxRight = currIdx; 56895 } 56896 if (idxUp < 0) { 56897 idxUp = 0; 56898 } 56899 if (idxDown >= maxIdx) { 56900 idxDown = currIdx; 56901 } 56902 colUp = Filters._getARGB(pixels, idxUp); 56903 colLeft = Filters._getARGB(pixels, idxLeft); 56904 colDown = Filters._getARGB(pixels, idxDown); 56905 colRight = Filters._getARGB(pixels, idxRight); 56906 56907 //compute luminance 56908 currLum = 56909 77 * ((colOrig >> 16) & 0xff) + 56910 151 * ((colOrig >> 8) & 0xff) + 56911 28 * (colOrig & 0xff); 56912 lumLeft = 56913 77 * ((colLeft >> 16) & 0xff) + 56914 151 * ((colLeft >> 8) & 0xff) + 56915 28 * (colLeft & 0xff); 56916 lumRight = 56917 77 * ((colRight >>
56917 16) & 0xff) + 56918 151 * ((colRight >> 8) & 0xff) + 56919 28 * (colRight & 0xff); 56920 lumUp = 56921 77 * ((colUp >> 16) & 0xff) + 56922 151 * ((colUp >> 8) & 0xff) + 56923 28 * (colUp & 0xff); 56924 lumDown = 56925 77 * ((colDown >> 16) & 0xff) + 56926 151 * ((colDown >> 8) & 0xff) + 56927 28 * (colDown & 0xff); 56928 56929 if (lumLeft < currLum) { 56930 colOut = colLeft; 56931 currLum = lumLeft; 56932 } 56933 if (lumRight < currLum) { 56934 colOut = colRight; 56935 currLum = lumRight; 56936 } 56937 if (lumUp < currLum) { 56938 colOut = colUp; 56939 currLum = lumUp; 56940 } 56941 if (lumDown < currLum) { 56942 colOut = colDown; 56943 currLum = lumDown; 56944 } 56945 56946 out[currIdx++] = colOut; 56947 } 56948 } 56949 Filters._setPixels(pixels, out); 56950}; 56951 56952// BLUR 56953 56954// internal kernel stuff for the gaussian blur filter 56955var blurRadius; 56956var blurKernelSize; 56957var blurKernel; 56958var blurMult; 56959 56960/* 56961 * Port of https://github.com/processing/processing/blob/ 56962 * master/core/src/processing/core/PImage.java#L1250 56963 * 56964 * Optimized code for building the blur kernel. 56965 * further optimized blur code (approx. 15% for radius=20) 56966 * bigger speed gains for larger radii (~30%) 56967 * added support for various image types (ALPHA, RGB, ARGB) 56968 * [toxi 050728] 56969 */ 56970function buildBlurKernel(r) { 56971 var radius = (r * 3.5) | 0; 56972 radius = radius < 1 ? 1 : radius < 248 ? radius : 248; 56973 56974 if (blurRadius !== radius) { 56975 blurRadius = radius; 56976 blurKernelSize = (1 + blurRadius) << 1; 56977 blurKernel = new Int32Array(blurKernelSize); 56978 blurMult = new Array(blurKernelSize); 56979 for (var l = 0; l < blurKernelSize; l++) { 56980 blurMult[l] = new Int32Array(256); 56981 } 56982 56983 var bk, bki; 56984 var bm, bmi; 56985
56986 for (var i = 1, radiusi = radius - 1; i < radius; i++) { 56987 blurKernel[radius + i] = blurKernel[radiusi] = bki = radiusi * radiusi; 56988 bm = blurMult[radius + i]; 56989 bmi = blurMult[radiusi--]; 56990 for (var j = 0; j < 256; j++) { 56991 bm[j] = bmi[j] = bki * j; 56992 } 56993 } 56994 bk = blurKernel[radius] = radius * radius; 56995 bm = blurMult[radius]; 56996 56997 for (var k = 0; k < 256; k++) { 56998 bm[k] = bk * k; 56999 } 57000 } 57001} 57002 57003// Port of https://github.com/processing/processing/blob/ 57004// master/core/src/processing/core/PImage.java#L1433 57005function blurARGB(canvas, radius) { 57006 var pixels = Filters._toPixels(canvas); 57007 var width = canvas.width; 57008 var height = canvas.height; 57009 var numPackedPixels = width * height; 57010 var argb = new Int32Array(numPackedPixels); 57011 for (var j = 0; j < numPackedPixels; j++) { 57012 argb[j] = Filters._getARGB(pixels, j); 57013 } 57014 var sum, cr, cg, cb, ca; 57015 var read, ri, ym, ymi, bk0; 57016 var a2 = new Int32Array(numPackedPixels); 57017 var r2 = new Int32Array(numPackedPixels); 57018 var g2 = new Int32Array(numPackedPixels); 57019 var b2 = new Int32Array(numPackedPixels); 57020 var yi = 0; 57021 buildBlurKernel(radius); 57022 var x, y, i; 57023 var bm; 57024 for (y = 0; y < height; y++) { 57025 for (x = 0; x < width; x++) { 57026 cb = cg = cr = ca = sum = 0; 57027 read = x - blurRadius; 57028 if (read < 0) { 57029 bk0 = -read; 57030 read = 0; 57031 } else { 57032 if (read >= width) { 57033 break; 57034 } 57035 bk0 = 0; 57036 } 57037 for (i = bk0; i < blurKernelSize; i++) { 57038 if (read >= width) { 57039 break; 57040 } 57041 var c = argb[read + yi]; 57042 bm = blurMult[i]; 57043 ca += bm[(c & -16777216) >>> 24]; 57044 cr += bm[(c & 16711680) >> 16]; 57045 cg += bm[(c & 65280) >> 8]; 57046 cb += bm[c & 255]; 57047 sum += blurKernel[i]; 57048 read++; 57049 } 57050 ri = yi + x; 57051 a2[ri] = ca / sum; 57052 r2[ri] = cr / sum; 57053 g2[ri] = cg / sum; 57054 b2[ri] = cb / sum; 57055 } 57056 yi += width; 57057 } 57058 yi = 0; 57059 ym = -blurRadius; 57060 ymi = ym * width; 57061 for (y = 0; y < height; y++) { 57062 for (x = 0; x < width; x++) { 57063 cb = cg = cr = ca = sum = 0; 57064 if (ym < 0) { 57065 bk0 = ri = -ym; 57066 read = x; 57067 } else { 57068 if (ym >= height) { 57069 break; 57070 } 57071 bk0 = 0; 57072 ri = ym; 57073 read = x + ymi; 57074 } 57075 for (i = bk0; i < blurKernelSize; i++) { 57076 if (ri >= height) { 57077 break; 57078 } 57079 bm = blurMult[i]; 57080 ca += bm[a2[read]]; 57081 cr += bm[r2[read]]; 57082 cg += bm[g2[read]]; 57083 cb += bm[b2[read]]; 57084 sum += blurKernel[i]; 57085 ri++; 57086 read += width; 57087 } 57088 argb[x + yi] = 57089 ((ca / sum) << 24) | 57090 ((cr / sum) << 16) | 57091 ((cg / sum) << 8) | 57092 (cb / sum); 57093 } 57094 yi += width; 57095 ymi += width; 57096 ym++; 57097 } 57098 Filters._setPixels(pixels, argb); 57099} 57100 57101Filters.blur = function(canvas, radius) { 57102 blurARGB(canvas, radius); 57103}; 57104 57105module.exports = Filters; 57106 57107},{}],42:[function(_dereq_,module,exports){ 57108/** 57109 * @module Image 57110 * @submodule Image 57111 * @for p5 57112 * @requires core 57113 */ 57114 57115/** 57116 * This module defines the p5 methods for the p5.Image class 57117 * for drawing images to the main display canvas. 57118 */ 57119'use strict'; 57120 57121var p5 = _dereq_('../core/core'); // This is not global, but JSHint is not aware that // this module is implicitly enclosed with Browserify: this overrides the // redefined-global error and permits using the name "frames" for the array // of saved animation frames. 57122 57123/* global frames:true */ var frames = []; 57124 57125/** 57126 * Creates a new p5.Image (the datatype for storing images). This provides a 57127 * fresh buffer of pixels to play with. Set the size of the buffer with the 57128 * width and height parameters. 57129 * <br><br> 57130 * .pixels gives access to an array containing the values for all the pixels 57131 * in the display window. 57132 * These values are numbers. This array is the size (including an appropriate 57133 * factor for the pixelDensity) of the display window x4, 57134 * representing the R, G, B, A values in order for each pixel, moving from 57135 * left to right across each row, then down each column. See .pixels for
57136 * more info. It may also be simpler to use set() or get(). 57137 * <br><br> 57138 * Before accessing the pixels of an image, the data must loaded with the 57139 * loadPixels() function. After the array data has been modified, the 57140 * updatePixels() function must be run to update the changes. 57141 * 57142 * @method createImage 57143 * @param {Integer} width width in pixels 57144 * @param {Integer} height height in pixels 57145 * @return {p5.Image} the p5.Image object 57146 * @example 57147 * <div> 57148 * <code> 57149 * var img = createImage(66, 66); 57150 * img.loadPixels(); 57151 * for (var i = 0; i < img.width; i++) { 57152 * for (var j = 0; j < img.height; j++) { 57153 * img.set(i, j, color(0, 90, 102)); 57154 * } 57155 * } 57156 * img.updatePixels(); 57157 * image(img, 17, 17); 57158 * </code> 57159 * </div> 57160 * 57161 * <div> 57162 * <code> 57163 * var img = createImage(66, 66); 57164 * img.loadPixels(); 57165 * for (var i = 0; i < img.width; i++) { 57166 * for (var j = 0; j < img.height; j++) { 57167 * img.set(i, j, color(0, 90, 102, (i % img.width) * 2)); 57168 * } 57169 * } 57170 * img.updatePixels(); 57171 * image(img, 17, 17); 57172 * image(img, 34, 34); 57173 * </code> 57174 * </div> 57175 * 57176 * <div> 57177 * <code> 57178 * var pink = color(255, 102, 204); 57179 * var img = createImage(66, 66); 57180 * img.loadPixels(); 57181 * var d = pixelDensity(); 57182 * var halfImage = 4 * (width * d) * (height / 2 * d); 57183 * for (var i = 0; i < halfImage; i += 4) { 57184 * img.pixels[i] = red(pink); 57185 * img.pixels[i + 1] = green(pink); 57186 * img.pixels[i + 2] = blue(pink); 57187 * img.pixels[i + 3] = alpha(pink); 57188 * } 57189 * img.updatePixels(); 57190 * image(img, 17, 17); 57191 * </code> 57192 * </div> 57193 * 57194 * @alt 57195 * 66x66 dark turquoise rect in center of canvas. 57196 * 2 gradated dark turquoise rects fade left. 1 center 1 bottom right of canvas 57197 * no image displayed 57198 * 57199 */ 57200p5.prototype.createImage = function(width, height) { 57201 p5._validateParameters('createImage', arguments); 57202 return new p5.Image(width, height); 57203}; 57204 57205/** 57206 * Save the current canvas as an image. In Safari, this will open the 57207 * image in the window and the user must provide their own 57208 * filename on save-as. Other browsers will either save the 57209 * file immediately, or prompt the user with a dialogue window. 57210 * 57211 * @method saveCanvas 57212 * @param {p5.Element|HTMLCanvasElement} selectedCanvas a variable 57213 * representing a specific html5 canvas (optional) 57214 * @param {String} [filename] 57215 * @param {String} [extension] 'jpg' or 'png' 57216 * 57217 * @example 57218 * <div class='norender notest'><code> 57219 * function setup() { 57220 * var c = createCanvas(100, 100); 57221 * background(255, 0, 0); 57222 * saveCanvas(c, 'myCanvas', 'jpg'); 57223 * } 57224 * </code></div> 57225 * <div class='norender notest'><code> 57226 * // note that this example has the same result as above 57227 * // if no canvas is specified, defaults to main canvas 57228 * function setup() { 57229 * var c = createCanvas(100, 100); 57230 * background(255, 0, 0); 57231 * saveCanvas('myCanvas', 'jpg'); 57232 * 57233 * // all of the following are valid 57234 * saveCanvas(c, 'myCanvas', 'jpg'); 57235 * saveCanvas(c, 'myCanvas.jpg'); 57236 * saveCanvas(c, 'myCanvas'); 57237 * saveCanvas(c); 57238 * saveCanvas('myCanvas', 'png'); 57239 * saveCanvas('myCanvas'); 57240 * saveCanvas(); 57241 * } 57242 * </code></div> 57243 * 57244 * @alt 57245 * no image displayed 57246 * no image displayed 57247 * no image displayed 57248 */ 57249/** 57250 * @method saveCanvas 57251 * @param {String} [filename] 57252 * @param {String} [extension] 57253 */ 57254p5.prototype.saveCanvas = function() { 57255 p5._validateParameters('saveCanvas', arguments); 57256 57257 // copy arguments to array 57258 var args = [].slice.call(arguments); 57259 var htmlCanvas, filename, extension; 57260 57261 if (arguments[0] instanceof HTMLCanvasElement) { 57262 htmlCanvas = arguments[0]; 57263 args.shift(); 57264 } else if (arguments[0] instanceof p5.Element) { 57265 htmlCanvas = arguments[0].elt; 57266 args.shift(); 57267 } else { 57268 htmlCanvas = this._curElement && this._curElement.elt; 57269 } 57270 57271 if (args.length >= 1) { 57272 filename = args[0]; 57273 } 57274 if (args.length >= 2) { 57275 extension = args[1]; 57276 } 57277 57278 extension = 57279 extension || 57280 p5.prototype._checkFileExtension(filename, extension)[1] || 57281 'png'; 57282 57283 var mimeType; 57284 switch (extension) { 57285 default: 57286 //case 'png': 57287 mimeType = 'image/png'; 57288 break; 57289 case 'jpeg': 57290 case 'jpg': 57291 mimeType = 'image/jpeg'; 57292 break; 57293 } 57294 57295 htmlCanvas.toBlob(function(blob) { 57296 p5.prototype.downloadFile(blob, filename, extension); 57297 }, mimeType); 57298}; 57299 57300/** 57301 * Capture a sequence of frames that can be used to create a movie.
57302 * Accepts a callback. For example, you may wish to send the frames 57303 * to a server where they can be stored or converted into a movie. 57304 * If no callback is provided, the browser will pop up save dialogues in an 57305 * attempt to download all of the images that have just been created. With the 57306 * callback provided the image data isn't saved by default but instead passed 57307 * as an argument to the callback function as an array of objects, with the 57308 * size of array equal to the total number of frames. 57309 * 57310 * Note that saveFrames() will only save the first 15 frames of an animation. 57311 * To export longer animations, you might look into a library like 57312 * <a href="https://github.com/spite/ccapture.js/">ccapture.js</a>. 57313 * 57314 * @method saveFrames 57315 * @param {String} filename 57316 * @param {String} extension 'jpg' or 'png' 57317 * @param {Number} duration Duration in seconds to save the frames for. 57318 * @param {Number} framerate Framerate to save the frames in. 57319 * @param {function(Array)} [callback] A callback function that will be executed 57320 to handle the image data. This function 57321 should accept an array as argument. The 57322 array will contain the specified number of 57323 frames of objects. Each object has three 57324 properties: imageData - an 57325 image/octet-stream, filename and extension. 57326 * @example 57327 * <div><code> 57328 * function draw() { 57329 * background(mouseX); 57330 * } 57331 * 57332 * function mousePressed() { 57333 * saveFrames('out', 'png', 1, 25, function(data) { 57334 * print(data); 57335 * }); 57336 * } 57337</code></div> 57338 * 57339 * @alt 57340 * canvas background goes from light to dark with mouse x. 57341 * 57342 */ 57343p5.prototype.saveFrames = function(fName, ext, _duration, _fps, callback) { 57344 p5._validateParameters('saveFrames', arguments); 57345 var duration = _duration || 3; 57346 duration = p5.prototype.constrain(duration, 0, 15); 57347 duration = duration * 1000; 57348 var fps = _fps || 15; 57349 fps = p5.prototype.constrain(fps, 0, 22); 57350 var count = 0; 57351 57352 var makeFrame = p5.prototype._makeFrame; 57353 var cnv = this._curElement.elt; 57354 var frameFactory = setInterval(function() { 57355 makeFrame(fName + count, ext, cnv); 57356 count++; 57357 }, 1000 / fps); 57358 57359 setTimeout(function() { 57360 clearInterval(frameFactory); 57361 if (callback) { 57362 callback(frames); 57363 } else { 57364 for (var i = 0; i < frames.length; i++) { 57365 var f = frames[i]; 57366 p5.prototype.downloadFile(f.imageData, f.filename, f.ext); 57367 } 57368 } 57369 frames = []; // clear frames 57370 }, duration + 0.01); 57371}; 57372 57373p5.prototype._makeFrame = function(filename, extension, _cnv) { 57374 var cnv; 57375 if (this) { 57376 cnv = this._curElement.elt; 57377 } else { 57378 cnv = _cnv; 57379 } 57380 var mimeType; 57381 if (!extension) { 57382 extension = 'png'; 57383 mimeType = 'image/png'; 57384 } else { 57385 switch (extension.toLowerCase()) { 57386 case 'png': 57387 mimeType = 'image/png'; 57388 break; 57389 case 'jpeg': 57390 mimeType = 'image/jpeg'; 57391 break; 57392 case 'jpg': 57393 mimeType = 'image/jpeg'; 57394 break; 57395 default: 57396 mimeType = 'image/png'; 57397 break; 57398 } 57399 } 57400 var downloadMime = 'image/octet-stream'; 57401 var imageData = cnv.toDataURL(mimeType); 57402 imageData = imageData.replace(mimeType, downloadMime); 57403 57404 var thisFrame = {}; 57405 thisFrame.imageData = imageData; 57406 thisFrame.filename = filename; 57407 thisFrame.ext = extension; 57408 frames.push(thisFrame); 57409}; 57410 57411module.exports = p5; 57412 57413},{"../core/core":22}],43:[function(_dereq_,module,exports){ 57414/** 57415 * @module Image 57416 * @submodule Loading & Displaying 57417 * @for p5 57418 * @requires core 57419 */ 57420 57421'use strict'; 57422 57423var p5 = _dereq_('../core/core'); 57424var Filters = _dereq_('./filters'); 57425var canvas = _dereq_('../core/canvas'); 57426var constants = _dereq_('../core/constants'); 57427 57428_dereq_('../core/error_helpers'); 57429 57430/** 57431 * Loads an image from a path and creates a p5.Image from it. 57432 * <br><br> 57433 * The image may not be immediately available for rendering 57434 * If you want to ensure that the image is ready before doing 57435 * anything with it, place the loadImage() call in preload(). 57436 * You may also supply a callback function to handle the image when it's ready. 57437 * <br><br> 57438 * The path to the image should be relative to the HTML file 57439 * that links in your sketch. Loading an image from a URL or other 57440 * remote location may be blocked due to your browser's built-in 57441 * security. 57442 * 57443 * @method loadImage 57444 * @param {String} path Path of the image to be loaded 57445 * @param {function(p5.Image)} [successCallback] Function to be called once 57446 * the image is loaded. Will be passed the 57447 * p5.Image. 57448 * @param {function(Event)} [failureCallback] called with event error if 57449 * the image fails to load. 57450 * @return {p5.Image} the p5.Image object 57451 * @example 57452 * <div> 57453 * <code> 57454 * var img; 57455 * function preload() { 57456 * img = loadImage('assets/laDefense.jpg'); 57457 * } 57458 * function setup() { 57459 * image(img, 0, 0); 57460 * } 57461 * </code> 57462 * </div> 57463 * <div> 57464 * <code> 57465 * function setup() { 57466 * // here we use a callback to display the image after loading 57467 * loadImage('assets/laDefense.jpg', function(img) { 57468 * image(img, 0, 0); 57469 * }); 57470 * } 57471 * </code> 57472 * </div> 57473 * 57474 * @alt 57475 * image of the underside of a white umbrella and grided ceililng above 57476 * image of the underside of a white umbrella and grided ceililng above 57477 * 57478 */ 57479p5.prototype.loadImage = function(path, successCallback, failureCallback) { 57480 p5._validateParameters('loadImage', arguments); 57481 var img = new Image(); 57482 var pImg = new p5.Image(1, 1, this); 57483 57484 var self = this; 57485 img.onload = function() { 57486 pImg.width = pImg.canvas.width = img.width;
57487 pImg.height = pImg.canvas.height = img.height; 57488 57489 // Draw the image into the backing canvas of the p5.Image 57490 pImg.drawingContext.drawImage(img, 0, 0); 57491 pImg.modified = true; 57492 57493 if (typeof successCallback === 'function') { 57494 successCallback(pImg); 57495 } 57496 57497 self._decrementPreload(); 57498 }; 57499 img.onerror = function(e) { 57500 p5._friendlyFileLoadError(0, img.src); 57501 if (typeof failureCallback === 'function') { 57502 failureCallback(e); 57503 } 57504 }; 57505 57506 //set crossOrigin in case image is served which CORS headers 57507 //this will let us draw to canvas without tainting it. 57508 //see https://developer.mozilla.org/en-US/docs/HTML/CORS_Enabled_Image 57509 // When using data-uris the file will be loaded locally 57510 // so we don't need to worry about crossOrigin with base64 file types 57511 if (path.indexOf('data:image/') !== 0) { 57512 img.crossOrigin = 'Anonymous'; 57513 } 57514 57515 //start loading the image 57516 img.src = path; 57517 57518 return pImg; 57519}; 57520 57521/** 57522 * Validates clipping params. Per drawImage spec sWidth and sHight cannot be 57523 * negative or greater than image intrinsic width and height 57524 * @private 57525 * @param {Number} sVal 57526 * @param {Number} iVal 57527 * @returns {Number} 57528 * @private 57529 */ 57530function _sAssign(sVal, iVal) { 57531 if (sVal > 0 && sVal < iVal) { 57532 return sVal; 57533 } else { 57534 return iVal; 57535 } 57536} 57537 57538/** 57539 * Draw an image to the p5.js canvas. 57540 * 57541 * This function can be used with different numbers of parameters. The 57542 * simplest use requires only three parameters: img, x, and yâwhere (x, y) is 57543 * the position of the image. Two more parameters can optionally be added to 57544 * specify the width and height of the image. 57545 * 57546 * This function can also be used with all eight Number parameters. To 57547 * differentiate between all these parameters, p5.js uses the language of 57548 * "destination rectangle" (which corresponds to "dx", "dy", etc.) and "source 57549 * image" (which corresponds to "sx", "sy", etc.) below. Specifying the 57550 * "source image" dimensions can be useful when you want to display a 57551 * subsection of the source image instead of the whole thing. Here's a diagram 57552 * to explain further: 57553 * <img src="assets/drawImage.png"></img> 57554 * 57555 * @method image 57556 * @param {p5.Image|p5.Element} img the image to display 57557 * @param {Number} x the x-coordinate of the top-left corner of the image 57558 * @param {Number} y the y-coordinate of the top-left corner of the image 57559 * @param {Number} [width] the width to draw the image 57560 * @param {Number} [height] the height to draw the image 57561 * @example 57562 * <div> 57563 * <code> 57564 * var img; 57565 * function preload() { 57566 * img = loadImage('assets/laDefense.jpg'); 57567 * } 57568 * function setup() { 57569 * // Top-left corner of the img is at (0, 0) 57570 * // Width and height are the img's original width and height 57571 * image(img, 0, 0); 57572 * } 57573 * </code> 57574 * </div> 57575 * <div> 57576 * <code> 57577 * var img; 57578 * function preload() { 57579 * img = loadImage('assets/laDefense.jpg'); 57580 * } 57581 * function setup() { 57582 * background(50); 57583 * // Top-left corner of the img is at (10, 10) 57584 * // Width and height are 50 x 50 57585 * image(img, 10, 10, 50, 50); 57586 * } 57587 * </code> 57588 * </div> 57589 * <div> 57590 * <code> 57591 * function setup() { 57592 * // Here, we use a callback to display the image after loading 57593 * loadImage('assets/laDefense.jpg', function(img) { 57594 * image(img, 0, 0); 57595 * }); 57596 * } 57597 * </code> 57598 * </div> 57599 * <div> 57600 * <code> 57601 * var img; 57602 * function preload() { 57603 * img = loadImage('assets/gradient.png'); 57604 * } 57605 * function setup() { 57606 * // 1. Background image 57607 * // Top-left corner of the img is at (0, 0) 57608 * // Width and height are the img's original width and height, 100 x 100 57609 * image(img, 0, 0); 57610 * // 2. Top right image 57611 * // Top-left corner of destination rectangle is at (50, 0) 57612 * // Destination rectangle width and height are 40 x 20 57613 * // The next parameters are relative to the source image: 57614 * // - Starting at position (50, 50) on the source image, capture a 50 x 50 57615 * // subsection 57616 * // - Draw this subsection to fill the dimensions of the destination rectangle 57617 * image(img, 50, 0, 40, 20, 50, 50, 50, 50); 57618 * } 57619 * </code> 57620 * </div> 57621 * @alt 57622 * image of the underside of a white umbrella and gridded ceiling above 57623 * image of the underside of a white umbrella and gridded ceiling above 57624 * 57625 */ 57626/** 57627 * @method image 57628 * @param {p5.Image|p5.Element} img 57629 * @param {Number} dx the x-coordinate of the destination 57630 * rectangle in which to draw the source image 57631 * @param {Number} dy the y-coordinate of the destination 57632 * rectangle in which to draw the source image 57633 * @param {Number} dWidth the width of the destination rectangle 57634 * @param {Number} dHeight the height of the destination rectangle 57635 * @param {Number} sx the x-coordinate of the subsection of the source 57636 * image to draw into the destination rectangle 57637 * @param {Number} sy the y-coordinate of the subsection of the source 57638 * image to draw into the destination rectangle 57639 * @param {Number} [sWidth] the width of the subsection of the 57640 * source image to draw into the destination 57641 * rectangle 57642 * @param {Number} [sHeight] the height of the subsection of the 57643 * source image to draw into the destination rectangle 57644 */ 57645p5.prototype.image = function( 57646 img, 57647 dx, 57648 dy, 57649 dWidth, 57650 dHeight, 57651 sx, 57652 sy, 57653 sWidth, 57654 sHeight 57655) { 57656 // set defaults per spec: https://goo.gl/3ykfOq 57657 57658 p5._validateParameters('image', arguments); 57659 57660 var defW = img.width;
57661 var defH = img.height; 57662 57663 if (img.elt && img.elt.videoWidth && !img.canvas) { 57664 // video no canvas 57665 defW = img.elt.videoWidth; 57666 defH = img.elt.videoHeight; 57667 } 57668 57669 var _dx = dx; 57670 var _dy = dy; 57671 var _dw = dWidth || defW; 57672 var _dh = dHeight || defH; 57673 var _sx = sx || 0; 57674 var _sy = sy || 0; 57675 var _sw = sWidth || defW; 57676 var _sh = sHeight || defH; 57677 57678 _sw = _sAssign(_sw, defW); 57679 _sh = _sAssign(_sh, defH); 57680 57681 // This part needs cleanup and unit tests 57682 // see issues https://github.com/processing/p5.js/issues/1741 57683 // and https://github.com/processing/p5.js/issues/1673 57684 var pd = 1; 57685 57686 if (img.elt && !img.canvas && img.elt.style.width) { 57687 //if img is video and img.elt.size() has been used and 57688 //no width passed to image() 57689 if (img.elt.videoWidth && !dWidth) { 57690 pd = img.elt.videoWidth; 57691 } else { 57692 //all other cases 57693 pd = img.elt.width; 57694 } 57695 pd /= parseInt(img.elt.style.width, 10); 57696 } 57697 57698 _sx *= pd; 57699 _sy *= pd; 57700 _sh *= pd; 57701 _sw *= pd; 57702 57703 var vals = canvas.modeAdjust(_dx, _dy, _dw, _dh, this._renderer._imageMode); 57704 57705 // tint the image if there is a tint 57706 this._renderer.image(img, _sx, _sy, _sw, _sh, vals.x, vals.y, vals.w, vals.h); 57707}; 57708 57709/** 57710 * Sets the fill value for displaying images. Images can be tinted to 57711 * specified colors or made transparent by including an alpha value. 57712 * <br><br> 57713 * To apply transparency to an image without affecting its color, use 57714 * white as the tint color and specify an alpha value. For instance, 57715 * tint(255, 128) will make an image 50% transparent (assuming the default 57716 * alpha range of 0-255, which can be changed with colorMode()). 57717 * <br><br> 57718 * The value for the gray parameter must be less than or equal to the current 57719 * maximum value as specified by colorMode(). The default maximum value is 57720 * 255. 57721 * 57722 * 57723 * @method tint 57724 * @param {Number} v1 red or hue value relative to 57725 * the current color range 57726 * @param {Number} v2 green or saturation value 57727 * relative to the current color range 57728 * @param {Number} v3 blue or brightness value 57729 * relative to the current color range 57730 * @param {Number} [alpha] 57731 * 57732 * @example 57733 * <div> 57734 * <code> 57735 * var img; 57736 * function preload() { 57737 * img = loadImage('assets/laDefense.jpg'); 57738 * } 57739 * function setup() { 57740 * image(img, 0, 0); 57741 * tint(0, 153, 204); // Tint blue 57742 * image(img, 50, 0); 57743 * } 57744 * </code> 57745 * </div> 57746 * 57747 * <div> 57748 * <code> 57749 * var img; 57750 * function preload() { 57751 * img = loadImage('assets/laDefense.jpg'); 57752 * } 57753 * function setup() { 57754 * image(img, 0, 0); 57755 * tint(0, 153, 204, 126); // Tint blue and set transparency 57756 * image(img, 50, 0); 57757 * } 57758 * </code> 57759 * </div> 57760 * 57761 * <div> 57762 * <code> 57763 * var img; 57764 * function preload() { 57765 * img = loadImage('assets/laDefense.jpg'); 57766 * } 57767 * function setup() { 57768 * image(img, 0, 0); 57769 * tint(255, 126); // Apply transparency without changing color 57770 * image(img, 50, 0); 57771 * } 57772 * </code> 57773 * </div> 57774 * 57775 * @alt 57776 * 2 side by side images of umbrella and ceiling, one image with blue tint 57777 * Images of umbrella and ceiling, one half of image with blue tint 57778 * 2 side by side images of umbrella and ceiling, one image translucent 57779 * 57780 */ 57781 57782/** 57783 * @method tint 57784 * @param {String} value a color string 57785 */ 57786 57787/** 57788 * @method tint 57789 * @param {Number} gray a gray value 57790 * @param {Number} [alpha] 57791 */ 57792 57793/** 57794 * @method tint 57795 * @param {Number[]} values an array containing the red,green,blue & 57796 * and alpha components of the color 57797 */ 57798 57799/** 57800 * @method tint 57801 * @param {p5.Color} color the tint color 57802 */ 57803p5.prototype.tint = function() { 57804 p5._validateParameters('tint', arguments); 57805 var c = this.color.apply(this, arguments); 57806 this._renderer._tint = c.levels; 57807}; 57808 57809/** 57810 * Removes the current fill value for displaying images and reverts to 57811 * displaying images with their original hues. 57812 * 57813 * @method noTint 57814 * @example 57815 * <div> 57816 * <code> 57817 * var img; 57818 * function preload() { 57819 * img = loadImage('assets/bricks.jpg'); 57820 * } 57821 * function setup() { 57822 * tint(0, 153, 204); // Tint blue 57823 * image(img, 0, 0); 57824 * noTint(); // Disable tint 57825 * image(img, 50, 0); 57826 * } 57827 * </code> 57828 * </div> 57829 * 57830 * @alt 57831 * 2 side by side images of bricks, left image with blue tint 57832 * 57833 */ 57834p5.prototype.noTint = function() { 57835 this._renderer._tint = null; 57836}; 57837 57838/** 57839 * Apply the current tint color to the input image, return the resulting 57840 * canvas. 57841 * 57842 * @private 57843 * @param {p5.Image} The image to be tinted 57844 * @return {canvas} The resulting tinted canvas 57845 * 57846 */ 57847p5.prototype._getTintedImageCanvas = function(img) { 57848 if (!img.canvas) { 57849 return img; 57850 } 57851 var pixels = Filters._toPixels(img.canvas); 57852 var tmpCanvas = document.createElement('canvas'); 57853 tmpCanvas.width = img.canvas.width; 57854 tmpCanvas.height = img.canvas.height; 57855 var tmpCtx = tmpCanvas.getContext('2d'); 57856 var id = tmpCtx.createImageData(img.canvas.width, img.canvas.height); 57857 var newPixels = id.data; 57858 57859 for (var i = 0; i < pixels.length; i += 4) { 57860 var r = pixels[i]; 57861 var g = pixels[i + 1]; 57862 var b = pixels[i + 2]; 57863 var a = pixels[i + 3]; 57864
57865 newPixels[i] = r * this._renderer._tint[0] / 255; 57866 newPixels[i + 1] = g * this._renderer._tint[1] / 255; 57867 newPixels[i + 2] = b * this._renderer._tint[2] / 255; 57868 newPixels[i + 3] = a * this._renderer._tint[3] / 255; 57869 } 57870 57871 tmpCtx.putImageData(id, 0, 0); 57872 return tmpCanvas; 57873}; 57874 57875/** 57876 * Set image mode. Modifies the location from which images are drawn by 57877 * changing the way in which parameters given to image() are interpreted. 57878 * The default mode is imageMode(CORNER), which interprets the second and 57879 * third parameters of image() as the upper-left corner of the image. If 57880 * two additional parameters are specified, they are used to set the image's 57881 * width and height. 57882 * <br><br> 57883 * imageMode(CORNERS) interprets the second and third parameters of image() 57884 * as the location of one corner, and the fourth and fifth parameters as the 57885 * opposite corner. 57886 * <br><br> 57887 * imageMode(CENTER) interprets the second and third parameters of image() 57888 * as the image's center point. If two additional parameters are specified, 57889 * they are used to set the image's width and height. 57890 * 57891 * @method imageMode 57892 * @param {Constant} mode either CORNER, CORNERS, or CENTER 57893 * @example 57894 * 57895 * <div> 57896 * <code> 57897 * var img; 57898 * function preload() { 57899 * img = loadImage('assets/bricks.jpg'); 57900 * } 57901 * function setup() { 57902 * imageMode(CORNER); 57903 * image(img, 10, 10, 50, 50); 57904 * } 57905 * </code> 57906 * </div> 57907 * 57908 * <div> 57909 * <code> 57910 * var img; 57911 * function preload() { 57912 * img = loadImage('assets/bricks.jpg'); 57913 * } 57914 * function setup() { 57915 * imageMode(CORNERS); 57916 * image(img, 10, 10, 90, 40); 57917 * } 57918 * </code> 57919 * </div> 57920 * 57921 * <div> 57922 * <code> 57923 * var img; 57924 * function preload() { 57925 * img = loadImage('assets/bricks.jpg'); 57926 * } 57927 * function setup() { 57928 * imageMode(CENTER); 57929 * image(img, 50, 50, 80, 80); 57930 * } 57931 * </code> 57932 * </div> 57933 * 57934 * @alt 57935 * small square image of bricks 57936 * horizontal rectangle image of bricks 57937 * large square image of bricks 57938 * 57939 */ 57940p5.prototype.imageMode = function(m) { 57941 p5._validateParameters('imageMode', arguments); 57942 if ( 57943 m === constants.CORNER || 57944 m === constants.CORNERS || 57945 m === constants.CENTER 57946 ) { 57947 this._renderer._imageMode = m; 57948 } 57949}; 57950 57951module.exports = p5; 57952 57953},{"../core/canvas":20,"../core/constants":21,"../core/core":22,"../core/error_helpers":25,"./filters":41}],44:[function(_dereq_,module,exports){ 57954/** 57955 * @module Image 57956 * @submodule Image 57957 * @requires core 57958 * @requires constants 57959 * @requires filters 57960 */ 57961 57962/** 57963 * This module defines the p5.Image class and P5 methods for 57964 * drawing images to the main display canvas. 57965 */ 57966 57967'use strict'; 57968 57969var p5 = _dereq_('../core/core'); 57970var Filters = _dereq_('./filters'); 57971 57972/* 57973 * Class methods 57974 */ 57975 57976/** 57977 * Creates a new p5.Image. A p5.Image is a canvas backed representation of an 57978 * image. 57979 * <br><br> 57980 * p5 can display .gif, .jpg and .png images. Images may be displayed 57981 * in 2D and 3D space. Before an image is used, it must be loaded with the 57982 * loadImage() function. The p5.Image class contains fields for the width and 57983 * height of the image, as well as an array called pixels[] that contains the 57984 * values for every pixel in the image. 57985 * <br><br> 57986 * The methods described below allow easy access to the image's pixels and 57987 * alpha channel and simplify the process of compositing. 57988 * <br><br> 57989 * Before using the pixels[] array, be sure to use the loadPixels() method on 57990 * the image to make sure that the pixel data is properly loaded. 57991 * @example 57992 * <div><code> 57993 * function setup() { 57994 * var img = createImage(100, 100); // same as new p5.Image(100, 100); 57995 * img.loadPixels(); 57996 * createCanvas(100, 100); 57997 * background(0); 57998 * 57999 * // helper for writing color to array 58000 * function writeColor(image, x, y, red, green, blue, alpha) { 58001 * var index = (x + y * width) * 4; 58002 * image.pixels[index] = red; 58003 * image.pixels[index + 1] = green; 58004 * image.pixels[index + 2] = blue; 58005 * image.pixels[index + 3] = alpha; 58006 * } 58007 * 58008 * var x, y; 58009 * // fill with random colors 58010 * for (y = 0; y < img.height; y++) { 58011 * for (x = 0; x < img.width; x++) { 58012 * var red = random(255); 58013 * var green = random(255); 58014 * var blue = random(255); 58015 * var alpha = 255; 58016 * writeColor(img, x, y, red, green, blue, alpha); 58017 * } 58018 * } 58019 * 58020 * // draw a red line 58021 * y = 0; 58022 * for (x = 0; x < img.width; x++) { 58023 * writeColor(img, x, y, 255, 0, 0, 255); 58024 * } 58025 * 58026 * // draw a green line
58027 * y = img.height - 1; 58028 * for (x = 0; x < img.width; x++) { 58029 * writeColor(img, x, y, 0, 255, 0, 255); 58030 * } 58031 * 58032 * img.updatePixels(); 58033 * image(img, 0, 0); 58034 * } 58035 * </code></div> 58036 * 58037 * 58038 * @class p5.Image 58039 * @param {Number} width 58040 * @param {Number} height 58041 */ 58042p5.Image = function(width, height) { 58043 /** 58044 * Image width. 58045 * @property {Number} width 58046 * @readOnly 58047 * @example 58048 * <div><code> 58049 * var img; 58050 * function preload() { 58051 * img = loadImage('assets/rockies.jpg'); 58052 * } 58053 * 58054 * function setup() { 58055 * createCanvas(100, 100); 58056 * image(img, 0, 0); 58057 * for (var i = 0; i < img.width; i++) { 58058 * var c = img.get(i, img.height / 2); 58059 * stroke(c); 58060 * line(i, height / 2, i, height); 58061 * } 58062 * } 58063 * </code></div> 58064 * 58065 * @alt 58066 * rocky mountains in top and horizontal lines in corresponding colors in bottom. 58067 * 58068 */ 58069 this.width = width; 58070 /** 58071 * Image height. 58072 * @property {Number} height 58073 * @readOnly 58074 * @example 58075 * <div><code> 58076 * var img; 58077 * function preload() { 58078 * img = loadImage('assets/rockies.jpg'); 58079 * } 58080 * 58081 * function setup() { 58082 * createCanvas(100, 100); 58083 * image(img, 0, 0); 58084 * for (var i = 0; i < img.height; i++) { 58085 * var c = img.get(img.width / 2, i); 58086 * stroke(c); 58087 * line(0, i, width / 2, i); 58088 * } 58089 * } 58090 * </code></div> 58091 * 58092 * @alt 58093 * rocky mountains on right and vertical lines in corresponding colors on left. 58094 * 58095 */ 58096 this.height = height; 58097 this.canvas = document.createElement('canvas'); 58098 this.canvas.width = this.width; 58099 this.canvas.height = this.height; 58100 this.drawingContext = this.canvas.getContext('2d'); 58101 this._pixelDensity = 1; 58102 //used for webgl texturing only 58103 this._modified = false; 58104 /** 58105 * Array containing the values for all the pixels in the display window. 58106 * These values are numbers. This array is the size (include an appropriate 58107 * factor for pixelDensity) of the display window x4, 58108 * representing the R, G, B, A values in order for each pixel, moving from 58109 * left to right across each row, then down each column. Retina and other 58110 * high denisty displays may have more pixels[] (by a factor of 58111 * pixelDensity^2). 58112 * For example, if the image is 100x100 pixels, there will be 40,000. With 58113 * pixelDensity = 2, there will be 160,000. The first four values 58114 * (indices 0-3) in the array will be the R, G, B, A values of the pixel at 58115 * (0, 0). The second four values (indices 4-7) will contain the R, G, B, A 58116 * values of the pixel at (1, 0). More generally, to set values for a pixel 58117 * at (x, y): 58118 * ```javascript 58119 * var d = pixelDensity(); 58120 * for (var i = 0; i < d; i++) { 58121 * for (var j = 0; j < d; j++) { 58122 * // loop over
58123 * idx = 4 * ((y * d + j) * width * d + (x * d + i)); 58124 * pixels[idx] = r; 58125 * pixels[idx+1] = g; 58126 * pixels[idx+2] = b; 58127 * pixels[idx+3] = a; 58128 * } 58129 * } 58130 * ``` 58131 * <br><br> 58132 * Before accessing this array, the data must loaded with the loadPixels() 58133 * function. After the array data has been modified, the updatePixels() 58134 * function must be run to update the changes. 58135 * @property {Number[]} pixels 58136 * @example 58137 * <div> 58138 * <code> 58139 * var img = createImage(66, 66); 58140 * img.loadPixels(); 58141 * for (var i = 0; i < img.width; i++) { 58142 * for (var j = 0; j < img.height; j++) { 58143 * img.set(i, j, color(0, 90, 102)); 58144 * } 58145 * } 58146 * img.updatePixels(); 58147 * image(img, 17, 17); 58148 * </code> 58149 * </div> 58150 * <div> 58151 * <code> 58152 * var pink = color(255, 102, 204); 58153 * var img = createImage(66, 66); 58154 * img.loadPixels(); 58155 * for (var i = 0; i < 4 * (width * height / 2); i += 4) { 58156 * img.pixels[i] = red(pink); 58157 * img.pixels[i + 1] = green(pink); 58158 * img.pixels[i + 2] = blue(pink); 58159 * img.pixels[i + 3] = alpha(pink); 58160 * } 58161 * img.updatePixels(); 58162 * image(img, 17, 17); 58163 * </code> 58164 * </div> 58165 * 58166 * @alt 58167 * 66x66 turquoise rect in center of canvas 58168 * 66x66 pink rect in center of canvas 58169 * 58170 */ 58171 this.pixels = []; 58172}; 58173 58174/** 58175 * Helper fxn for sharing pixel methods 58176 * 58177 */ 58178p5.Image.prototype._setProperty = function(prop, value) { 58179 this[prop] = value; 58180 this.setModified(true); 58181}; 58182 58183/** 58184 * Loads the pixels data for this image into the [pixels] attribute. 58185 * 58186 * @method loadPixels 58187 * @example 58188 * <div><code> 58189 * var myImage; 58190 * var halfImage; 58191 * 58192 * function preload() { 58193 * myImage = loadImage('assets/rockies.jpg'); 58194 * } 58195 * 58196 * function setup() { 58197 * myImage.loadPixels(); 58198 * halfImage = 4 * width * height / 2; 58199 * for (var i = 0; i < halfImage; i++) { 58200 * myImage.pixels[i + halfImage] = myImage.pixels[i]; 58201 * } 58202 * myImage.updatePixels(); 58203 * } 58204 * 58205 * function draw() { 58206 * image(myImage, 0, 0); 58207 * } 58208 * </code></div> 58209 * 58210 * @alt 58211 * 2 images of rocky mountains vertically stacked 58212 * 58213 */ 58214p5.Image.prototype.loadPixels = function() { 58215 p5.Renderer2D.prototype.loadPixels.call(this); 58216 this.setModified(true); 58217}; 58218 58219/** 58220 * Updates the backing canvas for this image with the contents of 58221 * the [pixels] array. 58222 * 58223 * @method updatePixels 58224 * @param {Integer} x x-offset of the target update area for the 58225 * underlying canvas 58226 * @param {Integer} y y-offset of the target update area for the 58227 * underlying canvas 58228 * @param {Integer} w height of the target update area for the 58229 * underlying canvas 58230 * @param {Integer} h height of the target update area for the 58231 * underlying canvas 58232 * @example 58233 * <div><code> 58234 * var myImage; 58235 * var halfImage; 58236 * 58237 * function preload() { 58238 * myImage = loadImage('assets/rockies.jpg'); 58239 * } 58240 * 58241 * function setup() { 58242 * myImage.loadPixels(); 58243 * halfImage = 4 * width * height / 2; 58244 * for (var i = 0; i < halfImage; i++) { 58245 * myImage.pixels[i + halfImage] = myImage.pixels[i]; 58246 * } 58247 * myImage.updatePixels(); 58248 * } 58249 * 58250 * function draw() { 58251 * image(myImage, 0, 0); 58252 * } 58253 * </code></div> 58254 * 58255 * @alt 58256 * 2 images of rocky mountains vertically stacked 58257 * 58258 */ 58259/** 58260 * @method updatePixels 58261 */ 58262p5.Image.prototype.updatePixels = function(x, y, w, h) { 58263 p5.Renderer2D.prototype.updatePixels.call(this, x, y, w, h); 58264 this.setModified(true); 58265}; 58266 58267/** 58268 * Get a region of pixels from an image. 58269 * 58270 * If no params are passed, those whole image is returned, 58271 * if x and y are the only params passed a single pixel is extracted 58272 * if all params are passed a rectangle region is extracted and a p5.Image 58273 * is returned. 58274 * 58275 * Returns undefined if the region is outside the bounds of the image 58276 * 58277 * @method get 58278 * @param {Number} [x] x-coordinate of the pixel 58279 * @param {Number} [y] y-coordinate of the pixel 58280 * @param {Number} [w] width 58281 * @param {Number} [h] height 58282 * @return {Number[]|Color|p5.Image} color of pixel at x,y in array format 58283 * [R, G, B, A] or p5.Image 58284 * @example 58285 * <div><code> 58286 * var myImage; 58287 * var c; 58288 * 58289 * function preload() { 58290 * myImage = loadImage('assets/rockies.jpg'); 58291 * } 58292 * 58293 * function setup() { 58294 * background(myImage); 58295 * noStroke(); 58296 * c = myImage.get(60, 90); 58297 * fill(c); 58298 * rect(25, 25, 50, 50); 58299 * } 58300 * 58301 * //get() returns color here 58302 * </code></div> 58303 * 58304 * @alt 58305 * image of rocky mountains with 50x50 green rect in front 58306 * 58307 */ 58308p5.Image.prototype.get = function(x, y, w, h) { 58309 return p5.Renderer2D.prototype.get.call(this, x, y, w, h); 58310}; 58311 58312/** 58313 * Set the color of a single pixel or write an image into 58314 * this p5.Image. 58315 *
58316 * Note that for a large number of pixels this will 58317 * be slower than directly manipulating the pixels array 58318 * and then calling updatePixels(). 58319 * 58320 * @method set 58321 * @param {Number} x x-coordinate of the pixel 58322 * @param {Number} y y-coordinate of the pixel 58323 * @param {Number|Number[]|Object} a grayscale value | pixel array | 58324 * a p5.Color | image to copy 58325 * @example 58326 * <div> 58327 * <code> 58328 * var img = createImage(66, 66); 58329 * img.loadPixels(); 58330 * for (var i = 0; i < img.width; i++) { 58331 * for (var j = 0; j < img.height; j++) { 58332 * img.set(i, j, color(0, 90, 102, (i % img.width) * 2)); 58333 * } 58334 * } 58335 * img.updatePixels(); 58336 * image(img, 17, 17); 58337 * image(img, 34, 34); 58338 * </code> 58339 * </div> 58340 * 58341 * @alt 58342 * 2 gradated dark turquoise rects fade left. 1 center 1 bottom right of canvas 58343 * 58344 */ 58345p5.Image.prototype.set = function(x, y, imgOrCol) { 58346 p5.Renderer2D.prototype.set.call(this, x, y, imgOrCol); 58347 this.setModified(true); 58348}; 58349 58350/** 58351 * Resize the image to a new width and height. To make the image scale 58352 * proportionally, use 0 as the value for the wide or high parameter. 58353 * For instance, to make the width of an image 150 pixels, and change 58354 * the height using the same proportion, use resize(150, 0). 58355 * 58356 * @method resize 58357 * @param {Number} width the resized image width 58358 * @param {Number} height the resized image height 58359 * @example 58360 * <div><code> 58361 * var img; 58362 * 58363 * function preload() { 58364 * img = loadImage('assets/rockies.jpg'); 58365 * } 58366 58367 * function draw() { 58368 * image(img, 0, 0); 58369 * } 58370 * 58371 * function mousePressed() { 58372 * img.resize(50, 100); 58373 * } 58374 * </code></div> 58375 * 58376 * @alt 58377 * image of rocky mountains. zoomed in 58378 * 58379 */ 58380p5.Image.prototype.resize = function(width, height) { 58381 // Copy contents to a temporary canvas, resize the original 58382 // and then copy back. 58383 // 58384 // There is a faster approach that involves just one copy and swapping the 58385 // this.canvas reference. We could switch to that approach if (as i think 58386 // is the case) there an expectation that the user would not hold a 58387 // reference to the backing canvas of a p5.Image. But since we do not 58388 // enforce that at the moment, I am leaving in the slower, but safer 58389 // implementation. 58390 58391 // auto-resize 58392 if (width === 0 && height === 0) { 58393 width = this.canvas.width; 58394 height = this.canvas.height; 58395 } else if (width === 0) { 58396 width = this.canvas.width * height / this.canvas.height; 58397 } else if (height === 0) { 58398 height = this.canvas.height * width / this.canvas.width; 58399 } 58400 58401 width = Math.floor(width); 58402 height = Math.floor(height); 58403 58404 var tempCanvas = document.createElement('canvas'); 58405 tempCanvas.width = width; 58406 tempCanvas.height = height; 58407 // prettier-ignore 58408 tempCanvas.getContext('2d').drawImage( 58409 this.canvas, 58410 0, 0, this.canvas.width, this.canvas.height, 58411 0, 0, tempCanvas.width, tempCanvas.height 58412 ); 58413 58414 // Resize the original canvas, which will clear its contents 58415 this.canvas.width = this.width = width; 58416 this.canvas.height = this.height = height; 58417 58418 //Copy the image back 58419 58420 // prettier-ignore 58421 this.drawingContext.drawImage( 58422 tempCanvas, 58423 0, 0, width, height, 58424 0, 0, width, height 58425 ); 58426 58427 if (this.pixels.length > 0) { 58428 this.loadPixels(); 58429 } 58430 58431 this.setModified(true); 58432}; 58433 58434/** 58435 * Copies a region of pixels from one image to another. If no 58436 * srcImage is specified this is used as the source. If the source 58437 * and destination regions aren't the same size, it will 58438 * automatically resize source pixels to fit the specified 58439 * target region. 58440 * 58441 * @method copy 58442 * @param {p5.Image|p5.Element} srcImage source image 58443 * @param {Integer} sx X coordinate of the source's upper left corner 58444 * @param {Integer} sy Y coordinate of the source's upper left corner 58445 * @param {Integer} sw source image width 58446 * @param {Integer} sh source image height 58447 * @param {Integer} dx X coordinate of the destination's upper left corner 58448 * @param {Integer} dy Y coordinate of the destination's upper left corner 58449 * @param {Integer} dw destination image width 58450 * @param {Integer} dh destination image height 58451 * @example 58452 * <div><code> 58453 * var photo; 58454 * var bricks; 58455 * var x; 58456 * var y; 58457 * 58458 * function preload() { 58459 * photo = loadImage('assets/rockies.jpg'); 58460 * bricks = loadImage('assets/bricks.jpg'); 58461 * } 58462 * 58463 * function setup() { 58464 * x = bricks.width / 2; 58465 * y = bricks.height / 2; 58466 * photo.copy(bricks, 0, 0, x, y, 0, 0, x, y); 58467 * image(photo, 0, 0); 58468 * } 58469 * </code></div> 58470 * 58471 * @alt 58472 * image of rocky mountains and smaller image on top of bricks at top left 58473 * 58474 */ 58475/** 58476 * @method copy 58477 * @param {Integer} sx 58478 * @param {Integer} sy 58479 * @param {Integer} sw 58480 * @param {Integer} sh 58481 * @param {Integer} dx 58482 * @param {Integer} dy 58483 * @param {Integer} dw 58484 * @param {Integer} dh 58485 */ 58486p5.Image.prototype.copy = function() { 58487 var srcImage, sx, sy, sw, sh, dx, dy, dw, dh; 58488 if (arguments.length === 9) { 58489 srcImage = arguments[0]; 58490 sx = arguments[1]; 58491 sy = arguments[2]; 58492 sw = arguments[3]; 58493 sh = arguments[4]; 58494 dx = arguments[5]; 58495 dy = arguments[6]; 58496 dw = arguments[7]; 58497 dh = arguments[8]; 58498 } else if (arguments.length === 8) { 58499 srcImage = this; 58500 sx = arguments[0]; 58501 sy = arguments[1]; 58502 sw = arguments[2]; 58503 sh = arguments[3]; 58504 dx = arguments[4]; 58505 dy = arguments[5]; 58506 dw = arguments[6]; 58507 dh = arguments[7]; 58508 } else { 58509 throw new Error('Signature not supported'); 58510 } 58511 p5.Renderer2D._copyHelper(this, srcImage, sx, sy, sw, sh, dx, dy, dw, dh); 58512}; 58513 58514/** 58515 * Masks part of an image from displaying by loading another 58516 * image and using it's alpha channel as an alpha channel for 58517 * this image. 58518 * 58519 * @method mask 58520 * @param {p5.Image} srcImage source image 58521 * @example 58522 * <div><code> 58523 * var photo, maskImage; 58524 * function preload() { 58525 * photo = loadImage('assets/rockies.jpg'); 58526 * maskImage = loadImage('assets/mask2.png'); 58527 * } 58528 * 58529 * function setup() { 58530 * createCanvas(100, 100); 58531 * photo.mask(maskImage); 58532 * image(photo, 0, 0); 58533 * } 58534 * </code></div> 58535 * 58536 * @alt 58537 * image of rocky mountains with white at right 58538 * 58539 * 58540 * http://blogs.adobe.com/webplatform/2013/01/28/blending-features-in-canvas/ 58541 * 58542 */ 58543// TODO: - Accept an array of alpha values. 58544// - Use other channels of an image. p5 uses the 58545// blue channel (which feels kind of arbitrary). Note: at the 58546// moment this method does not match native processings original 58547// functionality exactly. 58548p5.Image.prototype.mask = function(p5Image) { 58549 if (p5Image === undefined) { 58550 p5Image = this; 58551 } 58552 var currBlend = this.drawingContext.globalCompositeOperation; 58553 58554 var scaleFactor = 1; 58555 if (p5Image instanceof p5.Renderer) { 58556 scaleFactor = p5Image._pInst._pixelDensity; 58557 } 58558 58559 var copyArgs = [ 58560 p5Image, 58561 0, 58562 0, 58563 scaleFactor * p5Image.width, 58564 scaleFactor * p5Image.height, 58565 0, 58566 0, 58567 this.width, 58568 this.height 58569 ]; 58570 58571 this.drawingContext.globalCompositeOperation = 'destination-in'; 58572 p5.Image.prototype.copy.apply(this, copyArgs); 58573 this.drawingContext.globalCompositeOperation = currBlend; 58574 this.setModified(true); 58575}; 58576 58577/** 58578 * Applies an image filter to a p5.Image 58579 * 58580 * @method filter 58581 * @param {Constant} filterType either THRESHOLD, GRAY, OPAQUE, INVERT, 58582 * POSTERIZE, BLUR, ERODE, DILATE or BLUR. 58583 * See Filters.js for docs on 58584 * each available filter 58585 * @param {Number} [filterParam] an optional parameter unique 58586 * to each filter, see above 58587 * @example 58588 * <div><code> 58589 * var photo1; 58590 * var photo2; 58591 * 58592 * function preload() { 58593 * photo1 = loadImage('assets/rockies.jpg'); 58594 * photo2 = loadImage('assets/rockies.jpg'); 58595 * } 58596 * 58597 * function setup() { 58598 * photo2.filter('gray'); 58599 * image(photo1, 0, 0); 58600 * image(photo2, width / 2, 0); 58601 * } 58602 * </code></div> 58603 * 58604 * @alt 58605 * 2 images of rocky mountains left one in color, right in black and white 58606 * 58607 */ 58608p5.Image.prototype.filter = function(operation, value) { 58609 Filters.apply(this.canvas, Filters[operation.toLowerCase()], value); 58610 this.setModified(true); 58611}; 58612 58613/** 58614 * Copies a region of pixels from one image to another, using a specified 58615 * blend mode to do the operation. 58616 * 58617 * @method blend 58618 * @param {p5.Image} srcImage source image 58619 * @param {Integer} sx X coordinate of the source's upper left corner 58620 * @param {Integer} sy Y coordinate of the source's upper left corner 58621 * @param {Integer} sw source image width 58622 * @param {Integer} sh source image height 58623 * @param {Integer} dx X coordinate of the destination's upper left corner 58624 * @param {Integer} dy Y coordinate of the destination's upper left corner 58625 * @param {Integer} dw destination image width 58626 * @param {Integer} dh destination image height 58627 * @param {Constant} blendMode the blend mode. either 58628 * BLEND, DARKEST, LIGHTEST, DIFFERENCE, 58629 * MULTIPLY, EXCLUSION, SCREEN, REPLACE, OVERLAY, HARD_LIGHT, 58630 * SOFT_LIGHT, DODGE, BURN, ADD or NORMAL. 58631 * 58632 * Available blend modes are: normal | multiply | screen | overlay | 58633 * darken | lighten | color-dodge | color-burn | hard-light | 58634 * soft-light | difference | exclusion | hue | saturation | 58635 * color | luminosity 58636 * 58637 * 58638 * http://blogs.adobe.com/webplatform/2013/01/28/blending-features-in-canvas/ 58639 * @example 58640 * <div><code> 58641 * var mountains; 58642 * var bricks; 58643 * 58644 * function preload() {
58645 * mountains = loadImage('assets/rockies.jpg'); 58646 * bricks = loadImage('assets/bricks_third.jpg'); 58647 * } 58648 * 58649 * function setup() { 58650 * mountains.blend(bricks, 0, 0, 33, 100, 67, 0, 33, 100, ADD); 58651 * image(mountains, 0, 0); 58652 * image(bricks, 0, 0); 58653 * } 58654 * </code></div> 58655 * <div><code> 58656 * var mountains; 58657 * var bricks; 58658 * 58659 * function preload() { 58660 * mountains = loadImage('assets/rockies.jpg'); 58661 * bricks = loadImage('assets/bricks_third.jpg'); 58662 * } 58663 * 58664 * function setup() { 58665 * mountains.blend(bricks, 0, 0, 33, 100, 67, 0, 33, 100, DARKEST); 58666 * image(mountains, 0, 0); 58667 * image(bricks, 0, 0); 58668 * } 58669 * </code></div> 58670 * <div><code> 58671 * var mountains; 58672 * var bricks; 58673 * 58674 * function preload() { 58675 * mountains = loadImage('assets/rockies.jpg'); 58676 * bricks = loadImage('assets/bricks_third.jpg'); 58677 * } 58678 * 58679 * function setup() { 58680 * mountains.blend(bricks, 0, 0, 33, 100, 67, 0, 33, 100, LIGHTEST); 58681 * image(mountains, 0, 0); 58682 * image(bricks, 0, 0); 58683 * } 58684 * </code></div> 58685 * 58686 * @alt 58687 * image of rocky mountains. Brick images on left and right. Right overexposed 58688 * image of rockies. Brickwall images on left and right. Right mortar transparent 58689 * image of rockies. Brickwall images on left and right. Right translucent 58690 * 58691 */ 58692/** 58693 * @method blend 58694 * @param {Integer} sx 58695 * @param {Integer} sy 58696 * @param {Integer} sw 58697 * @param {Integer} sh 58698 * @param {Integer} dx 58699 * @param {Integer} dy 58700 * @param {Integer} dw 58701 * @param {Integer} dh 58702 * @param {Constant} blendMode 58703 */ 58704p5.Image.prototype.blend = function() { 58705 p5.prototype.blend.apply(this, arguments); 58706 this.setModified(true); 58707}; 58708 58709/** 58710 * helper method for web GL mode to indicate that an image has been 58711 * changed or unchanged since last upload. gl texture upload will 58712 * set this value to false after uploading the texture. 58713 * @method setModified 58714 * @param {boolean} val sets whether or not the image has been 58715 * modified. 58716 * @private 58717 */ 58718p5.Image.prototype.setModified = function(val) { 58719 this._modified = val; //enforce boolean? 58720}; 58721 58722/** 58723 * helper method for web GL mode to figure out if the image 58724 * has been modified and might need to be re-uploaded to texture 58725 * memory between frames. 58726 * @method isModified 58727 * @private 58728 * @return {boolean} a boolean indicating whether or not the 58729 * image has been updated or modified since last texture upload. 58730 */ 58731p5.Image.prototype.isModified = function() { 58732 return this._modified; 58733}; 58734 58735/** 58736 * Saves the image to a file and force the browser to download it. 58737 * Accepts two strings for filename and file extension 58738 * Supports png (default) and jpg. 58739 * 58740 * @method save 58741 * @param {String} filename give your file a name 58742 * @param {String} extension 'png' or 'jpg' 58743 * @example 58744 * <div><code> 58745 * var photo; 58746 * 58747 * function preload() { 58748 * photo = loadImage('assets/rockies.jpg'); 58749 * } 58750 * 58751 * function draw() { 58752 * image(photo, 0, 0); 58753 * } 58754 * 58755 * function keyTyped() { 58756 * if (key === 's') { 58757 * photo.save('photo', 'png'); 58758 * } 58759 * } 58760 * </code></div> 58761 * 58762 * @alt 58763 * image of rocky mountains. 58764 * 58765 */ 58766p5.Image.prototype.save = function(filename, extension) { 58767 p5.prototype.saveCanvas(this.canvas, filename, extension); 58768}; 58769 58770module.exports = p5.Image; 58771 58772},{"../core/core":22,"./filters":41}],45:[function(_dereq_,module,exports){ 58773/** 58774 * @module Image 58775 * @submodule Pixels 58776 * @for p5 58777 * @requires core 58778 */ 58779 58780'use strict'; 58781 58782var p5 = _dereq_('../core/core'); 58783var Filters = _dereq_('./filters'); 58784_dereq_('../color/p5.Color'); 58785 58786/** 58787 * <a href='https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference 58788 * /Global_Objects/Uint8ClampedArray' target='_blank'>Uint8ClampedArray</a> 58789 * containing the values for all the pixels in the display window. 58790 * These values are numbers. This array is the size (include an appropriate 58791 * factor for pixelDensity) of the display window x4, 58792 * representing the R, G, B, A values in order for each pixel, moving from 58793 * left to right across each row, then down each column. Retina and other 58794 * high density displays will have more pixels[] (by a factor of 58795 * pixelDensity^2). 58796 * For example, if the image is 100x100 pixels, there will be 40,000. On a 58797 * retina display, there will be 160,000. 58798 * <br><br> 58799 * The first four values (indices 0-3) in the array will be the R, G, B, A 58800 * values of the pixel at (0, 0). The second four values (indices 4-7) will 58801 * contain the R, G, B, A values of the pixel at (1, 0). More generally, to 58802 * set values for a pixel at (x, y): 58803 * ```javascript 58804 * var d = pixelDensity(); 58805 * for (var i = 0; i < d; i++) { 58806 * for (var j = 0; j < d; j++) { 58807 * // loop over
58808 * idx = 4 * ((y * d + j) * width * d + (x * d + i)); 58809 * pixels[idx] = r; 58810 * pixels[idx+1] = g; 58811 * pixels[idx+2] = b; 58812 * pixels[idx+3] = a; 58813 * } 58814 * } 58815 * ``` 58816 * <p>While the above method is complex, it is flexible enough to work with 58817 * any pixelDensity. Note that set() will automatically take care of 58818 * setting all the appropriate values in pixels[] for a given (x, y) at 58819 * any pixelDensity, but the performance may not be as fast when lots of 58820 * modifications are made to the pixel array. 58821 * <br><br> 58822 * Before accessing this array, the data must loaded with the loadPixels() 58823 * function. After the array data has been modified, the updatePixels() 58824 * function must be run to update the changes. 58825 * <br><br> 58826 * Note that this is not a standard javascript array. This means that 58827 * standard javascript functions such as <code>slice()</code> or 58828 * <code>arrayCopy()</code> do not 58829 * work.</p> 58830 * 58831 * @property {Number[]} pixels 58832 * @example 58833 * <div> 58834 * <code> 58835 * var pink = color(255, 102, 204); 58836 * loadPixels(); 58837 * var d = pixelDensity(); 58838 * var halfImage = 4 * (width * d) * (height / 2 * d); 58839 * for (var i = 0; i < halfImage; i += 4) { 58840 * pixels[i] = red(pink); 58841 * pixels[i + 1] = green(pink); 58842 * pixels[i + 2] = blue(pink); 58843 * pixels[i + 3] = alpha(pink); 58844 * } 58845 * updatePixels(); 58846 * </code> 58847 * </div> 58848 * 58849 * @alt 58850 * top half of canvas pink, bottom grey 58851 * 58852 */ 58853p5.prototype.pixels = []; 58854 58855/** 58856 * Copies a region of pixels from one image to another, using a specified 58857 * blend mode to do the operation. 58858 * 58859 * @method blend 58860 * @param {p5.Image} srcImage source image 58861 * @param {Integer} sx X coordinate of the source's upper left corner 58862 * @param {Integer} sy Y coordinate of the source's upper left corner 58863 * @param {Integer} sw source image width 58864 * @param {Integer} sh source image height 58865 * @param {Integer} dx X coordinate of the destination's upper left corner 58866 * @param {Integer} dy Y coordinate of the destination's upper left corner 58867 * @param {Integer} dw destination image width 58868 * @param {Integer} dh destination image height 58869 * @param {Constant} blendMode the blend mode. either 58870 * BLEND, DARKEST, LIGHTEST, DIFFERENCE, 58871 * MULTIPLY, EXCLUSION, SCREEN, REPLACE, OVERLAY, HARD_LIGHT, 58872 * SOFT_LIGHT, DODGE, BURN, ADD or NORMAL. 58873 * 58874 * @example 58875 * <div><code> 58876 * var img0; 58877 * var img1; 58878 * 58879 * function preload() { 58880 * img0 = loadImage('assets/rockies.jpg'); 58881 * img1 = loadImage('assets/bricks_third.jpg'); 58882 * } 58883 * 58884 * function setup() { 58885 * background(img0); 58886 * image(img1, 0, 0); 58887 * blend(img1, 0, 0, 33, 100, 67, 0, 33, 100, LIGHTEST); 58888 * } 58889 * </code></div> 58890 * <div><code> 58891 * var img0; 58892 * var img1; 58893 * 58894 * function preload() { 58895 * img0 = loadImage('assets/rockies.jpg'); 58896 * img1 = loadImage('assets/bricks_third.jpg'); 58897 * } 58898 * 58899 * function setup() { 58900 * background(img0); 58901 * image(img1, 0, 0); 58902 * blend(img1, 0, 0, 33, 100, 67, 0, 33, 100, DARKEST); 58903 * } 58904 * </code></div> 58905 * <div><code> 58906 * var img0; 58907 * var img1; 58908 * 58909 * function preload() { 58910 * img0 = loadImage('assets/rockies.jpg'); 58911 * img1 = loadImage('assets/bricks_third.jpg'); 58912 * } 58913 * 58914 * function setup() { 58915 * background(img0); 58916 * image(img1, 0, 0); 58917 * blend(img1, 0, 0, 33, 100, 67, 0, 33, 100, ADD); 58918 * } 58919 * </code></div> 58920 * 58921 * @alt 58922 * image of rocky mountains. Brick images on left and right. Right overexposed 58923 * image of rockies. Brickwall images on left and right. Right mortar transparent 58924 * image of rockies. Brickwall images on left and right. Right translucent 58925 * 58926 * 58927 */ 58928/** 58929 * @method blend 58930 * @param {Integer} sx 58931 * @param {Integer} sy 58932 * @param {Integer} sw 58933 * @param {Integer} sh 58934 * @param {Integer} dx 58935 * @param {Integer} dy 58936 * @param {Integer} dw 58937 * @param {Integer} dh 58938 * @param {Constant} blendMode 58939 */ 58940p5.prototype.blend = function() { 58941 p5._validateParameters('blend', arguments); 58942 if (this._renderer) { 58943 this._renderer.blend.apply(this._renderer, arguments); 58944 } else { 58945 p5.Renderer2D.prototype.blend.apply(this, arguments); 58946 } 58947}; 58948 58949/** 58950 * Copies a region of the canvas to another region of the canvas 58951 * and copies a region of pixels from an image used as the srcImg parameter 58952 * into the canvas srcImage is specified this is used as the source. If 58953 * the source and destination regions aren't the same size, it will 58954 * automatically resize source pixels to fit the specified 58955 * target region. 58956 * 58957 * @method copy 58958 * @param {p5.Image|p5.Element} srcImage source image 58959 * @param {Integer} sx X coordinate of the source's upper left corner 58960 * @param {Integer} sy Y coordinate of the source's upper left corner 58961 * @param {Integer} sw source image width 58962 * @param {Integer} sh source image height 58963 * @param {Integer} dx X coordinate of the destination's upper left corner 58964 * @param {Integer} dy Y coordinate of the destination's upper left corner 58965 * @param {Integer} dw destination image width 58966 * @param {Integer} dh destination image height 58967 * 58968 * @example 58969 * <div><code> 58970 * var img; 58971 * 58972 * function preload() { 58973 * img = loadImage('assets/rockies.jpg'); 58974 * } 58975 * 58976 * function setup() { 58977 * background(img); 58978 * copy(img, 7, 22, 10, 10, 35, 25, 50, 50);
58979 * stroke(255); 58980 * noFill(); 58981 * // Rectangle shows area being copied 58982 * rect(7, 22, 10, 10); 58983 * } 58984 * </code></div> 58985 * 58986 * @alt 58987 * image of rocky mountains. Brick images on left and right. Right overexposed 58988 * image of rockies. Brickwall images on left and right. Right mortar transparent 58989 * image of rockies. Brickwall images on left and right. Right translucent 58990 * 58991 */ 58992/** 58993 * @method copy 58994 * @param {Integer} sx 58995 * @param {Integer} sy 58996 * @param {Integer} sw 58997 * @param {Integer} sh 58998 * @param {Integer} dx 58999 * @param {Integer} dy 59000 * @param {Integer} dw 59001 * @param {Integer} dh 59002 */ 59003p5.prototype.copy = function() { 59004 p5._validateParameters('copy', arguments); 59005 p5.Renderer2D.prototype.copy.apply(this._renderer, arguments); 59006}; 59007 59008/** 59009 * Applies a filter to the canvas. 59010 * <br><br> 59011 * 59012 * The presets options are: 59013 * <br><br> 59014 * 59015 * THRESHOLD 59016 * Converts the image to black and white pixels depending if they are above or 59017 * below the threshold defined by the level parameter. The parameter must be 59018 * between 0.0 (black) and 1.0 (white). If no level is specified, 0.5 is used. 59019 * <br><br> 59020 * 59021 * GRAY 59022 * Converts any colors in the image to grayscale equivalents. No parameter 59023 * is used. 59024 * <br><br> 59025 * 59026 * OPAQUE 59027 * Sets the alpha channel to entirely opaque. No parameter is used. 59028 * <br><br> 59029 * 59030 * INVERT 59031 * Sets each pixel to its inverse value. No parameter is used. 59032 * <br><br> 59033 * 59034 * POSTERIZE 59035 * Limits each channel of the image to the number of colors specified as the 59036 * parameter. The parameter can be set to values between 2 and 255, but 59037 * results are most noticeable in the lower ranges. 59038 * <br><br> 59039 * 59040 * BLUR 59041 * Executes a Gaussian blur with the level parameter specifying the extent 59042 * of the blurring. If no parameter is used, the blur is equivalent to 59043 * Gaussian blur of radius 1. Larger values increase the blur. 59044 * <br><br> 59045 * 59046 * ERODE 59047 * Reduces the light areas. No parameter is used. 59048 * <br><br> 59049 * 59050 * DILATE 59051 * Increases the light areas. No parameter is used. 59052 * 59053 * @method filter 59054 * @param {Constant} filterType either THRESHOLD, GRAY, OPAQUE, INVERT, 59055 * POSTERIZE, BLUR, ERODE, DILATE or BLUR. 59056 * See Filters.js for docs on 59057 * each available filter 59058 * @param {Number} [filterParam] an optional parameter unique 59059 * to each filter, see above 59060 * 59061 * @example 59062 * <div> 59063 * <code> 59064 * var img; 59065 * function preload() { 59066 * img = loadImage('assets/bricks.jpg'); 59067 * } 59068 * function setup() { 59069 * image(img, 0, 0); 59070 * filter(THRESHOLD); 59071 * } 59072 * </code> 59073 * </div> 59074 * 59075 * <div> 59076 * <code> 59077 * var img; 59078 * function preload() { 59079 * img = loadImage('assets/bricks.jpg'); 59080 * } 59081 * function setup() { 59082 * image(img, 0, 0); 59083 * filter(GRAY); 59084 * } 59085 * </code> 59086 * </div> 59087 * 59088 * <div> 59089 * <code> 59090 * var img; 59091 * function preload() { 59092 * img = loadImage('assets/bricks.jpg'); 59093 * } 59094 * function setup() { 59095 * image(img, 0, 0); 59096 * filter(OPAQUE); 59097 * } 59098 * </code> 59099 * </div> 59100 * 59101 * <div> 59102 * <code> 59103 * var img; 59104 * function preload() { 59105 * img = loadImage('assets/bricks.jpg'); 59106 * } 59107 * function setup() { 59108 * image(img, 0, 0); 59109 * filter(INVERT); 59110 * } 59111 * </code> 59112 * </div> 59113 * 59114 * <div> 59115 * <code> 59116 * var img; 59117 * function preload() { 59118 * img = loadImage('assets/bricks.jpg'); 59119 * } 59120 * function setup() { 59121 * image(img, 0, 0); 59122 * filter(POSTERIZE, 3); 59123 * } 59124 * </code> 59125 * </div> 59126 * 59127 * <div> 59128 * <code> 59129 * var img; 59130 * function preload() { 59131 * img = loadImage('assets/bricks.jpg'); 59132 * } 59133 * function setup() { 59134 * image(img, 0, 0); 59135 * filter(DILATE); 59136 * } 59137 * </code> 59138 * </div> 59139 * 59140 * <div> 59141 * <code> 59142 * var img; 59143 * function preload() { 59144 * img = loadImage('assets/bricks.jpg'); 59145 * } 59146 * function setup() { 59147 * image(img, 0, 0); 59148 * filter(BLUR, 3); 59149 * } 59150 * </code> 59151 * </div> 59152 * 59153 * <div> 59154 * <code> 59155 * var img; 59156 * function preload() { 59157 * img = loadImage('assets/bricks.jpg'); 59158 * } 59159 * function setup() { 59160 * image(img, 0, 0); 59161 * filter(ERODE); 59162 * } 59163 * </code> 59164 * </div> 59165 * 59166 * @alt 59167 * black and white image of a brick wall. 59168 * greyscale image of a brickwall 59169 * image of a brickwall 59170 * jade colored image of a brickwall 59171 * red and pink image of a brickwall 59172 * image of a brickwall 59173 * blurry image of a brickwall 59174 * image of a brickwall 59175 * image of a brickwall with less detail 59176 * 59177 */ 59178p5.prototype.filter = function(operation, value) { 59179 p5._validateParameters('filter', arguments); 59180 if (this.canvas !== undefined) { 59181 Filters.apply(this.canvas, Filters[operation.toLowerCase()], value); 59182 } else { 59183 Filters.apply(this.elt, Filters[operation.toLowerCase()], value); 59184 } 59185}; 59186 59187/** 59188 * Returns an array of [R,G,B,A] values for any pixel or grabs a section of 59189 * an image. If no parameters are specified, the entire image is returned. 59190 * Use the x and y parameters to get the value of one pixel. Get a section of 59191 * the display window by specifying additional w and h parameters. When 59192 * getting an image, the x and y parameters define the coordinates for the 59193 * upper-left corner of the image, regardless of the current imageMode(). 59194 * <br><br> 59195 * If the pixel requested is outside of the image window, [0,0,0,255] is 59196 * returned. To get the numbers scaled according to the current color ranges 59197 * and taking into account colorMode, use getColor instead of get. 59198 * <br><br> 59199 * Getting the color of a single pixel with get(x, y) is easy, but not as fast 59200 * as grabbing the data directly from pixels[]. The equivalent statement to 59201 * get(x, y) using pixels[] with pixel density d is 59202 * <code> 59203 * var x, y, d; // set these to the coordinates 59204 * var off = (y * width + x) * d * 4; 59205 * var components = [ 59206 * pixels[off], 59207 * pixels[off + 1], 59208 * pixels[off + 2], 59209 * pixels[off + 3] 59210 * ]; 59211 * print(components); 59212 * </code> 59213 * <br><br> 59214 * See the reference for pixels[] for more information. 59215 * 59216 * @method get 59217 * @param {Number} [x] x-coordinate of the pixel 59218 * @param {Number} [y] y-coordinate of the pixel 59219 * @param {Number} [w] width 59220 * @param {Number} [h] height 59221 * @return {Number[]|p5.Image} values of pixel at x,y in array format 59222 * [R, G, B, A] or p5.Image 59223 * @example 59224 * <div> 59225 * <code> 59226 * var img; 59227 * function preload() { 59228 * img = loadImage('assets/rockies.jpg'); 59229 * } 59230 * function setup() { 59231 * image(img, 0, 0); 59232 * var c = get(); 59233 * image(c, width / 2, 0); 59234 * } 59235 * </code> 59236 * </div> 59237 * 59238 * <div> 59239 * <code> 59240 * var img; 59241 * function preload() { 59242 * img = loadImage('assets/rockies.jpg'); 59243 * } 59244 * function setup() { 59245 * image(img, 0, 0); 59246 * var c = get(50, 90); 59247 * fill(c); 59248 * noStroke(); 59249 * rect(25, 25, 50, 50); 59250 * } 59251 * </code> 59252 * </div> 59253 * 59254 * @alt 59255 * 2 images of the rocky mountains, side-by-side 59256 * Image of the rocky mountains with 50x50 green rect in center of canvas 59257 * 59258 */ 59259p5.prototype.get = function(x, y, w, h) { 59260 return this._renderer.get(x, y, w, h); 59261}; 59262 59263/** 59264 * Loads the pixel data for the display window into the pixels[] array. This
59265 * function must always be called before reading from or writing to pixels[]. 59266 * Note that only changes made with set() or direct manipulation of pixels[] 59267 * will occur. 59268 * 59269 * @method loadPixels 59270 * @example 59271 * <div> 59272 * <code> 59273 * var img; 59274 * function preload() { 59275 * img = loadImage('assets/rockies.jpg'); 59276 * } 59277 * 59278 * function setup() { 59279 * image(img, 0, 0); 59280 * var d = pixelDensity(); 59281 * var halfImage = 4 * (img.width * d) * (img.height * d / 2); 59282 * loadPixels(); 59283 * for (var i = 0; i < halfImage; i++) { 59284 * pixels[i + halfImage] = pixels[i]; 59285 * } 59286 * updatePixels(); 59287 * } 59288 * </code> 59289 * </div> 59290 * 59291 * @alt 59292 * two images of the rocky mountains. one on top, one on bottom of canvas. 59293 * 59294 */ 59295p5.prototype.loadPixels = function() { 59296 p5._validateParameters('loadPixels', arguments); 59297 this._renderer.loadPixels(); 59298}; 59299 59300/** 59301 * <p>Changes the color of any pixel, or writes an image directly to the 59302 * display window.</p> 59303 * <p>The x and y parameters specify the pixel to change and the c parameter 59304 * specifies the color value. This can be a p5.Color object, or [R, G, B, A] 59305 * pixel array. It can also be a single grayscale value. 59306 * When setting an image, the x and y parameters define the coordinates for 59307 * the upper-left corner of the image, regardless of the current imageMode(). 59308 * </p> 59309 * <p> 59310 * After using set(), you must call updatePixels() for your changes to appear. 59311 * This should be called once all pixels have been set, and must be called before 59312 * calling .get() or drawing the image. 59313 * </p> 59314 * <p>Setting the color of a single pixel with set(x, y) is easy, but not as 59315 * fast as putting the data directly into pixels[]. Setting the pixels[] 59316 * values directly may be complicated when working with a retina display, 59317 * but will perform better when lots of pixels need to be set directly on 59318 * every loop.</p> 59319 * <p>See the reference for pixels[] for more information.</p> 59320 * 59321 * @method set 59322 * @param {Number} x x-coordinate of the pixel 59323 * @param {Number} y y-coordinate of the pixel 59324 * @param {Number|Number[]|Object} c insert a grayscale value | a pixel array | 59325 * a p5.Color object | a p5.Image to copy 59326 * @example 59327 * <div> 59328 * <code> 59329 * var black = color(0); 59330 * set(30, 20, black); 59331 * set(85, 20, black); 59332 * set(85, 75, black); 59333 * set(30, 75, black); 59334 * updatePixels(); 59335 * </code> 59336 * </div> 59337 * 59338 * <div> 59339 * <code> 59340 * for (var i = 30; i < width - 15; i++) { 59341 * for (var j = 20; j < height - 25; j++) { 59342 * var c = color(204 - j, 153 - i, 0); 59343 * set(i, j, c); 59344 * } 59345 * } 59346 * updatePixels(); 59347 * </code> 59348 * </div> 59349 * 59350 * <div> 59351 * <code> 59352 * var img; 59353 * function preload() { 59354 * img = loadImage('assets/rockies.jpg'); 59355 * } 59356 * 59357 * function setup() { 59358 * set(0, 0, img); 59359 * updatePixels(); 59360 * line(0, 0, width, height); 59361 * line(0, height, width, 0); 59362 * } 59363 * </code> 59364 * </div> 59365 * 59366 * @alt 59367 * 4 black points in the shape of a square middle-right of canvas. 59368 * square with orangey-brown gradient lightening at bottom right. 59369 * image of the rocky mountains. with lines like an 'x' through the center. 59370 */ 59371p5.prototype.set = function(x, y, imgOrCol) { 59372 this._renderer.set(x, y, imgOrCol); 59373}; 59374/** 59375 * Updates the display window with the data in the pixels[] array. 59376 * Use in conjunction with loadPixels(). If you're only reading pixels from 59377 * the array, there's no need to call updatePixels() â updating is only 59378 * necessary to apply changes. updatePixels() should be called anytime the 59379 * pixels array is manipulated or set() is called, and only changes made with 59380 * set() or direct changes to pixels[] will occur. 59381 * 59382 * @method updatePixels 59383 * @param {Number} [x] x-coordinate of the upper-left corner of region 59384 * to update 59385 * @param {Number} [y] y-coordinate of the upper-left corner of region 59386 * to update 59387 * @param {Number} [w] width of region to update 59388 * @param {Number} [h] height of region to update 59389 * @example 59390 * <div> 59391 * <code> 59392 * var img; 59393 * function preload() { 59394 * img = loadImage('assets/rockies.jpg'); 59395 * } 59396 * 59397 * function setup() { 59398 * image(img, 0, 0); 59399 * var d = pixelDensity(); 59400 * var halfImage = 4 * (img.width * d) * (img.height * d / 2); 59401 * loadPixels(); 59402 * for (var i = 0; i < halfImage; i++) { 59403 * pixels[i + halfImage] = pixels[i]; 59404 * } 59405 * updatePixels(); 59406 * } 59407 * </code> 59408 * </div> 59409 * @alt 59410 * two images of the rocky mountains. one on top, one on bottom of canvas. 59411 */ 59412p5.prototype.updatePixels = function(x, y, w, h) { 59413 p5._validateParameters('updatePixels', arguments); 59414 // graceful fail - if loadPixels() or set() has not been called, pixel 59415 // array will be empty, ignore call to updatePixels() 59416 if (this.pixels.length === 0) { 59417 return; 59418 } 59419 this._renderer.updatePixels(x, y, w, h); 59420}; 59421 59422module.exports = p5; 59423 59424},{"../color/p5.Color":16,"../core/core":22,"./filters":41}],46:[function(_dereq_,module,exports){ 59425/** 59426 * @module IO 59427 * @submodule Input 59428 * @for p5 59429 * @requires core 59430 */ 59431 59432/* globals Request: false */ 59433/* globals Headers: false */ 59434 59435'use strict'; 59436 59437var p5 = _dereq_('../core/core'); 59438_dereq_('whatwg-fetch'); 59439_dereq_('es6-promise').polyfill(); 59440var fetchJsonp = _dereq_('fetch-jsonp'); 59441_dereq_('../core/error_helpers'); 59442 59443/** 59444 * Loads a JSON file from a file or a URL, and returns an Object. 59445 * Note that even if the JSON file contains an Array, an Object will be 59446 * returned with index numbers as keys. 59447 * 59448 * This method is asynchronous, meaning it may not finish before the next 59449 * line in your sketch is executed. JSONP is supported via a polyfill and
59449you 59450 * can pass in as the second argument an object with definitions of the json 59451 * callback following the syntax specified <a href="https://github.com/camsong/ 59452 * fetch-jsonp">here</a>. 59453 * 59454 * @method loadJSON 59455 * @param {String} path name of the file or url to load 59456 * @param {Object} [jsonpOptions] options object for jsonp related settings 59457 * @param {String} [datatype] "json" or "jsonp" 59458 * @param {function} [callback] function to be executed after 59459 * loadJSON() completes, data is passed 59460 * in as first argument 59461 * @param {function} [errorCallback] function to be executed if 59462 * there is an error, response is passed 59463 * in as first argument 59464 * @return {Object|Array} JSON data 59465 * @example 59466 * 59467 * <p>Calling loadJSON() inside preload() guarantees to complete the 59468 * operation before setup() and draw() are called.</p> 59469 * 59470 * <div><code> 59471 * // Examples use USGS Earthquake API: 59472 * // https://earthquake.usgs.gov/fdsnws/event/1/#methods 59473 * var earthquakes; 59474 * function preload() { 59475 * // Get the most recent earthquake in the database 59476 * var url = 59477 'https://earthquake.usgs.gov/earthquakes/feed/v1.0/' + 59478 * 'summary/all_day.geojson'; 59479 * earthquakes = loadJSON(url); 59480 * } 59481 * 59482 * function setup() { 59483 * noLoop(); 59484 * } 59485 * 59486 * function draw() { 59487 * background(200); 59488 * // Get the magnitude and name of the earthquake out of the loaded JSON 59489 * var earthquakeMag = earthquakes.features[0].properties.mag; 59490 * var earthquakeName = earthquakes.features[0].properties.place; 59491 * ellipse(width / 2, height / 2, earthquakeMag * 10, earthquakeMag * 10); 59492 * textAlign(CENTER); 59493 * text(earthquakeName, 0, height - 30, width, 30); 59494 * } 59495 * </code></div> 59496 * 59497 * 59498 * <p>Outside of preload(), you may supply a callback function to handle the 59499 * object:</p> 59500 * <div><code> 59501 * function setup() { 59502 * noLoop(); 59503 * var url = 59504 'https://earthquake.usgs.gov/earthquakes/feed/v1.0/' + 59505 * 'summary/all_day.geojson'; 59506 * loadJSON(url, drawEarthquake); 59507 * } 59508 * 59509 * function draw() { 59510 * background(200); 59511 * } 59512 * 59513 * function drawEarthquake(earthquakes) { 59514 * // Get the magnitude and name of the earthquake out of the loaded JSON 59515 * var earthquakeMag = earthquakes.features[0].properties.mag; 59516 * var earthquakeName = earthquakes.features[0].properties.place; 59517 * ellipse(width / 2, height / 2, earthquakeMag * 10, earthquakeMag * 10); 59518 * textAlign(CENTER); 59519 * text(earthquakeName, 0, height - 30, width, 30); 59520 * } 59521 * </code></div> 59522 * 59523 * @alt 59524 * 50x50 ellipse that changes from black to white depending on the current humidity 59525 * 50x50 ellipse that changes from black to white depending on the current humidity 59526 * 59527 */ 59528/** 59529 * @method loadJSON 59530 * @param {String} path 59531 * @param {String} datatype 59532 * @param {function} [callback] 59533 * @param {function} [errorCallback] 59534 * @return {Object|Array} 59535 */ 59536/** 59537 * @method loadJSON 59538 * @param {String} path 59539 * @param {function} callback 59540 * @param {function} [errorCallback] 59541 * @return {Object|Array} 59542 */ 59543p5.prototype.loadJSON = function() { 59544 p5._validateParameters('loadJSON', arguments); 59545 var path = arguments[0]; 59546 var callback; 59547 var errorCallback; 59548 var options; 59549 59550 var ret = {}; // object needed for preload 59551 var t = 'json'; 59552 59553 // check for explicit data type argument 59554 for (var i = 1; i < arguments.length; i++) { 59555 var arg = arguments[i]; 59556 if (typeof arg === 'string') { 59557 if (arg === 'jsonp' || arg === 'json') { 59558 t = arg; 59559 } 59560 } else if (typeof arg === 'function') { 59561 if (!callback) { 59562 callback = arg; 59563 } else { 59564 errorCallback = arg; 59565 } 59566 } else if (typeof arg === 'object' && arg.hasOwnProperty('jsonpCallback')) { 59567 t = 'jsonp'; 59568 options = arg; 59569 } 59570 } 59571 59572 var self = this; 59573 this.httpDo( 59574 path, 59575 'GET', 59576 options, 59577 t, 59578 function(resp) { 59579 for (var k in resp) { 59580 ret[k] = resp[k]; 59581 } 59582 if (typeof callback !== 'undefined') { 59583 callback(resp); 59584 } 59585 59586 self._decrementPreload(); 59587 }, 59588 errorCallback 59589 ); 59590 59591 return ret; 59592}; 59593 59594/** 59595 * Reads the contents of a file and creates a String array of its individual 59596 * lines. If the name of the file is used as the parameter, as in the above 59597 * example, the file must be located in the sketch directory/folder. 59598 * <br><br> 59599 * Alternatively, the file maybe be loaded from anywhere on the local 59600 * computer using an absolute path (something that starts with / on Unix and 59601 * Linux, or a drive letter on Windows), or the filename parameter can be a 59602 * URL for a file found on a network. 59603 * <br><br> 59604 * This method is asynchronous, meaning it may not finish before the next 59605 * line in your sketch is executed. 59606 * 59607 * @method loadStrings 59608 * @param {String} filename name of the file or url to load 59609 * @param {function} [callback] function to be executed after loadStrings() 59610 * completes, Array is passed in as first 59611 * argument 59612 * @param {function} [errorCallback] function to be executed if 59613 * there is an error, response is passed 59614 * in as first argument 59615 * @return {String[]} Array of Strings 59616 * @example 59617 * 59618 * <p>Calling loadStrings() inside preload() guarantees to complete the 59619 * operation before setup() and draw() are called.</p> 59620 * 59621 * <div><code> 59622 * var result; 59623 * function preload() { 59624 * result = loadStrings('assets/test.txt'); 59625 * } 59626 59627 * function setup() { 59628 * background(200); 59629 * var ind = floor(random(result.length)); 59630 * text(result[ind], 10, 10, 80, 80); 59631 * } 59632 * </code></div> 59633 * 59634 * <p>Outside of preload(), you may supply a callback function to handle the 59635 * object:</p> 59636 * 59637 * <div><code> 59638 * function setup() { 59639 * loadStrings('assets/test.txt', pickString); 59640 * } 59641 * 59642 * function pickString(result) { 59643 * background(200); 59644 * var ind = floor(random(result.length)); 59645 * text(result[ind], 10, 10, 80, 80); 59646 * } 59647 * </code></div> 59648 * 59649 * @alt 59650 * randomly generated text from a file, for example "i smell like butter" 59651 * randomly generated text from a file, for example "i have three feet" 59652 * 59653 */ 59654p5.prototype.loadStrings = function() { 59655 p5._validateParameters('loadStrings', arguments); 59656 59657 var ret = []; 59658 var callback, errorCallback; 59659 59660 for (var i = 1; i < arguments.length; i++) { 59661 var arg = arguments[i]; 59662 if (typeof arg === 'function') { 59663 if (typeof callback === 'undefined') { 59664 callback = arg; 59665 } else if (typeof errorCallback === 'undefined') { 59666 errorCallback = arg; 59667 } 59668 } 59669 } 59670 59671 var self = this; 59672 p5.prototype.httpDo.call( 59673 this, 59674 arguments[0], 59675 'GET', 59676 'text', 59677 function(data) { 59678 var arr = data.match(/[^\r\n]+/g); 59679 for (var k in arr) { 59680 ret[k] = arr[k]; 59681 } 59682 59683 if (typeof callback !== 'undefined') { 59684 callback(ret); 59685 } 59686 59687 self._decrementPreload(); 59688 }, 59689 errorCallback 59690 ); 59691 59692 return ret; 59693}; 59694 59695/** 59696 * <p>Reads the contents of a file or URL and creates a p5.Table object with 59697 * its values. If a file is specified, it must be located in the sketch's 59698 * "data" folder. The filename parameter can also be a URL to a file found 59699 * online. By default, the file is assumed to be comma-separated (in CSV 59700 * format). Table only looks for a header row if the 'header' option is 59701 * included.</p> 59702 * 59703 * <p>Possible options include: 59704 * <ul> 59705 * <li>csv - parse the table as comma-separated values</li> 59706 * <li>tsv - parse the table as tab-separated values</li> 59707 * <li>header - this table has a header (title) row</li> 59708 * </ul> 59709 * </p> 59710 * 59711 * <p>When passing in multiple options, pass them in as separate parameters, 59712 * seperated by commas. For example: 59713 * <br><br> 59714 * <code> 59715 * loadTable('my_csv_file.csv', 'csv', 'header'); 59716 * </code> 59717 * </p> 59718 * 59719 * <p> All files loaded and saved use UTF-8 encoding.</p> 59720 * 59721 * <p>This method is asynchronous, meaning it may not finish before the next 59722 * line in your sketch is executed. Calling loadTable() inside preload() 59723 * guarantees to complete the operation before setup() and draw() are called. 59724 * <p>Outside of preload(), you may supply a callback function to handle the 59725 * object:</p> 59726 * </p> 59727 * 59728 * @method loadTable 59729 * @param {String} filename name of the file or URL to load 59730 * @param {String} options "header" "csv" "tsv" 59731 * @param {function} [callback] function to be executed after 59732 * loadTable() completes. On success, the 59733 * Table object is passed in as the 59734 * first argument. 59735 * @param {function} [errorCallback] function to be executed if 59736 * there is an error, response is passed 59737 * in as first argument 59738 * @return {Object}
59738 Table object containing data 59739 * 59740 * @example 59741 * <div class="norender"> 59742 * <code> 59743 * // Given the following CSV file called "mammals.csv" 59744 * // located in the project's "assets" folder: 59745 * // 59746 * // id,species,name 59747 * // 0,Capra hircus,Goat 59748 * // 1,Panthera pardus,Leopard 59749 * // 2,Equus zebra,Zebra 59750 * 59751 * var table; 59752 * 59753 * function preload() { 59754 * //my table is comma separated value "csv" 59755 * //and has a header specifying the columns labels 59756 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 59757 * //the file can be remote 59758 * //table = loadTable("http://p5js.org/reference/assets/mammals.csv", 59759 * // "csv", "header"); 59760 * } 59761 * 59762 * function setup() { 59763 * //count the columns 59764 * print(table.getRowCount() + ' total rows in table'); 59765 * print(table.getColumnCount() + ' total columns in table'); 59766 * 59767 * print(table.getColumn('name')); 59768 * //["Goat", "Leopard", "Zebra"] 59769 * 59770 * //cycle through the table 59771 * for (var r = 0; r < table.getRowCount(); r++) 59772 * for (var c = 0; c < table.getColumnCount(); c++) { 59773 * print(table.getString(r, c)); 59774 * } 59775 * } 59776 * </code> 59777 * </div> 59778 * 59779 * @alt 59780 * randomly generated text from a file, for example "i smell like butter" 59781 * randomly generated text from a file, for example "i have three feet" 59782 * 59783 */ 59784/** 59785 * @method loadTable 59786 * @param {String} filename 59787 * @param {function} [callback] 59788 * @param {function} [errorCallback] 59789 * @return {Object} 59790 */ 59791p5.prototype.loadTable = function(path) { 59792 var callback; 59793 var errorCallback; 59794 var options = []; 59795 var header = false;
59796 var ext = path.substring(path.lastIndexOf('.') + 1, path.length); 59797 var sep = ','; 59798 var separatorSet = false; 59799 59800 if (ext === 'tsv') { 59801 //Only need to check extension is tsv because csv is default 59802 sep = '\t'; 59803 } 59804 59805 for (var i = 1; i < arguments.length; i++) { 59806 if (typeof arguments[i] === 'function') { 59807 if (typeof callback === 'undefined') { 59808 callback = arguments[i]; 59809 } else if (typeof errorCallback === 'undefined') { 59810 errorCallback = arguments[i]; 59811 } 59812 } else if (typeof arguments[i] === 'string') { 59813 options.push(arguments[i]); 59814 if (arguments[i] === 'header') { 59815 header = true; 59816 } 59817 if (arguments[i] === 'csv') { 59818 if (separatorSet) { 59819 throw new Error('Cannot set multiple separator types.'); 59820 } else { 59821 sep = ','; 59822 separatorSet = true; 59823 } 59824 } else if (arguments[i] === 'tsv') { 59825 if (separatorSet) { 59826 throw new Error('Cannot set multiple separator types.'); 59827 } else { 59828 sep = '\t'; 59829 separatorSet = true; 59830 } 59831 } 59832 } 59833 } 59834 59835 var t = new p5.Table(); 59836 59837 var self = this; 59838 this.httpDo( 59839 path, 59840 'GET', 59841 'text', 59842 function(resp) { 59843 var state = {}; 59844 59845 // define constants 59846 var PRE_TOKEN = 0, 59847 MID_TOKEN = 1, 59848 POST_TOKEN = 2, 59849 POST_RECORD = 4; 59850 59851 var QUOTE = '"', 59852 CR = '\r', 59853 LF = '\n'; 59854 59855 var records = []; 59856 var offset = 0; 59857 var currentRecord = null; 59858 var currentChar; 59859 59860 var tokenBegin = function() { 59861 state.currentState = PRE_TOKEN; 59862 state.token = ''; 59863 }; 59864 59865 var tokenEnd = function() { 59866 currentRecord.push(state.token); 59867 tokenBegin(); 59868 }; 59869 59870 var recordBegin = function() { 59871 state.escaped = false; 59872 currentRecord = []; 59873 tokenBegin(); 59874 }; 59875 59876 var recordEnd = function() { 59877 state.currentState = POST_RECORD; 59878 records.push(currentRecord); 59879 currentRecord = null; 59880 }; 59881 59882 for (;;) { 59883 currentChar = resp[offset++]; 59884 59885 // EOF 59886 if (currentChar == null) { 59887 if (state.escaped) { 59888 throw new Error('Unclosed quote in file.'); 59889 } 59890 if (currentRecord) { 59891 tokenEnd(); 59892 recordEnd(); 59893 break; 59894 } 59895 } 59896 if (currentRecord === null) { 59897 recordBegin(); 59898 } 59899 59900 // Handle opening quote 59901 if (state.currentState === PRE_TOKEN) { 59902 if (currentChar === QUOTE) { 59903 state.escaped = true; 59904 state.currentState = MID_TOKEN; 59905 continue; 59906 } 59907 state.currentState = MID_TOKEN; 59908 } 59909 59910 // mid-token and escaped, look for sequences and end quote 59911 if (state.currentState === MID_TOKEN && state.escaped) { 59912 if (currentChar === QUOTE) { 59913 if (resp[offset] === QUOTE) { 59914 state.token += QUOTE; 59915 offset++; 59916 } else { 59917 state.escaped = false; 59918 state.currentState = POST_TOKEN; 59919 } 59920 } else if (currentChar === CR) { 59921 continue; 59922 } else { 59923 state.token += currentChar; 59924 } 59925 continue; 59926 } 59927 59928 // fall-through: mid-token or post-token, not escaped 59929 if (currentChar === CR) { 59930 if (resp[offset] === LF) { 59931 offset++; 59932 } 59933 tokenEnd(); 59934 recordEnd(); 59935 } else if (currentChar === LF) { 59936 tokenEnd(); 59937 recordEnd(); 59938 } else if (currentChar === sep) { 59939 tokenEnd(); 59940 } else if (state.currentState === MID_TOKEN) { 59941 state.token += currentChar; 59942 } 59943 } 59944 59945 // set up column names 59946 if (header) { 59947 t.columns = records.shift(); 59948 } else { 59949 for (i = 0; i < records[0].length; i++) { 59950 t.columns[i] = 'null'; 59951 } 59952 } 59953 var row; 59954 for (i = 0; i < records.length; i++) { 59955 //Handles row of 'undefined' at end of some CSVs 59956 if (records[i].length === 1) { 59957 if (records[i][0] === 'undefined' || records[i][0] === '') { 59958 continue; 59959 } 59960 } 59961 row = new p5.TableRow(); 59962 row.arr = records[i]; 59963 row.obj = makeObject(records[i], t.columns); 59964 t.addRow(row); 59965 } 59966 if (typeof callback === 'function') { 59967 callback(t); 59968 } 59969 59970 self._decrementPreload(); 59971 }, 59972 function(err) { 59973 // Error handling 59974 p5._friendlyFileLoadError(2, path); 59975 59976 if (errorCallback) { 59977 errorCallback(err); 59978 } else { 59979 throw err; 59980 } 59981 } 59982 ); 59983 59984 return t; 59985}; 59986 59987// helper function to turn a row into a JSON object 59988function makeObject(row, headers) { 59989 var ret = {}; 59990 headers = headers || []; 59991 if (typeof headers === 'undefined') { 59992 for (var j = 0; j < row.length; j++) { 59993 headers[j.toString()] = j; 59994 } 59995 } 59996 for (var i = 0; i < headers.length; i++) { 59997 var key = headers[i]; 59998 var val = row[i]; 59999 ret[key] = val; 60000 } 60001 return ret; 60002} 60003 60004function parseXML(two) { 60005 var one = new p5.XML(); 60006 var children = two.childNodes; 60007 if (children && children.length) { 60008 for (var i = 0; i < children.length; i++) { 60009 var node = parseXML(children[i]); 60010 one.addChild(node); 60011 } 60012 one.setName(two.nodeName); 60013 one._setCont(two.textContent); 60014 one._setAttributes(two); 60015 for (var j = 0; j < one.children.length; j++) { 60016 one.children[j].parent = one; 60017 } 60018 return one; 60019 } else { 60020 one.setName(two.nodeName); 60021 one._setCont(two.textContent); 60022 one._setAttributes(two); 60023 return one; 60024 } 60025} 60026 60027/**
60028 * Reads the contents of a file and creates an XML object with its values. 60029 * If the name of the file is used as the parameter, as in the above example, 60030 * the file must be located in the sketch directory/folder. 60031 * 60032 * Alternatively, the file maybe be loaded from anywhere on the local 60033 * computer using an absolute path (something that starts with / on Unix and 60034 * Linux, or a drive letter on Windows), or the filename parameter can be a 60035 * URL for a file found on a network. 60036 * 60037 * This method is asynchronous, meaning it may not finish before the next 60038 * line in your sketch is executed. Calling loadXML() inside preload() 60039 * guarantees to complete the operation before setup() and draw() are called. 60040 * 60041 * Outside of preload(), you may supply a callback function to handle the 60042 * object. 60043 * 60044 * @method loadXML 60045 * @param {String} filename name of the file or URL to load 60046 * @param {function} [callback] function to be executed after loadXML() 60047 * completes, XML object is passed in as 60048 * first argument 60049 * @param {function} [errorCallback] function to be executed if 60050 * there is an error, response is passed 60051 * in as first argument 60052 * @return {Object} XML object containing data 60053 * @example 60054 * <div class='norender'><code> 60055 * // The following short XML file called "mammals.xml" is parsed 60056 * // in the code below. 60057 * // 60058 * // <?xml version="1.0"?> 60059 * // <mammals> 60060 * // <animal id="0" species="Capra hircus">Goat</animal> 60061 * // <animal id="1" species="Panthera pardus">Leopard</animal> 60062 * // <animal id="2" species="Equus zebra">Zebra</animal> 60063 * // </mammals> 60064 * 60065 * var xml; 60066 * 60067 * function preload() { 60068 * xml = loadXML('assets/mammals.xml'); 60069 * } 60070 * 60071 * function setup() { 60072 * var children = xml.getChildren('animal'); 60073 * 60074 * for (var i = 0; i < children.length; i++) { 60075 * var id = children[i].getNum('id'); 60076 * var coloring = children[i].getString('species'); 60077 * var name = children[i].getContent(); 60078 * print(id + ', ' + coloring + ', ' + name); 60079 * } 60080 * } 60081 * 60082 * // Sketch prints: 60083 * // 0, Capra hircus, Goat 60084 * // 1, Panthera pardus, Leopard 60085 * // 2, Equus zebra, Zebra 60086 * </code></div> 60087 * 60088 * @alt 60089 * no image displayed 60090 * 60091 */ 60092p5.prototype.loadXML = function() { 60093 var ret = {}; 60094 var callback, errorCallback; 60095 60096 for (var i = 1; i < arguments.length; i++) { 60097 var arg = arguments[i]; 60098 if (typeof arg === 'function') { 60099 if (typeof callback === 'undefined') { 60100 callback = arg; 60101 } else if (typeof errorCallback === 'undefined') { 60102 errorCallback = arg; 60103 } 60104 } 60105 } 60106 60107 var self = this; 60108 this.httpDo( 60109 arguments[0], 60110 'GET', 60111 'xml', 60112 function(xml) { 60113 for (var key in xml) { 60114 ret[key] = xml[key]; 60115 } 60116 if (typeof callback !== 'undefined') { 60117 callback(ret); 60118 } 60119 60120 self._decrementPreload(); 60121 }, 60122 errorCallback 60123 ); 60124 60125 return ret; 60126}; 60127 60128/** 60129 * @method loadBytes 60130 * @param {string} file name of the file or URL to load 60131 * @param {function} [callback] function to be executed after loadBytes() 60132 * completes 60133 * @param {function} [errorCallback] function to be executed if there 60134 * is an error 60135 * @returns {Object} an object whose 'bytes' property will be the loaded buffer 60136 * 60137 * @example 60138 * <div class='norender'><code> 60139 * var data; 60140 * 60141 * function preload() { 60142 * data = loadBytes('assets/mammals.xml'); 60143 * } 60144 * 60145 * function setup() { 60146 * for (var i = 0; i < 5; i++) { 60147 * console.log(data.bytes[i].toString(16)); 60148 * } 60149 * } 60150 * </code></div> 60151 * 60152 * @alt 60153 * no image displayed 60154 * 60155 */ 60156p5.prototype.loadBytes = function(file, callback, errorCallback) { 60157 var ret = {}; 60158 60159 var self = this; 60160 this.httpDo( 60161 file, 60162 'GET', 60163 'arrayBuffer', 60164 function(arrayBuffer) { 60165 ret.bytes = new Uint8Array(arrayBuffer); 60166 60167 if (typeof callback === 'function') { 60168 callback(ret); 60169 } 60170 60171 self._decrementPreload(); 60172 }, 60173 errorCallback 60174 ); 60175 return ret; 60176}; 60177 60178/** 60179 * Method for executing an HTTP GET request. If data type is not specified, 60180 * p5 will try to guess based on the URL, defaulting to text. This is equivalent to 60181 * calling <code>httpDo(path, 'GET')</code>. The 'binary' datatype will return 60182 * a Blob object, and the 'arrayBuffer' datatype will return an ArrayBuffer 60183 * which can be used to initialize typed arrays (such as Uint8Array). 60184 * 60185 * @method httpGet 60186 * @param {String} path name of the file or url to load 60187 * @param {String} [datatype] "json", "jsonp", "binary", "arrayBuffer", 60188 * "xml", or "text" 60189 * @param {Object|Boolean} [data] param data passed sent with request 60190 * @param {function} [callback] function to be executed after 60191 * httpGet() completes, data is passed in 60192 * as first argument 60193 * @param {function} [errorCallback] function to be executed if 60194 * there is an error, response is passed 60195 * in as first argument 60196 * @example 60197 * <div class='norender'><code> 60198 * // Examples use USGS Earthquake API: 60199 * // https://earthquake.usgs.gov/fdsnws/event/1/#methods 60200 * var earthquakes; 60201 * function preload() { 60202 * // Get the most recent earthquake in the database 60203 * var url = 60204 'https://earthquake.usgs.gov/fdsnws/event/1/query?' + 60205 * 'format=geojson&limit=1&orderby=time'; 60206 * httpGet(url, 'jsonp', false, function(response) { 60207 * // when the HTTP request completes, populate the variable that holds the 60208 * // earthquake data used in the visualization. 60209 * earthquakes = response; 60210 * }); 60211 * } 60212 * 60213 * function draw() { 60214 * if (!earthquakes) { 60215 * // Wait until the earthquake data has loaded before drawing. 60216 * return; 60217 * } 60218 * background(200); 60219 * // Get the magnitude and name of the earthquake out of the loaded JSON 60220 * var earthquakeMag = earthquakes.features[0].properties.mag; 60221 * var earthquakeName = earthquakes.features[0].properties.place; 60222 * ellipse(width / 2, height / 2, earthquakeMag * 10, earthquakeMag * 10); 60223 * textAlign(CENTER);
60224 * text(earthquakeName, 0, height - 30, width, 30); 60225 * noLoop(); 60226 * } 60227 * </code></div> 60228 */ 60229/** 60230 * @method httpGet 60231 * @param {String} path 60232 * @param {Object|Boolean} data 60233 * @param {function} [callback] 60234 * @param {function} [errorCallback] 60235 */ 60236/** 60237 * @method httpGet 60238 * @param {String} path 60239 * @param {function} callback 60240 * @param {function} [errorCallback] 60241 */ 60242p5.prototype.httpGet = function() { 60243 p5._validateParameters('httpGet', arguments); 60244 60245 var args = Array.prototype.slice.call(arguments); 60246 args.splice(1, 0, 'GET'); 60247 p5.prototype.httpDo.apply(this, args); 60248}; 60249 60250/** 60251 * Method for executing an HTTP POST request. If data type is not specified, 60252 * p5 will try to guess based on the URL, defaulting to text. This is equivalent to 60253 * calling <code>httpDo(path, 'POST')</code>. 60254 * 60255 * @method httpPost 60256 * @param {String} path name of the file or url to load 60257 * @param {String} [datatype] "json", "jsonp", "xml", or "text". 60258 * If omitted, httpPost() will guess. 60259 * @param {Object|Boolean} [data] param data passed sent with request 60260 * @param {function} [callback] function to be executed after 60261 * httpPost() completes, data is passed in 60262 * as first argument 60263 * @param {function} [errorCallback] function to be executed if 60264 * there is an error, response is passed 60265 * in as first argument 60266 * 60267 * @example 60268 * <div> 60269 * <code> 60270 * // Examples use jsonplaceholder.typicode.com for a Mock Data API 60271 * 60272 * var url = 'https://jsonplaceholder.typicode.com/posts'; 60273 * var postData = { userId: 1, title: 'p5 Clicked!', body: 'p5.js is way cool.' }; 60274 * 60275 * function setup() { 60276 * createCanvas(800, 800); 60277 * } 60278 * 60279 * function mousePressed() { 60280 * // Pick new random color values 60281 * var r = random(255); 60282 * var g = random(255); 60283 * var b = random(255); 60284 * 60285 * httpPost(url, 'json', postData, function(result) { 60286 * strokeWeight(2); 60287 * stroke(r, g, b); 60288 * fill(r, g, b, 127); 60289 * ellipse(mouseX, mouseY, 200, 200); 60290 * text(result.body, mouseX, mouseY); 60291 * }); 60292 * } 60293 * </code> 60294 * </div> 60295 * 60296 * 60297 * <div><code> 60298 * var url = 'https://invalidURL'; // A bad URL that will cause errors 60299 * var postData = { title: 'p5 Clicked!', body: 'p5.js is way cool.' }; 60300 * 60301 * function setup() { 60302 * createCanvas(800, 800); 60303 * } 60304 * 60305 * function mousePressed() { 60306 * // Pick new random color values 60307 * var r = random(255); 60308 * var g = random(255); 60309 * var b = random(255); 60310 * 60311 * httpPost( 60312 * url, 60313 * 'json', 60314 * postData, 60315 * function(result) { 60316 * // ... won't be called 60317 * }, 60318 * function(error) { 60319 * strokeWeight(2); 60320 * stroke(r, g, b); 60321 * fill(r, g, b, 127); 60322 * text(error.toString(), mouseX, mouseY); 60323 * } 60324 * ); 60325 * } 60326 * </code></div> 60327 * 60328 */ 60329/** 60330 * @method httpPost 60331 * @param {String} path 60332 * @param {Object|Boolean} data 60333 * @param {function} [callback] 60334 * @param {function} [errorCallback] 60335 */ 60336/** 60337 * @method httpPost 60338 * @param {String} path 60339 * @param {function} callback 60340 * @param {function} [errorCallback] 60341 */ 60342p5.prototype.httpPost = function() { 60343 p5._validateParameters('httpPost', arguments); 60344 60345 var args = Array.prototype.slice.call(arguments); 60346 args.splice(1, 0, 'POST'); 60347 p5.prototype.httpDo.apply(this, args); 60348}; 60349 60350/** 60351 * Method for executing an HTTP request. If data type is not specified, 60352 * p5 will try to guess based on the URL, defaulting to text.<br><br> 60353 * For more advanced use, you may also pass in the path as the first argument 60354 * and a object as the second argument, the signature follows the one specified 60355 * in the Fetch API specification. 60356 * 60357 * @method httpDo 60358 * @param {String} path name of the file or url to load 60359 * @param {String} [method] either "GET", "POST", or "PUT", 60360 * defaults to "GET" 60361 * @param {String} [datatype] "json", "jsonp", "xml", or "text" 60362 * @param {Object} [data] param data passed sent with request 60363 * @param {function} [callback] function to be executed after 60364 * httpGet() completes, data is passed in 60365 * as first argument 60366 * @param {function} [errorCallback] function to be executed if 60367 * there is an error, response is passed 60368 * in as first argument 60369 * 60370 * 60371 * @example 60372 * <div> 60373 * <code> 60374 * // Examples use USGS Earthquake API: 60375 * // https://earthquake.usgs.gov/fdsnws/event/1/#methods 60376 * 60377 * // displays an animation of all USGS earthquakes 60378 * var earthquakes; 60379 * var eqFeatureIndex = 0; 60380 * 60381 * function preload() { 60382 * var url = 'https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson'; 60383 * httpDo( 60384 * url, 60385 * { 60386 * method: 'GET', 60387 * // Other Request options, like special headers for apis 60388 * headers: { authorization: 'Bearer secretKey' } 60389 * }, 60390 * function(res) { 60391 * earthquakes = res; 60392 * } 60393 * ); 60394 * } 60395 * 60396 * function draw() { 60397 * // wait until the data is loaded 60398 * if (!earthquakes || !earthquakes.features[eqFeatureIndex]) { 60399 * return; 60400 * } 60401 * clear(); 60402 * 60403 * var feature = earthquakes.features[eqFeatureIndex]; 60404 * var mag = feature.properties.mag; 60405 * var rad = mag / 11 * ((width + height) / 2); 60406 * fill(255, 0, 0, 100); 60407 * ellipse(width / 2 + random(-2, 2), height / 2 + random(-2, 2), rad, rad); 60408 * 60409 * if (eqFeatureIndex >= earthquakes.features.length) { 60410 * eqFeatureIndex = 0; 60411 * } else { 60412 * eqFeatureIndex += 1; 60413 * } 60414 * } 60415 * </code> 60416 * </div> 60417 */ 60418/** 60419 * @method httpDo 60420 * @param {String} path 60421 * @param {Object} options Request object options as documented in the 60422 * "fetch" API 60423 * <a href="https://developer.mozilla.org/en/docs/Web/API/Fetch_API">reference</a> 60424 * @param {function} [callback] 60425 * @param {function} [errorCallback] 60426 */ 60427p5.prototype.httpDo = function() { 60428 var type; 60429 var callback; 60430 var errorCallback; 60431 var request; 60432 var jsonpOptions = {}; 60433 var cbCount = 0; 60434 var contentType = 'text/plain';
60435 // Trim the callbacks off the end to get an idea of how many arguments are passed 60436 for (var i = arguments.length - 1; i > 0; i--) { 60437 if (typeof arguments[i] === 'function') { 60438 cbCount++; 60439 } else { 60440 break; 60441 } 60442 } 60443 // The number of arguments minus callbacks 60444 var argsCount = arguments.length - cbCount; 60445 var path = arguments[0]; 60446 if ( 60447 argsCount === 2 && 60448 typeof path === 'string' && 60449 typeof arguments[1] === 'object' 60450 ) { 60451 // Intended for more advanced use, pass in Request parameters directly 60452 request = new Request(path, arguments[1]); 60453 callback = arguments[2]; 60454 errorCallback = arguments[3]; 60455 } else { 60456 // Provided with arguments 60457 var method = 'GET'; 60458 var data; 60459 60460 for (var j = 1; j < arguments.length; j++) { 60461 var a = arguments[j]; 60462 if (typeof a === 'string') { 60463 if (a === 'GET' || a === 'POST' || a === 'PUT' || a === 'DELETE') { 60464 method = a; 60465 } else if ( 60466 a === 'json' || 60467 a === 'jsonp' || 60468 a === 'binary' || 60469 a === 'arrayBuffer' || 60470 a === 'xml' || 60471 a === 'text' 60472 ) { 60473 type = a; 60474 } else { 60475 data = a; 60476 } 60477 } else if (typeof a === 'number') { 60478 data = a.toString(); 60479 } else if (typeof a === 'object') { 60480 if (a.hasOwnProperty('jsonpCallback')) { 60481 for (var attr in a) { 60482 jsonpOptions[attr] = a[attr]; 60483 } 60484 } else { 60485 data = JSON.stringify(a); 60486 contentType = 'application/json'; 60487 } 60488 } else if (typeof a === 'function') { 60489 if (!callback) { 60490 callback = a; 60491 } else { 60492 errorCallback = a; 60493 } 60494 } 60495 } 60496 60497 request = new Request(path, { 60498 method: method, 60499 mode: 'cors', 60500 body: data, 60501 headers: new Headers({ 60502 'Content-Type': contentType 60503 }) 60504 }); 60505 } 60506 60507 // do some sort of smart type checking 60508 if (!type) { 60509 if (path.indexOf('json') !== -1) { 60510 type = 'json'; 60511 } else if (path.indexOf('xml') !== -1) { 60512 type = 'xml'; 60513 } else { 60514 type = 'text'; 60515 } 60516 } 60517 60518 (type === 'jsonp' ? fetchJsonp(path, jsonpOptions) : fetch(request)) 60519 .then(function(res) { 60520 if (!res.ok) throw res; 60521 60522 switch (type) { 60523 case 'json': 60524 return res.json(); 60525 case 'binary': 60526 return res.blob(); 60527 case 'arrayBuffer': 60528 return res.arrayBuffer(); 60529 case 'xml': 60530 return res.text().then(function(text) { 60531 var parser = new DOMParser(); 60532 var xml = parser.parseFromString(text, 'text/xml'); 60533 return parseXML(xml.documentElement); 60534 }); 60535 default: 60536 return res.text(); 60537 } 60538 }) 60539 .then(callback || function() {}) 60540 .catch(errorCallback || console.error); 60541}; 60542 60543/** 60544 * @module IO 60545 * @submodule Output 60546 * @for p5 60547 */ 60548 60549window.URL = window.URL || window.webkitURL; 60550 60551// private array of p5.PrintWriter objects 60552p5.prototype._pWriters = []; 60553 60554/** 60555 * @method createWriter 60556 * @param {String} name name of the file to be created 60557 * @param {String} [extension] 60558 * @return {p5.PrintWriter} 60559 * @example 60560 * <div> 60561 * <code> 60562 * createButton('save') 60563 * .position(10, 10) 60564 * .mousePressed(function() { 60565 * var writer = createWriter('squares.txt'); 60566 * for (var i = 0; i < 10; i++) { 60567 * writer.print(i * i); 60568 * } 60569 * writer.close(); 60570 * writer.clear(); 60571 * }); 60572 * </code> 60573 * </div> 60574 */ 60575p5.prototype.createWriter = function(name, extension) { 60576 var newPW; 60577 // check that it doesn't already exist 60578 for (var i in p5.prototype._pWriters) { 60579 if (p5.prototype._pWriters[i].name === name) { 60580 // if a p5.PrintWriter w/ this name already exists... 60581 // return p5.prototype._pWriters[i]; // return it w/ contents intact. 60582 // or, could return a new, empty one with a unique name: 60583 newPW = new p5.PrintWriter(name + this.millis(), extension); 60584 p5.prototype._pWriters.push(newPW); 60585 return newPW; 60586 } 60587 } 60588 newPW = new p5.PrintWriter(name, extension); 60589 p5.prototype._pWriters.push(newPW); 60590 return newPW; 60591}; 60592 60593/** 60594 * @class p5.PrintWriter 60595 * @param {String} filename 60596 * @param {String} [extension] 60597 */ 60598p5.PrintWriter = function(filename, extension) { 60599 var self = this; 60600 this.name = filename; 60601 this.content = ''; 60602 //Changed to write because it was being overloaded by function below. 60603 /** 60604 * Writes data to the PrintWriter stream 60605 * @method write 60606 * @param {Array} data all data to be written by the PrintWriter 60607 * @example 60608 * <div class="norender notest"> 60609 * <code> 60610 * // creates a file called 'newFile.txt' 60611 * var writer = createWriter('newFile.txt'); 60612 * // write 'Hello world!'' to the file 60613 * writer.write(['Hello world!']); 60614 * // close the PrintWriter and save the file 60615 * writer.close(); 60616 * </code> 60617 * </div> 60618 * <div class='norender notest'> 60619 * <code> 60620 * // creates a file called 'newFile2.txt' 60621 * var writer = createWriter('newFile2.txt'); 60622 * // write 'apples,bananas,123' to the file 60623 * writer.write(['apples', 'bananas', 123]); 60624 * // close the PrintWriter and save the file 60625 * writer.close(); 60626 * </code> 60627 * </div> 60628 * <div class='norender notest'> 60629 * <code> 60630 * // creates a file called 'newFile3.txt' 60631 * var writer = createWriter('newFile3.txt'); 60632 * // write 'My name is: Teddy' to the file 60633 * writer.write('My name is:'); 60634 * writer.write(' Teddy'); 60635 * // close the PrintWriter and save the file 60636 * writer.close(); 60637 * </code> 60638 * </div> 60639 */ 60640 this.write = function(data) { 60641 this.content += data; 60642 }; 60643 /** 60644 * Writes data to the PrintWriter stream, and adds a new line at the end 60645 * @method print 60646 * @param {Array} data all data to be printed by the PrintWriter 60647 * @example 60648 * <div class='norender notest'> 60649 * <code> 60650 * // creates a file called 'newFile.txt' 60651 * var writer = createWriter('newFile.txt'); 60652 * // creates a file containing 60653 * // My name is: 60654 * // Teddy 60655 * writer.print('My name is:'); 60656 * writer.print('Teddy'); 60657 * // close the PrintWriter and save the file 60658 * writer.close(); 60659 * </code> 60660 * </div> 60661 * <div class='norender notest'> 60662 * <code> 60663 * var writer; 60664 * 60665 * function setup() { 60666 * createCanvas(400, 400); 60667 * // create a PrintWriter 60668 * writer = createWriter('newFile.txt'); 60669 * } 60670 * 60671 * function draw() { 60672 * // print all mouseX and mouseY coordinates to the stream 60673 * writer.print([mouseX, mouseY]); 60674 * } 60675 * 60676 * function mouseClicked() { 60677 * // close the PrintWriter and save the file 60678 * writer.close(); 60679 * } 60680 * </code> 60681 * </div> 60682 */ 60683 this.print = function(data) { 60684 this.content += data + '\n'; 60685 }; 60686 /** 60687 * Clears the data already written to the PrintWriter object 60688 * @method clear 60689 * @example 60690 * <div class ="norender notest"><code> 60691 * // create writer object 60692 * var writer = createWriter('newFile.txt'); 60693 * writer.write(['clear me']); 60694 * // clear writer object here 60695 * writer.clear(); 60696 * // close writer 60697 * writer.close(); 60698 * </code></div> 60699 * 60700 */ 60701 this.clear = function() { 60702 this.content = ''; 60703 }; 60704 /** 60705 * Closes the PrintWriter 60706 * @method close 60707 * @example 60708 * <div class="norender notest"> 60709 * <code> 60710 * // create a file called 'newFile.txt' 60711 * var writer = createWriter('newFile.txt'); 60712 * // close the PrintWriter and save the file 60713 * writer.close(); 60714 * </code> 60715 * </div> 60716 * <div class='norender notest'> 60717 * <code> 60718 * // create a file called 'newFile2.txt' 60719 * var writer = createWriter('newFile2.txt'); 60720 * // write some data to the file 60721 * writer.write([100, 101, 102]); 60722 * // close the PrintWriter and save the file 60723 * writer.close(); 60724 * </code> 60725 * </div> 60726 */ 60727 this.close = function() { 60728 // convert String to Array for the writeFile Blob 60729 var arr = []; 60730 arr.push(this.content); 60731 p5.prototype.writeFile(arr, filename, extension); 60732 // remove from _pWriters array and delete self 60733 for (var i in p5.prototype._pWriters) { 60734 if (p5.prototype._pWriters[i].name === this.name) { 60735 // remove from _pWriters array 60736 p5.prototype._pWriters.splice(i, 1); 60737 } 60738 } 60739 self.clear(); 60740 self = {}; 60741 }; 60742}; 60743 60744/** 60745 * @module IO 60746 * @submodule Output 60747 * @for p5 60748 */ 60749 60750// object, filename, options --> saveJSON, saveStrings, 60751// filename, [extension] [canvas] --> saveImage 60752 60753/** 60754 * <p>Save an image, text, json, csv, wav, or html. Prompts download to 60755 * the client's computer. <b>Note that it is not recommended to call save() 60756 * within draw if it's looping, as the save() function will open a new save 60757 * dialog every frame.</b></p> 60758 * <p>The default behavior is to save the canvas as an image. You can 60759 * optionally specify a filename. 60760 * For example:</p> 60761 * <pre class='language-javascript'><code> 60762 * save(); 60763 * save('myCanvas.jpg'); // save a specific canvas with a filename 60764 * </code></pre> 60765 * 60766 * <p>Alternately, the first parameter can be a pointer to a canvas 60767 * p5.Element, an Array of Strings, 60768 * an Array of JSON, a JSON object, a p5.Table, a p5.Image, or a 60769 * p5.SoundFile (requires p5.sound). The second parameter is a filename 60770 * (including extension). The third parameter is for options specific 60771 * to this type of object. This method will save a file that fits the 60772 * given paramaters. For example:</p> 60773 * 60774 * <pre class='language-javascript'><code> 60775 * // Saves canvas as an image 60776 * save('myCanvas.jpg'); 60777 * 60778 * // Saves pImage as a png image 60779 * var img = createImage(10, 10); 60780 * save(img, 'my.png'); 60781 * 60782 * // Saves canvas as an image 60783 * var cnv = createCanvas(100, 100); 60784 * save(cnv, 'myCanvas.jpg'); 60785 * 60786 * // Saves p5.Renderer object as an image 60787 * var gb = createGraphics(100, 100); 60788 * save(gb, 'myGraphics.jpg'); 60789 * 60790 * var myTable = new p5.Table(); 60791 * 60792 * // Saves table as html file 60793 * save(myTable, 'myTable.html'); 60794 * 60795 * // Comma Separated Values 60796 * save(myTable, 'myTable.csv'); 60797 * 60798 * // Tab Separated Values 60799 * save(myTable, 'myTable.tsv'); 60800 * 60801 * var myJSON = { a: 1, b: true }; 60802 * 60803 * // Saves pretty JSON 60804 * save(myJSON, 'my.json'); 60805 * 60806 * // Optimizes JSON filesize 60807 * save(myJSON, 'my.json', true); 60808 *
60809 * // Saves array of strings to a text file with line breaks after each item 60810 * var arrayOfStrings = ['a', 'b']; 60811 * save(arrayOfStrings, 'my.txt'); 60812 * </code></pre> 60813 * 60814 * @method save 60815 * @param {Object|String} [objectOrFilename] If filename is provided, will 60816 * save canvas as an image with 60817 * either png or jpg extension 60818 * depending on the filename. 60819 * If object is provided, will 60820 * save depending on the object 60821 * and filename (see examples 60822 * above). 60823 * @param {String} [filename] If an object is provided as the first 60824 * parameter, then the second parameter 60825 * indicates the filename, 60826 * and should include an appropriate 60827 * file extension (see examples above). 60828 * @param {Boolean|String} [options] Additional options depend on 60829 * filetype. For example, when saving JSON, 60830 * <code>true</code> indicates that the 60831 * output will be optimized for filesize, 60832 * rather than readability. 60833 */ 60834p5.prototype.save = function(object, _filename, _options) { 60835 // parse the arguments and figure out which things we are saving 60836 var args = arguments; 60837 // ================================================= 60838 // OPTION 1: saveCanvas... 60839 60840 // if no arguments are provided, save canvas 60841 var cnv = this._curElement.elt; 60842 if (args.length === 0) { 60843 p5.prototype.saveCanvas(cnv); 60844 return; 60845 } else if (args[0] instanceof p5.Renderer || args[0] instanceof p5.Graphics) { 60846 // otherwise, parse the arguments 60847 60848 // if first param is a p5Graphics, then saveCanvas 60849 p5.prototype.saveCanvas(args[0].elt, args[1], args[2]); 60850 return; 60851 } else if (args.length === 1 && typeof args[0] === 'string') { 60852 // if 1st param is String and only one arg, assume it is canvas filename 60853 p5.prototype.saveCanvas(cnv, args[0]); 60854 } else { 60855 // ================================================= 60856 // OPTION 2: extension clarifies saveStrings vs. saveJSON 60857 var extension = _checkFileExtension(args[1], args[2])[1]; 60858 switch (extension) { 60859 case 'json': 60860 p5.prototype.saveJSON(args[0], args[1], args[2]); 60861 return; 60862 case 'txt': 60863 p5.prototype.saveStrings(args[0], args[1], args[2]); 60864 return; 60865 // ================================================= 60866 // OPTION 3: decide based on object... 60867 default: 60868 if (args[0] instanceof Array) { 60869 p5.prototype.saveStrings(args[0], args[1], args[2]); 60870 } else if (args[0] instanceof p5.Table) { 60871 p5.prototype.saveTable(args[0], args[1], args[2]); 60872 } else if (args[0] instanceof p5.Image) { 60873 p5.prototype.saveCanvas(args[0].canvas, args[1]); 60874 } else if (args[0] instanceof p5.SoundFile) { 60875 p5.prototype.saveSound(args[0], args[1], args[2], args[3]); 60876 } 60877 } 60878 } 60879}; 60880 60881/** 60882 * Writes the contents of an Array or a JSON object to a .json file. 60883 * The file saving process and location of the saved file will 60884 * vary between web browsers. 60885 * 60886 * @method saveJSON 60887 * @param {Array|Object} json 60888 * @param {String} filename 60889 * @param {Boolean} [optimize] If true, removes line breaks 60890 * and spaces from the output 60891 * file to optimize filesize 60892 * (but not readability). 60893 * @example 60894 * <div><code> 60895 * var json = {}; // new JSON Object 60896 * 60897 * json.id = 0; 60898 * json.species = 'Panthera leo'; 60899 * json.name = 'Lion'; 60900 * 60901 * createButton('save') 60902 * .position(10, 10) 60903 * .mousePressed(function() { 60904 * saveJSON(json, 'lion.json'); 60905 * }); 60906 * 60907 * // saves the following to a file called "lion.json": 60908 * // { 60909 * // "id": 0, 60910 * // "species": "Panthera leo", 60911 * // "name": "Lion" 60912 * // } 60913 * </code></div> 60914 * 60915 * @alt 60916 * no image displayed 60917 * 60918 */ 60919p5.prototype.saveJSON = function(json, filename, opt) { 60920 p5._validateParameters('saveJSON', arguments); 60921 var stringify; 60922 if (opt) { 60923 stringify = JSON.stringify(json); 60924 } else { 60925 stringify = JSON.stringify(json, undefined, 2); 60926 } 60927 this.saveStrings(stringify.split('\n'), filename, 'json'); 60928}; 60929
60930p5.prototype.saveJSONObject = p5.prototype.saveJSON; 60931p5.prototype.saveJSONArray = p5.prototype.saveJSON; 60932 60933/** 60934 * Writes an array of Strings to a text file, one line per String. 60935 * The file saving process and location of the saved file will 60936 * vary between web browsers. 60937 * 60938 * @method saveStrings 60939 * @param {String[]} list string array to be written 60940 * @param {String} filename filename for output 60941 * @param {String} [extension] the filename's extension 60942 * @example 60943 * <div><code> 60944 * var words = 'apple bear cat dog'; 60945 * 60946 * // .split() outputs an Array 60947 * var list = split(words, ' '); 60948 * 60949 * createButton('save') 60950 * .position(10, 10) 60951 * .mousePressed(function() { 60952 * saveStrings(list, 'nouns.txt'); 60953 * }); 60954 * 60955 * // Saves the following to a file called 'nouns.txt': 60956 * // 60957 * // apple 60958 * // bear 60959 * // cat 60960 * // dog 60961 * </code></div> 60962 * 60963 * @alt 60964 * no image displayed 60965 * 60966 */ 60967p5.prototype.saveStrings = function(list, filename, extension) { 60968 p5._validateParameters('saveStrings', arguments); 60969 var ext = extension || 'txt'; 60970 var pWriter = this.createWriter(filename, ext); 60971 for (var i = 0; i < list.length; i++) { 60972 if (i < list.length - 1) { 60973 pWriter.print(list[i]); 60974 } else { 60975 pWriter.print(list[i]); 60976 } 60977 } 60978 pWriter.close(); 60979 pWriter.clear(); 60980}; 60981 60982// ======= 60983// HELPERS 60984// ======= 60985 60986function escapeHelper(content) { 60987 return content 60988 .replace(/&/g, '&') 60989 .replace(/</g, '<') 60990 .replace(/>/g, '>') 60991 .replace(/"/g, '"') 60992 .replace(/'/g, '''); 60993} 60994 60995/** 60996 * Writes the contents of a Table object to a file. Defaults to a 60997 * text file with comma-separated-values ('csv') but can also 60998 * use tab separation ('tsv'), or generate an HTML table ('html'). 60999 * The file saving process and location of the saved file will 61000 * vary between web browsers. 61001 * 61002 * @method saveTable 61003 * @param {p5.Table} Table the Table object to save to a file 61004 * @param {String} filename the filename to which the Table should be saved 61005 * @param {String} [options] can be one of "tsv", "csv", or "html" 61006 * @example 61007 * <div><code> 61008 * var table; 61009 * 61010 * function setup() { 61011 * table = new p5.Table(); 61012 * 61013 * table.addColumn('id'); 61014 * table.addColumn('species'); 61015 * table.addColumn('name'); 61016 * 61017 * var newRow = table.addRow(); 61018 * newRow.setNum('id', table.getRowCount() - 1); 61019 * newRow.setString('species', 'Panthera leo'); 61020 * newRow.setString('name', 'Lion'); 61021 * 61022 * // To save, un-comment next line then click 'run' 61023 * // saveTable(table, 'new.csv'); 61024 * } 61025 * 61026 * // Saves the following to a file called 'new.csv': 61027 * // id,species,name 61028 * // 0,Panthera leo,Lion 61029 * </code></div> 61030 * 61031 * @alt 61032 * no image displayed 61033 * 61034 */ 61035p5.prototype.saveTable = function(table, filename, options) { 61036 p5._validateParameters('saveTable', arguments); 61037 var ext; 61038 if (options === undefined) { 61039 ext = filename.substring(filename.lastIndexOf('.') + 1, filename.length); 61040 } else { 61041 ext = options; 61042 } 61043 var pWriter = this.createWriter(filename, ext); 61044 61045 var header = table.columns; 61046 61047 var sep = ','; // default to CSV 61048 if (ext === 'tsv') { 61049 sep = '\t'; 61050 } 61051 if (ext !== 'html') { 61052 // make header if it has values 61053 if (header[0] !== '0') { 61054 for (var h = 0; h < header.length; h++) { 61055 if (h < header.length - 1) { 61056 pWriter.write(header[h] + sep); 61057 } else { 61058 pWriter.write(header[h]); 61059 } 61060 } 61061 pWriter.write('\n'); 61062 } 61063 61064 // make rows 61065 for (var i = 0; i < table.rows.length; i++) { 61066 var j; 61067 for (j = 0; j < table.rows[i].arr.length; j++) { 61068 if (j < table.rows[i].arr.length - 1) { 61069 pWriter.write(table.rows[i].arr[j] + sep); 61070 } else if (i < table.rows.length - 1) { 61071 pWriter.write(table.rows[i].arr[j]); 61072 } else { 61073 pWriter.write(table.rows[i].arr[j]); 61074 } 61075 } 61076 pWriter.write('\n'); 61077 } 61078 } else { 61079 // otherwise, make HTML 61080 pWriter.print('<html>'); 61081 pWriter.print('<head>'); 61082 var str = ' <meta http-equiv="content-type" content'; 61083 str += '="text/html;charset=utf-8" />'; 61084 pWriter.print(str);
61085 pWriter.print('</head>'); 61086 61087 pWriter.print('<body>'); 61088 pWriter.print(' <table>'); 61089 61090 // make header if it has values 61091 if (header[0] !== '0') { 61092 pWriter.print(' <tr>'); 61093 for (var k = 0; k < header.length; k++) { 61094 var e = escapeHelper(header[k]); 61095 pWriter.print(' <td>' + e); 61096 pWriter.print(' </td>'); 61097 } 61098 pWriter.print(' </tr>'); 61099 } 61100 61101 // make rows 61102 for (var row = 0; row < table.rows.length; row++) { 61103 pWriter.print(' <tr>'); 61104 for (var col = 0; col < table.columns.length; col++) { 61105 var entry = table.rows[row].getString(col); 61106 var htmlEntry = escapeHelper(entry); 61107 pWriter.print(' <td>' + htmlEntry); 61108 pWriter.print(' </td>'); 61109 } 61110 pWriter.print(' </tr>'); 61111 } 61112 pWriter.print(' </table>'); 61113 pWriter.print('</body>'); 61114 pWriter.print('</html>'); 61115 } 61116 // close and clear the pWriter 61117 pWriter.close(); 61118 pWriter.clear(); 61119}; // end saveTable() 61120 61121/** 61122 * Generate a blob of file data as a url to prepare for download. 61123 * Accepts an array of data, a filename, and an extension (optional). 61124 * This is a private function because it does not do any formatting, 61125 * but it is used by saveStrings, saveJSON, saveTable etc. 61126 * 61127 * @param {Array} dataToDownload 61128 * @param {String} filename 61129 * @param {String} [extension] 61130 * @private 61131 */ 61132p5.prototype.writeFile = function(dataToDownload, filename, extension) { 61133 var type = 'application/octet-stream'; 61134 if (p5.prototype._isSafari()) { 61135 type = 'text/plain'; 61136 } 61137 var blob = new Blob(dataToDownload, { 61138 type: type 61139 }); 61140 p5.prototype.downloadFile(blob, filename, extension); 61141}; 61142 61143/** 61144 * Forces download. Accepts a url to filedata/blob, a filename, 61145 * and an extension (optional). 61146 * This is a private function because it does not do any formatting, 61147 * but it is used by saveStrings, saveJSON, saveTable etc. 61148 * 61149 * @method downloadFile 61150 * @private 61151 * @param {String|Blob} data either an href generated by createObjectURL, 61152 * or a Blob object containing the data 61153 * @param {String} [filename] 61154 * @param {String} [extension] 61155 */ 61156p5.prototype.downloadFile = function(data, fName, extension) { 61157 var fx = _checkFileExtension(fName, extension); 61158 var filename = fx[0]; 61159 61160 if (data instanceof Blob) { 61161 var fileSaver = _dereq_('file-saver'); 61162 fileSaver.saveAs(data, filename); 61163 return; 61164 } 61165 61166 var a = document.createElement('a'); 61167 a.href = data; 61168 a.download = filename; 61169 61170 // Firefox requires the link to be added to the DOM before click() 61171 a.onclick = function(e) { 61172 destroyClickedElement(e); 61173 e.stopPropagation(); 61174 }; 61175 61176 a.style.display = 'none'; 61177 document.body.appendChild(a); 61178 61179 // Safari will open this file in the same page as a confusing Blob. 61180 if (p5.prototype._isSafari()) { 61181 var aText = 'Hello, Safari user! To download this file...\n'; 61182 aText += '1. Go to File --> Save As.\n'; 61183 aText += '2. Choose "Page Source" as the Format.\n'; 61184 aText += '3. Name it with this extension: ."' + fx[1] + '"'; 61185 alert(aText); 61186 } 61187 a.click(); 61188}; 61189 61190/** 61191 * Returns a file extension, or another string 61192 * if the provided parameter has no extension. 61193 * 61194 * @param {String} filename 61195 * @param {String} [extension] 61196 * @return {String[]} [fileName, fileExtension] 61197 * 61198 * @private 61199 */ 61200function _checkFileExtension(filename, extension) { 61201 if (!extension || extension === true || extension === 'true') { 61202 extension = ''; 61203 } 61204 if (!filename) { 61205 filename = 'untitled'; 61206 } 61207 var ext = ''; 61208 // make sure the file will have a name, see if filename needs extension 61209 if (filename && filename.indexOf('.') > -1) { 61210 ext = filename.split('.').pop(); 61211 } 61212 // append extension if it doesn't exist 61213 if (extension) { 61214 if (ext !== extension) { 61215 ext = extension; 61216 filename = filename + '.' + ext; 61217 } 61218 } 61219 return [filename, ext]; 61220} 61221p5.prototype._checkFileExtension = _checkFileExtension; 61222 61223/** 61224 * Returns true if the browser is Safari, false if not. 61225 * Safari makes trouble for downloading files. 61226 * 61227 * @return {Boolean} [description] 61228 * @private 61229 */ 61230p5.prototype._isSafari = function() { 61231 var x = Object.prototype.toString.call(window.HTMLElement); 61232 return x.indexOf('Constructor') > 0; 61233}; 61234 61235/** 61236 * Helper function, a callback for download that deletes 61237 * an invisible anchor element from the DOM once the file 61238 * has been automatically downloaded.
61239 * 61240 * @private 61241 */ 61242function destroyClickedElement(event) { 61243 document.body.removeChild(event.target); 61244} 61245 61246module.exports = p5; 61247 61248},{"../core/core":22,"../core/error_helpers":25,"es6-promise":5,"fetch-jsonp":6,"file-saver":7,"whatwg-fetch":12}],47:[function(_dereq_,module,exports){ 61249/** 61250 * @module IO 61251 * @submodule Table 61252 * @requires core 61253 */ 61254 61255'use strict'; 61256 61257var p5 = _dereq_('../core/core'); 61258 61259/** 61260 * Table Options 61261 * <p>Generic class for handling tabular data, typically from a 61262 * CSV, TSV, or other sort of spreadsheet file.</p> 61263 * <p>CSV files are 61264 * <a href="http://en.wikipedia.org/wiki/Comma-separated_values"> 61265 * comma separated values</a>, often with the data in quotes. TSV 61266 * files use tabs as separators, and usually don't bother with the 61267 * quotes.</p> 61268 * <p>File names should end with .csv if they're comma separated.</p> 61269 * <p>A rough "spec" for CSV can be found 61270 * <a href="http://tools.ietf.org/html/rfc4180">here</a>.</p> 61271 * <p>To load files, use the loadTable method.</p> 61272 * <p>To save tables to your computer, use the save method 61273 * or the saveTable method.</p> 61274 * 61275 * Possible options include: 61276 * <ul> 61277 * <li>csv - parse the table as comma-separated values 61278 * <li>tsv - parse the table as tab-separated values 61279 * <li>header - this table has a header (title) row 61280 * </ul> 61281 */ 61282 61283/** 61284 * Table objects store data with multiple rows and columns, much 61285 * like in a traditional spreadsheet. Tables can be generated from 61286 * scratch, dynamically, or using data from an existing file. 61287 * 61288 * @class p5.Table 61289 * @constructor 61290 * @param {p5.TableRow[]} [rows] An array of p5.TableRow objects 61291 */ 61292p5.Table = function(rows) { 61293 /** 61294 * @property columns {String[]} 61295 */ 61296 this.columns = []; 61297 61298 /** 61299 * @property rows {p5.TableRow[]} 61300 */ 61301 this.rows = []; 61302}; 61303 61304/** 61305 * Use addRow() to add a new row of data to a p5.Table object. By default, 61306 * an empty row is created. Typically, you would store a reference to 61307 * the new row in a TableRow object (see newRow in the example above), 61308 * and then set individual values using set(). 61309 * 61310 * If a p5.TableRow object is included as a parameter, then that row is 61311 * duplicated and added to the table. 61312 * 61313 * @method addRow 61314 * @param {p5.TableRow} [row] row to be added to the table 61315 * 61316 * @example 61317 * <div class="norender"> 61318 * <code> 61319 * // Given the CSV file "mammals.csv" 61320 * // in the project's "assets" folder: 61321 * // 61322 * // id,species,name 61323 * // 0,Capra hircus,Goat 61324 * // 1,Panthera pardus,Leopard 61325 * // 2,Equus zebra,Zebra 61326 * 61327 * var table; 61328 * 61329 * function preload() { 61330 * //my table is comma separated value "csv" 61331 * //and has a header specifying the columns labels 61332 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 61333 * } 61334 * 61335 * function setup() { 61336 * //add a row 61337 * var newRow = table.addRow(); 61338 * newRow.setString('id', table.getRowCount() - 1); 61339 * newRow.setString('species', 'Canis Lupus'); 61340 * newRow.setString('name', 'Wolf'); 61341 * 61342 * //print the results 61343 * for (var r = 0; r < table.getRowCount(); r++) 61344 * for (var c = 0; c < table.getColumnCount(); c++) 61345 * print(table.getString(r, c)); 61346 * } 61347 * </code> 61348 * </div> 61349 * 61350 * @alt 61351 * no image displayed 61352 * 61353 */ 61354p5.Table.prototype.addRow = function(row) { 61355 // make sure it is a valid TableRow 61356 var r = row || new p5.TableRow(); 61357 61358 if (typeof r.arr === 'undefined' || typeof r.obj === 'undefined') { 61359 //r = new p5.prototype.TableRow(r); 61360 throw 'invalid TableRow: ' + r; 61361 } 61362 r.table = this; 61363 this.rows.push(r); 61364 return r; 61365}; 61366 61367/** 61368 * Removes a row from the table object. 61369 * 61370 * @method removeRow 61371 * @param {Integer} id ID number of the row to remove 61372 * 61373 * @example 61374 * <div class="norender"> 61375 * <code> 61376 * // Given the CSV file "mammals.csv" 61377 * // in the project's "assets" folder: 61378 * // 61379 * // id,species,name 61380 * // 0,Capra hircus,Goat 61381 * // 1,Panthera pardus,Leopard 61382 * // 2,Equus zebra,Zebra 61383 * 61384 * var table; 61385 * 61386 * function preload() { 61387 * //my table is comma separated value "csv" 61388 * //and has a header specifying the columns labels 61389 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 61390 * } 61391 * 61392 * function setup() { 61393 * //remove the first row 61394 * table.removeRow(0); 61395 * 61396 * //print the results 61397 * for (var r = 0; r < table.getRowCount(); r++) 61398 * for (var c = 0; c < table.getColumnCount(); c++) 61399 * print(table.getString(r, c)); 61400 * } 61401 * </code> 61402 * </div> 61403 * 61404 * @alt 61405 * no image displayed 61406 * 61407 */ 61408p5.Table.prototype.removeRow = function(id) { 61409 this.rows[id].table = null; // remove reference to table 61410 var chunk = this.rows.splice(id + 1, this.rows.length); 61411 this.rows.pop(); 61412 this.rows = this.rows.concat(chunk); 61413}; 61414 61415/** 61416 * Returns a reference to the specified p5.TableRow. The reference 61417 * can then be used to get and set values of the selected row. 61418 * 61419 * @method getRow 61420 * @param {Integer} rowID ID number of the row to get 61421 * @return {p5.TableRow} p5.TableRow object 61422 * 61423 * @example 61424 * <div class="norender"> 61425 * <code> 61426 * // Given the CSV file "mammals.csv" 61427 * // in the project's "assets" folder: 61428 * // 61429 * // id,species,name 61430 * // 0,Capra hircus,Goat 61431 * // 1,Panthera pardus,Leopard 61432 * // 2,Equus zebra,Zebra 61433 * 61434 * var table; 61435 * 61436 * function preload() { 61437 * //my table is comma separated value "csv" 61438 * //and has a header specifying the columns labels 61439 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 61440 * } 61441 * 61442 * function setup() { 61443 * var row = table.getRow(1); 61444 * //print it column by column 61445 * //note: a row is an object, not an array 61446 * for (var c = 0; c < table.getColumnCount(); c++) { 61447 * print(row.getString(c)); 61448 * } 61449 * } 61450 * </code> 61451 * </div> 61452 * 61453 *@alt 61454 * no image displayed 61455 * 61456 */ 61457p5.Table.prototype.getRow = function(r) { 61458 return this.rows[r]; 61459}; 61460 61461/** 61462 * Gets all rows from the table. Returns an array of p5.TableRows. 61463 * 61464 * @method getRows 61465 * @return {p5.TableRow[]} Array of p5.TableRows 61466 * 61467 * @example 61468 * <div class="norender"> 61469 * <code> 61470 * // Given the CSV file "mammals.csv" 61471 * // in the project's "assets" folder: 61472 * // 61473 * // id,species,name 61474 * // 0,Capra hircus,Goat 61475 * // 1,Panthera pardus,Leopard 61476 * // 2,Equus zebra,Zebra 61477 * 61478 * var table; 61479 * 61480 * function preload() { 61481 * //my table is comma separated value "csv" 61482 * //and has a header specifying the columns labels 61483 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 61484 * } 61485 * 61486 * function setup() { 61487 * var rows = table.getRows(); 61488 * 61489 * //warning: rows is an array of objects 61490 * for (var r = 0; r < rows.length; r++) { 61491 * rows[r].set('name', 'Unicorn'); 61492 * } 61493 * 61494 * //print the results 61495 * for (r = 0; r < table.getRowCount(); r++) 61496 * for (var c = 0; c < table.getColumnCount(); c++) 61497 * print(table.getString(r, c)); 61498 * } 61499 * </code> 61500 * </div> 61501 * 61502 * @alt 61503 * no image displayed 61504 * 61505 */ 61506p5.Table.prototype.getRows = function() { 61507 return this.rows; 61508}; 61509 61510/** 61511 * Finds the first row in the Table that contains the value 61512 * provided, and returns a reference to that row. Even if 61513 * multiple rows are possible matches, only the first matching 61514 * row is returned. The column to search may be specified by 61515 * either its ID or title. 61516 * 61517 * @method findRow 61518 * @param {String} value The value to match 61519 * @param {Integer|String} column ID number or title of the 61520 * column to search 61521 * @return {p5.TableRow} 61522 * 61523 * @example 61524 * <div class="norender"> 61525 * <code> 61526 * // Given the CSV file "mammals.csv" 61527 * // in the project's "assets" folder: 61528 * // 61529 * // id,species,name 61530 * // 0,Capra hircus,Goat 61531 * // 1,Panthera pardus,Leopard 61532 * // 2,Equus zebra,Zebra 61533 * 61534 * var table; 61535 * 61536 * function preload() { 61537 * //my table is comma separated value "csv" 61538 * //and has a header specifying the columns labels 61539 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 61540 * } 61541 * 61542 * function setup() { 61543 * //find the animal named zebra 61544 * var row = table.findRow('Zebra', 'name'); 61545 * //find the corresponding species 61546 * print(row.getString('species')); 61547 * } 61548 * </code> 61549 * </div> 61550 * 61551 * @alt 61552 * no image displayed 61553 * 61554 */ 61555p5.Table.prototype.findRow = function(value, column) { 61556 // try the Object 61557 if (typeof column === 'string') { 61558 for (var i = 0; i < this.rows.length; i++) { 61559 if (this.rows[i].obj[column] === value) { 61560 return this.rows[i]; 61561 } 61562 } 61563 } else { 61564 // try the Array 61565 for (var j = 0; j < this.rows.length; j++) { 61566 if (this.rows[j].arr[column] === value) { 61567 return this.rows[j]; 61568 } 61569 } 61570 } 61571 // otherwise... 61572 return null; 61573}; 61574 61575/** 61576 * Finds the rows in the Table that contain the value 61577 * provided, and returns references to those rows. Returns an 61578 * Array, so for must be used to iterate through all the rows, 61579 * as shown in the example above. The column to search may be 61580 * specified by either its ID or title. 61581 * 61582 * @method findRows 61583 * @param {String} value The value to match 61584 * @param {Integer|String} column ID number or title of the 61585 * column to search 61586 * @return {p5.TableRow[]} An Array of TableRow objects 61587 * 61588 * @example 61589 * <div class="norender"> 61590 * <code> 61591 * // Given the CSV file "mammals.csv" 61592 * // in the project's "assets" folder: 61593 * // 61594 * // id,species,name 61595 * // 0,Capra hircus,Goat 61596 * // 1,Panthera pardus,Leopard 61597 * // 2,Equus zebra,Zebra 61598 * 61599 * var table; 61600 * 61601 * function preload() { 61602 * //my table is comma separated value "csv" 61603 * //and has a header specifying the columns labels 61604 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 61605 * } 61606 * 61607 * function setup() { 61608 * //add another goat 61609 * var newRow = table.addRow(); 61610 * newRow.setString('id', table.getRowCount() - 1); 61611 * newRow.setString('species', 'Scape Goat'); 61612 * newRow.setString('name', 'Goat'); 61613 * 61614 * //find the rows containing animals named Goat 61615 * var rows = table.findRows('Goat', 'name'); 61616 * print(rows.length + ' Goats found'); 61617 * } 61618 * </code> 61619 * </div> 61620 * 61621 *@alt 61622 * no image displayed 61623 * 61624 */ 61625p5.Table.prototype.findRows = function(value, column) { 61626 var ret = []; 61627 if (typeof column === 'string') { 61628 for (var i = 0; i < this.rows.length; i++) { 61629 if (this.rows[i].obj[column] === value) {
61630 ret.push(this.rows[i]); 61631 } 61632 } 61633 } else { 61634 // try the Array 61635 for (var j = 0; j < this.rows.length; j++) { 61636 if (this.rows[j].arr[column] === value) { 61637 ret.push(this.rows[j]); 61638 } 61639 } 61640 } 61641 return ret; 61642}; 61643 61644/** 61645 * Finds the first row in the Table that matches the regular 61646 * expression provided, and returns a reference to that row. 61647 * Even if multiple rows are possible matches, only the first 61648 * matching row is returned. The column to search may be 61649 * specified by either its ID or title. 61650 * 61651 * @method matchRow 61652 * @param {String|RegExp} regexp The regular expression to match 61653 * @param {String|Integer} column The column ID (number) or 61654 * title (string) 61655 * @return {p5.TableRow} TableRow object 61656 * 61657 * @example 61658 * <div class="norender"> 61659 * <code> 61660 * // Given the CSV file "mammals.csv" 61661 * // in the project's "assets" folder: 61662 * // 61663 * // id,species,name 61664 * // 0,Capra hircus,Goat 61665 * // 1,Panthera pardus,Leopard 61666 * // 2,Equus zebra,Zebra 61667 * 61668 * var table; 61669 * 61670 * function preload() { 61671 * //my table is comma separated value "csv" 61672 * //and has a header specifying the columns labels 61673 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 61674 * } 61675 * 61676 * function setup() { 61677 * //Search using specified regex on a given column, return TableRow object 61678 * var mammal = table.matchRow(new RegExp('ant'), 1); 61679 * print(mammal.getString(1)); 61680 * //Output "Panthera pardus" 61681 * } 61682 * </code> 61683 * </div> 61684 * 61685 */ 61686p5.Table.prototype.matchRow = function(regexp, column) { 61687 if (typeof column === 'number') { 61688 for (var j = 0; j < this.rows.length; j++) { 61689 if (this.rows[j].arr[column].match(regexp)) { 61690 return this.rows[j]; 61691 } 61692 } 61693 } else { 61694 for (var i = 0; i < this.rows.length; i++) { 61695 if (this.rows[i].obj[column].match(regexp)) { 61696 return this.rows[i]; 61697 } 61698 } 61699 } 61700 return null; 61701}; 61702 61703/** 61704 * Finds the rows in the Table that match the regular expression provided, 61705 * and returns references to those rows. Returns an array, so for must be 61706 * used to iterate through all the rows, as shown in the example. The 61707 * column to search may be specified by either its ID or title. 61708 * 61709 * @method matchRows 61710 * @param {String} regexp The regular expression to match 61711 * @param {String|Integer} [column] The column ID (number) or 61712 * title (string) 61713 * @return {p5.TableRow[]} An Array of TableRow objects 61714 * @example 61715 * <div class="norender"> 61716 * <code> 61717 * var table; 61718 * 61719 * function setup() { 61720 * table = new p5.Table(); 61721 * 61722 * table.addColumn('name'); 61723 * table.addColumn('type'); 61724 * 61725 * var newRow = table.addRow(); 61726 * newRow.setString('name', 'Lion'); 61727 * newRow.setString('type', 'Mammal'); 61728 * 61729 * newRow = table.addRow(); 61730 * newRow.setString('name', 'Snake'); 61731 * newRow.setString('type', 'Reptile'); 61732 * 61733 * newRow = table.addRow(); 61734 * newRow.setString('name', 'Mosquito'); 61735 * newRow.setString('type', 'Insect'); 61736 * 61737 * newRow = table.addRow(); 61738 * newRow.setString('name', 'Lizard'); 61739 * newRow.setString('type', 'Reptile'); 61740 * 61741 * var rows = table.matchRows('R.*', 'type'); 61742 * for (var i = 0; i < rows.length; i++) { 61743 * print(rows[i].getString('name') + ': ' + rows[i].getString('type')); 61744 * } 61745 * } 61746 * // Sketch prints: 61747 * // Snake: Reptile 61748 * // Lizard: Reptile 61749 * </code> 61750 * </div> 61751 */ 61752p5.Table.prototype.matchRows = function(regexp, column) { 61753 var ret = []; 61754 if (typeof column === 'number') { 61755 for (var j = 0; j < this.rows.length; j++) { 61756 if (this.rows[j].arr[column].match(regexp)) { 61757 ret.push(this.rows[j]); 61758 } 61759 } 61760 } else { 61761 for (var i = 0; i < this.rows.length; i++) { 61762 if (this.rows[i].obj[column].match(regexp)) { 61763 ret.push(this.rows[i]); 61764 } 61765 } 61766 } 61767 return ret; 61768}; 61769 61770/** 61771 * Retrieves all values in the specified column, and returns them 61772 * as an array. The column may be specified by either its ID or title. 61773 * 61774 * @method getColumn 61775 * @param {String|Number} column String or Number of the column to return 61776 * @return {Array} Array of column values 61777 * 61778 * @example 61779 * <div class="norender"> 61780 * <code> 61781 * // Given the CSV file "mammals.csv" 61782 * // in the project's "assets" folder: 61783 * // 61784 * // id,species,name 61785 * // 0,Capra hircus,Goat 61786 * // 1,Panthera pardus,Leopard 61787 * // 2,Equus zebra,Zebra 61788 * 61789 * var table; 61790 * 61791 * function preload() { 61792 * //my table is comma separated value "csv" 61793 * //and has a header specifying the columns labels 61794 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 61795 * } 61796 * 61797 * function setup() { 61798 * //getColumn returns an array that can be printed directly 61799 * print(table.getColumn('species')); 61800 * //outputs ["Capra hircus", "Panthera pardus", "Equus zebra"] 61801 * } 61802 * </code> 61803 * </div> 61804 * 61805 *@alt 61806 * no image displayed 61807 * 61808 */ 61809p5.Table.prototype.getColumn = function(value) { 61810 var ret = []; 61811 if (typeof value === 'string') { 61812 for (var i = 0; i < this.rows.length; i++) {
61813 ret.push(this.rows[i].obj[value]); 61814 } 61815 } else { 61816 for (var j = 0; j < this.rows.length; j++) { 61817 ret.push(this.rows[j].arr[value]); 61818 } 61819 } 61820 return ret; 61821}; 61822 61823/** 61824 * Removes all rows from a Table. While all rows are removed, 61825 * columns and column titles are maintained. 61826 * 61827 * @method clearRows 61828 * 61829 * @example 61830 * <div class="norender"> 61831 * <code> 61832 * // Given the CSV file "mammals.csv" 61833 * // in the project's "assets" folder: 61834 * // 61835 * // id,species,name 61836 * // 0,Capra hircus,Goat 61837 * // 1,Panthera pardus,Leopard 61838 * // 2,Equus zebra,Zebra 61839 * 61840 * var table; 61841 * 61842 * function preload() { 61843 * //my table is comma separated value "csv" 61844 * //and has a header specifying the columns labels 61845 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 61846 * } 61847 * 61848 * function setup() { 61849 * table.clearRows(); 61850 * print(table.getRowCount() + ' total rows in table'); 61851 * print(table.getColumnCount() + ' total columns in table'); 61852 * } 61853 * </code> 61854 * </div> 61855 * 61856 *@alt 61857 * no image displayed 61858 * 61859 */ 61860p5.Table.prototype.clearRows = function() { 61861 delete this.rows; 61862 this.rows = []; 61863}; 61864 61865/** 61866 * Use addColumn() to add a new column to a Table object. 61867 * Typically, you will want to specify a title, so the column 61868 * may be easily referenced later by name. (If no title is 61869 * specified, the new column's title will be null.) 61870 * 61871 * @method addColumn 61872 * @param {String} [title] title of the given column 61873 * 61874 * @example 61875 * <div class="norender"> 61876 * <code> 61877 * // Given the CSV file "mammals.csv" 61878 * // in the project's "assets" folder: 61879 * // 61880 * // id,species,name 61881 * // 0,Capra hircus,Goat 61882 * // 1,Panthera pardus,Leopard 61883 * // 2,Equus zebra,Zebra 61884 * 61885 * var table; 61886 * 61887 * function preload() { 61888 * //my table is comma separated value "csv" 61889 * //and has a header specifying the columns labels 61890 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 61891 * } 61892 * 61893 * function setup() { 61894 * table.addColumn('carnivore'); 61895 * table.set(0, 'carnivore', 'no'); 61896 * table.set(1, 'carnivore', 'yes'); 61897 * table.set(2, 'carnivore', 'no'); 61898 * 61899 * //print the results 61900 * for (var r = 0; r < table.getRowCount(); r++) 61901 * for (var c = 0; c < table.getColumnCount(); c++) 61902 * print(table.getString(r, c)); 61903 * } 61904 * </code> 61905 * </div> 61906 * 61907 *@alt 61908 * no image displayed 61909 * 61910 */ 61911p5.Table.prototype.addColumn = function(title) { 61912 var t = title || null; 61913 this.columns.push(t); 61914}; 61915 61916/** 61917 * Returns the total number of columns in a Table. 61918 * 61919 * @method getColumnCount 61920 * @return {Integer} Number of columns in this table 61921 * @example 61922 * <div> 61923 * <code> 61924 * // given the cvs file "blobs.csv" in /assets directory 61925 * // ID, Name, Flavor, Shape, Color 61926 * // Blob1, Blobby, Sweet, Blob, Pink 61927 * // Blob2, Saddy, Savory, Blob, Blue 61928 * 61929 * var table; 61930 * 61931 * function preload() { 61932 * table = loadTable('assets/blobs.csv'); 61933 * } 61934 * 61935 * function setup() { 61936 * createCanvas(200, 100); 61937 * textAlign(CENTER); 61938 * background(255); 61939 * } 61940 * 61941 * function draw() { 61942 * var numOfColumn = table.getColumnCount(); 61943 * text('There are ' + numOfColumn + ' columns in the table.', 100, 50); 61944 * } 61945 * </code> 61946 * </div> 61947 */ 61948p5.Table.prototype.getColumnCount = function() { 61949 return this.columns.length; 61950}; 61951 61952/** 61953 * Returns the total number of rows in a Table. 61954 * 61955 * @method getRowCount 61956 * @return {Integer} Number of rows in this table 61957 * @example 61958 * <div> 61959 * <code> 61960 * // given the cvs file "blobs.csv" in /assets directory 61961 * // 61962 * // ID, Name, Flavor, Shape, Color 61963 * // Blob1, Blobby, Sweet, Blob, Pink 61964 * // Blob2, Saddy, Savory, Blob, Blue 61965 * 61966 * var table; 61967 * 61968 * function preload() { 61969 * table = loadTable('assets/blobs.csv'); 61970 * } 61971 * 61972 * function setup() { 61973 * createCanvas(200, 100); 61974 * textAlign(CENTER); 61975 * background(255); 61976 * } 61977 * 61978 * function draw() { 61979 * text('There are ' + table.getRowCount() + ' rows in the table.', 100, 50); 61980 * } 61981 * </code> 61982 * </div> 61983 */ 61984p5.Table.prototype.getRowCount = function() { 61985 return this.rows.length; 61986}; 61987 61988/** 61989 * <p>Removes any of the specified characters (or "tokens").</p> 61990 * 61991 * <p>If no column is specified, then the values in all columns and 61992 * rows are processed. A specific column may be referenced by 61993 * either its ID or title.</p> 61994 * 61995 * @method removeTokens 61996 * @param {String} chars String listing characters to be removed 61997 * @param {String|Integer} [column] Column ID (number) 61998 * or name (string) 61999 * 62000 * @example 62001 * <div class="norender"><code> 62002 * function setup() { 62003 * var table = new p5.Table(); 62004 * 62005 * table.addColumn('name'); 62006 * table.addColumn('type'); 62007 * 62008 * var newRow = table.addRow(); 62009 * newRow.setString('name', ' $Lion ,'); 62010 * newRow.setString('type', ',,,Mammal'); 62011 * 62012 * newRow = table.addRow(); 62013 * newRow.setString('name', '$Snake '); 62014 * newRow.setString('type', ',,,Reptile'); 62015 * 62016 * table.removeTokens(',$ '); 62017 * print(table.getArray()); 62018 * } 62019 * 62020 * // prints:
62021 * // 0 "Lion" "Mamal" 62022 * // 1 "Snake" "Reptile" 62023 * </code></div> 62024 */ 62025p5.Table.prototype.removeTokens = function(chars, column) { 62026 var escape = function(s) { 62027 return s.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&'); 62028 }; 62029 var charArray = []; 62030 for (var i = 0; i < chars.length; i++) { 62031 charArray.push(escape(chars.charAt(i))); 62032 } 62033 var regex = new RegExp(charArray.join('|'), 'g'); 62034 62035 if (typeof column === 'undefined') { 62036 for (var c = 0; c < this.columns.length; c++) { 62037 for (var d = 0; d < this.rows.length; d++) { 62038 var s = this.rows[d].arr[c]; 62039 s = s.replace(regex, ''); 62040 this.rows[d].arr[c] = s; 62041 this.rows[d].obj[this.columns[c]] = s; 62042 } 62043 } 62044 } else if (typeof column === 'string') { 62045 for (var j = 0; j < this.rows.length; j++) { 62046 var val = this.rows[j].obj[column]; 62047 val = val.replace(regex, ''); 62048 this.rows[j].obj[column] = val; 62049 var pos = this.columns.indexOf(column); 62050 this.rows[j].arr[pos] = val; 62051 } 62052 } else { 62053 for (var k = 0; k < this.rows.length; k++) { 62054 var str = this.rows[k].arr[column]; 62055 str = str.replace(regex, ''); 62056 this.rows[k].arr[column] = str; 62057 this.rows[k].obj[this.columns[column]] = str; 62058 } 62059 } 62060}; 62061 62062/** 62063 * Trims leading and trailing whitespace, such as spaces and tabs, 62064 * from String table values. If no column is specified, then the 62065 * values in all columns and rows are trimmed. A specific column 62066 * may be referenced by either its ID or title. 62067 * 62068 * @method trim 62069 * @param {String|Integer} [column] Column ID (number) 62070 * or name (string) 62071 * @example 62072 * <div class="norender"><code> 62073 * function setup() { 62074 * var table = new p5.Table(); 62075 * 62076 * table.addColumn('name'); 62077 * table.addColumn('type'); 62078 * 62079 * var newRow = table.addRow(); 62080 * newRow.setString('name', ' Lion ,'); 62081 * newRow.setString('type', ' Mammal '); 62082 * 62083 * newRow = table.addRow(); 62084 * newRow.setString('name', ' Snake '); 62085 * newRow.setString('type', ' Reptile '); 62086 * 62087 * table.trim(); 62088 * print(table.getArray()); 62089 * } 62090 * 62091 * // prints: 62092 * // 0 "Lion" "Mamal" 62093 * // 1 "Snake" "Reptile" 62094 * </code></div> 62095 */ 62096p5.Table.prototype.trim = function(column) { 62097 var regex = new RegExp(' ', 'g'); 62098 62099 if (typeof column === 'undefined') { 62100 for (var c = 0; c < this.columns.length; c++) { 62101 for (var d = 0; d < this.rows.length; d++) { 62102 var s = this.rows[d].arr[c]; 62103 s = s.replace(regex, ''); 62104 this.rows[d].arr[c] = s; 62105 this.rows[d].obj[this.columns[c]] = s; 62106 } 62107 } 62108 } else if (typeof column === 'string') { 62109 for (var j = 0; j < this.rows.length; j++) { 62110 var val = this.rows[j].obj[column]; 62111 val = val.replace(regex, ''); 62112 this.rows[j].obj[column] = val; 62113 var pos = this.columns.indexOf(column); 62114 this.rows[j].arr[pos] = val; 62115 } 62116 } else { 62117 for (var k = 0; k < this.rows.length; k++) { 62118 var str = this.rows[k].arr[column]; 62119 str = str.replace(regex, ''); 62120 this.rows[k].arr[column] = str; 62121 this.rows[k].obj[this.columns[column]] = str; 62122 } 62123 } 62124}; 62125 62126/** 62127 * Use removeColumn() to remove an existing column from a Table 62128 * object. The column to be removed may be identified by either 62129 * its title (a String) or its index value (an int). 62130 * removeColumn(0) would remove the first column, removeColumn(1) 62131 * would remove the second column, and so on. 62132 * 62133 * @method removeColumn 62134 * @param {String|Integer} column columnName (string) or ID (number) 62135 * 62136 * @example 62137 * <div class="norender"> 62138 * <code> 62139 * // Given the CSV file "mammals.csv" 62140 * // in the project's "assets" folder: 62141 * // 62142 * // id,species,name 62143 * // 0,Capra hircus,Goat 62144 * // 1,Panthera pardus,Leopard 62145 * // 2,Equus zebra,Zebra 62146 * 62147 * var table; 62148 * 62149 * function preload() { 62150 * //my table is comma separated value "csv" 62151 * //and has a header specifying the columns labels 62152 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 62153 * } 62154 * 62155 * function setup() { 62156 * table.removeColumn('id'); 62157 * print(table.getColumnCount()); 62158 * } 62159 * </code> 62160 * </div> 62161 * 62162 *@alt 62163 * no image displayed 62164 * 62165 */ 62166p5.Table.prototype.removeColumn = function(c) { 62167 var cString; 62168 var cNumber; 62169 if (typeof c === 'string') { 62170 // find the position of c in the columns 62171 cString = c; 62172 cNumber = this.columns.indexOf(c); 62173 console.log('string'); 62174 } else { 62175 cNumber = c; 62176 cString = this.columns[c]; 62177 } 62178 62179 var chunk = this.columns.splice(cNumber + 1, this.columns.length); 62180 this.columns.pop(); 62181 this.columns = this.columns.concat(chunk); 62182 62183 for (var i = 0; i < this.rows.length; i++) { 62184 var tempR = this.rows[i].arr; 62185 var chip = tempR.splice(cNumber + 1, tempR.length); 62186 tempR.pop(); 62187 this.rows[i].arr = tempR.concat(chip); 62188 delete this.rows[i].obj[cString]; 62189 } 62190}; 62191 62192/** 62193 * Stores a value in the Table's specified row and column. 62194 * The row is specified by its ID, while the column may be specified 62195 * by either its ID or title. 62196 * 62197 * @method set 62198 * @param {Integer} row row ID 62199 * @param {String|Integer} column column ID (Number) 62200 * or title (String) 62201 * @param {String|Number} value value to assign 62202 * 62203 * @example 62204 * <div class="norender"> 62205 * <code> 62206 * // Given the CSV file "mammals.csv" 62207 * // in the project's "assets" folder: 62208 * // 62209 * // id,species,name 62210 * // 0,Capra hircus,Goat 62211 * // 1,Panthera pardus,Leopard 62212 * // 2,Equus zebra,Zebra 62213 * 62214 * var table; 62215 * 62216 * function preload() { 62217 * //my table is comma separated value "csv" 62218 * //and has a header specifying the columns labels 62219 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 62220 * } 62221 * 62222 * function setup() { 62223 * table.set(0, 'species', 'Canis Lupus'); 62224 * table.set(0, 'name', 'Wolf'); 62225 * 62226 * //print the results 62227 * for (var r = 0; r < table.getRowCount(); r++) 62228 * for (var c = 0; c < table.getColumnCount(); c++) 62229 * print(table.getString(r, c)); 62230 * } 62231 * </code> 62232 * </div> 62233 * 62234 *@alt 62235 * no image displayed 62236 * 62237 */ 62238p5.Table.prototype.set = function(row, column, value) { 62239 this.rows[row].set(column, value); 62240}; 62241 62242/** 62243 * Stores a Float value in the Table's specified row and column. 62244 * The row is specified by its ID, while the column may be specified 62245 * by either its ID or title. 62246 * 62247 * @method setNum 62248 * @param {Integer} row row ID 62249 * @param {String|Integer} column column ID (Number) 62250 * or title (String) 62251 * @param {Number} value value to assign 62252 * 62253 * @example 62254 * <div class="norender"> 62255 * <code> 62256 * // Given the CSV file "mammals.csv" 62257 * // in the project's "assets" folder: 62258 * // 62259 * // id,species,name 62260 * // 0,Capra hircus,Goat 62261 * // 1,Panthera pardus,Leopard 62262 * // 2,Equus zebra,Zebra 62263 * 62264 * var table; 62265 * 62266 * function preload() { 62267 * //my table is comma separated value "csv" 62268 * //and has a header specifying the columns labels 62269 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 62270 * } 62271 * 62272 * function setup() { 62273 * table.setNum(1, 'id', 1); 62274 * 62275 * print(table.getColumn(0)); 62276 * //["0", 1, "2"] 62277 * } 62278 * </code> 62279 * </div> 62280 * 62281 *@alt 62282 * no image displayed 62283 */ 62284p5.Table.prototype.setNum = function(row, column, value) { 62285 this.rows[row].setNum(column, value); 62286}; 62287 62288/** 62289 * Stores a String value in the Table's specified row and column. 62290 * The row is specified by its ID, while the column may be specified 62291 * by either its ID or title. 62292 * 62293 * @method setString 62294 * @param {Integer} row row ID 62295 * @param {String|Integer} column column ID (Number) 62296 * or title (String) 62297 * @param {String} value value to assign 62298 * @example 62299 * <div class="norender"><code> 62300 * // Given the CSV file "mammals.csv" in the project's "assets" folder: 62301 * // 62302 * // id,species,name 62303 * // 0,Capra hircus,Goat 62304 * // 1,Panthera pardus,Leopard 62305 * // 2,Equus zebra,Zebra 62306 * 62307 * var table; 62308 * 62309 * function preload() { 62310 * //my table is comma separated value "csv" 62311 * //and has a header specifying the columns labels 62312 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 62313 * } 62314 * 62315 * function setup() { 62316 * //add a row 62317 * var newRow = table.addRow(); 62318 * newRow.setString('id', table.getRowCount() - 1); 62319 * newRow.setString('species', 'Canis Lupus'); 62320 * newRow.setString('name', 'Wolf'); 62321 * 62322 * print(table.getArray()); 62323 * } 62324 * </code></div> 62325 * 62326 * @alt 62327 * no image displayed 62328 */ 62329p5.Table.prototype.setString = function(row, column, value) { 62330 this.rows[row].setString(column, value); 62331}; 62332 62333/** 62334 * Retrieves a value from the Table's specified row and column. 62335 * The row is specified by its ID, while the column may be specified by 62336 * either its ID or title. 62337 * 62338 * @method get 62339 * @param {Integer} row row ID 62340 * @param {String|Integer} column columnName (string) or 62341 * ID (number) 62342 * @return {String|Number} 62343 * 62344 * @example 62345 * <div class="norender"> 62346 * <code> 62347 * // Given the CSV file "mammals.csv" 62348 * // in the project's "assets" folder: 62349 * // 62350 * // id,species,name 62351 * // 0,Capra hircus,Goat 62352 * // 1,Panthera pardus,Leopard 62353 * // 2,Equus zebra,Zebra 62354 * 62355 * var table; 62356 * 62357 * function preload() { 62358 * //my table is comma separated value "csv" 62359 * //and has a header specifying the columns labels 62360 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 62361 * } 62362 * 62363 * function setup() { 62364 * print(table.get(0, 1)); 62365 * //Capra hircus 62366 * print(table.get(0, 'species')); 62367 * //Capra hircus 62368 * } 62369 * </code> 62370 * </div> 62371 * 62372 *@alt 62373 * no image displayed 62374 * 62375 */ 62376p5.Table.prototype.get = function(row, column) { 62377 return this.rows[row].get(column); 62378}; 62379 62380/** 62381 * Retrieves a Float value from the Table's specified row and column. 62382 * The row is specified by its ID, while the column may be specified by 62383 * either its ID or title. 62384 * 62385 * @method getNum 62386 * @param {Integer} row row ID 62387 * @param {String|Integer} column columnName (string) or 62388 * ID (number) 62389 * @return {Number} 62390 * 62391 * @example 62392 * <div class="norender"> 62393 * <code> 62394 * // Given the CSV file "mammals.csv" 62395 * // in the project's "assets" folder: 62396 * // 62397 * // id,species,name 62398 * // 0,Capra hircus,Goat 62399 * // 1,Panthera pardus,Leopard 62400 * // 2,Equus zebra,Zebra 62401 * 62402 * var table; 62403 * 62404 * function preload() { 62405 * //my table is comma separated value "csv" 62406 * //and has a header specifying the columns labels 62407 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 62408 * } 62409 * 62410 * function setup() { 62411 * print(table.getNum(1, 0) + 100); 62412 * //id 1 + 100 = 101 62413 * } 62414 * </code> 62415 * </div> 62416 * 62417 *@alt 62418 * no image displayed 62419 * 62420 */ 62421p5.Table.prototype.getNum = function(row, column) { 62422 return this.rows[row].getNum(column); 62423}; 62424 62425/** 62426 * Retrieves a String value from the Table's specified row and column. 62427 * The row is specified by its ID, while the column may be specified by 62428 * either its ID or title. 62429 * 62430 * @method getString 62431 * @param {Integer} row row ID 62432 * @param {String|Integer} column columnName (string) or 62433 * ID (number) 62434 * @return {String} 62435 * 62436 * @example 62437 * <div class="norender"> 62438 * <code> 62439 * // Given the CSV file "mammals.csv" 62440 * // in the project's "assets" folder: 62441 * // 62442 * // id,species,name 62443 * // 0,Capra hircus,Goat 62444 * // 1,Panthera pardus,Leopard 62445 * // 2,Equus zebra,Zebra 62446 * 62447 * var table; 62448 * 62449 * function preload() { 62450 * // table is comma separated value "CSV" 62451 * // and has specifiying header for column labels 62452 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 62453 * } 62454 * 62455 * function setup() { 62456 * print(table.getString(0, 0)); // 0 62457 * print(table.getString(0, 1)); // Capra hircus 62458 * print(table.getString(0, 2)); // Goat 62459 * print(table.getString(1, 0)); // 1 62460 * print(table.getString(1, 1)); // Panthera pardus 62461 * print(table.getString(1, 2)); // Leopard 62462 * print(table.getString(2, 0)); // 2 62463 * print(table.getString(2, 1)); // Equus zebra 62464 * print(table.getString(2, 2)); // Zebra 62465 * } 62466 * </code> 62467 * </div> 62468 * 62469 *@alt 62470 * no image displayed 62471 * 62472 */ 62473 62474p5.Table.prototype.getString = function(row, column) { 62475 return this.rows[row].getString(column); 62476}; 62477 62478/** 62479 * Retrieves all table data and returns as an object. If a column name is 62480 * passed in, each row object will be stored with that attribute as its 62481 * title. 62482 * 62483 * @method getObject 62484 * @param {String} [headerColumn] Name of the column which should be used to 62485 * title each row object (optional) 62486 * @return {Object} 62487 * 62488 * @example 62489 * <div class="norender"> 62490 * <code> 62491 * // Given the CSV file "mammals.csv" 62492 * // in the project's "assets" folder: 62493 * // 62494 * // id,species,name 62495 * // 0,Capra hircus,Goat 62496 * // 1,Panthera pardus,Leopard 62497 * // 2,Equus zebra,Zebra 62498 * 62499 * var table; 62500 * 62501 * function preload() { 62502 * //my table is comma separated value "csv" 62503 * //and has a header specifying the columns labels 62504 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 62505 * } 62506 * 62507 * function setup() { 62508 * var tableObject = table.getObject(); 62509 * 62510 * print(tableObject); 62511 * //outputs an object 62512 * } 62513 * </code> 62514 * </div> 62515 * 62516 *@alt 62517 * no image displayed 62518 * 62519 */ 62520p5.Table.prototype.getObject = function(headerColumn) { 62521 var tableObject = {}; 62522 var obj, cPos, index; 62523 62524 for (var i = 0; i < this.rows.length; i++) { 62525 obj = this.rows[i].obj; 62526 62527 if (typeof headerColumn === 'string') { 62528 cPos = this.columns.indexOf(headerColumn); // index of columnID 62529 if (cPos >= 0) { 62530 index = obj[headerColumn]; 62531 tableObject[index] = obj; 62532 } else { 62533 throw 'This table has no column named "' + headerColumn + '"'; 62534 } 62535 } else { 62536 tableObject[i] = this.rows[i].obj; 62537 } 62538 } 62539 return tableObject; 62540}; 62541 62542/** 62543 * Retrieves all table data and returns it as a multidimensional array. 62544 * 62545 * @method getArray 62546 * @return {Array} 62547 * 62548 * @example 62549 * <div class="norender"> 62550 * <code> 62551 * // Given the CSV file "mammals.csv" 62552 * // in the project's "assets" folder 62553 * // 62554 * // id,species,name 62555 * // 0,Capra hircus,Goat 62556 * // 1,Panthera pardus,Leoperd 62557 * // 2,Equus zebra,Zebra 62558 * 62559 * var table; 62560 * 62561 * function preload() { 62562 * // table is comma separated value "CSV" 62563 * // and has specifiying header for column labels 62564 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 62565 * } 62566 * 62567 * function setup() { 62568 * var tableArray = table.getArray(); 62569 * for (var i = 0; i < tableArray.length; i++) { 62570 * print(tableArray[i]); 62571 * } 62572 * } 62573 * </code> 62574 * </div> 62575 * 62576 *@alt 62577 * no image displayed 62578 * 62579 */ 62580p5.Table.prototype.getArray = function() { 62581 var tableArray = []; 62582 for (var i = 0; i < this.rows.length; i++) { 62583 tableArray.push(this.rows[i].arr); 62584 } 62585 return tableArray; 62586}; 62587 62588module.exports = p5; 62589 62590},{"../core/core":22}],48:[function(_dereq_,module,exports){ 62591/** 62592 * @module IO 62593 * @submodule Table 62594 * @requires core 62595 */ 62596 62597'use strict'; 62598 62599var p5 = _dereq_('../core/core'); 62600 62601/** 62602 * A TableRow object represents a single row of data values, 62603 * stored in columns, from a table. 62604 * 62605 * A Table Row contains both an ordered array, and an unordered 62606 * JSON object. 62607 * 62608 * @class p5.TableRow 62609 * @constructor 62610 * @param {String} [str] optional: populate the row with a
62611 * string of values, separated by the 62612 * separator 62613 * @param {String} [separator] comma separated values (csv) by default 62614 */ 62615p5.TableRow = function(str, separator) { 62616 var arr = []; 62617 var obj = {}; 62618 if (str) { 62619 separator = separator || ','; 62620 arr = str.split(separator); 62621 } 62622 for (var i = 0; i < arr.length; i++) { 62623 var key = i; 62624 var val = arr[i]; 62625 obj[key] = val; 62626 } 62627 this.arr = arr; 62628 this.obj = obj; 62629 this.table = null; 62630}; 62631 62632/** 62633 * Stores a value in the TableRow's specified column. 62634 * The column may be specified by either its ID or title. 62635 * 62636 * @method set 62637 * @param {String|Integer} column Column ID (Number) 62638 * or Title (String) 62639 * @param {String|Number} value The value to be stored 62640 * 62641 * @example 62642 * <div class="norender"><code> 62643 * // Given the CSV file "mammals.csv" in the project's "assets" folder: 62644 * // 62645 * // id,species,name 62646 * // 0,Capra hircus,Goat 62647 * // 1,Panthera pardus,Leopard 62648 * // 2,Equus zebra,Zebra 62649 * 62650 * var table; 62651 * 62652 * function preload() { 62653 * //my table is comma separated value "csv" 62654 * //and has a header specifying the columns labels 62655 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 62656 * } 62657 * 62658 * function setup() { 62659 * var rows = table.getRows(); 62660 * for (var r = 0; r < rows.length; r++) { 62661 * rows[r].set('name', 'Unicorn'); 62662 * } 62663 * 62664 * //print the results 62665 * print(table.getArray()); 62666 * } 62667 * </code></div> 62668 * 62669 * @alt 62670 * no image displayed 62671 */ 62672p5.TableRow.prototype.set = function(column, value) { 62673 // if typeof column is string, use .obj 62674 if (typeof column === 'string') { 62675 var cPos = this.table.columns.indexOf(column); // index of columnID 62676 if (cPos >= 0) { 62677 this.obj[column] = value; 62678 this.arr[cPos] = value; 62679 } else { 62680 throw 'This table has no column named "' + column + '"'; 62681 } 62682 } else { 62683 // if typeof column is number, use .arr 62684 if (column < this.table.columns.length) { 62685 this.arr[column] = value; 62686 var cTitle = this.table.columns[column]; 62687 this.obj[cTitle] = value; 62688 } else { 62689 throw 'Column #' + column + ' is out of the range of this table'; 62690 } 62691 } 62692}; 62693 62694/** 62695 * Stores a Float value in the TableRow's specified column. 62696 * The column may be specified by either its ID or title. 62697 * 62698 * @method setNum 62699 * @param {String|Integer} column Column ID (Number) 62700 * or Title (String) 62701 * @param {Number|String} value The value to be stored 62702 * as a Float 62703 * @example 62704 * <div class="norender"><code> 62705 * // Given the CSV file "mammals.csv" in the project's "assets" folder: 62706 * // 62707 * // id,species,name 62708 * // 0,Capra hircus,Goat 62709 * // 1,Panthera pardus,Leopard 62710 * // 2,Equus zebra,Zebra 62711 * 62712 * var table; 62713 * 62714 * function preload() { 62715 * //my table is comma separated value "csv" 62716 * //and has a header specifying the columns labels 62717 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 62718 * } 62719 * 62720 * function setup() { 62721 * var rows = table.getRows(); 62722 * for (var r = 0; r < rows.length; r++) { 62723 * rows[r].setNum('id', r + 10); 62724 * } 62725 * 62726 * print(table.getArray()); 62727 * } 62728 * </code></div> 62729 * 62730 * @alt 62731 * no image displayed 62732 */ 62733p5.TableRow.prototype.setNum = function(column, value) { 62734 var floatVal = parseFloat(value); 62735 this.set(column, floatVal); 62736}; 62737 62738/** 62739 * Stores a String value in the TableRow's specified column. 62740 * The column may be specified by either its ID or title. 62741 * 62742 * @method setString 62743 * @param {String|Integer} column Column ID (Number) 62744 * or Title (String) 62745 * @param {String|Number|Boolean|Object} value The value to be stored 62746 * as a String 62747 * @example 62748 * <div class="norender"><code> 62749 * // Given the CSV file "mammals.csv" in the project's "assets" folder: 62750 * // 62751 * // id,species,name 62752 * // 0,Capra hircus,Goat 62753 * // 1,Panthera pardus,Leopard 62754 * // 2,Equus zebra,Zebra 62755 * 62756 * var table; 62757 * 62758 * function preload() { 62759 * //my table is comma separated value "csv" 62760 * //and has a header specifying the columns labels 62761 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 62762 * } 62763 * 62764 * function setup() { 62765 * var rows = table.getRows(); 62766 * for (var r = 0; r < rows.length; r++) { 62767 * var name = rows[r].getString('name'); 62768 * rows[r].setString('name', 'A ' + name + ' named George'); 62769 * } 62770 * 62771 * print(table.getArray()); 62772 * } 62773 * </code></div> 62774 * 62775 * @alt 62776 * no image displayed 62777 */ 62778p5.TableRow.prototype.setString = function(column, value) { 62779 var stringVal = value.toString(); 62780 this.set(column, stringVal); 62781}; 62782 62783/** 62784 * Retrieves a value from the TableRow's specified column. 62785 * The column may be specified by either its ID or title. 62786 * 62787 * @method get 62788 * @param {String|Integer} column columnName (string) or 62789 * ID (number) 62790 * @return {String|Number} 62791 * 62792 * @example 62793 * <div class="norender"><code> 62794 * // Given the CSV file "mammals.csv" in the project's "assets" folder: 62795 * // 62796 * // id,species,name 62797 * // 0,Capra hircus,Goat 62798 * // 1,Panthera pardus,Leopard 62799 * // 2,Equus zebra,Zebra 62800 * 62801 * var table; 62802 * 62803 * function preload() { 62804 * //my table is comma separated value "csv" 62805 * //and has a header specifying the columns labels 62806 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 62807 * } 62808 * 62809 * function setup() { 62810 * var names = []; 62811 * var rows = table.getRows(); 62812 * for (var r = 0; r < rows.length; r++) { 62813 * names.push(rows[r].get('name')); 62814 * } 62815 * 62816 * print(names); 62817 * } 62818 * </code></div> 62819 * 62820 * @alt 62821 * no image displayed 62822 */ 62823p5.TableRow.prototype.get = function(column) { 62824 if (typeof column === 'string') { 62825 return this.obj[column]; 62826 } else { 62827 return this.arr[column]; 62828 } 62829}; 62830 62831/** 62832 * Retrieves a Float value from the TableRow's specified 62833 * column. The column may be specified by either its ID or 62834 * title. 62835 * 62836 * @method getNum 62837 * @param {String|Integer} column columnName (string) or 62838 * ID (number) 62839 * @return {Number} Float Floating point number 62840 * @example 62841 * <div class="norender"><code> 62842 * // Given the CSV file "mammals.csv" in the project's "assets" folder: 62843 * // 62844 * // id,species,name 62845 * // 0,Capra hircus,Goat 62846 * // 1,Panthera pardus,Leopard 62847 * // 2,Equus zebra,Zebra 62848 * 62849 * var table; 62850 * 62851 * function preload() { 62852 * //my table is comma separated value "csv" 62853 * //and has a header specifying the columns labels 62854 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 62855 * } 62856 * 62857 * function setup() { 62858 * var rows = table.getRows(); 62859 * var minId = Infinity; 62860 * var maxId = -Infinity; 62861 * for (var r = 0; r < rows.length; r++) { 62862 * var id = rows[r].getNum('id'); 62863 * minId = min(minId, id); 62864 * maxId = min(maxId, id); 62865 * } 62866 * print('minimum id = ' + minId + ', maximum id = ' + maxId); 62867 * } 62868 * </code></div> 62869 * 62870 * @alt 62871 * no image displayed 62872 */ 62873p5.TableRow.prototype.getNum = function(column) { 62874 var ret; 62875 if (typeof column === 'string') { 62876 ret = parseFloat(this.obj[column]); 62877 } else { 62878 ret = parseFloat(this.arr[column]); 62879 } 62880 62881 if (ret.toString() === 'NaN') { 62882 throw 'Error: ' + this.obj[column] + ' is NaN (Not a Number)'; 62883 } 62884 return ret; 62885}; 62886 62887/** 62888 * Retrieves an String value from the TableRow's specified 62889 * column. The column may be specified by either its ID or 62890 * title. 62891 * 62892 * @method getString 62893 * @param {String|Integer} column columnName (string) or 62894 * ID (number) 62895 * @return {String} String 62896 * @example 62897 * <div class="norender"><code> 62898 * // Given the CSV file "mammals.csv" in the project's "assets" folder: 62899 * // 62900 * // id,species,name 62901 * // 0,Capra hircus,Goat 62902 * // 1,Panthera pardus,Leopard 62903 * // 2,Equus zebra,Zebra 62904 * 62905 * var table; 62906 * 62907 * function preload() { 62908 * //my table is comma separated value "csv" 62909 * //and has a header specifying the columns labels 62910 * table = loadTable('assets/mammals.csv', 'csv', 'header'); 62911 * } 62912 * 62913 * function setup() { 62914 * var rows = table.getRows(); 62915 * var longest = ''; 62916 * for (var r = 0; r < rows.length; r++) { 62917 * var species = rows[r].getString('species'); 62918 * if (longest.length < species.length) { 62919 * longest = species; 62920 * } 62921 * } 62922 * 62923 * print('longest: ' + longest); 62924 * } 62925 * </code></div> 62926 * 62927 * @alt 62928 * no image displayed 62929 */ 62930p5.TableRow.prototype.getString = function(column) { 62931 if (typeof column === 'string') { 62932 return this.obj[column].toString(); 62933 } else { 62934 return this.arr[column].toString(); 62935 } 62936}; 62937 62938module.exports = p5; 62939 62940},{"../core/core":22}],49:[function(_dereq_,module,exports){ 62941/** 62942 * @module IO 62943 * @submodule XML 62944 * @requires core 62945 */ 62946 62947'use strict'; 62948 62949var p5 = _dereq_('../core/core'); 62950 62951/** 62952 * XML is a representation of an XML object, able to parse XML code. Use 62953 * loadXML() to load external XML files and create XML objects. 62954 * 62955 * @class p5.XML 62956 * @constructor 62957 * @example 62958 * <div class='norender'><code> 62959 * // The following short XML file called "mammals.xml" is parsed 62960 * // in the code below. 62961 * // 62962 * // <?xml version="1.0"?> 62963 * // <mammals> 62964 * // <animal id="0" species="Capra hircus">Goat</animal> 62965 * // <animal id="1" species="Panthera pardus">Leopard</animal> 62966 * // <animal id="2" species="Equus zebra">
62966Zebra</animal> 62967 * // </mammals> 62968 * 62969 * var xml; 62970 * 62971 * function preload() { 62972 * xml = loadXML('assets/mammals.xml'); 62973 * } 62974 * 62975 * function setup() { 62976 * var children = xml.getChildren('animal'); 62977 * 62978 * for (var i = 0; i < children.length; i++) { 62979 * var id = children[i].getNum('id'); 62980 * var coloring = children[i].getString('species'); 62981 * var name = children[i].getContent(); 62982 * print(id + ', ' + coloring + ', ' + name); 62983 * } 62984 * } 62985 * 62986 * // Sketch prints: 62987 * // 0, Capra hircus, Goat 62988 * // 1, Panthera pardus, Leopard 62989 * // 2, Equus zebra, Zebra 62990 * </code></div> 62991 * 62992 * @alt 62993 * no image displayed 62994 * 62995 */ 62996p5.XML = function() { 62997 this.name = null; //done 62998 this.attributes = {}; //done 62999 this.children = []; 63000 this.parent = null; 63001 this.content = null; //done 63002}; 63003 63004/** 63005 * Gets a copy of the element's parent. Returns the parent as another 63006 * p5.XML object. 63007 * 63008 * @method getParent 63009 * @return {p5.XML} element parent 63010 * @example 63011 * <div class='norender'><code> 63012 * // The following short XML file called "mammals.xml" is parsed 63013 * // in the code below. 63014 * // 63015 * // <?xml version="1.0"?> 63016 * // <mammals> 63017 * // <animal id="0" species="Capra hircus">Goat</animal> 63018 * // <animal id="1" species="Panthera pardus">Leopard</animal> 63019 * // <animal id="2" species="Equus zebra">Zebra</animal> 63020 * // </mammals> 63021 * 63022 * var xml; 63023 * 63024 * function preload() { 63025 * xml = loadXML('assets/mammals.xml'); 63026 * } 63027 * 63028 * function setup() { 63029 * var children = xml.getChildren('animal'); 63030 * var parent = children[1].getParent(); 63031 * print(parent.getName()); 63032 * } 63033 * 63034 * // Sketch prints: 63035 * // mammals 63036 * </code></div> 63037 */ 63038p5.XML.prototype.getParent = function() { 63039 return this.parent; 63040}; 63041 63042/** 63043 * Gets the element's full name, which is returned as a String. 63044 * 63045 * @method getName 63046 * @return {String} the name of the node 63047 * @example<animal 63048 * <div class='norender'><code> 63049 * // The following short XML file called "mammals.xml" is parsed 63050 * // in the code below. 63051 * // 63052 * // <?xml version="1.0"?> 63053 * // <mammals> 63054 * // <animal id="0" species="Capra hircus">Goat</animal> 63055 * // <animal id="1" species="Panthera pardus">Leopard</animal> 63056 * // <animal id="2" species="Equus zebra">Zebra</animal> 63057 * // </mammals> 63058 * 63059 * var xml; 63060 * 63061 * function preload() { 63062 * xml = loadXML('assets/mammals.xml'); 63063 * } 63064 * 63065 * function setup() { 63066 * print(xml.getName()); 63067 * } 63068 * 63069 * // Sketch prints: 63070 * // mammals 63071 * </code></div> 63072 */ 63073p5.XML.prototype.getName = function() { 63074 return this.name; 63075}; 63076 63077/** 63078 * Sets the element's name, which is specified as a String. 63079 * 63080 * @method setName 63081 * @param {String} the new name of the node 63082 * @example<animal 63083 * <div class='norender'><code> 63084 * // The following short XML file called "mammals.xml" is parsed 63085 * // in the code below. 63086 * // 63087 * // <?xml version="1.0"?> 63088 * // <mammals> 63089 * // <animal id="0" species="Capra hircus">Goat</animal> 63090 * // <animal id="1" species="Panthera pardus">Leopard</animal> 63091 * // <animal id="2" species="Equus zebra">Zebra</animal> 63092 * // </mammals> 63093 * 63094 * var xml; 63095 * 63096 * function preload() { 63097 * xml = loadXML('assets/mammals.xml'); 63098 * } 63099 * 63100 * function setup() { 63101 * print(xml.getName()); 63102 * xml.setName('fish'); 63103 * print(xml.getName()); 63104 * } 63105 * 63106 * // Sketch prints: 63107 * // mammals 63108 * // fish 63109 * </code></div> 63110 */ 63111p5.XML.prototype.setName = function(name) { 63112 this.name = name; 63113}; 63114 63115/** 63116 * Checks whether or not the element has any children, and returns the result 63117 * as a boolean. 63118 * 63119 * @method hasChildren 63120 * @return {boolean} 63121 * @example<animal 63122 * <div class='norender'><code> 63123 * // The following short XML file called "mammals.xml" is parsed 63124 * // in the code below. 63125 * // 63126 * // <?xml version="1.0"?> 63127 * // <mammals> 63128 * // <animal id="0" species="Capra hircus">Goat</animal> 63129 * // <animal id="1" species="Panthera pardus">Leopard</animal> 63130 * // <animal id="2" species="Equus zebra">Zebra</animal> 63131 * // </mammals> 63132 * 63133 * var xml; 63134 * 63135 * function preload() { 63136 * xml = loadXML('assets/mammals.xml'); 63137 * } 63138 * 63139 * function setup() { 63140 * print(xml.hasChildren()); 63141 * } 63142 * 63143 * // Sketch prints: 63144 * // true 63145 * </code></div> 63146 */ 63147p5.XML.prototype.hasChildren = function() { 63148 return this.children.length > 0; 63149}; 63150 63151/** 63152 * Get the names of all of the element's children, and returns the names as an 63153 * array of Strings. This is the same as looping through and calling getName() 63154 * on each child element individually. 63155 * 63156 * @method listChildren 63157 * @return {String[]} names of the children of the element 63158 * @example<animal 63159 * <div class='norender'><code> 63160 * // The following short XML file called "mammals.xml" is parsed 63161 * // in the code below. 63162 * // 63163 * // <?xml version="1.0"?> 63164 * // <mammals> 63165 * // <animal id="0" species="Capra hircus">Goat</animal> 63166 * // <animal id="1" species="Panthera pardus">Leopard</animal> 63167 * // <animal id="2" species="Equus zebra">
63167Zebra</animal> 63168 * // </mammals> 63169 * 63170 * var xml; 63171 * 63172 * function preload() { 63173 * xml = loadXML('assets/mammals.xml'); 63174 * } 63175 * 63176 * function setup() { 63177 * print(xml.listChildren()); 63178 * } 63179 * 63180 * // Sketch prints: 63181 * // ["animal", "animal", "animal"] 63182 * </code></div> 63183 */ 63184p5.XML.prototype.listChildren = function() { 63185 return this.children.map(function(c) { 63186 return c.name; 63187 }); 63188}; 63189 63190/** 63191 * Returns all of the element's children as an array of p5.XML objects. When 63192 * the name parameter is specified, then it will return all children that match 63193 * that name. 63194 * 63195 * @method getChildren 63196 * @param {String} [name] element name 63197 * @return {p5.XML[]} children of the element 63198 * @example<animal 63199 * <div class='norender'><code> 63200 * // The following short XML file called "mammals.xml" is parsed 63201 * // in the code below. 63202 * // 63203 * // <?xml version="1.0"?> 63204 * // <mammals> 63205 * // <animal id="0" species="Capra hircus">Goat</animal> 63206 * // <animal id="1" species="Panthera pardus">Leopard</animal> 63207 * // <animal id="2" species="Equus zebra">Zebra</animal> 63208 * // </mammals> 63209 * 63210 * var xml; 63211 * 63212 * function preload() { 63213 * xml = loadXML('assets/mammals.xml'); 63214 * } 63215 * 63216 * function setup() { 63217 * var animals = xml.getChildren('animal'); 63218 * 63219 * for (var i = 0; i < animals.length; i++) { 63220 * print(animals[i].getContent()); 63221 * } 63222 * } 63223 * 63224 * // Sketch prints: 63225 * // "Goat" 63226 * // "Leopard" 63227 * // "Zebra" 63228 * </code></div> 63229 */ 63230p5.XML.prototype.getChildren = function(param) { 63231 if (param) { 63232 return this.children.filter(function(c) { 63233 return c.name === param; 63234 }); 63235 } else { 63236 return this.children; 63237 } 63238}; 63239 63240/** 63241 * Returns the first of the element's children that matches the name parameter 63242 * or the child of the given index.It returns undefined if no matching 63243 * child is found. 63244 * 63245 * @method getChild 63246 * @param {String|Integer} name element name or index 63247 * @return {p5.XML} 63248 * @example<animal 63249 * <div class='norender'><code> 63250 * // The following short XML file called "mammals.xml" is parsed 63251 * // in the code below. 63252 * // 63253 * // <?xml version="1.0"?> 63254 * // <mammals> 63255 * // <animal id="0" species="Capra hircus">Goat</animal> 63256 * // <animal id="1" species="Panthera pardus">Leopard</animal> 63257 * // <animal id="2" species="Equus zebra">Zebra</animal> 63258 * // </mammals> 63259 * 63260 * var xml; 63261 * 63262 * function preload() { 63263 * xml = loadXML('assets/mammals.xml'); 63264 * } 63265 * 63266 * function setup() { 63267 * var firstChild = xml.getChild('animal'); 63268 * print(firstChild.getContent()); 63269 * } 63270 * 63271 * // Sketch prints: 63272 * // "Goat" 63273 * </code></div> 63274 * <div class='norender'><code> 63275 * var xml; 63276 * 63277 * function preload() { 63278 * xml = loadXML('assets/mammals.xml'); 63279 * } 63280 * 63281 * function setup() { 63282 * var secondChild = xml.getChild(1); 63283 * print(secondChild.getContent()); 63284 * } 63285 * 63286 * // Sketch prints: 63287 * // "Leopard" 63288 * </code></div> 63289 */ 63290p5.XML.prototype.getChild = function(param) { 63291 if (typeof param === 'string') { 63292 for (var i = 0; i < this.children.length; i++) { 63293 var child = this.children[i]; 63294 if (child.name === param) return child; 63295 } 63296 } else { 63297 return this.children[param]; 63298 } 63299}; 63300 63301/** 63302 * Appends a new child to the element. The child can be specified with 63303 * either a String, which will be used as the new tag's name, or as a 63304 * reference to an existing p5.XML object. 63305 * A reference to the newly created child is returned as an p5.XML object. 63306 * 63307 * @method addChild 63308 * @param {p5.XML} node a p5.XML Object which will be the child to be added 63309 * @example 63310 * <div class='norender'><code> 63311 * // The following short XML file called "mammals.xml" is parsed 63312 * // in the code below. 63313 * // 63314 * // <?xml version="1.0"?> 63315 * // <mammals> 63316 * // <animal id="0" species="Capra hircus">Goat</animal> 63317 * // <animal id="1" species="Panthera pardus">Leopard</animal> 63318 * // <animal id="2" species="Equus zebra">Zebra</animal> 63319 * // </mammals> 63320 * 63321 * var xml; 63322 * 63323 * function preload() { 63324 * xml = loadXML('assets/mammals.xml'); 63325 * } 63326 * 63327 * function setup() { 63328 * var child = new p5.XML(); 63329 * child.setAttribute('id', '3');
63330 * child.setAttribute('species', 'Ornithorhynchus anatinus'); 63331 * child.setContent('Platypus'); 63332 * xml.addChild(child); 63333 * 63334 * var animals = xml.getChildren('animal'); 63335 * print(animals[animals.length - 1].getContent()); 63336 * } 63337 * 63338 * // Sketch prints: 63339 * // "Goat" 63340 * // "Leopard" 63341 * // "Zebra" 63342 * </code></div> 63343 */ 63344p5.XML.prototype.addChild = function(node) { 63345 if (node instanceof p5.XML) { 63346 this.children.push(node); 63347 } else { 63348 // PEND 63349 } 63350}; 63351 63352/** 63353 * Removes the element specified by name or index. 63354 * 63355 * @method removeChild 63356 * @param {String|Integer} name element name or index 63357 * @example 63358 * <div class='norender'><code> 63359 * // The following short XML file called "mammals.xml" is parsed 63360 * // in the code below. 63361 * // 63362 * // <?xml version="1.0"?> 63363 * // <mammals> 63364 * // <animal id="0" species="Capra hircus">Goat</animal> 63365 * // <animal id="1" species="Panthera pardus">Leopard</animal> 63366 * // <animal id="2" species="Equus zebra">Zebra</animal> 63367 * // </mammals> 63368 * 63369 * var xml; 63370 * 63371 * function preload() { 63372 * xml = loadXML('assets/mammals.xml'); 63373 * } 63374 * 63375 * function setup() { 63376 * xml.removeChild('animal'); 63377 * var children = xml.getChildren(); 63378 * for (var i = 0; i < children.length; i++) { 63379 * print(children[i].getContent()); 63380 * } 63381 * } 63382 * 63383 * // Sketch prints: 63384 * // "Leopard" 63385 * // "Zebra" 63386 * </code></div> 63387 * <div class='norender'><code> 63388 * var xml; 63389 * 63390 * function preload() { 63391 * xml = loadXML('assets/mammals.xml'); 63392 * } 63393 * 63394 * function setup() { 63395 * xml.removeChild(1); 63396 * var children = xml.getChildren(); 63397 * for (var i = 0; i < children.length; i++) { 63398 * print(children[i].getContent()); 63399 * } 63400 * } 63401 * 63402 * // Sketch prints: 63403 * // "Goat" 63404 * // "Zebra" 63405 * </code></div> 63406 */ 63407p5.XML.prototype.removeChild = function(param) { 63408 var ind = -1; 63409 if (typeof param === 'string') { 63410 for (var i = 0; i < this.children.length; i++) { 63411 if (this.children[i].name === param) { 63412 ind = i; 63413 break; 63414 } 63415 } 63416 } else { 63417 ind = param; 63418 } 63419 if (ind !== -1) { 63420 this.children.splice(ind, 1); 63421 } 63422}; 63423 63424/** 63425 * Counts the specified element's number of attributes, returned as an Number. 63426 * 63427 * @method getAttributeCount 63428 * @return {Integer} 63429 * @example 63430 * <div class='norender'><code> 63431 * // The following short XML file called "mammals.xml" is parsed 63432 * // in the code below. 63433 * // 63434 * // <?xml version="1.0"?> 63435 * // <mammals> 63436 * // <animal id="0" species="Capra hircus">Goat</animal> 63437 * // <animal id="1" species="Panthera pardus">Leopard</animal> 63438 * // <animal id="2" species="Equus zebra">Zebra</animal> 63439 * // </mammals> 63440 * 63441 * var xml; 63442 * 63443 * function preload() { 63444 * xml = loadXML('assets/mammals.xml'); 63445 * } 63446 * 63447 * function setup() { 63448 * var firstChild = xml.getChild('animal'); 63449 * print(firstChild.getAttributeCount()); 63450 * } 63451 * 63452 * // Sketch prints: 63453 * // 2 63454 * </code></div> 63455 */ 63456p5.XML.prototype.getAttributeCount = function() { 63457 return Object.keys(this.attributes).length; 63458}; 63459 63460/** 63461 * Gets all of the specified element's attributes, and returns them as an 63462 * array of Strings. 63463 * 63464 * @method listAttributes 63465 * @return {String[]} an array of strings containing the names of attributes 63466 * @example 63467 * <div class='norender'><code> 63468 * // The following short XML file called "mammals.xml" is parsed 63469 * // in the code below. 63470 * // 63471 * // <?xml version="1.0"?> 63472 * // <mammals> 63473 * // <animal id="0" species="Capra hircus">Goat</animal> 63474 * // <animal id="1" species="Panthera pardus">Leopard</animal> 63475 * // <animal id="2" species="Equus zebra">Zebra</animal> 63476 * // </mammals> 63477 * 63478 * var xml; 63479 * 63480 * function preload() { 63481 * xml = loadXML('assets/mammals.xml'); 63482 * } 63483 * 63484 * function setup() { 63485 * var firstChild = xml.getChild('animal'); 63486 * print(firstChild.listAttributes()); 63487 * } 63488 * 63489 * // Sketch prints: 63490 * // ["id", "species"] 63491 * </code></div> 63492 */ 63493p5.XML.prototype.listAttributes = function() { 63494 return Object.keys(this.attributes); 63495}; 63496 63497/** 63498 * Checks whether or not an element has the specified attribute. 63499 * 63500 * @method hasAttribute 63501 * @param {String} the attribute to be checked 63502 * @return {boolean} true if attribute found else false 63503 * @example 63504 * <div class='norender'><code> 63505 * // The following short XML file called "mammals.xml" is parsed 63506 * // in the code below. 63507 * // 63508 * // <?xml version="1.0"?> 63509 * // <mammals> 63510 * // <animal id="0" species="Capra hircus">Goat</animal> 63511 * // <animal id="1" species="Panthera pardus">Leopard</animal> 63512 * // <animal id="2" species="Equus zebra">
63512Zebra</animal> 63513 * // </mammals> 63514 * 63515 * var xml; 63516 * 63517 * function preload() { 63518 * xml = loadXML('assets/mammals.xml'); 63519 * } 63520 * 63521 * function setup() { 63522 * var firstChild = xml.getChild('animal'); 63523 * print(firstChild.hasAttribute('species')); 63524 * print(firstChild.hasAttribute('color')); 63525 * } 63526 * 63527 * // Sketch prints: 63528 * // true 63529 * // false 63530 * </code></div> 63531 */ 63532p5.XML.prototype.hasAttribute = function(name) { 63533 return this.attributes[name] ? true : false; 63534}; 63535 63536/** 63537 * Returns an attribute value of the element as an Number. If the defaultValue 63538 * parameter is specified and the attribute doesn't exist, then defaultValue 63539 * is returned. If no defaultValue is specified and the attribute doesn't 63540 * exist, the value 0 is returned. 63541 * 63542 * @method getNum 63543 * @param {String} name the non-null full name of the attribute 63544 * @param {Number} [defaultValue] the default value of the attribute 63545 * @return {Number} 63546 * @example 63547 * <div class='norender'><code> 63548 * // The following short XML file called "mammals.xml" is parsed 63549 * // in the code below. 63550 * // 63551 * // <?xml version="1.0"?> 63552 * // <mammals> 63553 * // <animal id="0" species="Capra hircus">Goat</animal> 63554 * // <animal id="1" species="Panthera pardus">Leopard</animal> 63555 * // <animal id="2" species="Equus zebra">Zebra</animal> 63556 * // </mammals> 63557 * 63558 * var xml; 63559 * 63560 * function preload() { 63561 * xml = loadXML('assets/mammals.xml'); 63562 * } 63563 * 63564 * function setup() { 63565 * var firstChild = xml.getChild('animal'); 63566 * print(firstChild.getNum('id')); 63567 * } 63568 * 63569 * // Sketch prints: 63570 * // 0 63571 * </code></div> 63572 */ 63573p5.XML.prototype.getNum = function(name, defaultValue) { 63574 return Number(this.attributes[name]) || defaultValue || 0; 63575}; 63576 63577/** 63578 * Returns an attribute value of the element as an String. If the defaultValue 63579 * parameter is specified and the attribute doesn't exist, then defaultValue 63580 * is returned. If no defaultValue is specified and the attribute doesn't 63581 * exist, null is returned. 63582 * 63583 * @method getString 63584 * @param {String} name the non-null full name of the attribute 63585 * @param {Number} [defaultValue] the default value of the attribute 63586 * @return {String} 63587 * @example 63588 * <div class='norender'><code> 63589 * // The following short XML file called "mammals.xml" is parsed 63590 * // in the code below. 63591 * // 63592 * // <?xml version="1.0"?> 63593 * // <mammals> 63594 * // <animal id="0" species="Capra hircus">Goat</animal> 63595 * // <animal id="1" species="Panthera pardus">Leopard</animal> 63596 * // <animal id="2" species="Equus zebra">Zebra</animal> 63597 * // </mammals> 63598 * 63599 * var xml; 63600 * 63601 * function preload() { 63602 * xml = loadXML('assets/mammals.xml'); 63603 * } 63604 * 63605 * function setup() { 63606 * var firstChild = xml.getChild('animal'); 63607 * print(firstChild.getString('species')); 63608 * } 63609 * 63610 * // Sketch prints: 63611 * // "Capra hircus" 63612 * </code></div> 63613 */ 63614p5.XML.prototype.getString = function(name, defaultValue) { 63615 return String(this.attributes[name]) || defaultValue || null; 63616}; 63617 63618/** 63619 * Sets the content of an element's attribute. The first parameter specifies 63620 * the attribute name, while the second specifies the new content. 63621 * 63622 * @method setAttribute 63623 * @param {String} name the full name of the attribute 63624 * @param {Number|String|Boolean} value the value of the attribute 63625 * @example 63626 * <div class='norender'><code> 63627 * // The following short XML file called "mammals.xml" is parsed 63628 * // in the code below. 63629 * // 63630 * // <?xml version="1.0"?> 63631 * // <mammals> 63632 * // <animal id="0" species="Capra hircus">Goat</animal> 63633 * // <animal id="1" species="Panthera pardus">Leopard</animal> 63634 * // <animal id="2" species="Equus zebra">Zebra</animal> 63635 * // </mammals> 63636 * 63637 * var xml; 63638 * 63639 * function preload() { 63640 * xml = loadXML('assets/mammals.xml'); 63641 * } 63642 * 63643 * function setup() { 63644 * var firstChild = xml.getChild('animal'); 63645 * print(firstChild.getString('species')); 63646 * firstChild.setAttribute('species', 'Jamides zebra'); 63647 * print(firstChild.getString('species')); 63648 * } 63649 * 63650 * // Sketch prints: 63651 * // "Capra hircus"
63652 * // "Jamides zebra" 63653 * </code></div> 63654 */ 63655p5.XML.prototype.setAttribute = function(name, value) { 63656 if (this.attributes[name]) { 63657 this.attributes[name] = value; 63658 } 63659}; 63660 63661/** 63662 * Returns the content of an element. If there is no such content, 63663 * defaultValue is returned if specified, otherwise null is returned. 63664 * 63665 * @method getContent 63666 * @param {String} [defaultValue] value returned if no content is found 63667 * @return {String} 63668 * @example 63669 * <div class='norender'><code> 63670 * // The following short XML file called "mammals.xml" is parsed 63671 * // in the code below. 63672 * // 63673 * // <?xml version="1.0"?> 63674 * // <mammals> 63675 * // <animal id="0" species="Capra hircus">Goat</animal> 63676 * // <animal id="1" species="Panthera pardus">Leopard</animal> 63677 * // <animal id="2" species="Equus zebra">Zebra</animal> 63678 * // </mammals> 63679 * 63680 * var xml; 63681 * 63682 * function preload() { 63683 * xml = loadXML('assets/mammals.xml'); 63684 * } 63685 * 63686 * function setup() { 63687 * var firstChild = xml.getChild('animal'); 63688 * print(firstChild.getContent()); 63689 * } 63690 * 63691 * // Sketch prints: 63692 * // "Goat" 63693 * </code></div> 63694 */ 63695p5.XML.prototype.getContent = function(defaultValue) { 63696 return this.content || defaultValue || null; 63697}; 63698 63699/** 63700 * Sets the element's content. 63701 * 63702 * @method setContent 63703 * @param {String} text the new content 63704 * @example 63705 * <div class='norender'><code> 63706 * // The following short XML file called "mammals.xml" is parsed 63707 * // in the code below. 63708 * // 63709 * // <?xml version="1.0"?> 63710 * // <mammals> 63711 * // <animal id="0" species="Capra hircus">Goat</animal> 63712 * // <animal id="1" species="Panthera pardus">Leopard</animal> 63713 * // <animal id="2" species="Equus zebra">Zebra</animal> 63714 * // </mammals> 63715 * 63716 * var xml; 63717 * 63718 * function preload() { 63719 * xml = loadXML('assets/mammals.xml'); 63720 * } 63721 * 63722 * function setup() { 63723 * var firstChild = xml.getChild('animal'); 63724 * print(firstChild.getContent()); 63725 * firstChild.setContent('Mountain Goat'); 63726 * print(firstChild.getContent()); 63727 * } 63728 * 63729 * // Sketch prints: 63730 * // "Goat" 63731 * // "Mountain Goat" 63732 * </code></div> 63733 */ 63734p5.XML.prototype.setContent = function(content) { 63735 if (!this.children.length) { 63736 this.content = content; 63737 } 63738}; 63739 63740/* HELPERS */ 63741/** 63742 * This method is called while the parsing of XML (when loadXML() is 63743 * called). The difference between this method and the setContent() 63744 * method defined later is that this one is used to set the content 63745 * when the node in question has more nodes under it and so on and 63746 * not directly text content. While in the other one is used when 63747 * the node in question directly has text inside it. 63748 * 63749 */ 63750p5.XML.prototype._setCont = function(content) { 63751 var str; 63752 str = content; 63753 str = str.replace(/\s\s+/g, ','); 63754 //str = str.split(','); 63755 this.content = str; 63756}; 63757 63758/** 63759 * This method is called while the parsing of XML (when loadXML() is 63760 * called). The XML node is passed and its attributes are stored in the 63761 * p5.XML's attribute Object. 63762 * 63763 */ 63764p5.XML.prototype._setAttributes = function(node) { 63765 var att = {}; 63766 var attributes = node.attributes; 63767 if (attributes) { 63768 for (var i = 0; i < attributes.length; i++) { 63769 var attribute = attributes[i]; 63770 att[attribute.nodeName] = attribute.nodeValue; 63771 } 63772 } 63773 this.attributes = att; 63774}; 63775 63776module.exports = p5; 63777 63778},{"../core/core":22}],50:[function(_dereq_,module,exports){ 63779/** 63780 * @module Math 63781 * @submodule Calculation 63782 * @for p5 63783 * @requires core 63784 */ 63785 63786'use strict'; 63787 63788var p5 = _dereq_('../core/core'); 63789 63790/** 63791 * Calculates the absolute value (magnitude) of a number. Maps to Math.abs(). 63792 * The absolute value of a number is always positive. 63793 * 63794 * @method abs 63795 * @param {Number} n number to compute 63796 * @return {Number} absolute value of given number 63797 * @example 63798 * <div class = "norender"><code> 63799 * function setup() { 63800 * var x = -3; 63801 * var y = abs(x); 63802 * 63803 * print(x); // -3 63804 * print(y); // 3 63805 * } 63806 * </code></div> 63807 * 63808 * @alt 63809 * no image displayed 63810 * 63811 */ 63812p5.prototype.abs = Math.abs; 63813 63814/** 63815 * Calculates the closest int value that is greater than or equal to the 63816 * value of the parameter. Maps to Math.ceil(). For example, ceil(9.03) 63817 * returns the value 10. 63818 * 63819 * @method ceil 63820 * @param {Number} n number to round up 63821 * @return {Integer}
63821 rounded up number 63822 * @example 63823 * <div><code> 63824 * function draw() { 63825 * background(200); 63826 * // map, mouseX between 0 and 5. 63827 * var ax = map(mouseX, 0, 100, 0, 5); 63828 * var ay = 66; 63829 * 63830 * //Get the ceiling of the mapped number. 63831 * var bx = ceil(map(mouseX, 0, 100, 0, 5)); 63832 * var by = 33; 63833 * 63834 * // Multiply the mapped numbers by 20 to more easily 63835 * // see the changes. 63836 * stroke(0); 63837 * fill(0); 63838 * line(0, ay, ax * 20, ay); 63839 * line(0, by, bx * 20, by); 63840 * 63841 * // Reformat the float returned by map and draw it. 63842 * noStroke(); 63843 * text(nfc(ax, 2), ax, ay - 5); 63844 * text(nfc(bx, 1), bx, by - 5); 63845 * } 63846 * </code></div> 63847 * 63848 * @alt 63849 * 2 horizontal lines & number sets. increase with mouse x. bottom to 2 decimals 63850 * 63851 */ 63852p5.prototype.ceil = Math.ceil; 63853 63854/** 63855 * Constrains a value between a minimum and maximum value. 63856 * 63857 * @method constrain 63858 * @param {Number} n number to constrain 63859 * @param {Number} low minimum limit 63860 * @param {Number} high maximum limit 63861 * @return {Number} constrained number 63862 * @example 63863 * <div><code> 63864 * function draw() { 63865 * background(200); 63866 * 63867 * var leftWall = 25; 63868 * var rightWall = 75; 63869 * 63870 * // xm is just the mouseX, while 63871 * // xc is the mouseX, but constrained 63872 * // between the leftWall and rightWall! 63873 * var xm = mouseX; 63874 * var xc = constrain(mouseX, leftWall, rightWall); 63875 * 63876 * // Draw the walls. 63877 * stroke(150); 63878 * line(leftWall, 0, leftWall, height); 63879 * line(rightWall, 0, rightWall, height); 63880 * 63881 * // Draw xm and xc as circles. 63882 * noStroke(); 63883 * fill(150); 63884 * ellipse(xm, 33, 9, 9); // Not Constrained 63885 * fill(0); 63886 * ellipse(xc, 66, 9, 9); // Constrained 63887 * } 63888 * </code></div> 63889 * 63890 * @alt 63891 * 2 vertical lines. 2 ellipses move with mouse X 1 does not move passed lines 63892 * 63893 */ 63894p5.prototype.constrain = function(n, low, high) { 63895 p5._validateParameters('constrain', arguments); 63896 return Math.max(Math.min(n, high), low); 63897}; 63898 63899/** 63900 * Calculates the distance between two points. 63901 * 63902 * @method dist 63903 * @param {Number} x1 x-coordinate of the first point 63904 * @param {Number} y1 y-coordinate of the first point 63905 * @param {Number} x2 x-coordinate of the second point 63906 * @param {Number} y2 y-coordinate of the second point 63907 * @return {Number} distance between the two points 63908 * 63909 * @example 63910 * <div><code> 63911 * // Move your mouse inside the canvas to see the 63912 * // change in distance between two points! 63913 * function draw() { 63914 * background(200); 63915 * fill(0); 63916 * 63917 * var x1 = 10; 63918 * var y1 = 90; 63919 * var x2 = mouseX; 63920 * var y2 = mouseY; 63921 * 63922 * line(x1, y1, x2, y2); 63923 * ellipse(x1, y1, 7, 7); 63924 * ellipse(x2, y2, 7, 7); 63925 * 63926 * // d is the length of the line 63927 * // the distance from point 1 to point 2. 63928 * var d = int(dist(x1, y1, x2, y2)); 63929 * 63930 * // Let's write d along the line we are drawing! 63931 * push(); 63932 * translate((x1 + x2) / 2, (y1 + y2) / 2); 63933 * rotate(atan2(y2 - y1, x2 - x1)); 63934 * text(nfc(d, 1), 0, -5); 63935 * pop(); 63936 * // Fancy! 63937 * } 63938 * </code></div> 63939 * 63940 * @alt 63941 * 2 ellipses joined by line. 1 ellipse moves with mouse X&Y. Distance displayed. 63942 */ 63943/** 63944 * @method dist 63945 * @param {Number} x1 63946 * @param {Number} y1 63947 * @param {Number} z1 z-coordinate of the first point 63948 * @param {Number} x2 63949 * @param {Number} y2 63950 * @param {Number} z2 z-coordinate of the second point 63951 * @return {Number} distance between the two points 63952 */ 63953p5.prototype.dist = function() { 63954 p5._validateParameters('dist', arguments); 63955 if (arguments.length === 4) { 63956 //2D 63957 return hypot(arguments[2] - arguments[0], arguments[3] - arguments[1]); 63958 } else if (arguments.length === 6) { 63959 //3D 63960 return hypot( 63961 arguments[3] - arguments[0], 63962 arguments[4] - arguments[1], 63963 arguments[5] - arguments[2] 63964 ); 63965 } 63966}; 63967 63968/** 63969 * Returns Euler's number e (2.71828...) raised to the power of the n 63970 * parameter. Maps to Math.exp(). 63971 * 63972 * @method exp 63973 * @param {Number} n exponent to raise 63974 * @return {Number} e^n 63975 * @example 63976 * <div><code> 63977 * function draw() { 63978 * background(200); 63979 * 63980 * // Compute the exp() function with a value between 0 and 2 63981 * var xValue = map(mouseX, 0, width, 0, 2); 63982 * var yValue = exp(xValue); 63983 * 63984 * var y = map(yValue, 0, 8, height, 0); 63985 * 63986 * var legend = 'exp (' + nfc(xValue, 3) + ')\n= ' + nf(yValue, 1, 4); 63987 * stroke(150); 63988 * line(mouseX, y, mouseX, height); 63989 * fill(0); 63990 * text(legend, 5, 15); 63991 * noStroke(); 63992 * ellipse(mouseX, y, 7, 7); 63993 * 63994 * // Draw the exp(x) curve, 63995 * // over the domain of x from 0 to 2 63996 * noFill(); 63997 * stroke(0); 63998 * beginShape(); 63999 * for (var x = 0; x < width; x++) { 64000 * xValue = map(x, 0, width, 0, 2); 64001 * yValue = exp(xValue); 64002 * y = map(yValue, 0, 8, height, 0); 64003 * vertex(x, y); 64004 * } 64005 * 64006 * endShape(); 64007 * line(0, 0, 0, height); 64008 * line(0, height - 1, width, height - 1); 64009 * } 64010 * </code></div> 64011 * 64012 * @alt 64013 * ellipse moves along a curve with mouse x. e^n displayed. 64014 * 64015 */ 64016p5.prototype.exp = Math.exp; 64017 64018/** 64019 * Calculates the closest int value that is less than or equal to the 64020 * value of the parameter. Maps to Math.floor(). 64021 * 64022 * @method floor 64023 * @param {Number} n number to round down 64024 * @return {Integer} rounded down number 64025 * @example 64026 * <div><code> 64027 * function draw() { 64028 * background(200); 64029 * //map, mouseX between 0 and 5. 64030 * var ax = map(mouseX, 0, 100, 0, 5); 64031 * var ay = 66; 64032 * 64033 * //Get the floor of the mapped number. 64034 * var bx = floor(map(mouseX, 0, 100, 0, 5)); 64035 * var by = 33; 64036 * 64037 * // Multiply the mapped numbers by 20 to more easily 64038 * // see the changes. 64039 * stroke(0); 64040 * fill(0); 64041 * line(0, ay, ax * 20, ay); 64042 * line(0, by, bx * 20, by); 64043 * 64044 * // Reformat the float returned by map and draw it. 64045 * noStroke(); 64046 * text(nfc(ax, 2), ax, ay - 5); 64047 * text(nfc(bx, 1), bx, by - 5); 64048 * } 64049 * </code></div> 64050 * 64051 * @alt 64052 * 2 horizontal lines & number sets. increase with mouse x. bottom to 2 decimals 64053 * 64054 */ 64055p5.prototype.floor = Math.floor; 64056 64057/** 64058 * Calculates a number between two numbers at a specific increment. The amt 64059 * parameter is the amount to interpolate between the two values where 0.0 64060 * equal to the first point, 0.1 is very near the first point, 0.5 is 64061 * half-way in between, etc. The lerp function is convenient for creating 64062 * motion along a straight path and for drawing dotted lines. 64063 * 64064 * @method lerp 64065 * @param {Number} start first value 64066 * @param {Number} stop second value 64067 * @param {Number} amt number between 0.0 and 1.0 64068 * @return {Number} lerped value 64069 * @example 64070 * <div><code> 64071 * function setup() { 64072 * background(200); 64073 * var a = 20; 64074 * var b = 80; 64075 * var c = lerp(a, b, 0.2); 64076 * var d = lerp(a, b, 0.5); 64077 * var e = lerp(a, b, 0.8); 64078 * 64079 * var y = 50; 64080 * 64081 * strokeWeight(5); 64082 * stroke(0); // Draw the original points in black 64083 * point(a, y); 64084 * point(b, y); 64085 * 64086 * stroke(100); // Draw the lerp points in gray 64087 * point(c, y); 64088 * point(d, y); 64089 * point(e, y); 64090 * } 64091 * </code></div> 64092 * 64093 * @alt 64094 * 5 points horizontally staggered mid-canvas. mid 3 are grey, outer black 64095 * 64096 */ 64097p5.prototype.lerp = function(start, stop, amt) { 64098 p5._validateParameters('lerp', arguments); 64099 return amt * (stop - start) + start; 64100}; 64101 64102/** 64103 * Calculates the natural logarithm (the base-e logarithm) of a number. This 64104 * function expects the n parameter to be a value greater than 0.0. Maps to 64105 * Math.log(). 64106 * 64107 * @method log 64108 * @param {Number} n number greater than 0 64109 * @return {Number} natural logarithm of n 64110 * @example 64111 * <div><code> 64112 * function draw() { 64113 * background(200); 64114 * var maxX = 2.8; 64115 * var maxY = 1.5; 64116 * 64117 * // Compute the natural log of a value between 0 and maxX 64118 * var xValue = map(mouseX, 0, width, 0, maxX); 64119 * if (xValue > 0) { 64120 // Cannot take the log of a negative number. 64121 * var yValue = log(xValue); 64122 * var y = map(yValue, -maxY, maxY, height, 0); 64123 * 64124 * // Display the calculation occurring. 64125 * var legend = 'log(' + nf(xValue, 1, 2) + ')\n= ' + nf(yValue, 1, 3); 64126 * stroke(150); 64127 * line(mouseX, y, mouseX, height); 64128 * fill(0); 64129 * text(legend, 5, 15); 64130 * noStroke(); 64131 * ellipse(mouseX, y, 7, 7); 64132 * } 64133 * 64134 * // Draw the log(x) curve, 64135 * // over the domain of x from 0 to maxX 64136 * noFill(); 64137 * stroke(0); 64138 * beginShape(); 64139 * for (var x = 0; x < width; x++) { 64140 * xValue = map(x, 0, width, 0, maxX); 64141 * yValue = log(xValue); 64142 * y = map(yValue, -maxY, maxY, height, 0); 64143 * vertex(x, y); 64144 * } 64145 * endShape(); 64146 * line(0, 0, 0, height); 64147 * line(0, height / 2, width, height / 2); 64148 * } 64149 * </code></div> 64150 * 64151 * @alt 64152 * ellipse moves along a curve with mouse x. natural logarithm of n displayed. 64153 * 64154 */ 64155p5.prototype.log = Math.log; 64156 64157/** 64158 * Calculates the magnitude (or length) of a vector. A vector is a direction 64159 * in space commonly used in computer graphics and linear algebra. Because it 64160 * has no "start" position, the magnitude of a vector can be thought of as 64161 * the distance from the coordinate 0,0 to its x,y value. Therefore, mag() is 64162 * a shortcut for writing dist(0, 0, x, y). 64163 * 64164 * @method mag 64165 * @param {Number} a first value 64166 * @param {Number} b second value 64167 * @return {Number} magnitude of vector from (0,0) to (a,b) 64168 * @example 64169 * <div><code> 64170 * function setup() { 64171 * var x1 = 20; 64172 * var x2 = 80; 64173 * var y1 = 30; 64174 * var y2 = 70; 64175 * 64176 * line(0, 0, x1, y1); 64177 * print(mag(x1, y1)); // Prints "36.05551275463989" 64178 * line(0, 0, x2, y1); 64179 * print(mag(x2, y1)); // Prints "85.44003745317531" 64180 * line(0, 0, x1, y2); 64181 * print(mag(x1, y2)); // Prints "72.80109889280519" 64182 * line(0, 0, x2, y2); 64183 * print(mag(x2, y2)); // Prints "106.3014581273465" 64184 * } 64185 * </code></div> 64186 * 64187 * @alt 64188 * 4 lines of different length radiate from top left of canvas. 64189 * 64190 */ 64191p5.prototype.mag = function(x, y) { 64192 p5._validateParameters('mag', arguments); 64193 return hypot(x, y); 64194}; 64195 64196/** 64197 * Re-maps a number from one range to another. 64198 * <br><br> 64199 * In the first example above, the number 25 is converted from a value in the 64200 * range of 0 to 100 into a value that ranges from the left edge of the 64201 * window (0) to the right edge (width). 64202 * 64203 * @method map 64204 * @param {Number} value the incoming value to be converted 64205 * @param {Number} start1 lower bound of the value's current range 64206 * @param {Number} stop1 upper bound of the value's current range 64207 * @param {Number} start2 lower bound of the value's target range 64208 * @param {Number} stop2 upper bound of the value's target range 64209 * @param {Boolean} [withinBounds] constrain the value to the newly mapped range 64210 * @return {Number} remapped number 64211 * @example 64212 * <div><code> 64213 * var value = 25; 64214 * var m = map(value, 0, 100, 0, width); 64215 * ellipse(m, 50, 10, 10); 64216</code></div> 64217 * 64218 * <div><code> 64219 * function setup() { 64220 * noStroke(); 64221 * } 64222 * 64223 * function draw() { 64224 * background(204); 64225 * var x1 = map(mouseX, 0, width, 25, 75); 64226 * ellipse(x1, 25, 25, 25); 64227 * //This ellipse is constrained to the 0-100 range 64228 * //after setting withinBounds to true 64229 * var x2 = map(mouseX, 0, width, 0, 100, true); 64230 * ellipse(x2, 75, 25, 25); 64231 * } 64232</code></div> 64233 * 64234 * @alt 64235 * 10 by 10 white ellipse with in mid left canvas 64236 * 2 25 by 25 white ellipses move with mouse x. Bottom has more range from X 64237 * 64238 */ 64239p5.prototype.map = function(n, start1, stop1, start2, stop2, withinBounds) { 64240 p5._validateParameters('map', arguments); 64241 var newval = (n - start1) / (stop1 - start1) * (stop2 - start2) + start2; 64242 if (!withinBounds) { 64243 return newval; 64244 } 64245 if (start2 < stop2) { 64246 return this.constrain(newval, start2, stop2); 64247 } else { 64248 return this.constrain(newval, stop2, start2); 64249 } 64250}; 64251 64252/** 64253 * Determines the largest value in a sequence of numbers, and then returns 64254 * that value. max() accepts any number of Number parameters, or an Array 64255 * of any length. 64256 * 64257 * @method max 64258 * @param {Number} n0 Number to compare 64259 * @param {Number} n1 Number to compare 64260 * @return {Number} maximum Number 64261 * @example 64262 * <div><code> 64263 * function setup() { 64264 * // Change the elements in the array and run the sketch 64265 * // to show how max() works! 64266 * var numArray = [2, 1, 5, 4, 8, 9]; 64267 * fill(0); 64268 * noStroke(); 64269 * text('Array Elements', 0, 10); 64270 * // Draw all numbers in the array 64271 * var spacing = 15; 64272 * var elemsY = 25; 64273 * for (var i = 0; i < numArray.length; i++) { 64274 * text(numArray[i], i * spacing, elemsY); 64275 * } 64276 * var maxX = 33; 64277 * var maxY = 80; 64278 * // Draw the Maximum value in the array. 64279 * textSize(32); 64280 * text(max(numArray), maxX, maxY); 64281 * } 64282 * </code></div> 64283 * 64284 * @alt 64285 * Small text at top reads: Array Elements 2 1 5 4 8 9. Large text at center: 9 64286 * 64287 */ 64288/** 64289 * @method max 64290 * @param {Number[]} nums Numbers to compare 64291 * @return {Number} 64292 */ 64293p5.prototype.max = function() { 64294 p5._validateParameters('max', arguments); 64295 if (arguments[0] instanceof Array) { 64296 return Math.max.apply(null, arguments[0]); 64297 } else { 64298 return Math.max.apply(null, arguments); 64299 } 64300}; 64301 64302/** 64303 * Determines the smallest value in a sequence of numbers, and then returns 64304 * that value. min() accepts any number of Number parameters, or an Array 64305 * of any length. 64306 * 64307 * @method min 64308 * @param {Number} n0 Number to compare 64309 * @param {Number} n1 Number to compare 64310 * @return {Number} minimum Number 64311 * @example 64312 * <div><code> 64313 * function setup() { 64314 * // Change the elements in the array and run the sketch 64315 * // to show how min() works! 64316 * var numArray = [2, 1, 5, 4, 8, 9]; 64317 * fill(0); 64318 * noStroke(); 64319 * text('Array Elements', 0, 10); 64320 * // Draw all numbers in the array 64321 * var spacing = 15; 64322 * var elemsY = 25; 64323 * for (var i = 0; i < numArray.length; i++) { 64324 * text(numArray[i], i * spacing, elemsY); 64325 * } 64326 * var maxX = 33; 64327 * var maxY = 80; 64328 * // Draw the Minimum value in the array. 64329 * textSize(32); 64330 * text(min(numArray), maxX, maxY); 64331 * } 64332 * </code></div> 64333 * 64334 * @alt 64335 * Small text at top reads: Array Elements 2 1 5 4 8 9. Large text at center: 1 64336 * 64337 */ 64338/** 64339 * @method min 64340 * @param {Number[]} nums Numbers to compare 64341 * @return {Number} 64342 */ 64343p5.prototype.min = function() { 64344 p5._validateParameters('min', arguments); 64345 if (arguments[0] instanceof Array) { 64346 return Math.min.apply(null, arguments[0]); 64347 } else { 64348 return Math.min.apply(null, arguments); 64349 } 64350}; 64351 64352/** 64353 * Normalizes a number from another range into a value between 0 and 1. 64354 * Identical to map(value, low, high, 0, 1). 64355 * Numbers outside of the range are not clamped to 0 and 1, because 64356 * out-of-range values are often intentional and useful. (See the second 64357 * example above.) 64358 * 64359 * @method norm 64360 * @param {Number} value incoming value to be normalized 64361 * @param {Number} start lower bound of the value's current range 64362 * @param {Number} stop upper bound of the value's current range 64363 * @return {Number} normalized number 64364 * @example 64365 * <div><code> 64366 * function draw() { 64367 * background(200); 64368 * var currentNum = mouseX; 64369 * var lowerBound = 0; 64370 * var upperBound = width; //100; 64371 * var normalized = norm(currentNum, lowerBound, upperBound); 64372 * var lineY = 70; 64373 * line(0, lineY, width, lineY); 64374 * //Draw an ellipse mapped to the non-normalized value. 64375 * noStroke(); 64376 * fill(50); 64377 * var s = 7; // ellipse size 64378 * ellipse(currentNum, lineY, s, s); 64379 * 64380 * // Draw the guide 64381 * var guideY = lineY + 15; 64382 * text('0', 0, guideY); 64383 * textAlign(RIGHT); 64384 * text('100', width, guideY); 64385 * 64386 * // Draw the normalized value 64387 * textAlign(LEFT); 64388 * fill(0); 64389 * textSize(32); 64390 * var normalY = 40; 64391 * var normalX = 20; 64392 * text(normalized, normalX, normalY); 64393 * } 64394 * </code></div> 64395 * 64396 * @alt 64397 * ellipse moves with mouse. 0 shown left & 100 right and updating values center 64398 * 64399 */ 64400p5.prototype.norm = function(n, start, stop) { 64401 p5._validateParameters('norm', arguments); 64402 return this.map(n, start, stop, 0, 1); 64403}; 64404 64405/** 64406 * Facilitates exponential expressions. The pow() function is an efficie
64406nt 64407 * way of multiplying numbers by themselves (or their reciprocals) in large 64408 * quantities. For example, pow(3, 5) is equivalent to the expression 64409 * 3*3*3*3*3 and pow(3, -5) is equivalent to 1 / 3*3*3*3*3. Maps to 64410 * Math.pow(). 64411 * 64412 * @method pow 64413 * @param {Number} n base of the exponential expression 64414 * @param {Number} e power by which to raise the base 64415 * @return {Number} n^e 64416 * @example 64417 * <div><code> 64418 * function setup() { 64419 * //Exponentially increase the size of an ellipse. 64420 * var eSize = 3; // Original Size 64421 * var eLoc = 10; // Original Location 64422 * 64423 * ellipse(eLoc, eLoc, eSize, eSize); 64424 * 64425 * ellipse(eLoc * 2, eLoc * 2, pow(eSize, 2), pow(eSize, 2)); 64426 * 64427 * ellipse(eLoc * 4, eLoc * 4, pow(eSize, 3), pow(eSize, 3)); 64428 * 64429 * ellipse(eLoc * 8, eLoc * 8, pow(eSize, 4), pow(eSize, 4)); 64430 * } 64431 * </code></div> 64432 * 64433 * @alt 64434 * small to large ellipses radiating from top left of canvas 64435 * 64436 */ 64437p5.prototype.pow = Math.pow; 64438 64439/** 64440 * Calculates the integer closest to the n parameter. For example, 64441 * round(133.8) returns the value 134. Maps to Math.round(). 64442 * 64443 * @method round 64444 * @param {Number} n number to round 64445 * @return {Integer} rounded number 64446 * @example 64447 * <div><code> 64448 * function draw() { 64449 * background(200); 64450 * //map, mouseX between 0 and 5. 64451 * var ax = map(mouseX, 0, 100, 0, 5); 64452 * var ay = 66; 64453 * 64454 * // Round the mapped number. 64455 * var bx = round(map(mouseX, 0, 100, 0, 5)); 64456 * var by = 33; 64457 * 64458 * // Multiply the mapped numbers by 20 to more easily 64459 * // see the changes. 64460 * stroke(0); 64461 * fill(0); 64462 * line(0, ay, ax * 20, ay); 64463 * line(0, by, bx * 20, by); 64464 * 64465 * // Reformat the float returned by map and draw it. 64466 * noStroke(); 64467 * text(nfc(ax, 2), ax, ay - 5); 64468 * text(nfc(bx, 1), bx, by - 5); 64469 * } 64470 * </code></div> 64471 * 64472 * @alt 64473 * horizontal center line squared values displayed on top and regular on bottom. 64474 * 64475 */ 64476p5.prototype.round = Math.round; 64477 64478/** 64479 * Squares a number (multiplies a number by itself). The result is always a 64480 * positive number, as multiplying two negative numbers always yields a 64481 * positive result. For example, -1 * -1 = 1. 64482 * 64483 * @method sq 64484 * @param {Number} n number to square 64485 * @return {Number} squared number 64486 * @example 64487 * <div><code> 64488 * function draw() { 64489 * background(200); 64490 * var eSize = 7; 64491 * var x1 = map(mouseX, 0, width, 0, 10); 64492 * var y1 = 80; 64493 * var x2 = sq(x1); 64494 * var y2 = 20; 64495 * 64496 * // Draw the non-squared. 64497 * line(0, y1, width, y1); 64498 * ellipse(x1, y1, eSize, eSize); 64499 * 64500 * // Draw the squared. 64501 * line(0, y2, width, y2); 64502 * ellipse(x2, y2, eSize, eSize); 64503 * 64504 * // Draw dividing line. 64505 * stroke(100); 64506 * line(0, height / 2, width, height / 2); 64507 * 64508 * // Draw text. 64509 * var spacing = 15; 64510 * noStroke(); 64511 * fill(0); 64512 * text('x = ' + x1, 0, y1 + spacing); 64513 * text('sq(x) = ' + x2, 0, y2 + spacing); 64514 * } 64515 * </code></div> 64516 * 64517 * @alt 64518 * horizontal center line squared values displayed on top and regular on bottom. 64519 * 64520 */ 64521p5.prototype.sq = function(n) { 64522 return n * n; 64523}; 64524 64525/** 64526 * Calculates the square root of a number. The square root of a number is 64527 * always positive, even though there may be a valid negative root. The 64528 * square root s of number a is such that s*s = a. It is the opposite of 64529 * squaring. Maps to Math.sqrt(). 64530 * 64531 * @method sqrt 64532 * @param {Number} n non-negative number to square root 64533 * @return {Number} square root of number 64534 * @example 64535 * <div><code> 64536 * function draw() { 64537 * background(200); 64538 * var eSize = 7; 64539 * var x1 = mouseX; 64540 * var y1 = 80; 64541 * var x2 = sqrt(x1); 64542 * var y2 = 20; 64543 * 64544 * // Draw the non-squared. 64545 * line(0, y1, width, y1); 64546 * ellipse(x1, y1, eSize, eSize); 64547 * 64548 * // Draw the squared. 64549 * line(0, y2, width, y2); 64550 * ellipse(x2, y2, eSize, eSize); 64551 * 64552 * // Draw dividing line. 64553 * stroke(100); 64554 * line(0, height / 2, width, height / 2); 64555 * 64556 * // Draw text. 64557 * noStroke(); 64558 * fill(0); 64559 * var spacing = 15; 64560 * text('x = ' + x1, 0, y1 + spacing); 64561 * text('sqrt(x) = ' + x2, 0, y2 + spacing); 64562 * } 64563 * </code></div> 64564 * 64565 * @alt 64566 * horizontal center line squareroot values displayed on top and regular on bottom. 64567 * 64568 */ 64569p5.prototype.sqrt = Math.sqrt; 64570 64571// Calculate the length of the hypotenuse of a right triangle 64572// This won't under- or overflow in intermediate steps 64573// https://en.wikipedia.org/wiki/Hypot 64574function hypot(x, y, z) { 64575 // Use the native implementation if it's available 64576 if (typeof Math.hypot === 'function') { 64577 return Math.hypot.apply(null, arguments); 64578 } 64579 64580 // Otherwise use the V8 implementation 64581 // https://github.com/v8/v8/blob/8cd3cf297287e581a49e487067f5cbd991b27123/src/js/math.js#L217 64582 var length = arguments.length; 64583 var args = []; 64584 var max = 0; 64585 for (var i = 0; i < length; i++) { 64586 var n = arguments[i]; 64587 n = +n; 64588 if (n === Infinity || n === -Infinity) { 64589 return Infinity; 64590 } 64591 n = Math.abs(n); 64592 if (n > max) { 64593 max = n; 64594 } 64595 args[i] = n; 64596 } 64597 64598 if (max === 0) { 64599 max = 1; 64600 } 64601 var sum = 0; 64602 var compensation = 0; 64603 for (var j = 0; j < length; j++) { 64604 var m = args[j] / max; 64605 var summand = m * m - compensation; 64606 var preliminary = sum + summand; 64607 compensation = preliminary - sum - summand; 64608 sum = preliminary; 64609 } 64610 return Math.sqrt(sum) * max; 64611} 64612 64613module.exports = p5; 64614 64615},{"../core/core":22}],51:[function(_dereq_,module,exports){ 64616/** 64617 * @module Math 64618 * @submodule Math 64619 * @for p5 64620 * @requires core 64621 */ 64622 64623'use strict'; 64624 64625var p5 = _dereq_('../core/core'); 64626 64627/** 64628 * Creates a new p5.Vector (the datatype for storing vectors). This provides a 64629 * two or three dimensional vector, specifically a Euclidean (also known as 64630 * geometric) vector. A vector is an entity that has both magnitude and 64631 * direction. 64632 * 64633 * @method createVector 64634 * @param {Number} [x] x component of the vector 64635 * @param {Number} [y] y component of the vector 64636 * @param {Number} [z] z component of the vector 64637 * @return {p5.Vector} 64638 * @example 64639 * <div modernizr='webgl'><code> 64640 * function setup() { 64641 * createCanvas(100, 100, WEBGL); 64642 * noStroke(); 64643 * fill(255, 102, 204); 64644 * } 64645 * 64646 * function draw() { 64647 * background(255); 64648 * pointLight(color(255), createVector(sin(millis() / 1000) * 20, -40, -10)); 64649 * scale(0.75); 64650 * sphere(); 64651 * } 64652 * </code></div> 64653 * 64654 * @alt 64655 * a purple sphere lit by a point light oscillating horizontally 64656 */ 64657p5.prototype.createVector = function(x, y, z) { 64658 if (this instanceof p5) { 64659 return new p5.Vector(this, arguments); 64660 } else { 64661 return new p5.Vector(x, y, z); 64662 } 64663}; 64664 64665module.exports = p5; 64666 64667},{"../core/core":22}],52:[function(_dereq_,module,exports){ 64668////////////////////////////////////////////////////////////// 64669 64670// http://mrl.nyu.edu/~perlin/noise/ 64671// Adapting from PApplet.java 64672// which was adapted from toxi 64673// which was adapted from the german demo group farbrausch 64674// as used in their demo "art": http://www.farb-rausch.de/fr010src.zip 64675 64676// someday we might consider using "improved noise" 64677// http://mrl.nyu.edu/~perlin/paper445.pdf
64678// See: https://github.com/shiffman/The-Nature-of-Code-Examples-p5.js/ 64679// blob/master/introduction/Noise1D/noise.js 64680 64681/** 64682 * @module Math 64683 * @submodule Noise 64684 * @for p5 64685 * @requires core 64686 */ 64687 64688'use strict'; 64689 64690var p5 = _dereq_('../core/core'); 64691 64692var PERLIN_YWRAPB = 4; 64693var PERLIN_YWRAP = 1 << PERLIN_YWRAPB; 64694var PERLIN_ZWRAPB = 8; 64695var PERLIN_ZWRAP = 1 << PERLIN_ZWRAPB; 64696var PERLIN_SIZE = 4095; 64697 64698var perlin_octaves = 4; // default to medium smooth 64699var perlin_amp_falloff = 0.5; // 50% reduction/octave 64700 64701var scaled_cosine = function(i) { 64702 return 0.5 * (1.0 - Math.cos(i * Math.PI)); 64703}; 64704 64705var perlin; // will be initialized lazily by noise() or noiseSeed() 64706 64707/** 64708 * Returns the Perlin noise value at specified coordinates. Perlin noise is 64709 * a random sequence generator producing a more natural ordered, harmonic 64710 * succession of numbers compared to the standard <b>random()</b> function. 64711 * It was invented by Ken Perlin in the 1980s and been used since in 64712 * graphical applications to produce procedural textures, natural motion, 64713 * shapes, terrains etc.<br /><br /> The main difference to the 64714 * <b>random()</b> function is that Perlin noise is defined in an infinite 64715 * n-dimensional space where each pair of coordinates corresponds to a 64716 * fixed semi-random value (fixed only for the lifespan of the program; see 64717 * the noiseSeed() function). p5.js can compute 1D, 2D and 3D noise, 64718 * depending on the number of coordinates given. The resulting value will 64719 * always be between 0.0 and 1.0. The noise value can be animated by moving 64720 * through the noise space as demonstrated in the example above. The 2nd 64721 * and 3rd dimension can also be interpreted as time.<br /><br />The actual 64722 * noise is structured similar to an audio signal, in respect to the 64723 * function's use of frequencies. Similar to the concept of harmonics in 64724 * physics, perlin noise is computed over several octaves which are added 64725 * together for the final result. <br /><br />Another way to adjust the 64726 * character of the resulting sequence is the scale of the input 64727 * coordinates. As the function works within an infinite space the value of 64728 * the coordinates doesn't matter as such, only the distance between 64729 * successive coordinates does (eg. when using <b>noise()</b> within a 64730 * loop). As a general rule the smaller the difference between coordinates, 64731 * the smoother the resulting noise sequence will be. Steps of 0.005-0.03 64732 * work best for most applications, but this will differ depending on use. 64733 * 64734 * 64735 * @method noise 64736 * @param {Number} x x-coordinate in noise space 64737 * @param {Number} [y] y-coordinate in noise space 64738 * @param {Number} [z] z-coordinate in noise space 64739 * @return {Number} Perlin noise value (between 0 and 1) at specified 64740 * coordinates 64741 * @example 64742 * <div> 64743 * <code> 64744 * var xoff = 0.0; 64745 * 64746 * function draw() { 64747 * background(204); 64748 * xoff = xoff + 0.01; 64749 * var n = noise(xoff) * width; 64750 * line(n, 0, n, height); 64751 * } 64752 * </code> 64753 * </div> 64754 * <div> 64755 * <code>var noiseScale=0.02; 64756 * 64757 * function draw() { 64758 * background(0); 64759 * for (var x=0; x < width; x++) { 64760 * var noiseVal = noise((mouseX+x)*noiseScale, mouseY*noiseScale); 64761 * stroke(noiseVal*255); 64762 * line(x, mouseY+noiseVal*80, x, height); 64763 * } 64764 * } 64765 * </code> 64766 * </div> 64767 * 64768 * @alt 64769 * vertical line moves left to right with updating noise values. 64770 * horizontal wave pattern effected by mouse x-position & updating noise values. 64771 * 64772 */ 64773 64774p5.prototype.noise = function(x, y, z) { 64775 y = y || 0; 64776 z = z || 0; 64777 64778 if (perlin == null) { 64779 perlin = new Array(PERLIN_SIZE + 1); 64780 for (var i = 0; i < PERLIN_SIZE + 1; i++) { 64781 perlin[i] = Math.random(); 64782 } 64783 } 64784 64785 if (x < 0) { 64786 x = -x; 64787 } 64788 if (y < 0) { 64789 y = -y; 64790 } 64791 if (z < 0) { 64792 z = -z; 64793 } 64794 64795 var xi = Math.floor(x), 64796 yi = Math.floor(y), 64797 zi = Math.floor(z); 64798 var xf = x - xi; 64799 var yf = y - yi; 64800 var zf = z - zi; 64801 var rxf, ryf; 64802 64803 var r = 0; 64804 var ampl = 0.5; 64805 64806 var n1, n2, n3; 64807 64808 for (var o = 0; o < perlin_octaves; o++) { 64809 var of = xi + (yi << PERLIN_YWRAPB) + (zi << PERLIN_ZWRAPB); 64810 64811 rxf = scaled_cosine(xf); 64812 ryf = scaled_cosine(yf); 64813 64814 n1 = perlin[of & PERLIN_SIZE]; 64815 n1 += rxf * (perlin[(of + 1) & PERLIN_SIZE] - n1); 64816 n2 = perlin[(of + PERLIN_YWRAP) & PERLIN_SIZE]; 64817 n2 += rxf * (perlin[(of + PERLIN_YWRAP + 1) & PERLIN_SIZE] - n2); 64818 n1 += ryf * (n2 - n1); 64819 64820 of += PERLIN_ZWRAP; 64821 n2 = perlin[of & PERLIN_SIZE]; 64822 n2 += rxf * (perlin[(of + 1) & PERLIN_SIZE] - n2); 64823 n3 = perlin[(of + PERLIN_YWRAP) & PERLIN_SIZE]; 64824 n3 += rxf * (perlin[(of + PERLIN_YWRAP + 1) & PERLIN_SIZE] - n3); 64825 n2 += ryf * (n3 - n2); 64826 64827 n1 += scaled_cosine(zf) * (n2 - n1); 64828 64829 r += n1 * ampl; 64830 ampl *= perlin_amp_falloff; 64831 xi <<= 1; 64832 xf *= 2; 64833 yi <<= 1; 64834 yf *= 2; 64835 zi <<= 1; 64836 zf *= 2; 64837 64838 if (xf >= 1.0) { 64839 xi++; 64840 xf--; 64841 } 64842 if (yf >= 1.0) { 64843 yi++; 64844 yf--; 64845 } 64846 if (zf >= 1.0) { 64847 zi++; 64848 zf--; 64849 } 64850 } 64851 return r; 64852}; 64853 64854/** 64855 * 64856 * Adjusts the character and level of detail produced by the Perlin noise 64857 * function. Similar to harmonics in physics, noise is computed over 64858 * several octaves. Lower octaves contribute more to the output signal and 64859 * as such define the overall intensity of the noise, whereas higher octaves 64860 * create finer grained details in the noise sequence. 64861 * <br><br> 64862 * By default, noise is computed over 4 octaves with each octave contributing 64863 * exactly half than its predecessor, starting at 50% strength for the 1st 64864 * octave. This falloff amount can be changed by adding an additional function 64865 * parameter. Eg. a falloff factor of 0.75 means each octave will now have 64866 * 75% impact (25% less) of the previous lower octave. Any value between 64867 * 0.0 and 1.0 is valid, however note that values greater than 0.5 might 64868 * result in greater than 1.0 values returned by <b>noise()</b>. 64869 * <br><br> 64870 * By changing these parameters, the signal created by the <b>noise()</b> 64871 * function can be adapted to fit very specific needs and characteristics. 64872 * 64873 * @method noiseDetail 64874 * @param {Number} lod number of octaves to be used by the noise 64875 * @param {Number} falloff falloff factor for each octave 64876 * @example 64877 * <div> 64878 * <code> 64879 * var noiseVal; 64880 * var noiseScale = 0.02; 64881 * 64882 * function setup() { 64883 * createCanvas(100, 100); 64884 * } 64885 * 64886 * function draw() { 64887 * background(0); 64888 * for (var y = 0; y < height; y++) { 64889 * for (var x = 0; x < width / 2; x++) { 64890 * noiseDetail(2, 0.2); 64891 * noiseVal = noise((mouseX + x) * noiseScale, (mouseY + y) * noiseScale); 64892 * stroke(noiseVal * 255); 64893 * point(x, y); 64894 * noiseDetail(8, 0.65); 64895 * noiseVal = noise( 64896 * (mouseX + x + width / 2) * noiseScale, 64897 * (mouseY + y) * noiseScale 64898 * ); 64899 * stroke(noiseVal * 255); 64900 * point(x + width / 2, y); 64901 * } 64902 * } 64903 * } 64904 * </code> 64905 * </div> 64906 * 64907 * @alt 64908 * 2 vertical grey smokey patterns affected my mouse x-position and noise. 64909 * 64910 */ 64911p5.prototype.noiseDetail = function(lod, falloff) { 64912 if (lod > 0) { 64913 perlin_octaves = lod; 64914 } 64915 if (falloff > 0) { 64916 perlin_amp_falloff = falloff; 64917 } 64918}; 64919 64920/** 64921 * Sets the seed value for <b>noise()</b>. By default, <b>noise()</b> 64922 * produces different results each time the program is run. Set the 64923 * <b>value</b> parameter to a constant to return the same pseudo-random
64924 * numbers each time the software is run. 64925 * 64926 * @method noiseSeed 64927 * @param {Number} seed the seed value 64928 * @example 64929 * <div> 64930 * <code>var xoff = 0.0; 64931 * 64932 * function setup() { 64933 * noiseSeed(99); 64934 * stroke(0, 10); 64935 * } 64936 * 64937 * function draw() { 64938 * xoff = xoff + .01; 64939 * var n = noise(xoff) * width; 64940 * line(n, 0, n, height); 64941 * } 64942 * </code> 64943 * </div> 64944 * 64945 * @alt 64946 * vertical grey lines drawing in pattern affected by noise. 64947 * 64948 */ 64949p5.prototype.noiseSeed = function(seed) { 64950 // Linear Congruential Generator 64951 // Variant of a Lehman Generator 64952 var lcg = (function() { 64953 // Set to values from http://en.wikipedia.org/wiki/Numerical_Recipes 64954 // m is basically chosen to be large (as it is the max period) 64955 // and for its relationships to a and c 64956 var m = 4294967296; 64957 // a - 1 should be divisible by m's prime factors 64958 var a = 1664525; 64959 // c and m should be co-prime 64960 var c = 1013904223; 64961 var seed, z; 64962 return { 64963 setSeed: function(val) { 64964 // pick a random seed if val is undefined or null 64965 // the >>> 0 casts the seed to an unsigned 32-bit integer 64966 z = seed = (val == null ? Math.random() * m : val) >>> 0; 64967 }, 64968 getSeed: function() { 64969 return seed; 64970 }, 64971 rand: function() { 64972 // define the recurrence relationship 64973 z = (a * z + c) % m; 64974 // return a float in [0, 1) 64975 // if z = m then z / m = 0 therefore (z % m) / m < 1 always 64976 return z / m; 64977 } 64978 }; 64979 })(); 64980
64981 lcg.setSeed(seed); 64982 perlin = new Array(PERLIN_SIZE + 1); 64983 for (var i = 0; i < PERLIN_SIZE + 1; i++) { 64984 perlin[i] = lcg.rand(); 64985 } 64986}; 64987 64988module.exports = p5; 64989 64990},{"../core/core":22}],53:[function(_dereq_,module,exports){ 64991/** 64992 * @module Math 64993 * @submodule Math 64994 * @requires constants 64995 */ 64996 64997'use strict'; 64998 64999var p5 = _dereq_('../core/core'); 65000var constants = _dereq_('../core/constants'); 65001 65002/** 65003 * A class to describe a two or three dimensional vector, specifically 65004 * a Euclidean (also known as geometric) vector. A vector is an entity 65005 * that has both magnitude and direction. The datatype, however, stores 65006 * the components of the vector (x, y for 2D, and x, y, z for 3D). The magnitude 65007 * and direction can be accessed via the methods mag() and heading(). 65008 * <br><br> 65009 * In many of the p5.js examples, you will see p5.Vector used to describe a 65010 * position, velocity, or acceleration. For example, if you consider a rectangle 65011 * moving across the screen, at any given instant it has a position (a vector 65012 * that points from the origin to its location), a velocity (the rate at which 65013 * the object's position changes per time unit, expressed as a vector), and 65014 * acceleration (the rate at which the object's velocity changes per time 65015 * unit, expressed as a vector). 65016 * <br><br> 65017 * Since vectors represent groupings of values, we cannot simply use 65018 * traditional addition/multiplication/etc. Instead, we'll need to do some 65019 * "vector" math, which is made easy by the methods inside the p5.Vector class. 65020 * 65021 * @class p5.Vector 65022 * @param {Number} [x] x component of the vector 65023 * @param {Number} [y] y component of the vector 65024 * @param {Number} [z] z component of the vector 65025 * @example 65026 * <div> 65027 * <code> 65028 * var v1 = createVector(40, 50); 65029 * var v2 = createVector(40, 50); 65030 * 65031 * ellipse(v1.x, v1.y, 50, 50); 65032 * ellipse(v2.x, v2.y, 50, 50); 65033 * v1.add(v2); 65034 * ellipse(v1.x, v1.y, 50, 50); 65035 * </code> 65036 * </div> 65037 * 65038 * @alt 65039 * 2 white ellipses. One center-left the other bottom right and off canvas 65040 * 65041 */ 65042p5.Vector = function Vector() { 65043 var x, y, z; 65044 // This is how it comes in with createVector() 65045 if (arguments[0] instanceof p5) { 65046 // save reference to p5 if passed in 65047 this.p5 = arguments[0]; 65048 x = arguments[1][0] || 0; 65049 y = arguments[1][1] || 0; 65050 z = arguments[1][2] || 0; 65051 // This is what we'll get with new p5.Vector() 65052 } else { 65053 x = arguments[0] || 0; 65054 y = arguments[1] || 0; 65055 z = arguments[2] || 0; 65056 } 65057 /** 65058 * The x component of the vector 65059 * @property x {Number} 65060 */ 65061 this.x = x; 65062 /** 65063 * The y component of the vector 65064 * @property y {Number} 65065 */ 65066 this.y = y; 65067 /** 65068 * The z component of the vector 65069 * @property z {Number} 65070 */ 65071 this.z = z; 65072}; 65073 65074/** 65075 * Returns a string representation of a vector v by calling String(v) 65076 * or v.toString(). This method is useful for logging vectors in the 65077 * console. 65078 * @method toString 65079 * @return {String} 65080 * @example 65081 * <div class = "norender"> 65082 * <code> 65083 * function setup() { 65084 * var v = createVector(20, 30); 65085 * print(String(v)); // prints "p5.Vector Object : [20, 30, 0]" 65086 * } 65087 * </code> 65088 * </div> 65089 * 65090 * <div> 65091 * <code> 65092 * function draw() { 65093 * background(240); 65094 * 65095 * var v0 = createVector(0, 0); 65096 * var v1 = createVector(mouseX, mouseY); 65097 * drawArrow(v0, v1, 'black'); 65098 * 65099 * noStroke(); 65100 * text(v1.toString(), 10, 25, 90, 75); 65101 * } 65102 * 65103 * // draw an arrow for a vector at a given base position 65104 * function drawArrow(base, vec, myColor) { 65105 * push(); 65106 * stroke(myColor); 65107 * strokeWeight(3); 65108 * fill(myColor); 65109 * translate(base.x, base.y); 65110 * line(0, 0, vec.x, vec.y); 65111 * rotate(vec.heading()); 65112 * var arrowSize = 7; 65113 * translate(vec.mag() - arrowSize, 0); 65114 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0); 65115 * pop(); 65116 * } 65117 * </code> 65118 * </div> 65119 */ 65120p5.Vector.prototype.toString = function p5VectorToString() { 65121 return 'p5.Vector Object : [' + this.x + ', ' + this.y + ', ' + this.z + ']'; 65122}; 65123 65124/** 65125 * Sets the x, y, and z component of the vector using two or three separate 65126 * variables, the data from a p5.Vector, or the values from a float array. 65127 * @method set 65128 * @param {Number} [x] the x component of the vector 65129 * @param {Number} [y] the y component of the vector 65130 * @param {Number} [z] the z component of the vector 65131 * @chainable 65132 * @example 65133 * <div class="norender"> 65134 * <code> 65135 * function setup() { 65136 * var v = createVector(1, 2, 3);
65137 * v.set(4, 5, 6); // Sets vector to [4, 5, 6] 65138 * 65139 * var v1 = createVector(0, 0, 0); 65140 * var arr = [1, 2, 3]; 65141 * v1.set(arr); // Sets vector to [1, 2, 3] 65142 * } 65143 * </code> 65144 * </div> 65145 * 65146 * <div> 65147 * <code> 65148 * var v0, v1; 65149 * function setup() { 65150 * createCanvas(100, 100); 65151 * 65152 * v0 = createVector(0, 0); 65153 * v1 = createVector(50, 50); 65154 * } 65155 * 65156 * function draw() { 65157 * background(240); 65158 * 65159 * drawArrow(v0, v1, 'black'); 65160 * v1.set(v1.x + random(-1, 1), v1.y + random(-1, 1)); 65161 * 65162 * noStroke(); 65163 * text('x: ' + round(v1.x) + ' y: ' + round(v1.y), 20, 90); 65164 * } 65165 * 65166 * // draw an arrow for a vector at a given base position 65167 * function drawArrow(base, vec, myColor) { 65168 * push(); 65169 * stroke(myColor); 65170 * strokeWeight(3); 65171 * fill(myColor); 65172 * translate(base.x, base.y); 65173 * line(0, 0, vec.x, vec.y); 65174 * rotate(vec.heading()); 65175 * var arrowSize = 7; 65176 * translate(vec.mag() - arrowSize, 0); 65177 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0); 65178 * pop(); 65179 * } 65180 * </code> 65181 * </div> 65182 */ 65183/** 65184 * @method set 65185 * @param {p5.Vector|Number[]} value the vector to set 65186 * @chainable 65187 */ 65188p5.Vector.prototype.set = function set(x, y, z) { 65189 if (x instanceof p5.Vector) { 65190 this.x = x.x || 0; 65191 this.y = x.y || 0; 65192 this.z = x.z || 0; 65193 return this; 65194 } 65195 if (x instanceof Array) { 65196 this.x = x[0] || 0; 65197 this.y = x[1] || 0; 65198 this.z = x[2] || 0; 65199 return this; 65200 } 65201 this.x = x || 0; 65202 this.y = y || 0; 65203 this.z = z || 0; 65204 return this; 65205}; 65206 65207/** 65208 * Gets a copy of the vector, returns a p5.Vector object. 65209 * 65210 * @method copy 65211 * @return {p5.Vector} the copy of the p5.Vector object 65212 * @example 65213 * <div class="norender"> 65214 * <code> 65215 * var v1 = createVector(1, 2, 3); 65216 * var v2 = v1.copy(); 65217 * print(v1.x === v2.x && v1.y === v2.y && v1.z === v2.z); 65218 * // Prints "true" 65219 * </code> 65220 * </div> 65221 */ 65222p5.Vector.prototype.copy = function copy() { 65223 if (this.p5) { 65224 return new p5.Vector(this.p5, [this.x, this.y, this.z]); 65225 } else { 65226 return new p5.Vector(this.x, this.y, this.z); 65227 } 65228}; 65229 65230/** 65231 * Adds x, y, and z components to a vector, adds one vector to another, or
65232 * adds two independent vectors together. The version of the method that adds 65233 * two vectors together is a static method and returns a p5.Vector, the others 65234 * acts directly on the vector. See the examples for more context. 65235 * 65236 * @method add 65237 * @param {Number} x the x component of the vector to be added 65238 * @param {Number} [y] the y component of the vector to be added 65239 * @param {Number} [z] the z component of the vector to be added 65240 * @chainable 65241 * @example 65242 * <div class="norender"> 65243 * <code> 65244 * var v = createVector(1, 2, 3); 65245 * v.add(4, 5, 6); 65246 * // v's components are set to [5, 7, 9] 65247 * </code> 65248 * </div> 65249 * 65250 * <div class="norender"> 65251 * <code> 65252 * // Static method 65253 * var v1 = createVector(1, 2, 3); 65254 * var v2 = createVector(2, 3, 4); 65255 * 65256 * var v3 = p5.Vector.add(v1, v2); 65257 * // v3 has components [3, 5, 7] 65258 * print(v3); 65259 * </code> 65260 * </div> 65261 * 65262 * <div> 65263 * <code> 65264 * // red vector + blue vector = purple vector 65265 * function draw() { 65266 * background(240); 65267 * 65268 * var v0 = createVector(0, 0); 65269 * var v1 = createVector(mouseX, mouseY); 65270 * drawArrow(v0, v1, 'red'); 65271 * 65272 * var v2 = createVector(-30, 20); 65273 * drawArrow(v1, v2, 'blue'); 65274 * 65275 * var v3 = p5.Vector.add(v1, v2); 65276 * drawArrow(v0, v3, 'purple'); 65277 * } 65278 * 65279 * // draw an arrow for a vector at a given base position 65280 * function drawArrow(base, vec, myColor) { 65281 * push(); 65282 * stroke(myColor); 65283 * strokeWeight(3); 65284 * fill(myColor); 65285 * translate(base.x, base.y); 65286 * line(0, 0, vec.x, vec.y); 65287 * rotate(vec.heading()); 65288 * var arrowSize = 7; 65289 * translate(vec.mag() - arrowSize, 0); 65290 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0); 65291 * pop(); 65292 * } 65293 * </code> 65294 * </div> 65295 */ 65296/** 65297 * @method add 65298 * @param {p5.Vector|Number[]} value the vector to add 65299 * @chainable 65300 */ 65301p5.Vector.prototype.add = function add(x, y, z) { 65302 if (x instanceof p5.Vector) { 65303 this.x += x.x || 0; 65304 this.y += x.y || 0; 65305 this.z += x.z || 0; 65306 return this; 65307 } 65308 if (x instanceof Array) { 65309 this.x += x[0] || 0; 65310 this.y += x[1] || 0; 65311 this.z += x[2] || 0; 65312 return this; 65313 } 65314 this.x += x || 0; 65315 this.y += y || 0; 65316 this.z += z || 0; 65317 return this; 65318}; 65319 65320/** 65321 * Subtracts x, y, and z components from a vector, subtracts one vector from 65322 * another, or subtracts two independent vectors. The version of the method 65323 * that subtracts two vectors is a static method and returns a p5.Vector, the 65324 * other acts directly on the vector. See the examples for more context. 65325 * 65326 * @method sub 65327 * @param {Number} x the x component of the vector to subtract 65328 * @param {Number} [y] the y component of the vector to subtract 65329 * @param {Number} [z] the z component of the vector to subtract 65330 * @chainable 65331 * @example 65332 * <div class="norender"> 65333 * <code> 65334 * var v = createVector(4, 5, 6); 65335 * v.sub(1, 1, 1); 65336 * // v's components are set to [3, 4, 5] 65337 * </code> 65338 * </div> 65339 * 65340 * <div class="norender"> 65341 * <code> 65342 * // Static method 65343 * var v1 = createVector(2, 3, 4); 65344 * var v2 = createVector(1, 2, 3); 65345 * 65346 * var v3 = p5.Vector.sub(v1, v2); 65347 * // v3 has components [1, 1, 1] 65348 * print(v3); 65349 * </code> 65350 * </div> 65351 * 65352 * <div> 65353 * <code> 65354 * // red vector - blue vector = purple vector 65355 * function draw() { 65356 * background(240); 65357 * 65358 * var v0 = createVector(0, 0); 65359 * var v1 = createVector(70, 50); 65360 * drawArrow(v0, v1, 'red'); 65361 * 65362 * var v2 = createVector(mouseX, mouseY); 65363 * drawArrow(v0, v2, 'blue'); 65364 * 65365 * var v3 = p5.Vector.sub(v1, v2); 65366 * drawArrow(v2, v3, 'purple'); 65367 * } 65368 * 65369 * // draw an arrow for a vector at a given base position 65370 * function drawArrow(base, vec, myColor) { 65371 * push(); 65372 * stroke(myColor); 65373 * strokeWeight(3); 65374 * fill(myColor); 65375 * translate(base.x, base.y); 65376 * line(0, 0, vec.x, vec.y); 65377 * rotate(vec.heading()); 65378 * var arrowSize = 7; 65379 * translate(vec.mag() - arrowSize, 0); 65380 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0); 65381 * pop(); 65382 * } 65383 * </code> 65384 * </div> 65385 */ 65386/** 65387 * @method sub 65388 * @param {p5.Vector|Number[]} value the vector to subtract 65389 * @chainable 65390 */ 65391p5.Vector.prototype.sub = function sub(x, y, z) { 65392 if (x instanceof p5.Vector) { 65393 this.x -= x.x || 0; 65394 this.y -= x.y || 0; 65395 this.z -= x.z || 0; 65396 return this; 65397 } 65398 if (x instanceof Array) { 65399 this.x -= x[0] || 0; 65400 this.y -= x[1] || 0; 65401 this.z -= x[2] || 0; 65402 return this; 65403 } 65404 this.x -= x || 0; 65405 this.y -= y || 0; 65406 this.z -= z || 0; 65407 return this; 65408}; 65409 65410/** 65411 * Multiply the vector by a scalar. The static version of this method 65412 * creates a new p5.Vector while the non static version acts on the vector 65413 * directly. See the examples for more context. 65414 * 65415 * @method mult 65416 * @param {Number} n the number to multiply with the vector 65417 * @chainable 65418 * @example 65419 * <div class="norender"> 65420 * <code> 65421 * var v = createVector(1, 2, 3); 65422 * v.mult(2); 65423 * // v's components are set to [2, 4, 6] 65424 * </code> 65425 * </div> 65426 * 65427 * <div class="norender"> 65428 * <code> 65429 * // Static method 65430 * var v1 = createVector(1, 2, 3); 65431 * var v2 = p5.Vector.mult(v1, 2); 65432 * // v2 has components [2, 4, 6] 65433 * print(v2); 65434 * </code> 65435 * </div> 65436 * 65437 * <div> 65438 * <code> 65439 * function draw() { 65440 * background(240); 65441 * 65442 * var v0 = createVector(50, 50); 65443 * var v1 = createVector(25, -25); 65444 * drawArrow(v0, v1, 'red'); 65445 * 65446 * var num = map(mouseX, 0, width, -2, 2, true); 65447 * var v2 = p5.Vector.mult(v1, num); 65448 * drawArrow(v0, v2, 'blue'); 65449 * 65450 * noStroke(); 65451 * text('multiplied by ' + num.toFixed(2), 5, 90); 65452 * } 65453 * 65454 * // draw an arrow for a vector at a given base position 65455 * function drawArrow(base, vec, myColor) { 65456 * push(); 65457 * stroke(myColor); 65458 * strokeWeight(3); 65459 * fill(myColor); 65460 * translate(base.x, base.y); 65461 * line(0, 0, vec.x, vec.y); 65462 * rotate(vec.heading()); 65463 * var arrowSize = 7; 65464 * translate(vec.mag() - arrowSize, 0); 65465 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0); 65466 * pop(); 65467 * } 65468 * </code> 65469 * </div> 65470 */ 65471p5.Vector.prototype.mult = function mult(n) { 65472 if (!(typeof n === 'number' && isFinite(n))) { 65473 console.warn( 65474 'p5.Vector.prototype.mult:', 65475 'n is undefined or not a finite number' 65476 ); 65477 return this; 65478 } 65479 this.x *= n; 65480 this.y *= n; 65481 this.z *= n; 65482 return this; 65483}; 65484 65485/** 65486 * Divide the vector by a scalar. The static version of this method creates a 65487 * new p5.Vector while the non static version acts on the vector directly. 65488 * See the examples for more context. 65489 * 65490 * @method div 65491 * @param {number} n the number to divide the vector by 65492 * @chainable 65493 * @example 65494 * <div class="norender"> 65495 * <code> 65496 * var v = createVector(6, 4, 2); 65497 * v.div(2); //v's components are set to [3, 2, 1] 65498 * </code> 65499 * </div> 65500 * 65501 * <div class="norender"> 65502 * <code> 65503 * // Static method 65504 * var v1 = createVector(6, 4, 2); 65505 * var v2 = p5.Vector.div(v1, 2); 65506 * // v2 has components [3, 2, 1] 65507 * print(v2); 65508 * </code> 65509 * </div> 65510 * 65511 * <div> 65512 * <code> 65513 * function draw() { 65514 * background(240); 65515 * 65516 * var v0 = createVector(0, 100); 65517 * var v1 = createVector(50, -50); 65518 * drawArrow(v0, v1, 'red'); 65519 * 65520 * var num = map(mouseX, 0, width, 10, 0.5, true); 65521 * var v2 = p5.Vector.div(v1, num); 65522 * drawArrow(v0, v2, 'blue'); 65523 * 65524 * noStroke(); 65525 * text('divided by ' + num.toFixed(2), 10, 90); 65526 * } 65527 * 65528 * // draw an arrow for a vector at a given base position 65529 * function drawArrow(base, vec, myColor) { 65530 * push(); 65531 * stroke(myColor); 65532 * strokeWeight(3); 65533 * fill(myColor); 65534 * translate(base.x, base.y); 65535 * line(0, 0, vec.x, vec.y); 65536 * rotate(vec.heading()); 65537 * var arrowSize = 7; 65538 * translate(vec.mag() - arrowSize, 0); 65539 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0); 65540 * pop(); 65541 * } 65542 * </code> 65543 * </div> 65544 */ 65545p5.Vector.prototype.div = function div(n) { 65546 if (!(typeof n === 'number' && isFinite(n))) { 65547 console.warn( 65548 'p5.Vector.prototype.div:', 65549 'n is undefined or not a finite number' 65550 ); 65551 return this; 65552 } 65553 if (n === 0) {
65554 console.warn('p5.Vector.prototype.div:', 'divide by 0'); 65555 return this; 65556 } 65557 this.x /= n; 65558 this.y /= n; 65559 this.z /= n; 65560 return this; 65561}; 65562 65563/** 65564 * Calculates the magnitude (length) of the vector and returns the result as 65565 * a float (this is simply the equation sqrt(x*x + y*y + z*z).) 65566 * 65567 * @method mag 65568 * @return {Number} magnitude of the vector 65569 * @example 65570 * <div> 65571 * <code> 65572 * function draw() { 65573 * background(240); 65574 * 65575 * var v0 = createVector(0, 0); 65576 * var v1 = createVector(mouseX, mouseY); 65577 * drawArrow(v0, v1, 'black'); 65578 * 65579 * noStroke(); 65580 * text('vector length: ' + v1.mag().toFixed(2), 10, 70, 90, 30); 65581 * } 65582 * 65583 * // draw an arrow for a vector at a given base position 65584 * function drawArrow(base, vec, myColor) { 65585 * push(); 65586 * stroke(myColor); 65587 * strokeWeight(3); 65588 * fill(myColor); 65589 * translate(base.x, base.y); 65590 * line(0, 0, vec.x, vec.y); 65591 * rotate(vec.heading()); 65592 * var arrowSize = 7; 65593 * translate(vec.mag() - arrowSize, 0); 65594 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0); 65595 * pop(); 65596 * } 65597 * </code> 65598 * </div> 65599 * <div class="norender"> 65600 * <code> 65601 * var v = createVector(20.0, 30.0, 40.0); 65602 * var m = v.mag(); 65603 * print(m); // Prints "53.85164807134504" 65604 * </code> 65605 * </div> 65606 */ 65607p5.Vector.prototype.mag = function mag() { 65608 return Math.sqrt(this.magSq()); 65609}; 65610 65611/** 65612 * Calculates the squared magnitude of the vector and returns the result 65613 * as a float (this is simply the equation <em>(x*x + y*y + z*z)</em>.) 65614 * Faster if the real length is not required in the 65615 * case of comparing vectors, etc. 65616 * 65617 * @method magSq 65618 * @return {number} squared magnitude of the vector 65619 * @example 65620 * <div class="norender"> 65621 * <code> 65622 * // Static method 65623 * var v1 = createVector(6, 4, 2); 65624 * print(v1.magSq()); // Prints "56" 65625 * </code> 65626 * </div> 65627 * 65628 * <div> 65629 * <code> 65630 * function draw() { 65631 * background(240); 65632 * 65633 * var v0 = createVector(0, 0); 65634 * var v1 = createVector(mouseX, mouseY); 65635 * drawArrow(v0, v1, 'black'); 65636 * 65637 * noStroke(); 65638 * text('vector length squared: ' + v1.magSq().toFixed(2), 10, 45, 90, 55); 65639 * } 65640 * 65641 * // draw an arrow for a vector at a given base position 65642 * function drawArrow(base, vec, myColor) { 65643 * push(); 65644 * stroke(myColor); 65645 * strokeWeight(3); 65646 * fill(myColor); 65647 * translate(base.x, base.y); 65648 * line(0, 0, vec.x, vec.y); 65649 * rotate(vec.heading()); 65650 * var arrowSize = 7; 65651 * translate(vec.mag() - arrowSize, 0); 65652 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0); 65653 * pop(); 65654 * } 65655 * </code> 65656 * </div> 65657 */ 65658p5.Vector.prototype.magSq = function magSq() { 65659 var x = this.x; 65660 var y = this.y; 65661 var z = this.z; 65662 return x * x + y * y + z * z; 65663}; 65664 65665/** 65666 * Calculates the dot product of two vectors. The version of the method 65667 * that computes the dot product of two independent vectors is a static 65668 * method. See the examples for more context. 65669 * 65670 * 65671 * @method dot 65672 * @param {Number} x x component of the vector 65673 * @param {Number} [y] y component of the vector 65674 * @param {Number} [z] z component of the vector 65675 * @return {Number} the dot product 65676 * 65677 * @example 65678 * <div class="norender"> 65679 * <code> 65680 * var v1 = createVector(1, 2, 3); 65681 * var v2 = createVector(2, 3, 4); 65682 * 65683 * print(v1.dot(v2)); // Prints "20" 65684 * </code> 65685 * </div> 65686 * 65687 * <div class="norender"> 65688 * <code> 65689 * //Static method 65690 * var v1 = createVector(1, 2, 3); 65691 * var v2 = createVector(3, 2, 1); 65692 * print(p5.Vector.dot(v1, v2)); // Prints "10" 65693 * </code> 65694 * </div> 65695 */ 65696/** 65697 * @method dot 65698 * @param {p5.Vector} value value component of the vector or a p5.Vector 65699 * @return {Number} 65700 */ 65701p5.Vector.prototype.dot = function dot(x, y, z) { 65702 if (x instanceof p5.Vector) { 65703 return this.dot(x.x, x.y, x.z); 65704 } 65705 return this.x * (x || 0) + this.y * (y || 0) + this.z * (z || 0); 65706}; 65707 65708/** 65709 * Calculates and returns a vector composed of the cross product between 65710 * two vectors. Both the static and non static methods return a new p5.Vector. 65711 * See the examples for more context. 65712 * 65713 * @method cross 65714 * @param {p5.Vector} v p5.Vector to be crossed 65715 * @return {p5.Vector} p5.Vector composed of cross product 65716 * @example 65717 * <div class="norender"> 65718 * <code> 65719 * var v1 = createVector(1, 2, 3); 65720 * var v2 = createVector(1, 2, 3); 65721 * 65722 * v1.cross(v2); // v's components are [0, 0, 0] 65723 * </code> 65724 * </div> 65725 * 65726 * <div class="norender"> 65727 * <code> 65728 * // Static method 65729 * var v1 = createVector(1, 0, 0); 65730 * var v2 = createVector(0, 1, 0); 65731 *
65732 * var crossProduct = p5.Vector.cross(v1, v2); 65733 * // crossProduct has components [0, 0, 1] 65734 * print(crossProduct); 65735 * </code> 65736 * </div> 65737 */ 65738p5.Vector.prototype.cross = function cross(v) { 65739 var x = this.y * v.z - this.z * v.y; 65740 var y = this.z * v.x - this.x * v.z; 65741 var z = this.x * v.y - this.y * v.x; 65742 if (this.p5) { 65743 return new p5.Vector(this.p5, [x, y, z]); 65744 } else { 65745 return new p5.Vector(x, y, z); 65746 } 65747}; 65748 65749/** 65750 * Calculates the Euclidean distance between two points (considering a 65751 * point as a vector object). 65752 * 65753 * @method dist 65754 * @param {p5.Vector} v the x, y, and z coordinates of a p5.Vector 65755 * @return {Number} the distance 65756 * @example 65757 * <div class="norender"> 65758 * <code> 65759 * var v1 = createVector(1, 0, 0); 65760 * var v2 = createVector(0, 1, 0); 65761 * 65762 * var distance = v1.dist(v2); // distance is 1.4142... 65763 * print(distance); 65764 * </code> 65765 * </div> 65766 * 65767 * <div class="norender"> 65768 * <code> 65769 * // Static method 65770 * var v1 = createVector(1, 0, 0); 65771 * var v2 = createVector(0, 1, 0); 65772 * 65773 * var distance = p5.Vector.dist(v1, v2); 65774 * // distance is 1.4142... 65775 * print(distance); 65776 * </code> 65777 * </div> 65778 * 65779 * <div> 65780 * <code> 65781 * function draw() { 65782 * background(240); 65783 * 65784 * var v0 = createVector(0, 0); 65785 * 65786 * var v1 = createVector(70, 50); 65787 * drawArrow(v0, v1, 'red'); 65788 * 65789 * var v2 = createVector(mouseX, mouseY); 65790 * drawArrow(v0, v2, 'blue'); 65791 * 65792 * noStroke(); 65793 * text('distance between vectors: ' + v2.dist(v1).toFixed(2), 5, 50, 95, 50); 65794 * } 65795 * 65796 * // draw an arrow for a vector at a given base position 65797 * function drawArrow(base, vec, myColor) { 65798 * push(); 65799 * stroke(myColor); 65800 * strokeWeight(3); 65801 * fill(myColor); 65802 * translate(base.x, base.y); 65803 * line(0, 0, vec.x, vec.y); 65804 * rotate(vec.heading()); 65805 * var arrowSize = 7; 65806 * translate(vec.mag() - arrowSize, 0); 65807 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0); 65808 * pop(); 65809 * } 65810 * </code> 65811 * </div> 65812 */ 65813p5.Vector.prototype.dist = function dist(v) { 65814 return v 65815 .copy() 65816 .sub(this) 65817 .mag(); 65818}; 65819 65820/** 65821 * Normalize the vector to length 1 (make it a unit vector). 65822 * 65823 * @method normalize 65824 * @return {p5.Vector} normalized p5.Vector 65825 * @example 65826 * <div class="norender"> 65827 * <code> 65828 * var v = createVector(10, 20, 2); 65829 * // v has components [10.0, 20.0, 2.0] 65830 * v.normalize(); 65831 * // v's components are set to 65832 * // [0.4454354, 0.8908708, 0.089087084] 65833 * </code> 65834 * </div> 65835 * <div> 65836 * <code> 65837 * function draw() { 65838 * background(240); 65839 * 65840 * var v0 = createVector(50, 50); 65841 * var v1 = createVector(mouseX - 50, mouseY - 50); 65842 * 65843 * drawArrow(v0, v1, 'red'); 65844 * v1.normalize(); 65845 * drawArrow(v0, v1.mult(35), 'blue'); 65846 * 65847 * noFill(); 65848 * ellipse(50, 50, 35 * 2); 65849 * } 65850 * 65851 * // draw an arrow for a vector at a given base position 65852 * function drawArrow(base, vec, myColor) { 65853 * push(); 65854 * stroke(myColor); 65855 * strokeWeight(3); 65856 * fill(myColor); 65857 * translate(base.x, base.y); 65858 * line(0, 0, vec.x, vec.y); 65859 * rotate(vec.heading()); 65860 * var arrowSize = 7; 65861 * translate(vec.mag() - arrowSize, 0); 65862 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0); 65863 * pop(); 65864 * } 65865 * </code> 65866 * </div> 65867 */ 65868p5.Vector.prototype.normalize = function normalize() { 65869 var len = this.mag(); 65870 // here we multiply by the reciprocal instead of calling 'div()' 65871 // since div duplicates this zero check. 65872 if (len !== 0) this.mult(1 / len); 65873 return this; 65874}; 65875 65876/** 65877 * Limit the magnitude of this vector to the value used for the <b>max</b> 65878 * parameter. 65879 * 65880 * @method limit 65881 * @param {Number} max the maximum magnitude for the vector 65882 * @chainable 65883 * @example 65884 * <div class="norender"> 65885 * <code> 65886 * var v = createVector(10, 20, 2); 65887 * // v has components [10.0, 20.0, 2.0] 65888 * v.limit(5); 65889 * // v's components are set to 65890 * // [2.2271771, 4.4543543, 0.4454354] 65891 * </code> 65892 * </div> 65893 * <div> 65894 * <code> 65895 * function draw() { 65896 * background(240); 65897 * 65898 * var v0 = createVector(50, 50); 65899 * var v1 = createVector(mouseX - 50, mouseY - 50); 65900 * 65901 * drawArrow(v0, v1, 'red'); 65902 * drawArrow(v0, v1.limit(35), 'blue'); 65903 * 65904 * noFill(); 65905 * ellipse(50, 50, 35 * 2); 65906 * } 65907 * 65908 * // draw an arrow for a vector at a given base position 65909 * function drawArrow(base, vec, myColor) { 65910 * push(); 65911 * stroke(myColor); 65912 * strokeWeight(3); 65913 * fill(myColor); 65914 * translate(base.x, base.y); 65915 * line(0, 0, vec.x, vec.y); 65916 * rotate(vec.heading()); 65917 * var arrowSize = 7; 65918 * translate(vec.mag() - arrowSize, 0); 65919 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0); 65920 * pop(); 65921 * } 65922 * </code> 65923 * </div> 65924 */ 65925p5.Vector.prototype.limit = function limit(max) { 65926 var mSq = this.magSq(); 65927 if (mSq > max * max) { 65928 this.div(Math.sqrt(mSq)) //normalize it 65929 .mult(max); 65930 } 65931 return this; 65932}; 65933 65934/** 65935 * Set the magnitude of this vector to the value used for the <b>len</b> 65936 * parameter. 65937 * 65938 * @method setMag 65939 * @param {number} len the new length for this vector 65940 * @chainable 65941 * @example 65942 * <div class="norender"> 65943 * <code> 65944 * var v = createVector(10, 20, 2); 65945 * // v has components [10.0, 20.0, 2.0] 65946 * v.setMag(10); 65947 * // v's components are set to [6.0, 8.0, 0.0] 65948 * </code> 65949 * </div> 65950 * 65951 * <div> 65952 * <code> 65953 * function draw() { 65954 * background(240); 65955 * 65956 * var v0 = createVector(0, 0); 65957 * var v1 = createVector(50, 50); 65958 * 65959 * drawArrow(v0, v1, 'red'); 65960 * 65961 * var length = map(mouseX, 0, width, 0, 141, true); 65962 * v1.setMag(length); 65963 * drawArrow(v0, v1, 'blue'); 65964 * 65965 * noStroke(); 65966 * text('magnitude set to: ' + length.toFixed(2), 10, 70, 90, 30); 65967 * } 65968 * 65969 * // draw an arrow for a vector at a given base position 65970 * function drawArrow(base, vec, myColor) { 65971 * push(); 65972 * stroke(myColor); 65973 * strokeWeight(3); 65974 * fill(myColor); 65975 * translate(base.x, base.y); 65976 * line(0, 0, vec.x, vec.y); 65977 * rotate(vec.heading()); 65978 * var arrowSize = 7; 65979 * translate(vec.mag() - arrowSize, 0); 65980 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0); 65981 * pop(); 65982 * } 65983 * </code> 65984 * </div> 65985 */ 65986p5.Vector.prototype.setMag = function setMag(n) { 65987 return this.normalize().mult(n); 65988}; 65989 65990/** 65991 * Calculate the angle of rotation for this vector (only 2D vectors) 65992 * 65993 * @method heading 65994 * @return {Number} the angle of rotation 65995 * @example 65996 * <div class = "norender"> 65997 * <code> 65998 * function setup() { 65999 * var v1 = createVector(30, 50); 66000 * print(v1.heading()); // 1.0303768265243125 66001 * 66002 * v1 = createVector(40, 50); 66003 * print(v1.heading());
66003 // 0.8960553845713439 66004 * 66005 * v1 = createVector(30, 70); 66006 * print(v1.heading()); // 1.1659045405098132 66007 * } 66008 * </code> 66009 * </div> 66010 * 66011 * <div> 66012 * <code> 66013 * function draw() { 66014 * background(240); 66015 * 66016 * var v0 = createVector(50, 50); 66017 * var v1 = createVector(mouseX - 50, mouseY - 50); 66018 * 66019 * drawArrow(v0, v1, 'black'); 66020 * 66021 * var myHeading = v1.heading(); 66022 * noStroke(); 66023 * text( 66024 * 'vector heading: ' + 66025 * myHeading.toFixed(2) + 66026 * ' radians or ' + 66027 * degrees(myHeading).toFixed(2) + 66028 * ' degrees', 66029 * 10, 66030 * 50, 66031 * 90, 66032 * 50 66033 * ); 66034 * } 66035 * 66036 * // draw an arrow for a vector at a given base position 66037 * function drawArrow(base, vec, myColor) { 66038 * push(); 66039 * stroke(myColor); 66040 * strokeWeight(3); 66041 * fill(myColor); 66042 * translate(base.x, base.y); 66043 * line(0, 0, vec.x, vec.y); 66044 * rotate(vec.heading()); 66045 * var arrowSize = 7; 66046 * translate(vec.mag() - arrowSize, 0); 66047 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0); 66048 * pop(); 66049 * } 66050 * </code> 66051 * </div> 66052 */ 66053p5.Vector.prototype.heading = function heading() {
66054 var h = Math.atan2(this.y, this.x); 66055 if (this.p5) return this.p5._fromRadians(h); 66056 return h; 66057}; 66058 66059/** 66060 * Rotate the vector by an angle (only 2D vectors), magnitude remains the 66061 * same 66062 * 66063 * @method rotate 66064 * @param {number} angle the angle of rotation 66065 * @chainable 66066 * @example 66067 * <div class="norender"> 66068 * <code> 66069 * var v = createVector(10.0, 20.0); 66070 * // v has components [10.0, 20.0, 0.0] 66071 * v.rotate(HALF_PI); 66072 * // v's components are set to [-20.0, 9.999999, 0.0] 66073 * </code> 66074 * </div> 66075 * 66076 * <div> 66077 * <code> 66078 * var angle = 0; 66079 * function draw() { 66080 * background(240); 66081 * 66082 * var v0 = createVector(50, 50); 66083 * var v1 = createVector(50, 0); 66084 * 66085 * drawArrow(v0, v1.rotate(angle), 'black'); 66086 * angle += 0.01; 66087 * } 66088 * 66089 * // draw an arrow for a vector at a given base position 66090 * function drawArrow(base, vec, myColor) { 66091 * push(); 66092 * stroke(myColor); 66093 * strokeWeight(3); 66094 * fill(myColor); 66095 * translate(base.x, base.y); 66096 * line(0, 0, vec.x, vec.y); 66097 * rotate(vec.heading()); 66098 * var arrowSize = 7; 66099 * translate(vec.mag() - arrowSize, 0); 66100 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0); 66101 * pop(); 66102 * } 66103 * </code> 66104 * </div> 66105 */ 66106p5.Vector.prototype.rotate = function rotate(a) { 66107 var newHeading = this.heading() + a; 66108 if (this.p5) newHeading = this.p5._toRadians(newHeading); 66109 var mag = this.mag(); 66110 this.x = Math.cos(newHeading) * mag; 66111 this.y = Math.sin(newHeading) * mag; 66112 return this; 66113}; 66114 66115/** 66116 * Calculates and returns the angle (in radians) between two vectors. 66117 * @method angleBetween 66118 * @param {p5.Vector} the x, y, and z components of a p5.Vector 66119 * @return {Number} the angle between (in radians) 66120 * @example 66121 * <div class="norender"> 66122 * <code> 66123 * var v1 = createVector(1, 0, 0); 66124 * var v2 = createVector(0, 1, 0); 66125 * 66126 * var angle = v1.angleBetween(v2); 66127 * // angle is PI/2 66128 * print(angle); 66129 * </code> 66130 * </div> 66131 * 66132 * <div> 66133 * <code> 66134 * function draw() { 66135 * background(240); 66136 * var v0 = createVector(50, 50); 66137 * 66138 * var v1 = createVector(50, 0); 66139 * drawArrow(v0, v1, 'red'); 66140 * 66141 * var v2 = createVector(mouseX - 50, mouseY - 50); 66142 * drawArrow(v0, v2, 'blue'); 66143 * 66144 * var angleBetween = v1.angleBetween(v2); 66145 * noStroke(); 66146 * text( 66147 * 'angle between: ' + 66148 * angleBetween.toFixed(2) + 66149 * ' radians or ' + 66150 * degrees(angleBetween).toFixed(2) + 66151 * ' degrees', 66152 * 10, 66153 * 50, 66154 * 90, 66155 * 50 66156 * ); 66157 * } 66158 * 66159 * // draw an arrow for a vector at a given base position 66160 * function drawArrow(base, vec, myColor) { 66161 * push(); 66162 * stroke(myColor); 66163 * strokeWeight(3); 66164 * fill(myColor); 66165 * translate(base.x, base.y); 66166 * line(0, 0, vec.x, vec.y); 66167 * rotate(vec.heading()); 66168 * var arrowSize = 7; 66169 * translate(vec.mag() - arrowSize, 0); 66170 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0); 66171 * pop(); 66172 * } 66173 * </code> 66174 * </div> 66175 */ 66176p5.Vector.prototype.angleBetween = function angleBetween(v) { 66177 var dotmagmag = this.dot(v) / (this.mag() * v.mag()); 66178 // Mathematically speaking: the dotmagmag variable will be between -1 and 1 66179 // inclusive. Practically though it could be slightly outside this range due 66180 // to floating-point rounding issues. This can make Math.acos return NaN. 66181 // 66182 // Solution: we'll clamp the value to the -1,1 range 66183 var angle = Math.acos(Math.min(1, Math.max(-1, dotmagmag))); 66184 if (this.p5) return this.p5._fromRadians(angle); 66185 return angle; 66186}; 66187 66188/** 66189 * Linear interpolate the vector to another vector 66190 * 66191 * @method lerp 66192 * @param {Number} x the x component 66193 * @param {Number} y the y component 66194 * @param {Number} z the z component 66195 * @param {Number} amt the amount of interpolation; some value between 0.0 66196 * (old vector) and 1.0 (new vector). 0.9 is very near 66197 * the new vector. 0.5 is halfway in between. 66198 * @chainable 66199 * 66200 * @example 66201 * <div class="norender"> 66202 * <code> 66203 * var v = createVector(1, 1, 0); 66204 * 66205 * v.lerp(3, 3, 0, 0.5); // v now has components [2,2,0] 66206 * </code> 66207 * </div> 66208 * 66209 * <div class="norender"> 66210 * <code> 66211 * var v1 = createVector(0, 0, 0); 66212 * var v2 = createVector(100, 100, 0); 66213 * 66214 * var v3 = p5.Vector.lerp(v1, v2, 0.5); 66215 * // v3 has components [50,50,0] 66216 * print(v3); 66217 * </code> 66218 * </div> 66219 * 66220 * <div> 66221 * <code> 66222 * var step = 0.01; 66223 * var amount = 0; 66224 * 66225 * function draw() { 66226 * background(240); 66227 * var v0 = createVector(0, 0); 66228 * 66229 * var v1 = createVector(mouseX, mouseY); 66230 * drawArrow(v0, v1, 'red'); 66231 * 66232 * var v2 = createVector(90, 90); 66233 * drawArrow(v0, v2, 'blue'); 66234 * 66235 * if (amount > 1 || amount < 0) { 66236 * step *= -1; 66237 * } 66238 * amount += step; 66239 * var v3 = p5.Vector.lerp(v1, v2, amount); 66240 * 66241 * drawArrow(v0, v3, 'purple'); 66242 * } 66243 * 66244 * // draw an arrow for a vector at a given base position 66245 * function drawArrow(base, vec, myColor) { 66246 * push(); 66247 * stroke(myColor); 66248 * strokeWeight(3); 66249 * fill(myColor); 66250 * translate(base.x, base.y); 66251 * line(0, 0, vec.x, vec.y); 66252 * rotate(vec.heading()); 66253 * var arrowSize = 7; 66254 * translate(vec.mag() - arrowSize, 0); 66255 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0); 66256 * pop(); 66257 * } 66258 * </code> 66259 * </div> 66260 */ 66261/** 66262 * @method lerp 66263 * @param {p5.Vector} v the p5.Vector to lerp to 66264 * @param {Number} amt 66265 * @chainable 66266 */ 66267p5.Vector.prototype.lerp = function lerp(x, y, z, amt) { 66268 if (x instanceof p5.Vector) { 66269 return this.lerp(x.x, x.y, x.z, y); 66270 } 66271 this.x += (x - this.x) * amt || 0; 66272 this.y += (y - this.y) * amt || 0; 66273 this.z += (z - this.z) * amt || 0; 66274 return this; 66275}; 66276 66277/** 66278 * Return a representation of this vector as a float array. This is only 66279 * for temporary use. If used in any other fashion, the contents should be 66280 * copied by using the <b>p5.Vector.copy()</b> method to copy into your own 66281 * array.
66282 * 66283 * @method array 66284 * @return {Number[]} an Array with the 3 values 66285 * @example 66286 * <div class = "norender"> 66287 * <code> 66288 * function setup() { 66289 * var v = createVector(20, 30); 66290 * print(v.array()); // Prints : Array [20, 30, 0] 66291 * } 66292 * </code> 66293 * </div> 66294 * 66295 * <div class="norender"> 66296 * <code> 66297 * var v = createVector(10.0, 20.0, 30.0); 66298 * var f = v.array(); 66299 * print(f[0]); // Prints "10.0" 66300 * print(f[1]); // Prints "20.0" 66301 * print(f[2]); // Prints "30.0" 66302 * </code> 66303 * </div> 66304 */ 66305p5.Vector.prototype.array = function array() { 66306 return [this.x || 0, this.y || 0, this.z || 0]; 66307}; 66308 66309/** 66310 * Equality check against a p5.Vector 66311 * 66312 * @method equals 66313 * @param {Number} [x] the x component of the vector 66314 * @param {Number} [y] the y component of the vector 66315 * @param {Number} [z] the z component of the vector 66316 * @return {Boolean} whether the vectors are equals 66317 * @example 66318 * <div class = "norender"> 66319 * <code> 66320 * var v1 = createVector(5, 10, 20); 66321 * var v2 = createVector(5, 10, 20); 66322 * var v3 = createVector(13, 10, 19); 66323 * 66324 * print(v1.equals(v2.x, v2.y, v2.z)); // true 66325 * print(v1.equals(v3.x, v3.y, v3.z)); // false 66326 * </code> 66327 * </div> 66328 * 66329 * <div class="norender"> 66330 * <code> 66331 * var v1 = createVector(10.0, 20.0, 30.0); 66332 * var v2 = createVector(10.0, 20.0, 30.0); 66333 * var v3 = createVector(0.0, 0.0, 0.0); 66334 * print(v1.equals(v2)); // true 66335 * print(v1.equals(v3)); // false 66336 * </code> 66337 * </div> 66338 */ 66339/** 66340 * @method equals 66341 * @param {p5.Vector|Array} value the vector to compare 66342 * @return {Boolean} 66343 */ 66344p5.Vector.prototype.equals = function equals(x, y, z) { 66345 var a, b, c; 66346 if (x instanceof p5.Vector) { 66347 a = x.x || 0; 66348 b = x.y || 0; 66349 c = x.z || 0; 66350 } else if (x instanceof Array) { 66351 a = x[0] || 0; 66352 b = x[1] || 0; 66353 c = x[2] || 0; 66354 } else { 66355 a = x || 0; 66356 b = y || 0; 66357 c = z || 0; 66358 } 66359 return this.x === a && this.y === b && this.z === c; 66360}; 66361 66362// Static Methods 66363 66364/** 66365 * Make a new 2D vector from an angle 66366 * 66367 * @method fromAngle 66368 * @static 66369 * @param {Number} angle the desired angle, in radians 66370 * @param {Number} [length] the length of the new vector (defaults to 1) 66371 * @return {p5.Vector} the new p5.Vector object 66372 * @example 66373 * <div> 66374 * <code> 66375 * function draw() { 66376 * background(200); 66377 * 66378 * // Create a variable, proportional to the mouseX, 66379 * // varying from 0-360, to represent an angle in degrees. 66380 * angleMode(DEGREES); 66381 * var myDegrees = map(mouseX, 0, width, 0, 360); 66382 * 66383 * // Display that variable in an onscreen text. 66384 * // (Note the nfc() function to truncate additional decimal places, 66385 * // and the "\xB0" character for the degree symbol.) 66386 * var readout = 'angle = ' + nfc(myDegrees, 1) + '\xB0'; 66387 * noStroke(); 66388 * fill(0); 66389 * text(readout, 5, 15); 66390 * 66391 * // Create a p5.Vector using the fromAngle function, 66392 * // and extract its x and y components. 66393 * var v = p5.Vector.fromAngle(radians(myDegrees), 30); 66394 * var vx = v.x; 66395 * var vy = v.y; 66396 * 66397 * push(); 66398 * translate(width / 2, height / 2); 66399 * noFill(); 66400 * stroke(150); 66401 * line(0, 0, 30, 0); 66402 * stroke(0); 66403 * line(0, 0, vx, vy); 66404 * pop(); 66405 * } 66406 * </code> 66407 * </div> 66408 */ 66409p5.Vector.fromAngle = function fromAngle(angle, length) { 66410 if (typeof length === 'undefined') { 66411 length = 1; 66412 } 66413 return new p5.Vector(length * Math.cos(angle), length * Math.sin(angle), 0); 66414}; 66415 66416/** 66417 * Make a new 3D vector from a pair of ISO spherical angles 66418 * 66419 * @method fromAngles 66420 * @static 66421 * @param {Number} theta the polar angle, in radians (zero is up) 66422 * @param {Number} phi the azimuthal angle, in radians 66423 * (zero is out of the screen) 66424 * @param {Number} [length] the length of the new vector (defaults to 1) 66425 * @return {p5.Vector} the new p5.Vector object 66426 * @example 66427 * <div modernizr='webgl'> 66428 * <code> 66429 * function setup() { 66430 * createCanvas(100, 100, WEBGL); 66431 * fill(255); 66432 * noStroke(); 66433 * } 66434 * function draw() { 66435 * background(255); 66436 * 66437 * var t = millis() / 1000; 66438 * 66439 * // add three point lights 66440 * pointLight(color('#f00'), p5.Vector.fromAngles(t * 1.0, t * 1.3, 100)); 66441 * pointLight(color('#0f0'), p5.Vector.fromAngles(t * 1.1, t * 1.2, 100)); 66442 * pointLight(color('#00f'), p5.Vector.fromAngles(t * 1.2, t * 1.1, 100)); 66443 * 66444 * sphere(35); 66445 * } 66446 * </code> 66447 * </div> 66448 */ 66449p5.Vector.fromAngles = function(theta, phi, length) { 66450 if (typeof length === 'undefined') { 66451 length = 1; 66452 } 66453 var cosPhi = Math.cos(phi);
66454 var sinPhi = Math.sin(phi); 66455 var cosTheta = Math.cos(theta); 66456 var sinTheta = Math.sin(theta); 66457 66458 return new p5.Vector( 66459 length * sinTheta * sinPhi, 66460 -length * cosTheta, 66461 length * sinTheta * cosPhi 66462 ); 66463}; 66464 66465/** 66466 * Make a new 2D unit vector from a random angle 66467 * 66468 * @method random2D 66469 * @static 66470 * @return {p5.Vector} the new p5.Vector object 66471 * @example 66472 * <div class="norender"> 66473 * <code> 66474 * var v = p5.Vector.random2D(); 66475 * // May make v's attributes something like: 66476 * // [0.61554617, -0.51195765, 0.0] or 66477 * // [-0.4695841, -0.14366731, 0.0] or 66478 * // [0.6091097, -0.22805278, 0.0] 66479 * print(v); 66480 * </code> 66481 * </div> 66482 * 66483 * <div> 66484 * <code> 66485 * function setup() { 66486 * frameRate(1); 66487 * } 66488 * 66489 * function draw() { 66490 * background(240); 66491 * 66492 * var v0 = createVector(50, 50); 66493 * var v1 = p5.Vector.random2D(); 66494 * drawArrow(v0, v1.mult(50), 'black'); 66495 * } 66496 * 66497 * // draw an arrow for a vector at a given base position 66498 * function drawArrow(base, vec, myColor) { 66499 * push(); 66500 * stroke(myColor); 66501 * strokeWeight(3); 66502 * fill(myColor); 66503 * translate(base.x, base.y); 66504 * line(0, 0, vec.x, vec.y); 66505 * rotate(vec.heading()); 66506 * var arrowSize = 7; 66507 * translate(vec.mag() - arrowSize, 0); 66508 * triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0); 66509 * pop(); 66510 * } 66511 * </code> 66512 * </div> 66513 */ 66514p5.Vector.random2D = function random2D() { 66515 return this.fromAngle(Math.random() * constants.TWO_PI); 66516}; 66517 66518/** 66519 * Make a new random 3D unit vector. 66520 * 66521 * @method random3D 66522 * @static 66523 * @return {p5.Vector} the new p5.Vector object 66524 * @example 66525 * <div class="norender"> 66526 * <code> 66527 * var v = p5.Vector.random3D(); 66528 * // May make v's attributes something like: 66529 * // [0.61554617, -0.51195765, 0.599168] or 66530 * // [-0.4695841, -0.14366731, -0.8711202] or 66531 * // [0.6091097, -0.22805278, -0.7595902] 66532 * print(v); 66533 * </code> 66534 * </div> 66535 */ 66536p5.Vector.random3D = function random3D() { 66537 var angle = Math.random() * constants.TWO_PI; 66538 var vz = Math.random() * 2 - 1; 66539 var vzBase = Math.sqrt(1 - vz * vz); 66540 var vx = vzBase * Math.cos(angle); 66541 var vy = vzBase * Math.sin(angle); 66542 return new p5.Vector(vx, vy, vz); 66543}; 66544 66545// Adds two vectors together and returns a new one. 66546/** 66547 * @method add 66548 * @static 66549 * @param {p5.Vector} v1 a p5.Vector to add 66550 * @param {p5.Vector} v2 a p5.Vector to add 66551 * @param {p5.Vector} target the vector to receive the result 66552 */ 66553/** 66554 * @method add 66555 * @static 66556 * @param {p5.Vector} v1 66557 * @param {p5.Vector} v2 66558 * @return {p5.Vector} the resulting p5.Vector 66559 * 66560 */ 66561 66562p5.Vector.add = function add(v1, v2, target) { 66563 if (!target) { 66564 target = v1.copy(); 66565 } else { 66566 target.set(v1); 66567 } 66568 target.add(v2); 66569 return target; 66570}; 66571 66572/* 66573 * Subtracts one p5.Vector from another and returns a new one. The second 66574 * vector (v2) is subtracted from the first (v1), resulting in v1-v2. 66575 */ 66576/** 66577 * @method sub 66578 * @static 66579 * @param {p5.Vector} v1 a p5.Vector to subtract from 66580 * @param {p5.Vector} v2 a p5.Vector to subtract 66581 * @param {p5.Vector} target if undefined a new vector will be created 66582 */ 66583/** 66584 * @method sub 66585 * @static 66586 * @param {p5.Vector} v1 66587 * @param {p5.Vector} v2 66588 * @return {p5.Vector} the resulting p5.Vector 66589 */ 66590 66591p5.Vector.sub = function sub(v1, v2, target) { 66592 if (!target) { 66593 target = v1.copy(); 66594 } else { 66595 target.set(v1); 66596 } 66597 target.sub(v2); 66598 return target; 66599}; 66600 66601/** 66602 * Multiplies a vector by a scalar and returns a new vector. 66603 */ 66604/** 66605 * @method mult 66606 * @static 66607 * @param {p5.Vector} v the vector to multiply 66608 * @param {Number} n 66609 * @param {p5.Vector} target if undefined a new vector will be created 66610 */ 66611/** 66612 * @method mult 66613 * @static 66614 * @param {p5.Vector} v 66615 * @param {Number} n 66616 * @return {p5.Vector} the resulting new p5.Vector 66617 */ 66618p5.Vector.mult = function mult(v, n, target) { 66619 if (!target) { 66620 target = v.copy(); 66621 } else { 66622 target.set(v); 66623 } 66624 target.mult(n); 66625 return target; 66626}; 66627 66628/** 66629 * Divides a vector by a scalar and returns a new vector. 66630 */ 66631/** 66632 * @method div 66633 * @static 66634 * @param {p5.Vector} v the vector to divide 66635 * @param {Number} n 66636 * @param {p5.Vector} target if undefined a new vector will be created 66637 */ 66638/** 66639 * @method div 66640 * @static 66641 * @param {p5.Vector} v 66642 * @param {Number} n 66643 * @return {p5.Vector} the resulting new p5.Vector 66644 */ 66645p5.Vector.div = function div(v, n, target) { 66646 if (!target) { 66647 target = v.copy(); 66648 } else { 66649 target.set(v); 66650 } 66651 target.div(n); 66652 return target; 66653}; 66654 66655/** 66656 * Calculates the dot product of two vectors. 66657 */ 66658/** 66659 * @method dot 66660 * @static 66661 * @param {p5.Vector} v1 the first p5.Vector 66662 * @param {p5.Vector} v2 the second p5.Vector 66663 * @return {Number} the dot product 66664 */ 66665p5.Vector.dot = function dot(v1, v2) { 66666 return v1.dot(v2); 66667}; 66668 66669/** 66670 * Calculates the cross product of two vectors. 66671 */ 66672/** 66673 * @method cross 66674 * @static 66675 * @param {p5.Vector} v1 the first p5.Vector 66676 * @param {p5.Vector} v2 the second p5.Vector 66677 * @return {Number} the cross product 66678 */ 66679p5.Vector.cross = function cross(v1, v2) { 66680 return v1.cross(v2); 66681}; 66682 66683/** 66684 * Calculates the Euclidean distance between two points (considering a 66685 * point as a vector object). 66686 */ 66687/** 66688 * @method dist 66689 * @static 66690 * @param {p5.Vector} v1 the first p5.Vector 66691 * @param {p5.Vector} v2 the second p5.Vector 66692 * @return {Number} the distance 66693 */ 66694p5.Vector.dist = function dist(v1, v2) { 66695 return v1.dist(v2); 66696}; 66697 66698/** 66699 * Linear interpolate a vector to another vector and return the result as a 66700 * new vector. 66701 */ 66702/** 66703 * @method lerp 66704 * @static 66705 * @param {p5.Vector} v1 66706 * @param {p5.Vector} v2 66707 * @param {Number} amt 66708 * @param {p5.Vector} target if undefined a new vector will be created 66709 */ 66710/** 66711 * @method lerp 66712 * @static 66713 * @param {p5.Vector} v1 66714 * @param {p5.Vector} v2 66715 * @param {Number} amt 66716 * @return {Number} the lerped value 66717 */ 66718p5.Vector.lerp = function lerp(v1, v2, amt, target) { 66719 if (!target) { 66720 target = v1.copy(); 66721 } else { 66722 target.set(v1); 66723 } 66724 target.lerp(v2, amt); 66725 return target; 66726}; 66727 66728/** 66729 * @method mag 66730 * @param {p5.Vector} vecT the vector to return the magnitude of 66731 * @return {Number} the magnitude of vecT 66732 * @static 66733 */ 66734p5.Vector.mag = function mag(vecT) { 66735 var x = vecT.x, 66736 y = vecT.y, 66737 z = vecT.z; 66738 var magSq = x * x + y * y + z * z; 66739 return Math.sqrt(magSq); 66740}; 66741 66742module.exports = p5.Vector; 66743 66744},{"../core/constants":21,"../core/core":22}],54:[function(_dereq_,module,exports){ 66745/** 66746 * @module Math 66747 * @submodule Random 66748 * @for p5 66749 * @requires core 66750 */ 66751 66752'use strict'; 66753 66754var p5 = _dereq_('../core/core'); 66755 66756var seeded = false;
66757var previous = false; 66758var y2 = 0; 66759 66760// Linear Congruential Generator 66761// Variant of a Lehman Generator 66762var lcg = (function() { 66763 // Set to values from http://en.wikipedia.org/wiki/Numerical_Recipes 66764 // m is basically chosen to be large (as it is the max period) 66765 // and for its relationships to a and c 66766 var m = 4294967296, 66767 // a - 1 should be divisible by m's prime factors 66768 a = 1664525, 66769 // c and m should be co-prime 66770 c = 1013904223, 66771 seed, 66772 z; 66773 return { 66774 setSeed: function(val) { 66775 // pick a random seed if val is undefined or null 66776 // the >>> 0 casts the seed to an unsigned 32-bit integer 66777 z = seed = (val == null ? Math.random() * m : val) >>> 0; 66778 }, 66779 getSeed: function() { 66780 return seed; 66781 }, 66782 rand: function() { 66783 // define the recurrence relationship 66784 z = (a * z + c) % m; 66785 // return a float in [0, 1) 66786 // if z = m then z / m = 0 therefore (z % m) / m < 1 always 66787 return z / m; 66788 } 66789 }; 66790})(); 66791 66792/** 66793 * Sets the seed value for random(). 66794 * 66795 * By default, random() produces different results each time the program 66796 * is run. Set the seed parameter to a constant to return the same 66797 * pseudo-random numbers each time the software is run. 66798 * 66799 * @method randomSeed 66800 * @param {Number} seed the seed value 66801 * @example 66802 * <div> 66803 * <code> 66804 * randomSeed(99); 66805 * for (var i = 0; i < 100; i++) { 66806 * var r = random(0, 255); 66807 * stroke(r); 66808 * line(i, 0, i, 100); 66809 * } 66810 * </code> 66811 * </div> 66812 * 66813 * @alt 66814 * many vertical lines drawn in white, black or grey. 66815 * 66816 */ 66817p5.prototype.randomSeed = function(seed) { 66818 lcg.setSeed(seed); 66819 seeded = true; 66820 previous = false; 66821}; 66822 66823/** 66824 * Return a random floating-point number. 66825 * 66826 * Takes either 0, 1 or 2 arguments. 66827 * 66828 * If no argument is given, returns a random number from 0 66829 * up to (but not including) 1. 66830 * 66831 * If one argument is given and it is a number, returns a random number from 0 66832 * up to (but not including) the number. 66833 * 66834 * If one argument is given and it is an array, returns a random element from 66835 * that array. 66836 * 66837 * If two arguments are given, returns a random number from the 66838 * first argument up to (but not including) the second argument. 66839 * 66840 * @method random 66841 * @param {Number} [min] the lower bound (inclusive) 66842 * @param {Number} [max] the upper bound (exclusive) 66843 * @return {Number} the random number 66844 * @example 66845 * <div> 66846 * <code> 66847 * for (var i = 0; i < 100; i++) { 66848 * var r = random(50); 66849 * stroke(r * 5); 66850 * line(50, i, 50 + r, i); 66851 * } 66852 * </code> 66853 * </div> 66854 * <div> 66855 * <code> 66856 * for (var i = 0; i < 100; i++) { 66857 * var r = random(-50, 50); 66858 * line(50, i, 50 + r, i); 66859 * } 66860 * </code> 66861 * </div> 66862 * <div> 66863 * <code> 66864 * // Get a random element from an array using the random(Array) syntax 66865 * var words = ['apple', 'bear', 'cat', 'dog']; 66866 * var word = random(words); // select random word 66867 * text(word, 10, 50); // draw the word 66868 * </code> 66869 * </div> 66870 * 66871 * @alt 66872 * 100 horizontal lines from center canvas to right. size+fill change each time 66873 * 100 horizontal lines from center of canvas. height & side change each render 66874 * word displayed at random. Either apple, bear, cat, or dog 66875 * 66876 */ 66877/** 66878 * @method random 66879 * @param {Array} choices the array to choose from 66880 * @return {*} the random element from the array 66881 * @example 66882 */ 66883p5.prototype.random = function(min, max) { 66884 var rand; 66885 66886 if (seeded) { 66887 rand = lcg.rand(); 66888 } else { 66889 rand = Math.random(); 66890 } 66891 if (typeof min === 'undefined') { 66892 return rand; 66893 } else if (typeof max === 'undefined') { 66894 if (min instanceof Array) { 66895 return min[Math.floor(rand * min.length)]; 66896 } else { 66897 return rand * min; 66898 } 66899 } else { 66900 if (min > max) { 66901 var tmp = min; 66902 min = max; 66903 max = tmp; 66904 } 66905 66906 return rand * (max - min) + min; 66907 } 66908}; 66909 66910/** 66911 * 66912 * Returns a random number fitting a Gaussian, or 66913 * normal, distribution. There is theoretically no minimum or maximum 66914 * value that randomGaussian() might return. Rather, there is 66915 * just a very low probability that values far from the mean will be 66916 * returned; and a higher probability that numbers near the mean will 66917 * be returned. 66918 * <br><br> 66919 * Takes either 0, 1 or 2 arguments.<br> 66920 * If no args, returns a mean of 0 and standard deviation of 1.<br> 66921 * If one arg, that arg is the mean (standard deviation is 1).<br> 66922 * If two args, first is mean, second is standard deviation. 66923 * 66924 * @method randomGaussian 66925 * @param {Number} mean the mean 66926 * @param {Number} sd the standard deviation 66927 * @return {Number} the random number 66928 * @example 66929 * <div> 66930 * <code> 66931 * for (var y = 0; y < 100; y++) { 66932 * var x = randomGaussian(50, 15); 66933 * line(50, y, x, y); 66934 * } 66935 * </code> 66936 * </div> 66937 * <div> 66938 * <code> 66939 * var distribution = new Array(360); 66940 * 66941 * function setup() { 66942 * createCanvas(100, 100); 66943 * for (var i = 0; i < distribution.length; i++) { 66944 * distribution[i] = floor(randomGaussian(0, 15)); 66945 * } 66946 * } 66947 * 66948 * function draw() { 66949 * background(204); 66950 * 66951 * translate(width / 2, width / 2); 66952 * 66953 * for (var i = 0; i < distribution.length; i++) { 66954 * rotate(TWO_PI / distribution.length); 66955 * stroke(0); 66956 * var dist = abs(distribution[i]); 66957 * line(0, 0, dist, 0); 66958 * } 66959 * } 66960 * </code> 66961 * </div> 66962 * @alt 66963 * 100 horizontal lines from center of canvas. height & side change each render 66964 * black lines radiate from center of canvas. size determined each render 66965 */ 66966p5.prototype.randomGaussian = function(mean, sd) { 66967 var y1, x1, x2, w; 66968 if (previous) { 66969 y1 = y2; 66970 previous = false;
66971 } else { 66972 do { 66973 x1 = this.random(2) - 1; 66974 x2 = this.random(2) - 1; 66975 w = x1 * x1 + x2 * x2; 66976 } while (w >= 1); 66977 w = Math.sqrt(-2 * Math.log(w) / w); 66978 y1 = x1 * w; 66979 y2 = x2 * w; 66980 previous = true; 66981 } 66982 66983 var m = mean || 0; 66984 var s = sd || 1; 66985 return y1 * s + m; 66986}; 66987 66988module.exports = p5; 66989 66990},{"../core/core":22}],55:[function(_dereq_,module,exports){ 66991/** 66992 * @module Math 66993 * @submodule Trigonometry 66994 * @for p5 66995 * @requires core 66996 * @requires constants 66997 */ 66998 66999'use strict'; 67000 67001var p5 = _dereq_('../core/core'); 67002var constants = _dereq_('../core/constants'); 67003 67004/* 67005 * all DEGREES/RADIANS conversion should be done in the p5 instance 67006 * if possible, using the p5._toRadians(), p5._fromRadians() methods. 67007 */ 67008p5.prototype._angleMode = constants.RADIANS; 67009 67010/** 67011 * The inverse of cos(), returns the arc cosine of a value. This function 67012 * expects the values in the range of -1 to 1 and values are returned in 67013 * the range 0 to PI (3.1415927). 67014 * 67015 * @method acos 67016 * @param {Number} value the value whose arc cosine is to be returned 67017 * @return {Number} the arc cosine of the given value 67018 * 67019 * @example 67020 * <div class= ânorender"> 67021 * <code> 67022 * var a = PI; 67023 * var c = cos(a); 67024 * var ac = acos(c); 67025 * // Prints: "3.1415927 : -1.0 : 3.1415927" 67026 * print(a + ' : ' + c + ' : ' + ac); 67027 * </code> 67028 * </div> 67029 * 67030 * <div class= ânorender"> 67031 * <code> 67032 * var a = PI + PI / 4.0; 67033 * var c = cos(a); 67034 * var ac = acos(c); 67035 * // Prints: "3.926991 : -0.70710665 : 2.3561943" 67036 * print(a + ' : ' + c + ' : ' + ac); 67037 * </code> 67038 * </div> 67039 */ 67040p5.prototype.acos = function(ratio) { 67041 return this._fromRadians(Math.acos(ratio)); 67042}; 67043 67044/** 67045 * The inverse of sin(), returns the arc sine of a value. This function 67046 * expects the values in the range of -1 to 1 and values are returned 67047 * in the range -PI/2 to PI/2. 67048 * 67049 * @method asin 67050 * @param {Number} value the value whose arc sine is to be returned 67051 * @return {Number} the arc sine of the given value 67052 * 67053 * @example 67054 * <div class= ânorender"> 67055 * <code> 67056 * var a = PI + PI / 3; 67057 * var s = sin(a); 67058 * var as = asin(s); 67059 * // Prints: "1.0471976 : 0.86602545 : 1.0471976" 67060 * print(a + ' : ' + s + ' : ' + as); 67061 * </code> 67062 * </div> 67063 * 67064 * <div class= ânorender"> 67065 * <code> 67066 * var a = PI + PI / 3.0; 67067 * var s = sin(a); 67068 * var as = asin(s); 67069 * // Prints: "4.1887903 : -0.86602545 : -1.0471976" 67070 * print(a + ' : ' + s + ' : ' + as); 67071 * </code> 67072 * </div> 67073 * 67074 */ 67075p5.prototype.asin = function(ratio) { 67076 return this._fromRadians(Math.asin(ratio)); 67077}; 67078 67079/** 67080 * The inverse of tan(), returns the arc tangent of a value. This function 67081 * expects the values in the range of -Infinity to Infinity (exclusive) and 67082 * values are returned in the range -PI/2 to PI/2. 67083 * 67084 * @method atan 67085 * @param {Number} value the value whose arc tangent is to be returned 67086 * @return {Number} the arc tangent of the given value 67087 * 67088 * @example 67089 * <div class= ânorender"> 67090 * <code> 67091 * var a = PI + PI / 3; 67092 * var t = tan(a); 67093 * var at = atan(t); 67094 * // Prints: "1.0471976 : 1.7320509 : 1.0471976" 67095 * print(a + ' : ' + t + ' : ' + at); 67096 * </code> 67097 * </div> 67098 * 67099 * <div class= ânorender"> 67100 * <code> 67101 * var a = PI + PI / 3.0; 67102 * var t = tan(a); 67103 * var at = atan(t); 67104 * // Prints: "4.1887903 : 1.7320513 : 1.0471977" 67105 * print(a + ' : ' + t + ' : ' + at); 67106 * </code> 67107 * </div> 67108 * 67109 */ 67110p5.prototype.atan = function(ratio) { 67111 return this._fromRadians(Math.atan(ratio)); 67112}; 67113 67114/** 67115 * Calculates the angle (in radians) from a specified point to the coordinate 67116 * origin as measured from the positive x-axis. Values are returned as a 67117 * float in the range from PI to -PI. The atan2() function is most often used 67118 * for orienting geometry to the position of the cursor. 67119 * <br><br> 67120 * Note: The y-coordinate of the point is the first parameter, and the 67121 * x-coordinate is the second parameter, due the the structure of calculating 67122 * the tangent. 67123 * 67124 * @method atan2 67125 * @param {Number} y y-coordinate of the point 67126 * @param {Number} x x-coordinate of the point 67127 * @return {Number} the arc tangent of the given point 67128 * 67129 * @example 67130 * <div> 67131 * <code> 67132 * function draw() { 67133 * background(204); 67134 * translate(width / 2, height / 2);
67135 * var a = atan2(mouseY - height / 2, mouseX - width / 2); 67136 * rotate(a); 67137 * rect(-30, -5, 60, 10); 67138 * } 67139 * </code> 67140 * </div> 67141 * 67142 * @alt 67143 * 60 by 10 rect at center of canvas rotates with mouse movements 67144 * 67145 */ 67146p5.prototype.atan2 = function(y, x) { 67147 return this._fromRadians(Math.atan2(y, x)); 67148}; 67149 67150/** 67151 * Calculates the cosine of an angle. This function takes into account the 67152 * current angleMode. Values are returned in the range -1 to 1. 67153 * 67154 * @method cos 67155 * @param {Number} angle the angle 67156 * @return {Number} the cosine of the angle 67157 * 67158 * @example 67159 * <div> 67160 * <code> 67161 * var a = 0.0; 67162 * var inc = TWO_PI / 25.0; 67163 * for (var i = 0; i < 25; i++) { 67164 * line(i * 4, 50, i * 4, 50 + cos(a) * 40.0); 67165 * a = a + inc; 67166 * } 67167 * </code> 67168 * </div> 67169 * 67170 * @alt 67171 * vertical black lines form wave patterns, extend-down on left and right side 67172 * 67173 */ 67174p5.prototype.cos = function(angle) { 67175 return Math.cos(this._toRadians(angle)); 67176}; 67177 67178/** 67179 * Calculates the sine of an angle. This function takes into account the 67180 * current angleMode. Values are returned in the range -1 to 1. 67181 * 67182 * @method sin 67183 * @param {Number} angle the angle 67184 * @return {Number} the sine of the angle 67185 * 67186 * @example 67187 * <div> 67188 * <code> 67189 * var a = 0.0; 67190 * var inc = TWO_PI / 25.0; 67191 * for (var i = 0; i < 25; i++) { 67192 * line(i * 4, 50, i * 4, 50 + sin(a) * 40.0); 67193 * a = a + inc; 67194 * } 67195 * </code> 67196 * </div> 67197 * 67198 * @alt 67199 * vertical black lines extend down and up from center to form wave pattern 67200 * 67201 */ 67202p5.prototype.sin = function(angle) { 67203 return Math.sin(this._toRadians(angle)); 67204}; 67205 67206/** 67207 * Calculates the tangent of an angle. This function takes into account 67208 * the current angleMode. Values are returned in the range -1 to 1. 67209 * 67210 * @method tan 67211 * @param {Number} angle the angle 67212 * @return {Number} the tangent of the angle 67213 * 67214 * @example 67215 * <div> 67216 * <code> 67217 * var a = 0.0; 67218 * var inc = TWO_PI / 50.0; 67219 * for (var i = 0; i < 100; i = i + 2) { 67220 * line(i, 50, i, 50 + tan(a) * 2.0); 67221 * a = a + inc; 67222 * } 67223 * </code> 67224 * 67225 * 67226 * @alt 67227 * vertical black lines end down and up from center to form spike pattern 67228 * 67229 */ 67230p5.prototype.tan = function(angle) { 67231 return Math.tan(this._toRadians(angle)); 67232}; 67233 67234/** 67235 * Converts a radian measurement to its corresponding value in degrees. 67236 * Radians and degrees are two ways of measuring the same thing. There are 67237 * 360 degrees in a circle and 2*PI radians in a circle. For example, 67238 * 90° = PI/2 = 1.5707964. This function does not take into account the 67239 * current angleMode. 67240 * 67241 * @method degrees 67242 * @param {Number} radians the radians value to convert to degrees 67243 * @return {Number} the converted angle 67244 * 67245 * 67246 * @example 67247 * <div class= ânorender"> 67248 * <code> 67249 * var rad = PI / 4; 67250 * var deg = degrees(rad); 67251 * print(rad + ' radians is ' + deg + ' degrees'); 67252 * // Prints: 0.7853981633974483 radians is 45 degrees 67253 * </code> 67254 * </div> 67255 * 67256 */ 67257p5.prototype.degrees = function(angle) { 67258 return angle * constants.RAD_TO_DEG; 67259}; 67260 67261/** 67262 * Converts a degree measurement to its corresponding value in radians. 67263 * Radians and degrees are two ways of measuring the same thing. There are 67264 * 360 degrees in a circle and 2*PI radians in a circle. For example, 67265 * 90° = PI/2 = 1.5707964. This function does not take into account the 67266 * current angleMode. 67267 * 67268 * @method radians 67269 * @param {Number} degrees the degree value to convert to radians 67270 * @return {Number} the converted angle 67271 * 67272 * @example 67273 * <div class= ânorender"> 67274 * <code> 67275 * var deg = 45.0; 67276 * var rad = radians(deg); 67277 * print(deg + ' degrees is ' + rad + ' radians'); 67278 * // Prints: 45 degrees is 0.7853981633974483 radians 67279 * </code> 67280 * </div> 67281 */ 67282p5.prototype.radians = function(angle) { 67283 return angle * constants.DEG_TO_RAD; 67284}; 67285 67286/** 67287 * Sets the current mode of p5 to given mode. Default mode is RADIANS. 67288 * 67289 * @method angleMode 67290 * @param {Constant} mode either RADIANS or DEGREES 67291 * 67292 * @example 67293 * <div> 67294 * <code> 67295 * function draw() { 67296 * background(204); 67297 * angleMode(DEGREES); // Change the mode to DEGREES 67298 * var a = atan2(mouseY - height / 2, mouseX - width / 2); 67299 * translate(width / 2, height / 2); 67300 * push(); 67301 * rotate(a); 67302 * rect(-20, -5, 40, 10); // Larger rectangle is rotating in degrees 67303 * pop(); 67304 * angleMode(RADIANS); // Change the mode to RADIANS 67305 * rotate(a); // var a stays the same 67306 * rect(-40, -5, 20, 10); // Smaller rectangle is rotating in radians 67307 * } 67308 * </code> 67309 * </div> 67310 * 67311 * @alt 67312 * 40 by 10 rect in center rotates with mouse moves. 20 by 10 rect moves faster. 67313 * 67314 * 67315 */ 67316p5.prototype.angleMode = function(mode) { 67317 if (mode === constants.DEGREES || mode === constants.RADIANS) { 67318 this._angleMode = mode; 67319 } 67320}; 67321 67322/** 67323 * converts angles from the current angleMode to RADIANS 67324 * 67325 * @method _toRadians 67326 * @private 67327 * @param {Number} angle 67328 * @returns {Number} 67329 */ 67330p5.prototype._toRadians = function(angle) { 67331 if (this._angleMode === constants.DEGREES) { 67332 return angle * constants.DEG_TO_RAD; 67333 } 67334 return angle; 67335}; 67336 67337/** 67338 * converts angles from the current angleMode to DEGREES 67339 * 67340 * @method _toDegrees 67341 * @private 67342 * @param {Number} angle 67343 * @returns {Number} 67344 */ 67345p5.prototype._toDegrees = function(angle) { 67346 if (this._angleMode === constants.RADIANS) { 67347 return angle * constants.RAD_TO_DEG; 67348 } 67349 return angle; 67350}; 67351 67352/** 67353 * converts angles from RADIANS into the current angleMode 67354 * 67355 * @method _fromRadians 67356 * @private 67357 * @param {Number} angle 67358 * @returns {Number} 67359 */ 67360p5.prototype._fromRadians = function(angle) { 67361 if (this._angleMode === constants.DEGREES) { 67362 return angle * constants.RAD_TO_DEG; 67363 } 67364 return angle; 67365}; 67366 67367module.exports = p5; 67368 67369},{"../core/constants":21,"../core/core":22}],56:[function(_dereq_,module,exports){ 67370/** 67371 * @module Typography 67372 * @submodule Attributes 67373 * @for p5 67374 * @requires core 67375 * @requires constants 67376 */ 67377 67378'use strict'; 67379 67380var p5 = _dereq_('../core/core'); 67381 67382/** 67383 * Sets the current alignment for drawing text. Accepts two 67384 * arguments: horizAlign (LEFT, CENTER, or RIGHT) and 67385 * vertAlign (TOP, BOTTOM, CENTER, or BASELINE). 67386 * 67387 * The horizAlign parameter is in reference to the x value 67388 * of the text() function, while the vertAlign parameter is 67389 * in reference to the y value. 67390 *
67391 * So if you write textAlign(LEFT), you are aligning the left 67392 * edge of your text to the x value you give in text(). If you 67393 * write textAlign(RIGHT, TOP), you are aligning the right edge 67394 * of your text to the x value and the top of edge of the text 67395 * to the y value. 67396 * 67397 * @method textAlign 67398 * @param {Constant} horizAlign horizontal alignment, either LEFT, 67399 * CENTER, or RIGHT 67400 * @param {Constant} [vertAlign] vertical alignment, either TOP, 67401 * BOTTOM, CENTER, or BASELINE 67402 * @chainable 67403 * @example 67404 * <div> 67405 * <code> 67406 * textSize(16); 67407 * textAlign(RIGHT); 67408 * text('ABCD', 50, 30); 67409 * textAlign(CENTER); 67410 * text('EFGH', 50, 50); 67411 * textAlign(LEFT); 67412 * text('IJKL', 50, 70); 67413 * </code> 67414 * </div> 67415 * 67416 * @alt 67417 *Letters ABCD displayed at top right, EFGH at center and IJKL at bottom left. 67418 * 67419 */ 67420/** 67421 * @method textAlign 67422 * @return {Object} 67423 */ 67424p5.prototype.textAlign = function(horizAlign, vertAlign) { 67425 p5._validateParameters('textAlign', arguments); 67426 return this._renderer.textAlign.apply(this._renderer, arguments); 67427}; 67428 67429/** 67430 * Sets/gets the spacing, in pixels, between lines of text. This 67431 * setting will be used in all subsequent calls to the text() function. 67432 * 67433 * @method textLeading 67434 * @param {Number} leading the size in pixels for spacing between lines 67435 * @chainable 67436 * 67437 * @example 67438 * <div> 67439 * <code> 67440 * // Text to display. The "\n" is a "new line" character 67441 * var lines = 'L1\nL2\nL3'; 67442 * textSize(12); 67443 * 67444 * textLeading(10); // Set leading to 10 67445 * text(lines, 10, 25); 67446 * 67447 * textLeading(20); // Set leading to 20 67448 * text(lines, 40, 25); 67449 * 67450 * textLeading(30); // Set leading to 30 67451 * text(lines, 70, 25); 67452 * </code> 67453 * </div> 67454 * 67455 * @alt 67456 *set L1 L2 & L3 displayed vertically 3 times. spacing increases for each set 67457 */ 67458/** 67459 * @method textLeading 67460 * @return {Number} 67461 */ 67462p5.prototype.textLeading = function(theLeading) { 67463 p5._validateParameters('textLeading', arguments); 67464 return this._renderer.textLeading.apply(this._renderer, arguments); 67465}; 67466 67467/** 67468 * Sets/gets the current font size. This size will be used in all subsequent 67469 * calls to the text() function. Font size is measured in pixels. 67470 * 67471 * @method textSize 67472 * @param {Number} theSize the size of the letters in units of pixels 67473 * @chainable 67474 * 67475 * @example 67476 * <div> 67477 * <code> 67478 * textSize(12); 67479 * text('Font Size 12', 10, 30); 67480 * textSize(14); 67481 * text('Font Size 14', 10, 60); 67482 * textSize(16); 67483 * text('Font Size 16', 10, 90); 67484 * </code> 67485 * </div> 67486 * 67487 * @alt 67488 *Font Size 12 displayed small, Font Size 14 medium & Font Size 16 large 67489 */ 67490/** 67491 * @method textSize 67492 * @return {Number} 67493 */ 67494p5.prototype.textSize = function(theSize) { 67495 p5._validateParameters('textSize', arguments); 67496 return this._renderer.textSize.apply(this._renderer, arguments); 67497}; 67498 67499/** 67500 * Sets/gets the style of the text for system fonts to NORMAL, ITALIC, or BOLD. 67501 * Note: this may be is overridden by CSS styling. For non-system fonts 67502 * (opentype, truetype, etc.) please load styled fonts instead. 67503 * 67504 * @method textStyle 67505 * @param {Constant} theStyle styling for text, either NORMAL, 67506 * ITALIC, or BOLD 67507 * @chainable 67508 * @example 67509 * <div> 67510 * <code> 67511 * strokeWeight(0); 67512 * textSize(12); 67513 * textStyle(NORMAL); 67514 * text('Font Style Normal', 10, 30); 67515 * textStyle(ITALIC); 67516 * text('Font Style Italic', 10, 60); 67517 * textStyle(BOLD); 67518 * text('Font Style Bold', 10, 90); 67519 * </code> 67520 * </div> 67521 * 67522 * @alt 67523 *words Font Style Normal displayed normally, Italic in italic and bold in bold 67524 */ 67525/** 67526 * @method textStyle 67527 * @return {String} 67528 */ 67529p5.prototype.textStyle = function(theStyle) { 67530 p5._validateParameters('textStyle', arguments); 67531 return this._renderer.textStyle.apply(this._renderer, arguments); 67532}; 67533 67534/** 67535 * Calculates and returns the width of any character or text string. 67536 * 67537 * @method textWidth 67538 * @param {String} theText the String of characters to measure 67539 * @return {Number} 67540 * @example 67541 * <div> 67542 * <code> 67543 * textSize(28); 67544 * 67545 * var aChar = 'P'; 67546 * var cWidth = textWidth(aChar); 67547 * text(aChar, 0, 40); 67548 * line(cWidth, 0, cWidth, 50); 67549 * 67550 * var aString = 'p5.js'; 67551 * var sWidth = textWidth(aString); 67552 * text(aString, 0, 85); 67553 * line(sWidth, 50, sWidth, 100); 67554 * </code> 67555 * </div> 67556 * 67557 * @alt 67558 *Letter P and p5.js are displayed with vertical lines at end. P is wide 67559 * 67560 */ 67561p5.prototype.textWidth = function(theText) { 67562 p5._validateParameters('textWidth', arguments); 67563 if (theText.length === 0) { 67564 return 0; 67565 } 67566 return this._renderer.textWidth.apply(this._renderer, arguments); 67567}; 67568 67569/** 67570 * Returns the ascent of the current font at its current size. The ascent 67571 * represents the distance, in pixels, of the tallest character above 67572 * the baseline. 67573 * @method textAscent 67574 * @return {Number} 67575 * @example 67576 * <div> 67577 * <code> 67578 * var base = height * 0.75; 67579 * var scalar = 0.8; // Different for each font 67580 * 67581 * textSize(32); // Set initial text size 67582 * var asc = textAscent() * scalar; // Calc ascent 67583 * line(0, base - asc, width, base - asc); 67584 * text('dp', 0, base); // Draw text on baseline 67585 * 67586 * textSize(64); // Increase text size 67587 * asc = textAscent() * scalar; // Recalc ascent 67588 * line(40, base - asc, width, base - asc); 67589 * text('dp', 40, base); // Draw text on baseline 67590 * </code> 67591 * </div> 67592 */ 67593p5.prototype.textAscent = function() { 67594 p5._validateParameters('textAscent', arguments); 67595 return this._renderer.textAscent(); 67596}; 67597 67598/** 67599 * Returns the descent of the current font at its current size. The descent 67600 * represents the distance, in pixels, of the character with the longest 67601 * descender below the baseline. 67602 * @method textDescent 67603 * @return {Number} 67604 * @example 67605 * <div> 67606 * <code> 67607 * var base = height * 0.75; 67608 * var scalar = 0.8; // Different for each font 67609 * 67610 * textSize(32); // Set initial text size 67611 * var desc = textDescent() * scalar; // Calc ascent 67612 * line(0, base + desc, width, base + desc); 67613 * text('dp', 0, base); // Draw text on baseline 67614 * 67615 * textSize(64); // Increase text size 67616 * desc = textDescent() * scalar; // Recalc ascent 67617 * line(40, base + desc, width, base + desc); 67618 * text('dp', 40, base); // Draw text on baseline 67619 * </code> 67620 * </div> 67621 */ 67622p5.prototype.textDescent = function() { 67623 p5._validateParameters('textDescent', arguments); 67624 return this._renderer.textDescent(); 67625}; 67626 67627/**
67628 * Helper function to measure ascent and descent. 67629 */ 67630p5.prototype._updateTextMetrics = function() { 67631 return this._renderer._updateTextMetrics(); 67632}; 67633 67634module.exports = p5; 67635 67636},{"../core/core":22}],57:[function(_dereq_,module,exports){ 67637/** 67638 * @module Typography 67639 * @submodule Loading & Displaying 67640 * @for p5 67641 * @requires core 67642 */ 67643 67644'use strict'; 67645 67646var p5 = _dereq_('../core/core'); 67647var constants = _dereq_('../core/constants'); 67648var opentype = _dereq_('opentype.js'); 67649 67650_dereq_('../core/error_helpers'); 67651 67652/** 67653 * Loads an opentype font file (.otf, .ttf) from a file or a URL, 67654 * and returns a PFont Object. This method is asynchronous, 67655 * meaning it may not finish before the next line in your sketch 67656 * is executed. 67657 * <br><br> 67658 * The path to the font should be relative to the HTML file 67659 * that links in your sketch. Loading an from a URL or other 67660 * remote location may be blocked due to your browser's built-in 67661 * security. 67662 * 67663 * @method loadFont 67664 * @param {String} path name of the file or url to load 67665 * @param {Function} [callback] function to be executed after 67666 * loadFont() completes 67667 * @param {Function} [onError] function to be executed if 67668 * an error occurs 67669 * @return {p5.Font} p5.Font object 67670 * @example 67671 * 67672 * <p>Calling loadFont() inside preload() guarantees that the load 67673 * operation will have completed before setup() and draw() are called.</p> 67674 * 67675 * <div><code> 67676 * var myFont; 67677 * function preload() { 67678 * myFont = loadFont('assets/AvenirNextLTPro-Demi.otf'); 67679 * } 67680 * 67681 * function setup() { 67682 * fill('#ED225D'); 67683 * textFont(myFont); 67684 * textSize(36); 67685 * text('p5*js', 10, 50); 67686 * } 67687 * </code></div> 67688 * 67689 * Outside of preload(), you may supply a callback function to handle the 67690 * object: 67691 * 67692 * <div><code> 67693 * function setup() { 67694 * loadFont('assets/AvenirNextLTPro-Demi.otf', drawText); 67695 * } 67696 * 67697 * function drawText(font) { 67698 * fill('#ED225D'); 67699 * textFont(font, 36); 67700 * text('p5*js', 10, 50); 67701 * } 67702 * </code></div> 67703 * 67704 * <p>You can also use the string name of the font to style other HTML 67705 * elements.</p> 67706 * 67707 * <div><code> 67708 * function preload() { 67709 * loadFont('assets/Avenir.otf'); 67710 * } 67711 * 67712 * function setup() { 67713 * var myDiv = createDiv('hello there'); 67714 * myDiv.style('font-family', 'Avenir'); 67715 * } 67716 * </code></div> 67717 * 67718 * @alt 67719 * p5*js in p5's theme dark pink 67720 * p5*js in p5's theme dark pink 67721 * 67722 */ 67723p5.prototype.loadFont = function(path, onSuccess, onError) { 67724 p5._validateParameters('loadFont', arguments); 67725 var p5Font = new p5.Font(this); 67726 67727 var self = this; 67728 opentype.load(path, function(err, font) { 67729 if (err) { 67730 if (typeof onError !== 'undefined') { 67731 return onError(err); 67732 } 67733 p5._friendlyFileLoadError(4, path); 67734 console.error(err, path); 67735 return; 67736 } 67737 67738 p5Font.font = font; 67739 67740 if (typeof onSuccess !== 'undefined') { 67741 onSuccess(p5Font); 67742 } 67743 67744 self._decrementPreload(); 67745 67746 // check that we have an acceptable font type 67747 var validFontTypes = ['ttf', 'otf', 'woff', 'woff2'], 67748 fileNoPath = path 67749 .split('\\') 67750 .pop() 67751 .split('/') 67752 .pop(), 67753 lastDotIdx = fileNoPath.lastIndexOf('.'), 67754 fontFamily, 67755 newStyle, 67756 fileExt = lastDotIdx < 1 ? null : fileNoPath.substr(lastDotIdx + 1); 67757 67758 // if so, add it to the DOM (name-only) for use with p5.dom 67759 if (validFontTypes.indexOf(fileExt) > -1) { 67760 fontFamily = fileNoPath.substr(0, lastDotIdx); 67761 newStyle = document.createElement('style'); 67762 newStyle.appendChild( 67763 document.createTextNode( 67764 '\n@font-face {' + 67765 '\nfont-family: ' + 67766 fontFamily + 67767 ';\nsrc: url(' + 67768 path + 67769 ');\n}\n' 67770 ) 67771 ); 67772 document.head.appendChild(newStyle); 67773 } 67774 }); 67775 67776 return p5Font; 67777}; 67778 67779/** 67780 * Draws text to the screen. Displays the information specified in the first 67781 * parameter on the screen in the position specified by the additional 67782 * parameters. A default font will be used unless a font is set with the 67783 * textFont() function and a default size will be used unless a font is set 67784 * with textSize(). Change the color of the text with the fill() function. 67785 * Change the outline of the text with the stroke() and strokeWeight(
67785) 67786 * functions. 67787 * <br><br> 67788 * The text displays in relation to the textAlign() function, which gives the 67789 * option to draw to the left, right, and center of the coordinates. 67790 * <br><br> 67791 * The x2 and y2 parameters define a rectangular area to display within and 67792 * may only be used with string data. When these parameters are specified, 67793 * they are interpreted based on the current rectMode() setting. Text that 67794 * does not fit completely within the rectangle specified will not be drawn 67795 * to the screen. 67796 * 67797 * @method text 67798 * @param {String|Object|Array|Number|Boolean} str the alphanumeric 67799 * symbols to be displayed 67800 * @param {Number} x x-coordinate of text 67801 * @param {Number} y y-coordinate of text 67802 * @param {Number} [x2] by default, the width of the text box, 67803 * see rectMode() for more info 67804 * @param {Number} [y2] by default, the height of the text box, 67805 * see rectMode() for more info 67806 * @chainable 67807 * @example 67808 * <div> 67809 * <code> 67810 * textSize(32); 67811 * text('word', 10, 30); 67812 * fill(0, 102, 153); 67813 * text('word', 10, 60); 67814 * fill(0, 102, 153, 51); 67815 * text('word', 10, 90); 67816 * </code> 67817 * </div> 67818 * <div> 67819 * <code> 67820 * var s = 'The quick brown fox jumped over the lazy dog.'; 67821 * fill(50); 67822 * text(s, 10, 10, 70, 80); // Text wraps within text box 67823 * </code> 67824 * </div> 67825 * 67826 * @alt 67827 *'word' displayed 3 times going from black, blue to translucent blue 67828 * The quick brown fox jumped over the lazy dog. 67829 * 67830 */ 67831p5.prototype.text = function(str, x, y, maxWidth, maxHeight) { 67832 p5._validateParameters('text', arguments); 67833 return !(this._renderer._doFill || this._renderer._doStroke) 67834 ? this 67835 : this._renderer.text.apply(this._renderer, arguments); 67836}; 67837 67838/** 67839 * Sets the current font that will be drawn with the text() function. 67840 * 67841 * @method textFont 67842 * @return {Object} the current font 67843 * 67844 * @example 67845 * <div> 67846 * <code> 67847 * fill(0); 67848 * textSize(12); 67849 * textFont('Georgia'); 67850 * text('Georgia', 12, 30); 67851 * textFont('Helvetica'); 67852 * text('Helvetica', 12, 60); 67853 * </code> 67854 * </div> 67855 * <div> 67856 * <code> 67857 * var fontRegular, fontItalic, fontBold; 67858 * function preload() { 67859 * fontRegular = loadFont('assets/Regular.otf'); 67860 * fontItalic = loadFont('assets/Italic.ttf'); 67861 * fontBold = loadFont('assets/Bold.ttf'); 67862 * } 67863 * function setup() { 67864 * background(210); 67865 * fill(0) 67866 .strokeWeight(0) 67867 .textSize(10); 67868 * textFont(fontRegular); 67869 * text('Font Style Normal', 10, 30); 67870 * textFont(fontItalic); 67871 * text('Font Style Italic', 10, 50); 67872 * textFont(fontBold); 67873 * text('Font Style Bold', 10, 70); 67874 * } 67875 * </code> 67876 * </div> 67877 * 67878 * @alt 67879 *words Font Style Normal displayed normally, Italic in italic and bold in bold 67880 */ 67881/** 67882 * @method textFont 67883 * @param {Object|String} font a font loaded via loadFont(), or a String 67884 * representing a <a href="https://mzl.la/2dOw8WD">web safe font</a> (a font 67885 * that is generally available across all systems) 67886 * @param {Number} [size] the font size to use 67887 * @chainable 67888 */ 67889p5.prototype.textFont = function(theFont, theSize) { 67890 p5._validateParameters('textFont', arguments); 67891 if (arguments.length) { 67892 if (!theFont) { 67893 throw Error('null font passed to textFont'); 67894 } 67895 67896 this._renderer._setProperty('_textFont', theFont); 67897 67898 if (theSize) { 67899 this._renderer._setProperty('_textSize', theSize); 67900 this._renderer._setProperty( 67901 '_textLeading', 67902 theSize * constants._DEFAULT_LEADMULT 67903 ); 67904 } 67905 67906 return this._renderer._applyTextProperties(); 67907 } 67908 67909 return this._renderer._textFont; 67910}; 67911 67912module.exports = p5; 67913 67914},{"../core/constants":21,"../core/core":22,"../core/error_helpers":25,"opentype.js":10}],58:[function(_dereq_,module,exports){ 67915/** 67916 * This module defines the p5.Font class and functions for 67917 * drawing text to the display canvas. 67918 * @module Typography 67919 * @submodule Font 67920 * @requires core 67921 * @requires constants 67922 */ 67923 67924'use strict'; 67925 67926var p5 = _dereq_('../core/core'); 67927var constants = _dereq_('../core/constants'); 67928 67929/* 67930 * TODO: 67931 * -- kerning 67932 * -- alignment: justified? 67933 */ 67934 67935/** 67936 * Base class for font handling 67937 * @class p5.Font 67938 * @param {p5} [pInst] pointer to p5 instance 67939 */ 67940p5.Font = function(p) { 67941 this.parent = p; 67942 67943 this.cache = {}; 67944 67945 /** 67946 * Underlying opentype font implementation 67947 * @property font 67948 */ 67949 this.font = undefined; 67950}; 67951 67952p5.Font.prototype.list = function() { 67953 // TODO 67954 throw 'not yet implemented'; 67955}; 67956 67957/**
67958 * Returns a tight bounding box for the given text string using this 67959 * font (currently only supports single lines) 67960 * 67961 * @method textBounds 67962 * @param {String} line a line of text 67963 * @param {Number} x x-position 67964 * @param {Number} y y-position 67965 * @param {Number} [fontSize] font size to use (optional) 67966 * @param {Object} [options] opentype options (optional) 67967 * 67968 * @return {Object} a rectangle object with properties: x, y, w, h 67969 * 67970 * @example 67971 * <div> 67972 * <code> 67973 * var font; 67974 * var textString = 'Lorem ipsum dolor sit amet.'; 67975 * function preload() { 67976 * font = loadFont('./assets/Regular.otf'); 67977 * } 67978 * function setup() { 67979 * background(210); 67980 * 67981 * var bbox = font.textBounds(textString, 10, 30, 12); 67982 * fill(255); 67983 * stroke(0); 67984 * rect(bbox.x, bbox.y, bbox.w, bbox.h); 67985 * fill(0); 67986 * noStroke(); 67987 * 67988 * textFont(font); 67989 * textSize(12); 67990 * text(textString, 10, 30); 67991 * } 67992 * </code> 67993 * </div> 67994 * 67995 * @alt 67996 *words Lorem ipsum dol go off canvas and contained by white bounding box 67997 * 67998 */ 67999p5.Font.prototype.textBounds = function(str, x, y, fontSize, options) { 68000 x = x !== undefined ? x : 0; 68001 y = y !== undefined ? y : 0; 68002 fontSize = fontSize || this.parent._renderer._textSize; 68003 68004 // Check cache for existing bounds. Take into consideration the text alignment 68005 // settings. Default alignment should match opentype's origin: left-aligned & 68006 // alphabetic baseline. 68007 var p = 68008 (options && options.renderer && options.renderer._pInst) || this.parent, 68009 ctx = p._renderer.drawingContext, 68010 alignment = ctx.textAlign || constants.LEFT, 68011 baseline = ctx.textBaseline || constants.BASELINE, 68012 key = cacheKey('textBounds', str, x, y, fontSize, alignment, baseline), 68013 result = this.cache[key]; 68014 68015 if (!result) { 68016 var minX, 68017 minY, 68018 maxX, 68019 maxY, 68020 pos, 68021 xCoords = [], 68022 yCoords = [], 68023 scale = this._scale(fontSize); 68024 68025 this.font.forEachGlyph(str, x, y, fontSize, options, function( 68026 glyph, 68027 gX, 68028 gY, 68029 gFontSize 68030 ) { 68031 var gm = glyph.getMetrics(); 68032 xCoords.push(gX + gm.xMin * scale); 68033 xCoords.push(gX + gm.xMax * scale); 68034 yCoords.push(gY + -gm.yMin * scale); 68035 yCoords.push(gY + -gm.yMax * scale); 68036 }); 68037 68038 minX = Math.min.apply(null, xCoords); 68039 minY = Math.min.apply(null, yCoords); 68040 maxX = Math.max.apply(null, xCoords); 68041 maxY = Math.max.apply(null, yCoords); 68042 68043 result = { 68044 x: minX, 68045 y: minY, 68046 h: maxY - minY, 68047 w: maxX - minX, 68048 advance: minX - x 68049 }; 68050 68051 // Bounds are now calculated, so shift the x & y to match alignment settings 68052 pos = this._handleAlignment( 68053 p, 68054 ctx, 68055 str, 68056 result.x, 68057 result.y, 68058 result.w + result.advance 68059 ); 68060 68061 result.x = pos.x; 68062 result.y = pos.y; 68063 68064 this.cache[ 68065 cacheKey('textBounds', str, x, y, fontSize, alignment, baseline) 68066 ] = result; 68067 } 68068 68069 return result; 68070}; 68071 68072/** 68073 * Computes an array of points following the path for specified text 68074 * 68075 * @method textToPoints 68076 * @param {String} txt a line of text 68077 * @param {Number} x x-position 68078 * @param {Number} y y-position 68079 * @param {Number} fontSize font size to use (optional) 68080 * @param {Object} [options] an (optional) object that can contain: 68081 * 68082 * <br>sampleFactor - the ratio of path-length to number of samples 68083 * (default=.25); higher values yield more points and are therefore 68084 * more precise 68085 * 68086 * <br>simplifyThreshold - if set to a non-zero value, collinear points will be 68087 * be removed from the polygon; the value represents the threshold angle to use 68088 * when determining whether two edges are collinear 68089 * 68090 * @return {Array} an array of points, each with x, y, alpha (the path angle) 68091 * @example 68092 * <div> 68093 * <code> 68094 * var font; 68095 * function preload() { 68096 * font = loadFont('./assets/Avenir.otf'); 68097 * } 68098 * 68099 * var points; 68100 * var bounds; 68101 * function setup() { 68102 * createCanvas(100, 100); 68103 * stroke(0); 68104 * fill(255, 104, 204); 68105 * 68106 * points = font.textToPoints('p5', 0, 0, 10, { 68107 * sampleFactor: 5, 68108 * simplifyThreshold: 0 68109 * }); 68110 * bounds = font.textBounds(' p5 ', 0, 0, 10); 68111 * } 68112 * 68113 * function draw() { 68114 * background(255); 68115 * beginShape(); 68116 * translate(-bounds.x * width / bounds.w, -bounds.y * height / bounds.h); 68117 * for (var i = 0; i < points.length; i++) { 68118 * var p = points[i]; 68119 * vertex( 68120 * p.x * width / bounds.w +
68121 * sin(20 * p.y / bounds.h + millis() / 1000) * width / 30, 68122 * p.y * height / bounds.h 68123 * ); 68124 * } 68125 * endShape(CLOSE); 68126 * } 68127 * </code> 68128 * </div> 68129 * 68130 */ 68131p5.Font.prototype.textToPoints = function(txt, x, y, fontSize, options) { 68132 var xoff = 0, 68133 result = [], 68134 glyphs = this._getGlyphs(txt); 68135 68136 function isSpace(i) { 68137 return ( 68138 (glyphs[i].name && glyphs[i].name === 'space') || 68139 (txt.length === glyphs.length && txt[i] === ' ') || 68140 (glyphs[i].index && glyphs[i].index === 3) 68141 ); 68142 } 68143 68144 fontSize = fontSize || this.parent._renderer._textSize; 68145 68146 for (var i = 0; i < glyphs.length; i++) { 68147 if (!isSpace(i)) { 68148 // fix to #1817, #2069 68149 68150 var gpath = glyphs[i].getPath(x, y, fontSize), 68151 paths = splitPaths(gpath.commands); 68152 68153 for (var j = 0; j < paths.length; j++) { 68154 var pts = pathToPoints(paths[j], options); 68155 68156 for (var k = 0; k < pts.length; k++) { 68157 pts[k].x += xoff; 68158 result.push(pts[k]); 68159 } 68160 } 68161 } 68162 68163 xoff += glyphs[i].advanceWidth * this._scale(fontSize); 68164 } 68165 68166 return result; 68167}; 68168 68169// ----------------------------- End API ------------------------------ 68170 68171/** 68172 * Returns the set of opentype glyphs for the supplied string. 68173 * 68174 * Note that there is not a strict one-to-one mapping between characters 68175 * and glyphs, so the list of returned glyphs can be larger or smaller 68176 * than the length of the given string. 68177 * 68178 * @private 68179 * @param {String} str the string to be converted 68180 * @return {Array} the opentype glyphs 68181 */ 68182p5.Font.prototype._getGlyphs = function(str) { 68183 return this.font.stringToGlyphs(str); 68184}; 68185 68186/** 68187 * Returns an opentype path for the supplied string and position. 68188 * 68189 * @private 68190 * @param {String} line a line of text 68191 * @param {Number} x x-position 68192 * @param {Number} y y-position 68193 * @param {Object} options opentype options (optional) 68194 * @return {Object} the opentype path 68195 */ 68196p5.Font.prototype._getPath = function(line, x, y, options) { 68197 var p = 68198 (options && options.renderer && options.renderer._pInst) || this.parent, 68199 ctx = p._renderer.drawingContext, 68200 pos = this._handleAlignment(p, ctx, line, x, y); 68201 68202 return this.font.getPath(line, pos.x, pos.y, p._renderer._textSize, options); 68203}; 68204 68205/* 68206 * Creates an SVG-formatted path-data string 68207 * (See http://www.w3.org/TR/SVG/paths.html#PathData) 68208 * from the given opentype path or string/position 68209 * 68210 * @param {Object} path an opentype path, OR the following: 68211 * 68212 * @param {String} line a line of text 68213 * @param {Number} x x-position 68214 * @param {Number} y y-position 68215 * @param {Object} options opentype options (optional), set options.decimals 68216 * to set the decimal precision of the path-data 68217 * 68218 * @return {Object} this p5.Font object 68219 */ 68220p5.Font.prototype._getPathData = function(line, x, y, options) { 68221 var decimals = 3; 68222 68223 // create path from string/position 68224 if (typeof line === 'string' && arguments.length > 2) { 68225 line = this._getPath(line, x, y, options); 68226 } else if (typeof x === 'object') { 68227 // handle options specified in 2nd arg 68228 options = x; 68229 } 68230 68231 // handle svg arguments 68232 if (options && typeof options.decimals === 'number') { 68233 decimals = options.decimals; 68234 } 68235 68236 return line.toPathData(decimals); 68237}; 68238 68239/* 68240 * Creates an SVG <path> element, as a string, 68241 * from the given opentype path or string/position 68242 * 68243 * @param {Object} path an opentype path, OR the following: 68244 * 68245 * @param {String} line a line of text 68246 * @param {Number} x x-position 68247 * @param {Number} y y-position 68248 * @param {Object} options opentype options (optional), set options.decimals 68249 * to set the decimal precision of the path-data in the <path> element, 68250 * options.fill to set the fill color for the <path> element, 68251 * options.stroke to set the stroke color for the <path> element, 68252 * options.strokeWidth to set the strokeWidth for the <path> element. 68253 * 68254 * @return {Object} this p5.Font object 68255 */ 68256p5.Font.prototype._getSVG = function(line, x, y, options) { 68257 var decimals = 3; 68258 68259 // create path from string/position 68260 if (typeof line === 'string' && arguments.length > 2) { 68261 line = this._getPath(line, x, y, options); 68262 } else if (typeof x === 'object') { 68263 // handle options specified in 2nd arg 68264 options = x; 68265 } 68266 68267 // handle svg arguments 68268 if (options) { 68269 if (typeof options.decimals === 'number') { 68270 decimals = options.decimals; 68271 } 68272 if (typeof options.strokeWidth === 'number') { 68273 line.strokeWidth = options.strokeWidth; 68274 } 68275 if (typeof options.fill !== 'undefined') { 68276 line.fill = options.fill; 68277 } 68278 if (typeof options.stroke !== 'undefined') { 68279 line.stroke = options.stroke; 68280 } 68281 } 68282 68283 return line.toSVG(decimals); 68284}; 68285 68286/* 68287 * Renders an opentype path or string/position 68288 * to the current graphics context 68289 * 68290 * @param {Object} path an opentype path, OR the following: 68291 * 68292 * @param {String} line a line of text 68293 * @param {Number} x x-position 68294 * @param {Number} y y-position 68295 * @param {Object} options opentype options (optional) 68296 * 68297 * @return {p5.Font} this p5.Font object 68298 */ 68299p5.Font.prototype._renderPath = function(line, x, y, options) { 68300 var pdata, 68301 pg = (options && options.renderer) || this.parent._renderer, 68302 ctx = pg.drawingContext; 68303 68304 if (typeof line === 'object' && line.commands) { 68305 pdata = line.commands; 68306 } else { 68307 //pos = handleAlignment(p, ctx, line, x, y); 68308 pdata = this._getPath(line, x, y, options).commands; 68309 } 68310 68311 ctx.beginPath(); 68312 for (var i = 0; i < pdata.length; i += 1) { 68313 var cmd = pdata[i]; 68314 if (cmd.type === 'M') { 68315 ctx.moveTo(cmd.x, cmd.y); 68316 } else if (cmd.type === 'L') { 68317 ctx.lineTo(cmd.x, cmd.y); 68318 } else if (cmd.type === 'C') { 68319 ctx.bezierCurveTo(cmd.x1, cmd.y1, cmd.x2, cmd.y2, cmd.x, cmd.y); 68320 } else if (cmd.type === 'Q') { 68321 ctx.quadraticCurveTo(cmd.x1, cmd.y1, cmd.x, cmd.y); 68322 } else if (cmd.type === 'Z') { 68323 ctx.closePath(); 68324 } 68325 } 68326 68327 // only draw stroke if manually set by user 68328 if (pg._doStroke && pg._strokeSet) { 68329 ctx.stroke(); 68330 } 68331 68332 if (pg._doFill) { 68333 // if fill hasn't been set by user, use default-text-fill 68334 if (!pg._fillSet) { 68335 pg._setFill(constants._DEFAULT_TEXT_FILL); 68336 } 68337 ctx.fill(); 68338 } 68339 68340 return this; 68341}; 68342 68343p5.Font.prototype._textWidth = function(str, fontSize) { 68344 return this.font.getAdvanceWidth(str, fontSize); 68345}; 68346 68347p5.Font.prototype._textAscent = function(fontSize) { 68348 return this.font.ascender * this._scale(fontSize); 68349}; 68350 68351p5.Font.prototype._textDescent = function(fontSize) { 68352 return -this.font.descender * this._scale(fontSize); 68353}; 68354 68355p5.Font.prototype._scale = function(fontSize) { 68356 return ( 68357 1 / this.font.unitsPerEm * (fontSize || this.parent._renderer._textSize) 68358 ); 68359}; 68360 68361p5.Font.prototype._handleAlignment = function(p, ctx, line, x, y, textWidth) { 68362 var fontSize = p._renderer._textSize, 68363 textAscent = this._textAscent(fontSize), 68364 textDescent = this._textDescent(fontSize); 68365 68366 textWidth = 68367 textWidth !== undefined ? textWidth : this._textWidth(line, fontSize); 68368 68369 if (ctx.textAlign === constants.CENTER) { 68370 x -= textWidth / 2; 68371 } else if (ctx.textAlign === constants.RIGHT) { 68372 x -= textWidth; 68373 } 68374 68375 if (ctx.textBaseline === constants.TOP) { 68376 y += textAscent; 68377 } else if (ctx.textBaseline === constants._CTX_MIDDLE) { 68378 y += textAscent / 2; 68379 } else if (ctx.textBaseline === constants.BOTTOM) { 68380 y -= textDescent; 68381 } 68382 68383 return { x: x, y: y }; 68384}; 68385 68386// path-utils 68387 68388function pathToPoints(cmds, options) { 68389 var opts = parseOpts(options, { 68390 sampleFactor: 0.1, 68391 simplifyThreshold: 0 68392 }); 68393 68394 var len = pointAtLength(cmds, 0, 1), // total-length 68395 t = len / (len * opts.sampleFactor), 68396 pts = []; 68397 68398 for (var i = 0; i < len; i += t) { 68399 pts.push(pointAtLength(cmds, i)); 68400 } 68401 68402 if (opts.simplifyThreshold) { 68403 /*var count = */ simplify(pts, opts.simplifyThreshold); 68404 //console.log('Simplify: removed ' + count + ' pts'); 68405 } 68406 68407 return pts; 68408} 68409 68410function simplify(pts, angle) { 68411 angle = typeof angle === 'undefined' ? 0 : angle; 68412 68413 var num = 0; 68414 for (var i = pts.length - 1; pts.length > 3 && i >= 0; --i) { 68415 if (collinear(at(pts, i - 1), at(pts, i), at(pts, i + 1), angle)) { 68416 // Remove the middle point 68417 pts.splice(i % pts.length, 1); 68418 num++; 68419 } 68420 } 68421 return num; 68422} 68423 68424function splitPaths(cmds) { 68425 var paths = [], 68426 current; 68427 for (var i = 0; i < cmds.length; i++) { 68428 if (cmds[i].type === 'M') { 68429 if (current) { 68430 paths.push(current); 68431 } 68432 current = []; 68433 } 68434 current.push(cmdToArr(cmds[i])); 68435 } 68436 paths.push(current); 68437 68438 return paths; 68439} 68440 68441function cmdToArr(cmd) { 68442 var arr = [cmd.type]; 68443 if (cmd.type === 'M' || cmd.type === 'L') { 68444 // moveto or lineto 68445 arr.push(cmd.x, cmd.y); 68446 } else if (cmd.type === 'C') { 68447 arr.push(cmd.x1, cmd.y1, cmd.x2, cmd.y2, cmd.x, cmd.y); 68448 } else if (cmd.type === 'Q') { 68449 arr.push(cmd.x1, cmd.y1, cmd.x, cmd.y); 68450 } 68451 // else if (cmd.type === 'Z') { /* no-op */ } 68452 return arr; 68453} 68454 68455function parseOpts(options, defaults) { 68456 if (typeof options !== 'object') { 68457 options = defaults; 68458 } else { 68459 for (var key in defaults) { 68460 if (typeof options[key] === 'undefined') { 68461 options[key] = defaults[key]; 68462 } 68463 } 68464 } 68465 return options; 68466} 68467
68468//////////////////////// Helpers //////////////////////////// 68469 68470function at(v, i) { 68471 var s = v.length; 68472 return v[i < 0 ? i % s + s : i % s]; 68473} 68474 68475function collinear(a, b, c, thresholdAngle) { 68476 if (!thresholdAngle) { 68477 return areaTriangle(a, b, c) === 0; 68478 } 68479 68480 if (typeof collinear.tmpPoint1 === 'undefined') { 68481 collinear.tmpPoint1 = []; 68482 collinear.tmpPoint2 = []; 68483 } 68484 68485 var ab = collinear.tmpPoint1, 68486 bc = collinear.tmpPoint2; 68487 ab.x = b.x - a.x; 68488 ab.y = b.y - a.y; 68489 bc.x = c.x - b.x; 68490 bc.y = c.y - b.y; 68491 68492 var dot = ab.x * bc.x + ab.y * bc.y, 68493 magA = Math.sqrt(ab.x * ab.x + ab.y * ab.y), 68494 magB = Math.sqrt(bc.x * bc.x + bc.y * bc.y), 68495 angle = Math.acos(dot / (magA * magB)); 68496 68497 return angle < thresholdAngle; 68498} 68499 68500function areaTriangle(a, b, c) { 68501 return (b[0] - a[0]) * (c[1] - a[1]) - (c[0] - a[0]) * (b[1] - a[1]); 68502} 68503 68504// Portions of below code copyright 2008 Dmitry Baranovskiy (via MIT license) 68505 68506function findDotsAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) { 68507 var t1 = 1 - t, 68508 t13 = Math.pow(t1, 3), 68509 t12 = Math.pow(t1, 2), 68510 t2 = t * t, 68511 t3 = t2 * t, 68512 x = t13 * p1x + t12 * 3 * t * c1x + t1 * 3 * t * t * c2x + t3 * p2x, 68513 y = t13 * p1y + t12 * 3 * t * c1y + t1 * 3 * t * t * c2y + t3 * p2y, 68514 mx = p1x + 2 * t * (c1x - p1x) + t2 * (c2x - 2 * c1x + p1x), 68515 my = p1y + 2 * t * (c1y - p1y) + t2 * (c2y - 2 * c1y + p1y), 68516 nx = c1x + 2 * t * (c2x - c1x) + t2 * (p2x - 2 * c2x + c1x), 68517 ny = c1y + 2 * t * (c2y - c1y) + t2 * (p2y - 2 * c2y + c1y), 68518 ax = t1 * p1x + t * c1x, 68519 ay = t1 * p1y + t * c1y, 68520 cx = t1 * c2x + t * p2x, 68521 cy = t1 * c2y + t * p2y, 68522 alpha = 90 - Math.atan2(mx - nx, my - ny) * 180 / Math.PI; 68523 68524 if (mx > nx || my < ny) { 68525 alpha += 180; 68526 } 68527 68528 return { 68529 x: x, 68530 y: y, 68531 m: { x: mx, y: my }, 68532 n: { x: nx, y: ny }, 68533 start: { x: ax, y: ay }, 68534 end: { x: cx, y: cy },
68535 alpha: alpha 68536 }; 68537} 68538 68539function getPointAtSegmentLength( 68540 p1x, 68541 p1y, 68542 c1x, 68543 c1y, 68544 c2x, 68545 c2y, 68546 p2x, 68547 p2y, 68548 length 68549) { 68550 return length == null 68551 ? bezlen(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) 68552 : findDotsAtSegment( 68553 p1x, 68554 p1y, 68555 c1x, 68556 c1y, 68557 c2x, 68558 c2y, 68559 p2x, 68560 p2y, 68561 getTatLen(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, length) 68562 ); 68563} 68564 68565function pointAtLength(path, length, istotal) { 68566 path = path2curve(path); 68567 var x, 68568 y, 68569 p, 68570 l, 68571 sp = '', 68572 subpaths = {}, 68573 point, 68574 len = 0; 68575 for (var i = 0, ii = path.length; i < ii; i++) { 68576 p = path[i]; 68577 if (p[0] === 'M') { 68578 x = +p[1]; 68579 y = +p[2]; 68580 } else { 68581 l = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6]); 68582 if (len + l > length) { 68583 if (!istotal) { 68584 point = getPointAtSegmentLength( 68585 x, 68586 y, 68587 p[1], 68588 p[2], 68589 p[3], 68590 p[4], 68591 p[5], 68592 p[6], 68593 length - len 68594 ); 68595 return { x: point.x, y: point.y, alpha: point.alpha }; 68596 } 68597 } 68598 len += l; 68599 x = +p[5]; 68600 y = +p[6]; 68601 } 68602 sp += p.shift() + p; 68603 } 68604 subpaths.end = sp; 68605 68606 point = istotal 68607 ? len 68608 : findDotsAtSegment(x, y, p[0], p[1], p[2], p[3], p[4], p[5], 1); 68609 68610 if (point.alpha) { 68611 point = { x: point.x, y: point.y, alpha: point.alpha }; 68612 } 68613 68614 return point; 68615} 68616 68617function pathToAbsolute(pathArray) { 68618 var res = [], 68619 x = 0, 68620 y = 0, 68621 mx = 0, 68622 my = 0, 68623 start = 0; 68624 if (!pathArray) { 68625 // console.warn("Unexpected state: undefined pathArray"); // shouldn't happen 68626 return res; 68627 } 68628 if (pathArray[0][0] === 'M') { 68629 x = +pathArray[0][1]; 68630 y = +pathArray[0][2]; 68631 mx = x; 68632 my = y; 68633 start++; 68634 res[0] = ['M', x, y]; 68635 } 68636 68637 var dots, 68638 crz = 68639 pathArray.length === 3 && 68640 pathArray[0][0] === 'M' && 68641 pathArray[1][0].toUpperCase() === 'R' && 68642 pathArray[2][0].toUpperCase() === 'Z'; 68643 68644 for (var r, pa, i = start, ii = pathArray.length; i < ii; i++) { 68645 res.push((r = [])); 68646 pa = pathArray[i]; 68647 if (pa[0] !== String.prototype.toUpperCase.call(pa[0])) { 68648 r[0] = String.prototype.toUpperCase.call(pa[0]); 68649 switch (r[0]) { 68650 case 'A': 68651 r[1] = pa[1]; 68652 r[2] = pa[2]; 68653 r[3] = pa[3]; 68654 r[4] = pa[4]; 68655 r[5] = pa[5]; 68656 r[6] = +(pa[6] + x); 68657 r[7] = +(pa[7] + y); 68658 break; 68659 case 'V': 68660 r[1] = +pa[1] + y; 68661 break; 68662 case 'H': 68663 r[1] = +pa[1] + x; 68664 break; 68665 case 'R': 68666 dots = [x, y].concat(pa.slice(1)); 68667 for (var j = 2, jj = dots.length; j < jj; j++) { 68668 dots[j] = +dots[j] + x; 68669 dots[++j] = +dots[j] + y; 68670 } 68671 res.pop(); 68672 res = res.concat(catmullRom2bezier(dots, crz)); 68673 break; 68674 case 'M': 68675 mx = +pa[1] + x; 68676 my = +pa[2] + y; 68677 break; 68678 default: 68679 for (j = 1, jj = pa.length; j < jj; j++) { 68680 r[j] = +pa[j] + (j % 2 ? x : y); 68681 } 68682 } 68683 } else if (pa[0] === 'R') { 68684 dots = [x, y].concat(pa.slice(1)); 68685 res.pop(); 68686 res = res.concat(catmullRom2bezier(dots, crz)); 68687 r = ['R'].concat(pa.slice(-2)); 68688 } else { 68689 for (var k = 0, kk = pa.length; k < kk; k++) { 68690 r[k] = pa[k]; 68691 } 68692 } 68693 switch (r[0]) { 68694 case 'Z': 68695 x = mx; 68696 y = my; 68697 break; 68698 case 'H': 68699 x = r[1]; 68700 break; 68701 case 'V': 68702 y = r[1]; 68703 break; 68704 case 'M': 68705 mx = r[r.length - 2]; 68706 my = r[r.length - 1]; 68707 break; 68708 default: 68709 x = r[r.length - 2]; 68710 y = r[r.length - 1]; 68711 } 68712 } 68713 return res; 68714} 68715 68716function path2curve(path, path2) { 68717 var p = pathToAbsolute(path), 68718 p2 = path2 && pathToAbsolute(path2); 68719 var attrs = { x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null }; 68720 var attrs2 = { x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null }; 68721 var pcoms1 = []; // path commands of original path p 68722 var pcoms2 = []; // path commands of original path p2 68723 var ii; 68724 68725 var processPath = function(path, d, pcom) { 68726 var nx, 68727 ny, 68728 tq = { T: 1, Q: 1 }; 68729 if (!path) { 68730 return ['C', d.x, d.y, d.x, d.y, d.x, d.y]; 68731 } 68732 if (!(path[0] in tq)) { 68733 d.qx = d.qy = null; 68734 } 68735 switch (path[0]) { 68736 case 'M': 68737 d.X = path[1]; 68738 d.Y = path[2]; 68739 break; 68740 case 'A': 68741 path = ['C'].concat(a2c.apply(0, [d.x, d.y].concat(path.slice(1)))); 68742 break; 68743 case 'S': 68744 if (pcom === 'C' || pcom === 'S') { 68745 nx = d.x * 2 - d.bx; 68746 ny = d.y * 2 - d.by; 68747 } else { 68748 nx = d.x; 68749 ny = d.y; 68750 } 68751 path = ['C', nx, ny].concat(path.slice(1)); 68752 break; 68753 case 'T': 68754 if (pcom === 'Q' || pcom === 'T') { 68755 d.qx = d.x * 2 - d.qx; 68756 d.qy = d.y * 2 - d.qy; 68757 } else { 68758 d.qx = d.x; 68759 d.qy = d.y; 68760 } 68761 path = ['C'].concat(q2c(d.x, d.y, d.qx, d.qy, path[1], path[2])); 68762 break; 68763 case 'Q': 68764 d.qx = path[1]; 68765 d.qy = path[2]; 68766 path = ['C'].concat( 68767 q2c(d.x, d.y, path[1], path[2], path[3], path[4]) 68768 ); 68769 break; 68770 case 'L': 68771 path = ['C'].concat(l2c(d.x, d.y, path[1], path[2])); 68772 break; 68773 case 'H': 68774 path = ['C'].concat(l2c(d.x, d.y, path[1], d.y)); 68775 break; 68776 case 'V': 68777 path = ['C'].concat(l2c(d.x, d.y, d.x, path[1])); 68778 break; 68779 case 'Z': 68780 path = ['C'].concat(l2c(d.x, d.y, d.X, d.Y)); 68781 break; 68782 } 68783 return path; 68784 }, 68785 fixArc = function(pp, i) { 68786 if (pp[i].length > 7) { 68787 pp[i].shift(); 68788 var pi = pp[i]; 68789 while (pi.length) { 68790 pcoms1[i] = 'A'; 68791 if (p2) { 68792 pcoms2[i] = 'A'; 68793 } 68794 pp.splice(i++, 0, ['C'].concat(pi.splice(0, 6))); 68795 } 68796 pp.splice(i, 1); 68797 ii = Math.max(p.length, (p2 && p2.length) || 0); 68798 } 68799 }, 68800 fixM = function(path1, path2, a1, a2, i) { 68801 if (path1 && path2 && path1[i][0] === 'M' && path2[i][0] !== 'M') { 68802 path2.splice(i, 0, ['M', a2.x, a2.y]); 68803 a1.bx = 0; 68804 a1.by = 0; 68805 a1.x = path1[i][1]; 68806 a1.y = path1[i][2]; 68807 ii = Math.max(p.length, (p2 && p2.length) || 0); 68808 } 68809 }; 68810 68811 var pfirst = ''; // temporary holder for original path command 68812 var pcom = ''; // holder for previous path command of original path 68813 68814 ii = Math.max(p.length, (p2 && p2.length) || 0); 68815 for (var i = 0; i < ii; i++) { 68816 if (p[i]) { 68817 pfirst = p[i][0]; 68818 } // save current path command 68819 68820 if (pfirst !== 'C') { 68821 pcoms1[i] = pfirst; // Save current path command 68822 if (i) { 68823 pcom = pcoms1[i - 1]; 68824 } // Get previous path command pcom 68825 } 68826 p[i] = processPath(p[i], attrs, pcom); 68827 68828 if (pcoms1[i] !== 'A' && pfirst === 'C') { 68829 pcoms1[i] = 'C'; 68830 } 68831 68832 fixArc(p, i);
68832 // fixArc adds also the right amount of A:s to pcoms1 68833 68834 if (p2) { 68835 // the same procedures is done to p2 68836 if (p2[i]) { 68837 pfirst = p2[i][0]; 68838 } 68839 if (pfirst !== 'C') { 68840 pcoms2[i] = pfirst; 68841 if (i) { 68842 pcom = pcoms2[i - 1]; 68843 } 68844 } 68845 p2[i] = processPath(p2[i], attrs2, pcom); 68846 68847 if (pcoms2[i] !== 'A' && pfirst === 'C') { 68848 pcoms2[i] = 'C'; 68849 } 68850 68851 fixArc(p2, i); 68852 } 68853 fixM(p, p2, attrs, attrs2, i); 68854 fixM(p2, p, attrs2, attrs, i); 68855 var seg = p[i], 68856 seg2 = p2 && p2[i], 68857 seglen = seg.length, 68858 seg2len = p2 && seg2.length; 68859 attrs.x = seg[seglen - 2]; 68860 attrs.y = seg[seglen - 1]; 68861 attrs.bx = parseFloat(seg[seglen - 4]) || attrs.x; 68862 attrs.by = parseFloat(seg[seglen - 3]) || attrs.y; 68863 attrs2.bx = p2 && (parseFloat(seg2[seg2len - 4]) || attrs2.x); 68864 attrs2.by = p2 && (parseFloat(seg2[seg2len - 3]) || attrs2.y); 68865 attrs2.x = p2 && seg2[seg2len - 2]; 68866 attrs2.y = p2 && seg2[seg2len - 1]; 68867 } 68868 68869 return p2 ? [p, p2] : p; 68870} 68871 68872function a2c(x1, y1, rx, ry, angle, lac, sweep_flag, x2, y2, recursive) { 68873 // for more information of where this Math came from visit: 68874 // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes 68875 var PI = Math.PI, 68876 _120 = PI * 120 / 180, 68877 f1, 68878 f2, 68879 cx, 68880 cy, 68881 rad = PI / 180 * (+angle || 0), 68882 res = [], 68883 xy, 68884 rotate = function(x, y, rad) { 68885 var X = x * Math.cos(rad) - y * Math.sin(rad), 68886 Y = x * Math.sin(rad) + y * Math.cos(rad); 68887 return { x: X, y: Y }; 68888 }; 68889 if (!recursive) { 68890 xy = rotate(x1, y1, -rad); 68891 x1 = xy.x; 68892 y1 = xy.y; 68893 xy = rotate(x2, y2, -rad); 68894 x2 = xy.x; 68895 y2 = xy.y; 68896 var x = (x1 - x2) / 2, 68897 y = (y1 - y2) / 2, 68898 h = x * x / (rx * rx) + y * y / (ry * ry); 68899 if (h > 1) { 68900 h = Math.sqrt(h); 68901 rx = h * rx; 68902 ry = h * ry; 68903 } 68904 var rx2 = rx * rx, 68905 ry2 = ry * ry; 68906 var k = 68907 (lac === sweep_flag ? -1 : 1) * 68908 Math.sqrt( 68909 Math.abs( 68910 (rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x) 68911 ) 68912 ); 68913 68914 cx = k * rx * y / ry + (x1 + x2) / 2; 68915 cy = k * -ry * x / rx + (y1 + y2) / 2; 68916 f1 = Math.asin(((y1 - cy) / ry).toFixed(9)); 68917 f2 = Math.asin(((y2 - cy) / ry).toFixed(9)); 68918 68919 f1 = x1 < cx ? PI - f1 : f1; 68920 f2 = x2 < cx ? PI - f2 : f2; 68921 68922 if (f1 < 0) { 68923 f1 = PI * 2 + f1; 68924 } 68925 if (f2 < 0) { 68926 f2 = PI * 2 + f2; 68927 } 68928 68929 if (sweep_flag && f1 > f2) { 68930 f1 = f1 - PI * 2; 68931 } 68932 if (!sweep_flag && f2 > f1) { 68933 f2 = f2 - PI * 2; 68934 } 68935 } else { 68936 f1 = recursive[0]; 68937 f2 = recursive[1]; 68938 cx = recursive[2]; 68939 cy = recursive[3]; 68940 } 68941 var df = f2 - f1; 68942 if (Math.abs(df) > _120) { 68943 var f2old = f2, 68944 x2old = x2, 68945 y2old = y2; 68946 f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1); 68947 x2 = cx + rx * Math.cos(f2); 68948 y2 = cy + ry * Math.sin(f2); 68949 res = a2c(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old, [ 68950 f2, 68951 f2old, 68952 cx, 68953 cy 68954 ]); 68955 } 68956 df = f2 - f1; 68957 var c1 = Math.cos(f1), 68958 s1 = Math.sin(f1), 68959 c2 = Math.cos(f2), 68960 s2 = Math.sin(f2), 68961 t = Math.tan(df / 4), 68962 hx = 4 / 3 * rx * t, 68963 hy = 4 / 3 * ry * t, 68964 m1 = [x1, y1], 68965 m2 = [x1 + hx * s1, y1 - hy * c1], 68966 m3 = [x2 + hx * s2, y2 - hy * c2], 68967 m4 = [x2, y2]; 68968 m2[0] = 2 * m1[0] - m2[0]; 68969 m2[1] = 2 * m1[1] - m2[1]; 68970 if (recursive) { 68971 return [m2, m3, m4].concat(res); 68972 } else { 68973 res = [m2, m3, m4] 68974 .concat(res) 68975 .join() 68976 .split(','); 68977 var newres = []; 68978 for (var i = 0, ii = res.length; i < ii; i++) { 68979 newres[i] = 68980 i % 2 68981 ? rotate(res[i - 1], res[i], rad).y 68982 : rotate(res[i], res[i + 1], rad).x; 68983 } 68984 return newres; 68985 } 68986} 68987 68988// http://schepers.cc/getting-to-the-point 68989function catmullRom2bezier(crp, z) { 68990 var d = []; 68991 for (var i = 0, iLen = crp.length; iLen - 2 * !z > i; i += 2) { 68992 var p = [ 68993 { 68994 x: +crp[i - 2], 68995 y: +crp[i - 1] 68996 }, 68997 { 68998 x: +crp[i], 68999 y: +crp[i + 1] 69000 }, 69001 { 69002 x: +crp[i + 2], 69003 y: +crp[i + 3] 69004 }, 69005 { 69006 x: +crp[i + 4], 69007 y: +crp[i + 5] 69008 } 69009 ]; 69010 if (z) { 69011 if (!i) { 69012 p[0] = { 69013 x: +crp[iLen - 2], 69014 y: +crp[iLen - 1] 69015 }; 69016 } else if (iLen - 4 === i) { 69017 p[3] = { 69018 x: +crp[0], 69019 y: +crp[1] 69020 }; 69021 } else if (iLen - 2 === i) { 69022 p[2] = { 69023 x: +crp[0], 69024 y: +crp[1] 69025 }; 69026 p[3] = { 69027 x: +crp[2], 69028 y: +crp[3] 69029 }; 69030 } 69031 } else { 69032 if (iLen - 4 === i) { 69033 p[3] = p[2]; 69034 } else if (!i) { 69035 p[0] = { 69036 x: +crp[i], 69037 y: +crp[i + 1] 69038 }; 69039 } 69040 } 69041 d.push([ 69042 'C', 69043 (-p[0].x + 6 * p[1].x + p[2].x) / 6, 69044 (-p[0].y + 6 * p[1].y + p[2].y) / 6, 69045 (p[1].x + 6 * p[2].x - p[3].x) / 6, 69046 (p[1].y + 6 * p[2].y - p[3].y) / 6, 69047 p[2].x, 69048 p[2].y 69049 ]); 69050 } 69051 69052 return d; 69053} 69054 69055function l2c(x1, y1, x2, y2) { 69056 return [x1, y1, x2, y2, x2, y2]; 69057} 69058 69059function q2c(x1, y1, ax, ay, x2, y2) { 69060 var _13 = 1 / 3, 69061 _23 = 2 / 3; 69062 return [ 69063 _13 * x1 + _23 * ax, 69064 _13 * y1 + _23 * ay, 69065 _13 * x2 + _23 * ax, 69066 _13 * y2 + _23 * ay, 69067 x2, 69068 y2 69069 ]; 69070} 69071 69072function bezlen(x1, y1, x2, y2, x3, y3, x4, y4, z) { 69073 if (z == null) { 69074 z = 1; 69075 } 69076 z = z > 1 ? 1 : z < 0 ? 0 : z; 69077 var z2 = z / 2; 69078 var n = 12; 69079 var Tvalues = [ 69080 -0.1252, 69081 0.1252, 69082 -0.3678, 69083 0.3678, 69084 -0.5873, 69085 0.5873, 69086 -0.7699, 69087 0.7699, 69088 -0.9041, 69089 0.9041, 69090 -0.9816, 69091 0.9816 69092 ]; 69093 69094 var sum = 0; 69095 var Cvalues = [ 69096 0.2491, 69097 0.2491, 69098 0.2335, 69099 0.2335, 69100 0.2032, 69101 0.2032, 69102 0.1601, 69103 0.1601, 69104 0.1069, 69105 0.1069, 69106 0.0472, 69107 0.0472 69108 ]; 69109 69110 for (var i = 0; i < n; i++) { 69111 var ct = z2 * Tvalues[i] + z2, 69112 xbase = base3(ct, x1, x2, x3, x4), 69113 ybase = base3(ct, y1, y2, y3, y4), 69114 comb = xbase * xbase + ybase * ybase; 69115 sum += Cvalues[i] * Math.sqrt(comb); 69116 } 69117 return z2 * sum; 69118} 69119 69120function getTatLen(x1, y1, x2, y2, x3, y3, x4, y4, ll) { 69121 if (ll < 0 || bezlen(x1, y1, x2, y2, x3, y3, x4, y4) < ll) { 69122 return; 69123 } 69124 var t = 1, 69125 step = t / 2, 69126 t2 = t - step, 69127 l, 69128 e = 0.01; 69129 l = bezlen(x1, y1, x2, y2, x3, y3, x4, y4, t2); 69130 while (Math.abs(l - ll) > e) { 69131 step /= 2; 69132 t2 += (l < ll ? 1 : -1) * step; 69133 l = bezlen(x1, y1, x2, y2, x3, y3, x4, y4, t2); 69134 } 69135 return t2; 69136} 69137 69138function base3(t, p1, p2, p3, p4) { 69139 var t1 = -3 * p1 + 9 * p2 - 9 * p3 + 3 * p4, 69140 t2 = t * t1 + 6 * p1 - 12 * p2 + 6 * p3; 69141 return t * t2 - 3 * p1 + 3 * p2; 69142} 69143 69144function cacheKey() { 69145 var hash = ''; 69146 for (var i = arguments.length - 1; i >= 0; --i) { 69147 var v = arguments[i]; 69148 hash += v === Object(v) ? JSON.stringify(v) : v; 69149 } 69150 return hash; 69151} 69152 69153module.exports = p5; 69154 69155},{"../core/constants":21,"../core/core":22}],59:[function(_dereq_,module,exports){ 69156/** 69157 * @module Data 69158 * @submodule Array Functions 69159 * @for p5 69160 * @requires core 69161 */ 69162 69163'use strict'; 69164 69165var p5 = _dereq_('../core/core'); 69166 69167/** 69168 * Adds a value to the end of an array. Extends the length of 69169 * the array by one. Maps to Array.push(). 69170 * 69171 * @method append 69172 * @deprecated Use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push">array.push(value)</a> instead. 69173 * @param {Array} array Array to append 69174 * @param {any} value to be added to the Array 69175 * @example 69176 * <div class='norender'><code> 69177 * function setup() { 69178 * var myArray = ['Mango', 'Apple', 'Papaya']; 69179 * print(myArray); // ['Mango', 'Apple', 'Papaya'] 69180 * 69181 * append(myArray, 'Peach'); 69182 * print(myArray); // ['Mango', 'Apple', 'Papaya', 'Peach'] 69183 * } 69184 * </code></div> 69185 */ 69186p5.prototype.append = function(array, value) { 69187 array.push(value); 69188 return array; 69189}; 69190 69191/** 69192 * Copies an array (or part of an array) to another array. The src array is 69193 * copied to the dst array, beginning at the position specified by 69194 * srcPosition and into the position specified by dstPosition. The number of 69195 * elements to copy is determined by length. Note that copying values 69196 * overwrites existing values in the destination array. To append values 69197 * instead of overwriting them, use concat(). 69198 * <br><br> 69199 * The simplified version with only two arguments, arrayCopy(src, dst), 69200 * copies an entire array to another of the same size. It is equivalent to 69201 * arrayCopy(src, 0, dst, 0, src.length). 69202 * <br><br> 69203 * Using this function is far more efficient for copying array data than 69204 * iterating through a for() loop and copying each element individually. 69205 * 69206 * @method arrayCopy 69207 * @deprecated 69208 * @param {Array} src the source Array 69209 * @param {Integer} srcPosition starting position in the source Array 69210 * @param {Array} dst the destination Array 69211 * @param {Integer} dstPosition starting position in the destination Array 69212 * @param {Integer} length number of Array elements to be copied 69213 * 69214 * @example 69215 * <div class='norender'><code> 69216 * var src = ['A', 'B', 'C']; 69217 * var dst = [1, 2, 3]; 69218 * var srcPosition = 1; 69219 * var dstPosition = 0; 69220 * var length = 2; 69221 * 69222 * print(src); // ['A', 'B', 'C'] 69223 * print(dst); // [ 1 , 2 , 3 ] 69224 * 69225 * arrayCopy(src, srcPosition, dst, dstPosition, length); 69226 * print(dst); // ['B', 'C', 3] 69227 * </code></div> 69228 */ 69229/** 69230 * @method arrayCopy 69231 * @deprecated Use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin">arr1.copyWithin(arr2)</a> instead. 69232 * @param {Array} src 69233 * @param {Array} dst 69234 * @param {Integer} [length] 69235 */ 69236p5.prototype.arrayCopy = function(src, srcPosition, dst, dstPosition, length) { 69237 // the index to begin splicing from dst array 69238 var start; 69239 var end; 69240 69241 if (typeof length !== 'undefined') { 69242 end = Math.min(length, src.length); 69243 start = dstPosition;
69244 src = src.slice(srcPosition, end + srcPosition); 69245 } else { 69246 if (typeof dst !== 'undefined') { 69247 // src, dst, length 69248 // rename so we don't get confused 69249 end = dst; 69250 end = Math.min(end, src.length); 69251 } else { 69252 // src, dst 69253 end = src.length; 69254 } 69255 69256 start = 0; 69257 // rename so we don't get confused 69258 dst = srcPosition; 69259 src = src.slice(0, end); 69260 } 69261 69262 // Since we are not returning the array and JavaScript is pass by reference 69263 // we must modify the actual values of the array 69264 // instead of reassigning arrays 69265 Array.prototype.splice.apply(dst, [start, end].concat(src)); 69266}; 69267 69268/** 69269 * Concatenates two arrays, maps to Array.concat(). Does not modify the 69270 * input arrays. 69271 * 69272 * @method concat 69273 * @deprecated Use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat">arr1.concat(arr2)</a> instead. 69274 * @param {Array} a first Array to concatenate 69275 * @param {Array} b second Array to concatenate 69276 * @return {Array} concatenated array 69277 * 69278 * @example 69279 * <div class = 'norender'><code> 69280 * function setup() { 69281 * var arr1 = ['A', 'B', 'C']; 69282 * var arr2 = [1, 2, 3]; 69283 * 69284 * print(arr1); // ['A','B','C'] 69285 * print(arr2); // [1,2,3] 69286 * 69287 * var arr3 = concat(arr1, arr2); 69288 * 69289 * print(arr1); // ['A','B','C'] 69290 * print(arr2); // [1, 2, 3] 69291 * print(arr3); // ['A','B','C', 1, 2, 3] 69292 * } 69293 * </code></div> 69294 */ 69295p5.prototype.concat = function(list0, list1) { 69296 return list0.concat(list1); 69297}; 69298 69299/** 69300 * Reverses the order of an array, maps to Array.reverse() 69301 * 69302 * @method reverse 69303 * @deprecated Use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse">array.reverse()</a> instead. 69304 * @param {Array} list Array to reverse 69305 * @example 69306 * <div class='norender'><code> 69307 * function setup() { 69308 * var myArray = ['A', 'B', 'C']; 69309 * print(myArray); // ['A','B','C'] 69310 * 69311 * reverse(myArray); 69312 * print(myArray); // ['C','B','A'] 69313 * } 69314 * </code></div> 69315 */ 69316p5.prototype.reverse = function(list) { 69317 return list.reverse(); 69318}; 69319 69320/** 69321 * Decreases an array by one element and returns the shortened array, 69322 * maps to Array.pop(). 69323 * 69324 * @method shorten 69325 * @deprecated Use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/pop">array.pop()</a> instead. 69326 * @param {Array} list Array to shorten 69327 * @return {Array} shortened Array 69328 * @example 69329 * <div class = 'norender'><code> 69330 * function setup() { 69331 * var myArray = ['A', 'B', 'C']; 69332 * print(myArray); // ['A', 'B', 'C'] 69333 * var newArray = shorten(myArray); 69334 * print(myArray); // ['A','B','C'] 69335 * print(newArray); // ['A','B'] 69336 * } 69337 * </code></div> 69338 */ 69339p5.prototype.shorten = function(list) { 69340 list.pop(); 69341 return list; 69342}; 69343 69344/** 69345 * Randomizes the order of the elements of an array. Implements 69346 * <a href='http://Bost.Ocks.org/mike/shuffle/' target=_blank> 69347 * Fisher-Yates Shuffle Algorithm</a>. 69348 * 69349 * @method shuffle 69350 * @deprecated See <a href="https://stackoverflow.com/questions/6274339/how-can-i-shuffle-an-array">shuffling an array with JS</a> instead. 69351 * @param {Array} array Array to shuffle 69352 * @param {Boolean} [bool] modify passed array 69353 * @return {Array} shuffled Array 69354 * @example 69355 * <div><code> 69356 * function setup() { 69357 * var regularArr = ['ABC', 'def', createVector(), TAU, Math.E]; 69358 * print(regularArr); 69359 * shuffle(regularArr, true); // force modifications to passed array 69360 * print(regularArr); 69361 * 69362 * // By default shuffle() returns a shuffled cloned array: 69363 * var newArr = shuffle(regularArr); 69364 * print(regularArr); 69365 * print(newArr); 69366 * } 69367 * </code></div> 69368 */ 69369p5.prototype.shuffle = function(arr, bool) { 69370 var isView = ArrayBuffer && ArrayBuffer.isView && ArrayBuffer.isView(arr); 69371 arr = bool || isView ? arr : arr.slice(); 69372 69373 var rnd, 69374 tmp, 69375 idx = arr.length; 69376 while (idx > 1) { 69377 rnd = (Math.random() * idx) | 0; 69378 69379 tmp = arr[--idx]; 69380 arr[idx] = arr[rnd]; 69381 arr[rnd] = tmp; 69382 } 69383 69384 return arr; 69385}; 69386 69387/** 69388 * Sorts an array of numbers from smallest to largest, or puts an array of 69389 * words in alphabetical order. The original array is not modified; a 69390 * re-ordered array is returned. The count parameter states the number of 69391 * elements to sort. For example, if there are 12 elements in an array and 69392 * count is set to 5, only the first 5 elements in the array will be sorted. 69393 * 69394 * @method sort 69395 * @deprecated Use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort">array.sort()</a> instead. 69396 * @param {Array} list Array to sort 69397 * @param {Integer} [count] number of elements to sort, starting from 0 69398 * 69399 * @example 69400 * <div class = 'norender'><code> 69401 * function setup() { 69402 * var words = ['banana', 'apple', 'pear', 'lime']; 69403 * print(words); // ['banana', 'apple', 'pear', 'lime'] 69404 * var count = 4; // length of array 69405 * 69406 * words = sort(words, count); 69407 * print(words); // ['apple', 'banana', 'lime', 'pear'] 69408 * } 69409 * </code></div> 69410 * <div class = 'norender'><code> 69411 * function setup() { 69412 * var numbers = [2, 6, 1, 5, 14, 9, 8, 12]; 69413 * print(numbers); // [2, 6, 1, 5, 14, 9, 8, 12] 69414 * var count = 5; // Less than the length of the array 69415 * 69416 * numbers = sort(numbers, count); 69417 * print(numbers); // [1,2,5,6,14,9,8,12] 69418 * } 69419 * </code></div> 69420 */ 69421p5.prototype.sort = function(list, count) { 69422 var arr = count ? list.slice(0, Math.min(count, list.length)) : list; 69423 var rest = count ? list.slice(Math.min(count, list.length)) : []; 69424 if (typeof arr[0] === 'string') { 69425 arr = arr.sort(); 69426 } else { 69427 arr = arr.sort(function(a, b) { 69428 return a - b; 69429 }); 69430 } 69431 return arr.concat(rest); 69432}; 69433 69434/** 69435 * Inserts a value or an array of values into an existing array. The first 69436 * parameter specifies the initial array to be modified, and the second 69437 * parameter defines the data to be inserted. The third parameter is an index 69438 * value which specifies the array position from which to insert data. 69439 * (Remember that array index numbering starts at zero, so the first position 69440 * is 0, the second position is 1, and so on.) 69441 * 69442 * @method splice 69443 * @deprecated Use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice">array.splice()</a> instead. 69444 * @param {Array} list Array to splice into 69445 * @param {any} value value to be spliced in 69446 * @param {Integer} position in the array from which to insert data 69447 * 69448 * @example 69449 * <div class = 'norender'><code> 69450 * function setup() { 69451 * var myArray = [0, 1, 2, 3, 4]; 69452 * var insArray = ['A', 'B', 'C']; 69453 * print(myArray); // [0, 1, 2, 3, 4] 69454 * print(insArray); // ['A','B','C'] 69455 * 69456 * splice(myArray, insArray, 3); 69457 * print(myArray); // [0,1,2,'A','B','C',3,4] 69458 * } 69459 * </code></div> 69460 */ 69461p5.prototype.splice = function(list, value, index) { 69462 // note that splice returns spliced elements and not an array 69463 Array.prototype.splice.apply(list, [index, 0].concat(value)); 69464 69465 return list; 69466}; 69467 69468/** 69469 * Extracts an array of elements from an existing array. The list parameter 69470 * defines the array from which the elements will be copied, and the start 69471 * and count parameters specify which elements to extract. If no count is 69472 * given, elements will be extracted from the start to the end of the array. 69473 * When specifying the start, remember that the first array element is 0. 69474 * This function does not change the source array. 69475 * 69476 * @method subset 69477 * @deprecated Use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice">array.slice()</a> instead. 69478 * @param {Array} list Array to extract from 69479 * @param {Integer} start position to begin 69480 * @param {Integer} [count] number of values to extract 69481 * @return {Array} Array of extracted elements 69482 * 69483 * @example 69484 * <div class = 'norender'><code> 69485 * function setup() { 69486 * var myArray = [1, 2, 3, 4, 5]; 69487 * print(myArray); // [1, 2, 3, 4, 5] 69488 * 69489 * var sub1 = subset(myArray, 0, 3); 69490 * var sub2 = subset(myArray, 2, 2); 69491 * print(sub1); // [1,2,3] 69492 * print(sub2); // [3,4] 69493 * } 69494 * </code></div> 69495 */ 69496p5.prototype.subset = function(list, start, count) { 69497 if (typeof count !== 'undefined') { 69498 return list.slice(start, start + count); 69499 } else { 69500 return list.slice(start, list.length); 69501 } 69502}; 69503 69504module.exports = p5; 69505 69506},{"../core/core":22}],60:[function(_dereq_,module,exports){ 69507/** 69508 * @module Data 69509 * @submodule Conversion 69510 * @for p5 69511 * @requires core 69512 */ 69513 69514'use strict'; 69515 69516var p5 = _dereq_('../core/core'); 69517 69518/** 69519 * Converts a string to its floating point representation. The contents of a 69520 * string must resemble a number, or NaN (not a number) will be returned. 69521 * For example, float("1234.56") evaluates to 1234.56, but float("giraffe") 69522 * will return NaN. 69523 * 69524 * When an array of values is passed in, then an array of floats of the same 69525 * length is returned. 69526 * 69527 * @method float 69528 * @param {String} str float string to parse 69529 * @return {Number}
69529 floating point representation of string 69530 * @example 69531 * <div><code> 69532 * var str = '20'; 69533 * var diameter = float(str); 69534 * ellipse(width / 2, height / 2, diameter, diameter); 69535 * </code></div> 69536 * 69537 * @alt 69538 * 20 by 20 white ellipse in the center of the canvas 69539 * 69540 */ 69541p5.prototype.float = function(str) { 69542 if (str instanceof Array) { 69543 return str.map(parseFloat); 69544 } 69545 return parseFloat(str); 69546}; 69547 69548/** 69549 * Converts a boolean, string, or float to its integer representation. 69550 * When an array of values is passed in, then an int array of the same length 69551 * is returned. 69552 * 69553 * @method int 69554 * @param {String|Boolean|Number} n value to parse 69555 * @param {Integer} [radix] the radix to convert to (default: 10) 69556 * @return {Number} integer representation of value 69557 * 69558 * @example 69559 * <div class='norender'><code> 69560 * print(int('10')); // 10 69561 * print(int(10.31)); // 10 69562 * print(int(-10)); // -10 69563 * print(int(true)); // 1 69564 * print(int(false)); // 0 69565 * print(int([false, true, '10.3', 9.8])); // [0, 1, 10, 9] 69566 * </code></div> 69567 */ 69568/** 69569 * @method int 69570 * @param {Array} ns values to parse 69571 * @return {Number[]} integer representation of values 69572 */ 69573p5.prototype.int = function(n, radix) { 69574 radix = radix || 10; 69575 if (typeof n === 'string') { 69576 return parseInt(n, radix); 69577 } else if (typeof n === 'number') { 69578 return n | 0; 69579 } else if (typeof n === 'boolean') { 69580 return n ? 1 : 0; 69581 } else if (n instanceof Array) { 69582 return n.map(function(n) { 69583 return p5.prototype.int(n, radix); 69584 }); 69585 } 69586}; 69587 69588/** 69589 * Converts a boolean, string or number to its string representation. 69590 * When an array of values is passed in, then an array of strings of the same 69591 * length is returned. 69592 * 69593 * @method str 69594 * @param {String|Boolean|Number|Array} n value to parse 69595 * @return {String} string representation of value 69596 * @example 69597 * <div class='norender'><code> 69598 * print(str('10')); // "10" 69599 * print(str(10.31)); // "10.31" 69600 * print(str(-10)); // "-10" 69601 * print(str(true)); // "true" 69602 * print(str(false)); // "false" 69603 * print(str([true, '10.3', 9.8])); // [ "true", "10.3", "9.8" ] 69604 * </code></div> 69605 */ 69606p5.prototype.str = function(n) { 69607 if (n instanceof Array) { 69608 return n.map(p5.prototype.str); 69609 } else { 69610 return String(n); 69611 } 69612}; 69613 69614/** 69615 * Converts a number or string to its boolean representation. 69616 * For a number, any non-zero value (positive or negative) evaluates to true, 69617 * while zero evaluates to false. For a string, the value "true" evaluates to 69618 * true, while any other value evaluates to false. When an array of number or 69619 * string values is passed in, then a array of booleans of the same length is 69620 * returned. 69621 * 69622 * @method boolean 69623 * @param {String|Boolean|Number|Array} n value to parse 69624 * @return {Boolean} boolean representation of value 69625 * @example 69626 * <div class='norender'><code> 69627 * print(boolean(0)); // false 69628 * print(boolean(1)); // true 69629 * print(boolean('true')); // true 69630 * print(boolean('abcd')); // false 69631 * print(boolean([0, 12, 'true'])); // [false, true, false] 69632 * </code></div> 69633 */ 69634p5.prototype.boolean = function(n) { 69635 if (typeof n === 'number') { 69636 return n !== 0; 69637 } else if (typeof n === 'string') { 69638 return n.toLowerCase() === 'true'; 69639 } else if (typeof n === 'boolean') { 69640 return n; 69641 } else if (n instanceof Array) { 69642 return n.map(p5.prototype.boolean); 69643 } 69644}; 69645 69646/** 69647 * Converts a number, string representation of a number, or boolean to its byte 69648 * representation. A byte can be only a whole number between -128 and 127, so 69649 * when a value outside of this range is converted, it wraps around to the 69650 * corresponding byte representation. When an array of number, string or boolean 69651 * values is passed in, then an array of bytes the same length is returned. 69652 * 69653 * @method byte 69654 * @param {String|Boolean|Number} n value to parse 69655 * @return {Number} byte representation of value 69656 * 69657 * @example 69658 * <div class='norender'><code> 69659 * print(byte(127)); // 127 69660 * print(byte(128)); // -128 69661 * print(byte(23.4)); // 23 69662 * print(byte('23.4')); // 23 69663 * print(byte('hello')); // NaN 69664 * print(byte(true)); // 1 69665 * print(byte([0, 255, '100'])); // [0, -1, 100] 69666 * </code></div> 69667 */ 69668/** 69669 * @method byte 69670 * @param {Array} ns values to parse 69671 * @return {Number[]} array of byte representation of values 69672 */ 69673p5.prototype.byte = function(n) { 69674 var nn = p5.prototype.int(n, 10); 69675 if (typeof nn === 'number') { 69676 return (nn + 128) % 256 - 128; 69677 } else if (nn instanceof Array) { 69678 return nn.map(p5.prototype.byte); 69679 } 69680}; 69681 69682/** 69683 * Converts a number or string to its corresponding single-character 69684 * string representation. If a string parameter is provided, it is first 69685 * parsed as an integer and then translated into a single-character string. 69686 * When an array of number or string values is passed in, then an array of 69687 * single-character strings of the same length is returned. 69688 * 69689 * @method char 69690 * @param {String|Number} n value to parse 69691 * @return {String}
69691 string representation of value 69692 * 69693 * @example 69694 * <div class='norender'><code> 69695 * print(char(65)); // "A" 69696 * print(char('65')); // "A" 69697 * print(char([65, 66, 67])); // [ "A", "B", "C" ] 69698 * print(join(char([65, 66, 67]), '')); // "ABC" 69699 * </code></div> 69700 */ 69701/** 69702 * @method char 69703 * @param {Array} ns values to parse 69704 * @return {String[]} array of string representation of values 69705 */ 69706p5.prototype.char = function(n) { 69707 if (typeof n === 'number' && !isNaN(n)) { 69708 return String.fromCharCode(n); 69709 } else if (n instanceof Array) { 69710 return n.map(p5.prototype.char); 69711 } else if (typeof n === 'string') { 69712 return p5.prototype.char(parseInt(n, 10)); 69713 } 69714}; 69715 69716/** 69717 * Converts a single-character string to its corresponding integer 69718 * representation. When an array of single-character string values is passed 69719 * in, then an array of integers of the same length is returned. 69720 * 69721 * @method unchar 69722 * @param {String} n value to parse 69723 * @return {Number} integer representation of value 69724 * 69725 * @example 69726 * <div class='norender'><code> 69727 * print(unchar('A')); // 65 69728 * print(unchar(['A', 'B', 'C'])); // [ 65, 66, 67 ] 69729 * print(unchar(split('ABC', ''))); // [ 65, 66, 67 ] 69730 * </code></div> 69731 */ 69732/** 69733 * @method unchar 69734 * @param {Array} ns values to parse 69735 * @return {Number[]} integer representation of values 69736 */ 69737p5.prototype.unchar = function(n) { 69738 if (typeof n === 'string' && n.length === 1) { 69739 return n.charCodeAt(0); 69740 } else if (n instanceof Array) { 69741 return n.map(p5.prototype.unchar); 69742 } 69743}; 69744 69745/** 69746 * Converts a number to a string in its equivalent hexadecimal notation. If a 69747 * second parameter is passed, it is used to set the number of characters to 69748 * generate in the hexadecimal notation. When an array is passed in, an 69749 * array of strings in hexadecimal notation of the same length is returned. 69750 * 69751 * @method hex 69752 * @param {Number} n value to parse 69753 * @param {Number} [digits] 69754 * @return {String} hexadecimal string representation of value 69755 * 69756 * @example 69757 * <div class='norender'><code> 69758 * print(hex(255)); // "000000FF" 69759 * print(hex(255, 6)); // "0000FF" 69760 * print(hex([0, 127, 255], 6)); // [ "000000", "00007F", "0000FF" ] 69761 * </code></div> 69762 */ 69763/** 69764 * @method hex 69765 * @param {Number[]} ns array of values to parse 69766 * @param {Number} [digits] 69767 * @return {String[]} hexadecimal string representation of values 69768 */ 69769p5.prototype.hex = function(n, digits) { 69770 digits = digits === undefined || digits === null ? (digits = 8) : digits; 69771 if (n instanceof Array) { 69772 return n.map(function(n) { 69773 return p5.prototype.hex(n, digits); 69774 }); 69775 } else if (typeof n === 'number') { 69776 if (n < 0) { 69777 n = 0xffffffff + n + 1; 69778 } 69779 var hex = Number(n) 69780 .toString(16) 69781 .toUpperCase(); 69782 while (hex.length < digits) { 69783 hex = '0' + hex; 69784 } 69785 if (hex.length >= digits) { 69786 hex = hex.substring(hex.length - digits, hex.length); 69787 } 69788 return hex; 69789 } 69790}; 69791 69792/** 69793 * Converts a string representation of a hexadecimal number to its equivalent 69794 * integer value. When an array of strings in hexadecimal notation is passed 69795 * in, an array of integers of the same length is returned. 69796 * 69797 * @method unhex 69798 * @param {String} n value to parse 69799 * @return {Number} integer representation of hexadecimal value 69800 * 69801 * @example 69802 * <div class='norender'><code> 69803 * print(unhex('A')); // 10 69804 * print(unhex('FF')); // 255 69805 * print(unhex(['FF', 'AA', '00'])); // [ 255, 170, 0 ] 69806 * </code></div> 69807 */ 69808/** 69809 * @method unhex 69810 * @param {Array} ns values to parse 69811 * @return {Number[]} integer representations of hexadecimal value 69812 */ 69813p5.prototype.unhex = function(n) { 69814 if (n instanceof Array) { 69815 return n.map(p5.prototype.unhex); 69816 } else { 69817 return parseInt('0x' + n, 16); 69818 } 69819}; 69820 69821module.exports = p5; 69822 69823},{"../core/core":22}],61:[function(_dereq_,module,exports){ 69824/** 69825 * @module Data 69826 * @submodule String Functions 69827 * @for p5 69828 * @requires core 69829 */ 69830 69831'use strict'; 69832 69833var p5 = _dereq_('../core/core'); 69834_dereq_('../core/error_helpers'); 69835 69836//return p5; //LM is this a mistake? 69837 69838/** 69839 * Combines an array of Strings into one String, each separated by the 69840 * character(s) used for the separator parameter. To join arrays of ints or 69841 * floats, it's necessary to first convert them to Strings using nf() or
69842 * nfs(). 69843 * 69844 * @method join 69845 * @param {Array} list array of Strings to be joined 69846 * @param {String} separator String to be placed between each item 69847 * @return {String} joined String 69848 * @example 69849 * <div> 69850 * <code> 69851 * var array = ['Hello', 'world!']; 69852 * var separator = ' '; 69853 * var message = join(array, separator); 69854 * text(message, 5, 50); 69855 * </code> 69856 * </div> 69857 * 69858 * @alt 69859 * "hello world!" displayed middle left of canvas. 69860 * 69861 */ 69862p5.prototype.join = function(list, separator) { 69863 p5._validateParameters('join', arguments); 69864 return list.join(separator); 69865}; 69866 69867/** 69868 * This function is used to apply a regular expression to a piece of text, 69869 * and return matching groups (elements found inside parentheses) as a 69870 * String array. If there are no matches, a null value will be returned. 69871 * If no groups are specified in the regular expression, but the sequence 69872 * matches, an array of length 1 (with the matched text as the first element 69873 * of the array) will be returned. 69874 * <br><br> 69875 * To use the function, first check to see if the result is null. If the 69876 * result is null, then the sequence did not match at all. If the sequence 69877 * did match, an array is returned. 69878 * <br><br> 69879 * If there are groups (specified by sets of parentheses) in the regular 69880 * expression, then the contents of each will be returned in the array. 69881 * Element [0] of a regular expression match returns the entire matching 69882 * string, and the match groups start at element [1] (the first group is [1], 69883 * the second [2], and so on). 69884 * 69885 * @method match 69886 * @param {String} str the String to be searched 69887 * @param {String} regexp the regexp to be used for matching 69888 * @return {String[]} Array of Strings found 69889 * @example 69890 * <div> 69891 * <code> 69892 * var string = 'Hello p5js*!'; 69893 * var regexp = 'p5js\\*'; 69894 * var m = match(string, regexp); 69895 * text(m, 5, 50); 69896 * </code> 69897 * </div> 69898 * 69899 * @alt 69900 * "p5js*" displayed middle left of canvas. 69901 * 69902 */ 69903p5.prototype.match = function(str, reg) { 69904 p5._validateParameters('match', arguments); 69905 return str.match(reg); 69906}; 69907 69908/** 69909 * This function is used to apply a regular expression to a piece of text, 69910 * and return a list of matching groups (elements found inside parentheses) 69911 * as a two-dimensional String array. If there are no matches, a null value 69912 * will be returned. If no groups are specified in the regular expression, 69913 * but the sequence matches, a two dimensional array is still returned, but 69914 * the second dimension is only of length one. 69915 * <br><br> 69916 * To use the function, first check to see if the result is null. If the 69917 * result is null, then the sequence did not match at all. If the sequence 69918 * did match, a 2D array is returned. 69919 * <br><br> 69920 * If there are groups (specified by sets of parentheses) in the regular 69921 * expression, then the contents of each will be returned in the array. 69922 * Assuming a loop with counter variable i, element [i][0] of a regular 69923 * expression match returns the entire matching string, and the match groups 69924 * start at element [i][1] (the first group is [i][1], the second [i][2], 69925 * and so on). 69926 * 69927 * @method matchAll 69928 * @param {String} str the String to be searched 69929 * @param {String} regexp the regexp to be used for matching 69930 * @return {String[]} 2d Array of Strings found 69931 * @example 69932 * <div class="norender"> 69933 * <code> 69934 * var string = 'Hello p5js*! Hello world!'; 69935 * var regexp = 'Hello'; 69936 * matchAll(string, regexp); 69937 * </code> 69938 * </div> 69939 */ 69940p5.prototype.matchAll = function(str, reg) { 69941 p5._validateParameters('matchAll', arguments); 69942 var re = new RegExp(reg, 'g'); 69943 var match = re.exec(str); 69944 var matches = []; 69945 while (match !== null) { 69946 matches.push(match); 69947 // matched text: match[0] 69948 // match start: match.index 69949 // capturing group n: match[n] 69950 match = re.exec(str); 69951 } 69952 return matches; 69953}; 69954 69955/** 69956 * Utility function for formatting numbers into strings. There are two 69957 * versions: one for formatting floats, and one for formatting ints. 69958 * The values for the digits, left, and right parameters should always 69959 * be positive integers. 69960 * 69961 * @method nf 69962 * @param {Number|String} num the Number to format 69963 * @param {Integer|String} [left] number of digits to the left of the 69964 * decimal point 69965 * @param {Integer|String} [right] number of digits to the right of the 69966 * decimal point 69967 * @return {String} formatted String 69968 * 69969 * @example 69970 * <div> 69971 * <code> 69972 * function setup() { 69973 * background(200); 69974 * var num = 112.53106115; 69975 * 69976 * noStroke(); 69977 * fill(0); 69978 * textSize(14); 69979 * // Draw formatted numbers 69980 * text(nf(num, 5, 2), 10, 20); 69981 * 69982 * text(nf(num, 4, 3), 10, 55); 69983 * 69984 * text(nf(num, 3, 6), 10, 85); 69985 * 69986 * // Draw dividing lines 69987 * stroke(120);
69988 * line(0, 30, width, 30); 69989 * line(0, 65, width, 65); 69990 * } 69991 * </code> 69992 * </div> 69993 * 69994 * @alt 69995 * "0011253" top left, "0112.531" mid left, "112.531061" bottom left canvas 69996 */ 69997/** 69998 * @method nf 69999 * @param {Array} nums the Numbers to format 70000 * @param {Integer|String} [left] 70001 * @param {Integer|String} [right] 70002 * @return {String[]} formatted Strings 70003 */ 70004p5.prototype.nf = function(nums, left, right) { 70005 p5._validateParameters('nf', arguments); 70006 if (nums instanceof Array) { 70007 return nums.map(function(x) { 70008 return doNf(x, left, right); 70009 }); 70010 } else { 70011 var typeOfFirst = Object.prototype.toString.call(nums); 70012 if (typeOfFirst === '[object Arguments]') { 70013 if (nums.length === 3) { 70014 return this.nf(nums[0], nums[1], nums[2]); 70015 } else if (nums.length === 2) { 70016 return this.nf(nums[0], nums[1]); 70017 } else { 70018 return this.nf(nums[0]); 70019 } 70020 } else { 70021 return doNf(nums, left, right); 70022 } 70023 } 70024}; 70025 70026function doNf(num, left, right) { 70027 var neg = num < 0; 70028 var n = neg ? num.toString().substring(1) : num.toString(); 70029 var decimalInd = n.indexOf('.'); 70030 var intPart = decimalInd !== -1 ? n.substring(0, decimalInd) : n; 70031 var decPart = decimalInd !== -1 ? n.substring(decimalInd + 1) : ''; 70032 var str = neg ? '-' : ''; 70033 if (typeof right !== 'undefined') { 70034 var decimal = ''; 70035 if (decimalInd !== -1 || right - decPart.length > 0) { 70036 decimal = '.'; 70037 } 70038 if (decPart.length > right) { 70039 decPart = decPart.substring(0, right); 70040 } 70041 for (var i = 0; i < left - intPart.length; i++) { 70042 str += '0'; 70043 } 70044 str += intPart; 70045 str += decimal; 70046 str += decPart; 70047 for (var j = 0; j < right - decPart.length; j++) { 70048 str += '0'; 70049 } 70050 return str; 70051 } else { 70052 for (var k = 0; k < Math.max(left - intPart.length, 0); k++) { 70053 str += '0'; 70054 } 70055 str += n; 70056 return str; 70057 } 70058} 70059 70060/** 70061 * Utility function for formatting numbers into strings and placing 70062 * appropriate commas to mark units of 1000. There are two versions: one 70063 * for formatting ints, and one for formatting an array of ints. The value 70064 * for the right parameter should always be a positive integer. 70065 * 70066 * @method nfc 70067 * @param {Number|String} num the Number to format 70068 * @param {Integer|String} [right] number of digits to the right of the 70069 * decimal point 70070 * @return {String} formatted String 70071 * 70072 * @example 70073 * <div> 70074 * <code> 70075 * function setup() { 70076 * background(200); 70077 * var num = 11253106.115; 70078 * var numArr = [1, 1, 2]; 70079 * 70080 * noStroke(); 70081 * fill(0); 70082 * textSize(12); 70083 * 70084 * // Draw formatted numbers 70085 * text(nfc(num, 4), 10, 30); 70086 * text(nfc(numArr, 2), 10, 80); 70087 * 70088 * // Draw dividing line 70089 * stroke(120); 70090 * line(0, 50, width, 50); 70091 * } 70092 * </code> 70093 * </div> 70094 * 70095 * @alt 70096 * "11,253,106.115" top middle and "1.00,1.00,2.00" displayed bottom mid 70097 */ 70098/** 70099 * @method nfc 70100 * @param {Array} nums the Numbers to format 70101 * @param {Integer|String} [right] 70102 * @return {String[]} formatted Strings 70103 */ 70104p5.prototype.nfc = function(num, right) { 70105 p5._validateParameters('nfc', arguments); 70106 if (num instanceof Array) { 70107 return num.map(function(x) { 70108 return doNfc(x, right); 70109 }); 70110 } else { 70111 return doNfc(num, right); 70112 } 70113}; 70114function doNfc(num, right) { 70115 num = num.toString(); 70116 var dec = num.indexOf('.'); 70117 var rem = dec !== -1 ? num.substring(dec) : ''; 70118 var n = dec !== -1 ? num.substring(0, dec) : num; 70119 n = n.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ','); 70120 if (right === 0) { 70121 rem = ''; 70122 } else if (typeof right !== 'undefined') { 70123 if (right > rem.length) { 70124 rem += dec === -1 ? '.' : ''; 70125 var len = right - rem.length + 1; 70126 for (var i = 0; i < len; i++) { 70127 rem += '0'; 70128 } 70129 } else { 70130 rem = rem.substring(0, right + 1); 70131 } 70132 } 70133 return n + rem; 70134} 70135 70136/** 70137 * Utility function for formatting numbers into strings. Similar to nf() but 70138 * puts a "+" in front of positive numbers and a "-" in front of negative 70139 * numbers. There are two versions: one for formatting floats, and one for 70140 * formatting ints. The values for left, and right parameters 70141 * should always be positive integers. 70142 * 70143 * @method nfp 70144 * @param {Number} num the Number to format 70145 * @param {Integer} [left] number of digits to the left of the decimal 70146 * point 70147 * @param {Integer} [right] number of digits to the right of the 70148 * decimal point 70149 * @return {String} formatted String 70150 * 70151 * @example 70152 * <div> 70153 * <code> 70154 * function setup() { 70155 * background(200); 70156 * var num1 = 11253106.115; 70157 * var num2 = -11253106.115; 70158 * 70159 * noStroke(); 70160 * fill(0); 70161 * textSize(12); 70162 * 70163 * // Draw formatted numbers 70164 * text(nfp(num1, 4, 2), 10, 30); 70165 * text(nfp(num2, 4, 2), 10, 80); 70166 * 70167 * // Draw dividing line 70168 * stroke(120); 70169 * line(0, 50, width, 50); 70170 * } 70171 * </code> 70172 * </div> 70173 * 70174 * @alt 70175 * "+11253106.11" top middle and "-11253106.11" displayed bottom middle 70176 */ 70177/** 70178 * @method nfp 70179 * @param {Number[]} nums the Numbers to format 70180 * @param {Integer} [left] 70181 * @param {Integer} [right] 70182 * @return {String[]} formatted Strings 70183 */ 70184p5.prototype.nfp = function() { 70185 p5._validateParameters('nfp', arguments); 70186 var nfRes = p5.prototype.nf.apply(this, arguments); 70187 if (nfRes instanceof Array) { 70188 return nfRes.map(addNfp); 70189 } else { 70190 return addNfp(nfRes); 70191 } 70192}; 70193 70194function addNfp(num) { 70195 return parseFloat(num) > 0 ? '+' + num.toString() : num.toString(); 70196} 70197 70198/** 70199 * Utility function for formatting numbers into strings. Similar to nf() but 70200 * puts a " " (space) in front of positive numbers and a "-" in front of 70201 * negative numbers. There are two versions: one for formatting floats, and 70202 * one for formatting ints. The values for the digits, left, and right 70203 * parameters should always be positive integers. 70204 * 70205 * @method nfs 70206 * @param {Number} num the Number to format 70207 * @param {Integer} [left] number of digits to the left of the decimal 70208 * point 70209 * @param {Integer} [right] number of digits to the right of the 70210 * decimal point 70211 * @return {String} formatted String 70212 * 70213 * @example 70214 * <div> 70215 * <code> 70216 * function setup() { 70217 * background(200); 70218 * var num1 = 11253106.115; 70219 * var num2 = -11253106.115; 70220 * 70221 * noStroke(); 70222 * fill(0); 70223 * textSize(12); 70224 * // Draw formatted numbers 70225 * text(nfs(num1, 4, 2), 10, 30); 70226 * 70227 * text(nfs(num2, 4, 2), 10, 80); 70228 * 70229 * // Draw dividing line 70230 * stroke(120); 70231 * line(0, 50, width, 50); 70232 * } 70233 * </code> 70234 * </div> 70235 * 70236 * @alt 70237 * "11253106.11" top middle and "-11253106.11" displayed bottom middle 70238 */ 70239/** 70240 * @method nfs 70241 * @param {Array} nums the Numbers to format 70242 * @param {Integer} [left] 70243 * @param {Integer} [right] 70244 * @return {String[]} formatted Strings 70245 */ 70246p5.prototype.nfs = function() { 70247 p5._validateParameters('nfs', arguments); 70248 var nfRes = p5.prototype.nf.apply(this, arguments); 70249 if (nfRes instanceof Array) { 70250 return nfRes.map(addNfs); 70251 } else { 70252 return addNfs(nfRes); 70253 } 70254}; 70255 70256function addNfs(num) { 70257 return parseFloat(num) > 0 ? ' ' + num.toString() : num.toString(); 70258} 70259 70260/** 70261 * The split() function maps to String.split(), it breaks a String into 70262 * pieces using a character or string as the delimiter. The delim parameter 70263 * specifies the character or characters that mark the boundaries between 70264 * each piece. A String[] array is returned that contains each of the pieces. 70265 * 70266 * The splitTokens() function works in a similar fashion, except that it 70267 * splits using a range of characters instead of a specific character or 70268 * sequence. 70269 * 70270 * @method split 70271 * @param {String} value the String to be split 70272 * @param {String} delim the String used to separate the data 70273 * @return {String[]} Array of Strings 70274 * @example 70275 * <div> 70276 * <code> 70277 * var names = 'Pat,Xio,Alex'; 70278 * var splitString = split(names, ',');
70279 * text(splitString[0], 5, 30); 70280 * text(splitString[1], 5, 50); 70281 * text(splitString[2], 5, 70); 70282 * </code> 70283 * </div> 70284 * 70285 * @alt 70286 * "pat" top left, "Xio" mid left and "Alex" displayed bottom left 70287 * 70288 */ 70289p5.prototype.split = function(str, delim) { 70290 p5._validateParameters('split', arguments); 70291 return str.split(delim); 70292}; 70293 70294/** 70295 * The splitTokens() function splits a String at one or many character 70296 * delimiters or "tokens." The delim parameter specifies the character or 70297 * characters to be used as a boundary. 70298 * <br><br> 70299 * If no delim characters are specified, any whitespace character is used to 70300 * split. Whitespace characters include tab (\t), line feed (\n), carriage 70301 * return (\r), form feed (\f), and space. 70302 * 70303 * @method splitTokens 70304 * @param {String} value the String to be split 70305 * @param {String} [delim] list of individual Strings that will be used as 70306 * separators 70307 * @return {String[]} Array of Strings 70308 * @example 70309 * <div class = "norender"> 70310 * <code> 70311 * function setup() { 70312 * var myStr = 'Mango, Banana, Lime'; 70313 * var myStrArr = splitTokens(myStr, ','); 70314 * 70315 * print(myStrArr); // prints : ["Mango"," Banana"," Lime"] 70316 * } 70317 * </code> 70318 * </div> 70319 */ 70320p5.prototype.splitTokens = function(value, delims) { 70321 p5._validateParameters('splitTokens', arguments); 70322 var d; 70323 if (typeof delims !== 'undefined') { 70324 var str = delims; 70325 var sqc = /\]/g.exec(str); 70326 var sqo = /\[/g.exec(str); 70327 if (sqo && sqc) { 70328 str = str.slice(0, sqc.index) + str.slice(sqc.index + 1); 70329 sqo = /\[/g.exec(str); 70330 str = str.slice(0, sqo.index) + str.slice(sqo.index + 1); 70331 d = new RegExp('[\\[' + str + '\\]]', 'g'); 70332 } else if (sqc) { 70333 str = str.slice(0, sqc.index) + str.slice(sqc.index + 1); 70334 d = new RegExp('[' + str + '\\]]', 'g'); 70335 } else if (sqo) { 70336 str = str.slice(0, sqo.index) + str.slice(sqo.index + 1); 70337 d = new RegExp('[' + str + '\\[]', 'g'); 70338 } else { 70339 d = new RegExp('[' + str + ']', 'g'); 70340 } 70341 } else { 70342 d = /\s/g; 70343 } 70344 return value.split(d).filter(function(n) { 70345 return n; 70346 }); 70347}; 70348 70349/** 70350 * Removes whitespace characters from the beginning and end of a String. In 70351 * addition to standard whitespace characters such as space, carriage return, 70352 * and tab, this function also removes the Unicode "nbsp" character. 70353 * 70354 * @method trim 70355 * @param {String} str a String to be trimmed 70356 * @return {String} a trimmed String 70357 * 70358 * @example 70359 * <div> 70360 * <code> 70361 * var string = trim(' No new lines\n '); 70362 * text(string + ' here', 2, 50); 70363 * </code> 70364 * </div> 70365 * 70366 * @alt 70367 * "No new lines here" displayed center canvas 70368 */ 70369/** 70370 * @method trim 70371 * @param {Array} strs an Array of Strings to be trimmed 70372 * @return {String[]} an Array of trimmed Strings 70373 */ 70374p5.prototype.trim = function(str) { 70375 p5._validateParameters('trim', arguments); 70376 if (str instanceof Array) { 70377 return str.map(this.trim); 70378 } else { 70379 return str.trim(); 70380 } 70381}; 70382 70383module.exports = p5; 70384 70385},{"../core/core":22,"../core/error_helpers":25}],62:[function(_dereq_,module,exports){ 70386/** 70387 * @module IO 70388 * @submodule Time & Date 70389 * @for p5 70390 * @requires core 70391 */ 70392 70393'use strict'; 70394 70395var p5 = _dereq_('../core/core'); 70396 70397/** 70398 * p5.js communicates with the clock on your computer. The day() function 70399 * returns the current day as a value from 1 - 31. 70400 * 70401 * @method day 70402 * @return {Integer} the current day 70403 * @example 70404 * <div> 70405 * <code> 70406 * var d = day(); 70407 * text('Current day: \n' + d, 5, 50); 70408 * </code> 70409 * </div> 70410 * 70411 * @alt 70412 * Current day is displayed 70413 * 70414 */ 70415p5.prototype.day = function() { 70416 return new Date().getDate(); 70417}; 70418 70419/** 70420 * p5.js communicates with the clock on your computer. The hour() function 70421 * returns the current hour as a value from 0 - 23. 70422 * 70423 * @method hour 70424 * @return {Integer} the current hour 70425 * @example 70426 * <div> 70427 * <code> 70428 * var h = hour(); 70429 * text('Current hour:\n' + h, 5, 50); 70430 * </code> 70431 * </div> 70432 * 70433 * @alt 70434 * Current hour is displayed 70435 * 70436 */ 70437p5.prototype.hour = function() { 70438 return new Date().getHours(); 70439}; 70440 70441/** 70442 * p5.js communicates with the clock on your computer. The minute() function 70443 * returns the current minute as a value from 0 - 59. 70444 * 70445 * @method minute 70446 * @return {Integer} the current minute 70447 * @example 70448 * <div> 70449 * <code> 70450 * var m = minute(); 70451 * text('Current minute: \n' + m, 5, 50); 70452 * </code> 70453 * </div> 70454 * 70455 * @alt 70456 * Current minute is displayed 70457 * 70458 */ 70459p5.prototype.minute = function() { 70460 return new Date().getMinutes(); 70461}; 70462 70463/** 70464 * Returns the number of milliseconds (thousandths of a second) since 70465 * starting the program. This information is often used for timing events and 70466 * animation sequences. 70467 * 70468 * @method millis 70469 * @return {Number} the number of milliseconds since starting the program 70470 * @example 70471 * <div> 70472 * <code> 70473 * var millisecond = millis(); 70474 * text('Milliseconds \nrunning: \n' + millisecond, 5, 40); 70475 * </code> 70476 * </div> 70477 * 70478 * @alt 70479 * number of milliseconds since program has started displayed 70480 * 70481 */ 70482p5.prototype.millis = function() { 70483 return window.performance.now(); 70484}; 70485 70486/** 70487 * p5.js communicates with the clock on your computer. The month() function 70488 * returns the current month as a value from 1 - 12. 70489 * 70490 * @method month 70491 * @return {Integer} the current month 70492 * @example 70493 * <div> 70494 * <code> 70495 * var m = month(); 70496 * text('Current month: \n' + m, 5, 50); 70497 * </code> 70498 * </div> 70499 * 70500 * @alt 70501 * Current month is displayed 70502 * 70503 */ 70504p5.prototype.month = function() { 70505 return new Date().getMonth() + 1; //January is 0! 70506}; 70507 70508/** 70509 * p5.js communicates with the clock on your computer. The second() function 70510 * returns the current second as a value from 0 - 59. 70511 * 70512 * @method second 70513 * @return {Integer} the current second 70514 * @example 70515 * <div> 70516 * <code> 70517 * var s = second(); 70518 * text('Current second: \n' + s, 5, 50); 70519 * </code> 70520 * </div> 70521 * 70522 * @alt 70523 * Current second is displayed 70524 * 70525 */ 70526p5.prototype.second = function() { 70527 return new Date().getSeconds(); 70528}; 70529 70530/** 70531 * p5.js communicates with the clock on your computer. The year() function 70532 * returns the current year as an integer (2014, 2015, 2016, etc). 70533 * 70534 * @method year 70535 * @return {Integer} the current year 70536 * @example 70537 * <div> 70538 * <code> 70539 * var y = year(); 70540 * text('Current year: \n' + y, 5, 50); 70541 * </code> 70542 * </div> 70543 * 70544 * @alt 70545 * Current year is displayed 70546 * 70547 */ 70548p5.prototype.year = function() { 70549 return new Date().getFullYear(); 70550}; 70551 70552module.exports = p5; 70553 70554},{"../core/core":22}],63:[function(_dereq_,module,exports){ 70555/** 70556 * @module Lights, Camera 70557 * @submodule Camera 70558 * @for p5 70559 * @requires core 70560 */ 70561 70562'use strict'; 70563 70564var p5 = _dereq_('../core/core'); 70565 70566/** 70567 * Sets camera position for a 3D sketch. The function behaves similarly 70568 * gluLookAt, except that it replaces the existing modelview matrix instead 70569 * of applying any transformations calculated here on top of the existing 70570 * model view. 70571 * When called with no arguments, this function 70572 * sets a default camera equivalent to calling 70573 * camera(0, 0, (height/2.0) / tan(PI*30.0 / 180.0), 0, 0, 0, 0, 1, 0); 70574 * @method camera 70575 * @param {Number} [x] camera position value on x axis 70576 * @param {Number} [y] camera position value on y axis 70577 * @param {Number} [z] camera position value on z axis 70578 * @param {Number} [centerX] x coordinate representing center of the sketch 70579 * @param {Number} [centerY] y coordinate representing center of the sketch 70580 * @param {Number} [centerZ] z coordinate representing center of the sketch 70581 * @param {Number} [upX] x component of direction 'up' from camera 70582 * @param {Number} [upY] y component of direction 'up' from camera 70583 * @param {Number} [upZ] z component of direction 'up' from camera 70584 * @chainable 70585 * @example 70586 * <div> 70587 * <code> 70588 * function setup() { 70589 * createCanvas(100, 100, WEBGL); 70590 * } 70591 * function draw() { 70592 * //move the camera away from the plane by a sin wave 70593 * camera(0, 0, sin(frameCount * 0.01) * 100, 0, 0, 0, 0, 1, 0); 70594 * plane(120, 120); 70595 * } 70596 * </code> 70597 * </div> 70598 * 70599 * @alt 70600 * blue square shrinks in size grows to fill canvas. disappears then loops. 70601 * 70602 */ 70603p5.prototype.camera = function() { 70604 this._assert3d('camera'); 70605 p5._validateParameters('camera', arguments); 70606 this._renderer.camera.apply(this._renderer, arguments); 70607 return this; 70608}; 70609 70610p5.RendererGL.prototype.camera = function( 70611 eyeX, 70612 eyeY, 70613 eyeZ, 70614 centerX, 70615 centerY, 70616 centerZ, 70617 upX, 70618 upY, 70619 upZ 70620) { 70621 if (typeof eyeX === 'undefined') { 70622 eyeX = this.defaultCameraX; 70623 eyeY = this.defaultCameraY; 70624 eyeZ = this.defaultCameraZ; 70625 centerX = eyeX; 70626 centerY = eyeY; 70627 centerZ = 0; 70628 upX = 0; 70629 upY = 1; 70630 upZ = 0; 70631 } 70632 70633 this.cameraX = eyeX; 70634 this.cameraY = eyeY; 70635 this.cameraZ = eyeZ; 70636 70637 // calculate camera Z vector 70638 var z0 = eyeX - centerX; 70639 var z1 = eyeY - centerY; 70640 var z2 = eyeZ - centerZ; 70641 70642 this.eyeDist = Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2); 70643 if (this.eyeDist !== 0) { 70644 z0 /= this.eyeDist; 70645 z1 /= this.eyeDist; 70646 z2 /= this.eyeDist; 70647 } 70648 70649 // calculate camera Y vector 70650 var y0 = upX; 70651 var y1 = upY;
70652 var y2 = upZ; 70653 70654 // computer x vector as y cross z 70655 var x0 = y1 * z2 - y2 * z1; 70656 var x1 = -y0 * z2 + y2 * z0; 70657 var x2 = y0 * z1 - y1 * z0; 70658 70659 // recomputer y = z cross x 70660 y0 = z1 * x2 - z2 * x1; 70661 y1 = -z0 * x2 + z2 * x0; 70662 y2 = z0 * x1 - z1 * x0; 70663 70664 // cross product gives area of parallelogram, which is < 1.0 for 70665 // non-perpendicular unit-length vectors; so normalize x, y here: 70666 var xmag = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2); 70667 if (xmag !== 0) { 70668 x0 /= xmag; 70669 x1 /= xmag; 70670 x2 /= xmag; 70671 } 70672 70673 var ymag = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2); 70674 if (ymag !== 0) { 70675 y0 /= ymag; 70676 y1 /= ymag; 70677 y2 /= ymag; 70678 } 70679 70680 // the camera affects the model view matrix, insofar as it 70681 // inverse translates the world to the eye position of the camera 70682 // and rotates it. 70683 // prettier-ignore 70684 this.cameraMatrix.set(x0, y0, z0, 0, 70685 x1, y1, z1, 0, 70686 x2, y2, z2, 0, 70687 0, 0, 0, 1); 70688 70689 var tx = -eyeX; 70690 var ty = -eyeY; 70691 var tz = -eyeZ; 70692 70693 this.cameraMatrix.translate([tx, ty, tz]); 70694 this.uMVMatrix.set( 70695 this.cameraMatrix.mat4[0], 70696 this.cameraMatrix.mat4[1], 70697 this.cameraMatrix.mat4[2], 70698 this.cameraMatrix.mat4[3], 70699 this.cameraMatrix.mat4[4], 70700 this.cameraMatrix.mat4[5], 70701 this.cameraMatrix.mat4[6], 70702 this.cameraMatrix.mat4[7], 70703 this.cameraMatrix.mat4[8], 70704 this.cameraMatrix.mat4[9], 70705 this.cameraMatrix.mat4[10], 70706 this.cameraMatrix.mat4[11], 70707 this.cameraMatrix.mat4[12], 70708 this.cameraMatrix.mat4[13], 70709 this.cameraMatrix.mat4[14], 70710 this.cameraMatrix.mat4[15] 70711 ); 70712 return this; 70713}; 70714 70715/** 70716 * Sets perspective camera. When called with no arguments, the defaults 70717 * provided are equivalent to 70718 * perspective(PI/3.0, width/height, cameraZ/10.0, cameraZ*10.0) 70719 * where cameraZ is ((height/2.0) / tan(PI*60.0/360.0)); 70720 * @method perspective 70721 * @param {Number} [fovy] camera frustum vertical field of view, 70722 * from bottom to top of view, in angleMode units 70723 * @param {Number} [aspect] camera frustum aspect ratio 70724 * @param {Number} [near] frustum near plane length 70725 * @param {Number} [far] frustum far plane length 70726 * @chainable 70727 * @example 70728 * <div> 70729 * <code> 70730 * //drag mouse to toggle the world! 70731 * //you will see there's a vanish point 70732 * function setup() { 70733 * createCanvas(100, 100, WEBGL); 70734 * var fov = 60 / 180 * PI; 70735 * var cameraZ = height / 2.0 / tan(fov / 2.0); 70736 * perspective(60 / 180 * PI, width / height, cameraZ * 0.1, cameraZ * 10); 70737 * } 70738 * function draw() { 70739 * background(200); 70740 * orbitControl(); 70741 * for (var i = -1; i < 2; i++) { 70742 * for (var j = -2; j < 3; j++) { 70743 * push(); 70744 * translate(i * 160, 0, j * 160); 70745 * box(40, 40, 40); 70746 * pop(); 70747 * } 70748 * } 70749 * } 70750 * </code> 70751 * </div> 70752 * 70753 * @alt 70754 * colored 3d boxes toggleable with mouse position 70755 * 70756 */ 70757p5.prototype.perspective = function() { 70758 this._assert3d('perspective'); 70759 p5._validateParameters('perspective', arguments); 70760 this._renderer.perspective.apply(this._renderer, arguments); 70761 return this; 70762}; 70763 70764p5.RendererGL.prototype.perspective = function(fovy, aspect, near, far) { 70765 if (typeof fovy === 'undefined') { 70766 fovy = this.defaultCameraFOV; 70767 } 70768 if (typeof aspect === 'undefined') { 70769 aspect = this.defaultCameraAspect; 70770 } 70771 if (typeof near === 'undefined') { 70772 near = this.defaultCameraNear; 70773 } 70774 if (typeof far === 'undefined') { 70775 far = this.defaultCameraFar; 70776 } 70777 70778 this.cameraFOV = this._pInst._toRadians(fovy); 70779 this.cameraAspect = aspect; 70780 this.cameraNear = near; 70781 this.cameraFar = far; 70782 70783 this.uPMatrix = p5.Matrix.identity(); 70784 70785 var f = 1.0 / Math.tan(this.cameraFOV / 2); 70786 var nf = 1.0 / (this.cameraNear - this.cameraFar); 70787 70788 // prettier-ignore 70789 this.uPMatrix.set(f / aspect, 0, 0, 0, 70790 0, -f, 0, 0, 70791 0, 0, (far + near) * nf, -1, 70792 0, 0, (2 * far * near) * nf, 0); 70793 70794 this._curCamera = 'custom'; 70795}; 70796 70797/** 70798 * Setup ortho camera 70799 * @method ortho 70800 * @param {Number} [left] camera frustum left plane 70801 * @param {Number} [right] camera frustum right plane 70802 * @param {Number} [bottom] camera frustum bottom plane 70803 * @param {Number} [top] camera frustum top plane 70804 * @param {Number} [near] camera frustum near plane 70805 * @param {Number} [far] camera frustum far plane 70806 * @chainable 70807 * @example 70808 * <div> 70809 * <code> 70810 * //drag mouse to toggle the world! 70811 * //there's no vanish point 70812 * function setup() { 70813 * createCanvas(100, 100, WEBGL); 70814 * ortho(-width / 2, width / 2, height / 2, -height / 2, 0, 500); 70815 * } 70816 * function draw() { 70817 * background(200); 70818 * orbitControl(); 70819 * strokeWeight(0.1);
70820 * for (var i = -1; i < 2; i++) { 70821 * for (var j = -2; j < 3; j++) { 70822 * push(); 70823 * translate(i * 160, 0, j * 160); 70824 * box(40, 40, 40); 70825 * pop(); 70826 * } 70827 * } 70828 * } 70829 * </code> 70830 * </div> 70831 * 70832 * @alt 70833 * 3 3d boxes, reveal several more boxes on 3d plane when mouse used to toggle 70834 * 70835 */ 70836p5.prototype.ortho = function() { 70837 this._assert3d('ortho'); 70838 p5._validateParameters('ortho', arguments); 70839 this._renderer.ortho.apply(this._renderer, arguments); 70840 return this; 70841}; 70842 70843p5.RendererGL.prototype.ortho = function(left, right, bottom, top, near, far) { 70844 if (left === undefined) left = -this.width / 2; 70845 if (right === undefined) right = +this.width / 2; 70846 if (bottom === undefined) bottom = -this.height / 2; 70847 if (top === undefined) top = +this.height / 2; 70848 if (near === undefined) near = 0; 70849 if (far === undefined) far = Math.max(this.width, this.height); 70850 70851 var w = right - left; 70852 var h = top - bottom; 70853 var d = far - near; 70854 70855 var x = +2.0 / w; 70856 var y = +2.0 / h; 70857 var z = -2.0 / d; 70858 70859 var tx = -(right + left) / w; 70860 var ty = -(top + bottom) / h; 70861 var tz = -(far + near) / d; 70862 70863 this.uPMatrix = p5.Matrix.identity(); 70864 70865 // prettier-ignore 70866 this.uPMatrix.set( x, 0, 0, 0, 70867 0, -y, 0, 0, 70868 0, 0, z, 0, 70869 tx, ty, tz, 1); 70870 70871 this._curCamera = 'custom'; 70872}; 70873 70874module.exports = p5; 70875 70876},{"../core/core":22}],64:[function(_dereq_,module,exports){ 70877'use strict'; 70878 70879var p5 = _dereq_('../core/core'); 70880 70881/** 70882 * @method orbitControl 70883 * @for p5 70884 * @chainable 70885 * 70886 * @example 70887 * <div> 70888 * <code> 70889 * function setup() { 70890 * createCanvas(100, 100, WEBGL); 70891 * } 70892 * 70893 * function draw() { 70894 * background(50); 70895 * // Orbit control allows the camera to orbit around a target. 70896 * orbitControl(); 70897 * box(30, 50); 70898 * } 70899 * </code> 70900 * </div> 70901 * 70902 * @alt 70903 * Camera orbits around box when mouse is hold-clicked & then moved. 70904 */ 70905//@TODO: implement full orbit controls including 70906//pan, zoom, quaternion rotation, etc. 70907p5.prototype.orbitControl = function() { 70908 this._assert3d('orbitControl'); 70909 p5._validateParameters('orbitControl', arguments); 70910 if (this.mouseIsPressed) { 70911 this.rotateY((this.mouseX - this.width / 2) / (this.width / 2)); 70912 this.rotateX((this.mouseY - this.height / 2) / (this.width / 2)); 70913 } 70914 return this; 70915}; 70916 70917module.exports = p5; 70918 70919},{"../core/core":22}],65:[function(_dereq_,module,exports){ 70920/** 70921 * @module Lights, Camera 70922 * @submodule Lights 70923 * @for p5 70924 * @requires core 70925 */ 70926 70927'use strict'; 70928 70929var p5 = _dereq_('../core/core'); 70930 70931/** 70932 * Creates an ambient light with a color 70933 * 70934 * @method ambientLight 70935 * @param {Number} v1 red or hue value relative to 70936 * the current color range 70937 * @param {Number} v2 green or saturation value 70938 * relative to the current color range 70939 * @param {Number} v3 blue or brightness value 70940 * relative to the current color range 70941 * @param {Number} [alpha] 70942 * @chainable 70943 * 70944 * @example 70945 * <div> 70946 * <code> 70947 * function setup() { 70948 * createCanvas(100, 100, WEBGL); 70949 * } 70950 * function draw() { 70951 * background(0); 70952 * ambientLight(150); 70953 * ambientMaterial(250); 70954 * noStroke(); 70955 * sphere(25); 70956 * } 70957 * </code> 70958 * </div> 70959 * 70960 * @alt 70961 * evenly distributed light across a sphere 70962 * 70963 */ 70964 70965/** 70966 * @method ambientLight 70967 * @param {String} value a color string 70968 * @chainable 70969 */ 70970 70971/** 70972 * @method ambientLight 70973 * @param {Number} gray a gray value 70974 * @param {Number} [alpha] 70975 * @chainable 70976 */ 70977 70978/** 70979 * @method ambientLight 70980 * @param {Number[]} values an array containing the red,green,blue & 70981 * and alpha components of the color 70982 * @chainable 70983 */ 70984 70985/** 70986 * @method ambientLight 70987 * @param {p5.Color} color the ambient light color 70988 * @chainable 70989 */ 70990p5.prototype.ambientLight = function(v1, v2, v3, a) { 70991 this._assert3d('ambientLight'); 70992 p5._validateParameters('ambientLight', arguments); 70993 var color = this.color.apply(this, arguments); 70994 70995 var shader = this._renderer._useLightShader(); 70996 70997 //@todo this is a bit icky. array uniforms have 70998 //to be multiples of the type 3(rgb) in this case. 70999 //a preallocated Float32Array(24) that we copy into 71000 //would be better 71001 shader.setUniform('uUseLighting', true); 71002 //in case there's no material color for the geometry 71003 shader.setUniform('uMaterialColor', this._renderer.curFillColor); 71004 71005 this._renderer.ambientLightColors.push( 71006 color._array[0], 71007 color._array[1], 71008 color._array[2] 71009 ); 71010 shader.setUniform('uAmbientColor', this._renderer.ambientLightColors); 71011 71012 shader.setUniform( 71013 'uAmbientLightCount', 71014 this._renderer.ambientLightColors.length / 3 71015 ); 71016 71017 return this; 71018}; 71019 71020/** 71021 * Creates a directional light with a color and a direction 71022 * @method directionalLight 71023 * @param {Number} v1 red or hue value (depending on the current 71024 * color mode), 71025 * @param {Number} v2 green or saturation value 71026 * @param {Number} v3 blue or brightness value 71027 * @param {p5.Vector} position the direction of the light 71028 * @chainable 71029 * @example 71030 * <div> 71031 * <code> 71032 * function setup() { 71033 * createCanvas(100, 100, WEBGL); 71034 * } 71035 * function draw() { 71036 * background(0); 71037 * //move your mouse to change light direction 71038 * var dirX = (mouseX / width - 0.5) * 2; 71039 * var dirY = (mouseY / height - 0.5) * 2; 71040 * directionalLight(250, 250, 250, -dirX, -dirY, 0.25); 71041 * ambientMaterial(250); 71042 * noStroke(); 71043 * sphere(25); 71044 * } 71045 * </code> 71046 * </div> 71047 * 71048 * @alt 71049 * light source on canvas changeable with mouse position 71050 * 71051 */ 71052 71053/** 71054 * @method directionalLight 71055 * @param {Number[]|String|p5.Color} color color Array, CSS color string, 71056 * or p5.Color value 71057 * @param {Number} x x axis direction 71058 * @param {Number} y y axis direction 71059 * @param {Number} z z axis direction 71060 * @chainable 71061 */ 71062 71063/** 71064 * @method directionalLight 71065 * @param {Number[]|String|p5.Color} color 71066 * @param {p5.Vector} position 71067 * @chainable 71068 */ 71069 71070/** 71071 * @method directionalLight 71072 * @param {Number} v1 71073 * @param {Number} v2 71074 * @param {Number} v3 71075 * @param {Number} x 71076 * @param {Number} y 71077 * @param {Number} z 71078 * @chainable 71079 */ 71080p5.prototype.directionalLight = function(v1, v2, v3, x, y, z) { 71081 this._assert3d('directionalLight'); 71082 p5._validateParameters('directionalLight', arguments); 71083 var shader = this._renderer._useLightShader(); 71084 71085 //@TODO: check parameters number 71086 var color = this.color.apply(this, [v1, v2, v3]); 71087 71088 var _x, _y, _z; 71089 var v = arguments[arguments.length - 1]; 71090 if (typeof v === 'number') { 71091 _x = arguments[arguments.length - 3]; 71092 _y = arguments[arguments.length - 2]; 71093 _z = arguments[arguments.length - 1]; 71094 } else { 71095 _x = v.x; 71096 _y = v.y; 71097 _z = v.z; 71098 } 71099 shader.setUniform('uUseLighting', true); 71100 //in case there's no material color for the geometry 71101 shader.setUniform('uMaterialColor', this._renderer.curFillColor); 71102 71103 // normalize direction 71104 var l = Math.sqrt(_x * _x + _y * _y + _z * _z); 71105 this._renderer.directionalLightDirections.push(_x / l, _y / l, _z / l); 71106 shader.setUniform( 71107 'uLightingDirection', 71108 this._renderer.directionalLightDirections 71109 ); 71110 71111 this._renderer.directionalLightColors.push( 71112 color._array[0], 71113 color._array[1], 71114 color._array[2] 71115 ); 71116 shader.setUniform('uDirectionalColor', this._renderer.directionalLightColors); 71117 71118 shader.setUniform( 71119 'uDirectionalLightCount', 71120 this._renderer.directionalLightColors.length / 3 71121 ); 71122 71123 return this; 71124}; 71125 71126/** 71127 * Creates a point light with a color and a light position 71128 * @method pointLight 71129 * @param {Number} v1 red or hue value (depending on the current 71130 * color mode), 71131 * @param {Number} v2 green or saturation value 71132 * @param {Number} v3 blue or brightness value 71133 * @param {Number} x x axis position 71134 * @param {Number} y y axis position 71135 * @param {Number} z z axis position 71136 * @chainable 71137 * @example 71138 * <div> 71139 * <code> 71140 * function setup() { 71141 * createCanvas(100, 100, WEBGL); 71142 * } 71143 * function draw() { 71144 * background(0); 71145 * //move your mouse to change light position 71146 * var locX = mouseX - width / 2;
71147 * var locY = mouseY - height / 2; 71148 * // to set the light position, 71149 * // think of the world's coordinate as: 71150 * // -width/2,-height/2 -------- width/2,-height/2 71151 * // | | 71152 * // | 0,0 | 71153 * // | | 71154 * // -width/2,height/2--------width/2,height/2 71155 * pointLight(250, 250, 250, locX, locY, 50); 71156 * ambientMaterial(250); 71157 * noStroke(); 71158 * sphere(25); 71159 * } 71160 * </code> 71161 * </div> 71162 * 71163 * @alt 71164 * spot light on canvas changes position with mouse 71165 * 71166 */ 71167 71168/** 71169 * @method pointLight 71170 * @param {Number} v1 71171 * @param {Number} v2 71172 * @param {Number} v3 71173 * @param {p5.Vector} position the position of the light 71174 * @chainable 71175 */ 71176 71177/** 71178 * @method pointLight 71179 * @param {Number[]|String|p5.Color} color color Array, CSS color string, 71180 * or p5.Color value 71181 * @param {Number} x 71182 * @param {Number} y 71183 * @param {Number} z 71184 * @chainable 71185 */ 71186 71187/** 71188 * @method pointLight 71189 * @param {Number[]|String|p5.Color} color 71190 * @param {p5.Vector} position 71191 * @chainable 71192 */ 71193p5.prototype.pointLight = function(v1, v2, v3, x, y, z) { 71194 this._assert3d('pointLight'); 71195 p5._validateParameters('pointLight', arguments); 71196 //@TODO: check parameters number 71197 var color = this._renderer._pInst.color.apply(this, [v1, v2, v3]); 71198 71199 var _x, _y, _z; 71200 var v = arguments[arguments.length - 1]; 71201 if (typeof v === 'number') { 71202 _x = arguments[arguments.length - 3]; 71203 _y = arguments[arguments.length - 2]; 71204 _z = arguments[arguments.length - 1]; 71205 } else { 71206 _x = v.x; 71207 _y = v.y; 71208 _z = v.z; 71209 } 71210 71211 var shader = this._renderer._useLightShader(); 71212 shader.setUniform('uUseLighting', true); 71213 //in case there's no material color for the geometry 71214 shader.setUniform('uMaterialColor', this._renderer.curFillColor); 71215 71216 this._renderer.pointLightPositions.push(_x, _y, _z); 71217 shader.setUniform('uPointLightLocation', this._renderer.pointLightPositions); 71218 71219 this._renderer.pointLightColors.push( 71220 color._array[0], 71221 color._array[1], 71222 color._array[2] 71223 ); 71224 shader.setUniform('uPointLightColor', this._renderer.pointLightColors); 71225 71226 shader.setUniform( 71227 'uPointLightCount', 71228 this._renderer.pointLightColors.length / 3 71229 ); 71230 71231 return this; 71232}; 71233 71234module.exports = p5; 71235 71236},{"../core/core":22}],66:[function(_dereq_,module,exports){ 71237/** 71238 * @module Shape 71239 * @submodule 3D Models 71240 * @for p5 71241 * @requires core 71242 * @requires p5.Geometry 71243 */ 71244 71245'use strict'; 71246 71247var p5 = _dereq_('../core/core'); 71248_dereq_('./p5.Geometry'); 71249 71250/** 71251 * Load a 3d model from an OBJ file. 71252 * <br><br> 71253 * One of the limitations of the OBJ format is that it doesn't have a built-in 71254 * sense of scale. This means that models exported from different programs might 71255 * be very different sizes. If your model isn't displaying, try calling 71256 * loadModel() with the normalized parameter set to true. This will resize the 71257 * model to a scale appropriate for p5. You can also make additional changes to 71258 * the final size of your model with the scale() function. 71259 * 71260 * @method loadModel 71261 * @param {String} path Path of the model to be loaded 71262 * @param {Boolean} normalize If true, scale the model to a 71263 * standardized size when loading 71264 * @param {function(p5.Geometry)} [successCallback] Function to be called 71265 * once the model is loaded. Will be passed 71266 * the 3D model object. 71267 * @param {function(Event)} [failureCallback] called with event error if 71268 * the image fails to load. 71269 * @return {p5.Geometry} the p5.Geometry object 71270 * 71271 * @example 71272 * <div> 71273 * <code> 71274 * //draw a spinning teapot 71275 * var teapot; 71276 * 71277 * function preload() { 71278 * teapot = loadModel('assets/teapot.obj'); 71279 * } 71280 * 71281 * function setup() { 71282 * createCanvas(100, 100, WEBGL); 71283 * } 71284 * 71285 * function draw() { 71286 * background(200); 71287 * rotateX(frameCount * 0.01); 71288 * rotateY(frameCount * 0.01); 71289 * model(teapot); 71290 * } 71291 * </code> 71292 * </div> 71293 * 71294 * @alt 71295 * Vertically rotating 3-d teapot with red, green and blue gradient. 71296 */ 71297/** 71298 * @method loadModel 71299 * @param {String} path 71300 * @param {function(p5.Geometry)} [successCallback] 71301 * @param {function(Event)} [failureCallback] 71302 * @return {p5.Geometry} the p5.Geometry object 71303 */ 71304p5.prototype.loadModel = function(path) { 71305 p5._validateParameters('loadModel', arguments); 71306 var normalize; 71307 var successCallback; 71308 var failureCallback; 71309 if (typeof arguments[1] === 'boolean') { 71310 normalize = arguments[1]; 71311 successCallback = arguments[2]; 71312 failureCallback = arguments[3]; 71313 } else { 71314 normalize = false;
71315 successCallback = arguments[1]; 71316 failureCallback = arguments[2]; 71317 } 71318 71319 var model = new p5.Geometry(); 71320 model.gid = path + '|' + normalize; 71321 var self = this; 71322 this.loadStrings( 71323 path, 71324 function(strings) { 71325 parseObj(model, strings); 71326 71327 if (normalize) { 71328 model.normalize(); 71329 } 71330 71331 self._decrementPreload(); 71332 if (typeof successCallback === 'function') { 71333 successCallback(model); 71334 } 71335 }.bind(this), 71336 failureCallback 71337 ); 71338 71339 return model; 71340}; 71341 71342/** 71343 * Parse OBJ lines into model. For reference, this is what a simple model of a 71344 * square might look like: 71345 * 71346 * v -0.5 -0.5 0.5 71347 * v -0.5 -0.5 -0.5 71348 * v -0.5 0.5 -0.5 71349 * v -0.5 0.5 0.5 71350 * 71351 * f 4 3 2 1 71352 */ 71353function parseObj(model, lines) { 71354 // OBJ allows a face to specify an index for a vertex (in the above example), 71355 // but it also allows you to specify a custom combination of vertex, UV 71356 // coordinate, and vertex normal. So, "3/4/3" would mean, "use vertex 3 with 71357 // UV coordinate 4 and vertex normal 3". In WebGL, every vertex with different 71358 // parameters must be a different vertex, so loadedVerts is used to 71359 // temporarily store the parsed vertices, normals, etc., and indexedVerts is 71360 // used to map a specific combination (keyed on, for example, the string 71361 // "3/4/3"), to the actual index of the newly created vertex in the final 71362 // object. 71363 var loadedVerts = { 71364 v: [], 71365 vt: [], 71366 vn: [] 71367 }; 71368 var indexedVerts = {}; 71369 71370 for (var line = 0; line < lines.length; ++line) { 71371 // Each line is a separate object (vertex, face, vertex normal, etc) 71372 // For each line, split it into tokens on whitespace. The first token 71373 // describes the type. 71374 var tokens = lines[line].trim().split(/\b\s+/); 71375 71376 if (tokens.length > 0) { 71377 if (tokens[0] === 'v' || tokens[0] === 'vn') { 71378 // Check if this line describes a vertex or vertex normal. 71379 // It will have three numeric parameters. 71380 var vertex = new p5.Vector( 71381 parseFloat(tokens[1]), 71382 parseFloat(tokens[2]), 71383 parseFloat(tokens[3]) 71384 ); 71385 loadedVerts[tokens[0]].push(vertex); 71386 } else if (tokens[0] === 'vt') { 71387 // Check if this line describes a texture coordinate. 71388 // It will have two numeric parameters. 71389 var texVertex = [parseFloat(tokens[1]), parseFloat(tokens[2])]; 71390 loadedVerts[tokens[0]].push(texVertex); 71391 } else if (tokens[0] === 'f') { 71392 // Check if this line describes a face. 71393 // OBJ faces can have more than three points. Triangulate points. 71394 for (var tri = 3; tri < tokens.length; ++tri) { 71395 var face = []; 71396 71397 var vertexTokens = [1, tri - 1, tri]; 71398 71399 for (var tokenInd = 0; tokenInd < vertexTokens.length; ++tokenInd) { 71400 // Now, convert the given token into an index 71401 var vertString = tokens[vertexTokens[tokenInd]]; 71402 var vertIndex = 0; 71403 71404 // TODO: Faces can technically use negative numbers to refer to the 71405 // previous nth vertex. I haven't seen this used in practice, but 71406 // it might be good to implement this in the future. 71407 71408 if (indexedVerts[vertString] !== undefined) { 71409 vertIndex = indexedVerts[vertString]; 71410 } else { 71411 var vertParts = vertString.split('/'); 71412 for (var i = 0; i < vertParts.length; i++) { 71413 vertParts[i] = parseInt(vertParts[i]) - 1; 71414 } 71415 71416 vertIndex = indexedVerts[vertString] = model.vertices.length; 71417 model.vertices.push(loadedVerts.v[vertParts[0]].copy()); 71418 if (loadedVerts.vt[vertParts[1]]) { 71419 model.uvs.push(loadedVerts.vt[vertParts[1]].slice()); 71420 } else { 71421 model.uvs.push([0, 0]); 71422 } 71423 71424 if (loadedVerts.vn[vertParts[2]]) { 71425 model.vertexNormals.push(loadedVerts.vn[vertParts[2]].copy()); 71426 } 71427 } 71428 71429 face.push(vertIndex); 71430 } 71431 71432 if ( 71433 face[0] !== face[1] && 71434 face[0] !== face[2] && 71435 face[1] !== face[2] 71436 ) { 71437 model.faces.push(face); 71438 } 71439 } 71440 } 71441 } 71442 } 71443 // If the model doesn't have normals, compute the normals 71444 if (model.vertexNormals.length === 0) { 71445 model.computeNormals(); 71446 } 71447 71448 return model; 71449} 71450
71451/** 71452 * Render a 3d model to the screen. 71453 * 71454 * @method model 71455 * @param {p5.Geometry} model Loaded 3d model to be rendered 71456 * @example 71457 * <div> 71458 * <code> 71459 * //draw a spinning teapot 71460 * var teapot; 71461 * 71462 * function preload() { 71463 * teapot = loadModel('assets/teapot.obj'); 71464 * } 71465 * 71466 * function setup() { 71467 * createCanvas(100, 100, WEBGL); 71468 * } 71469 * 71470 * function draw() { 71471 * background(200); 71472 * rotateX(frameCount * 0.01); 71473 * rotateY(frameCount * 0.01); 71474 * model(teapot); 71475 * } 71476 * </code> 71477 * </div> 71478 * 71479 * @alt 71480 * Vertically rotating 3-d teapot with red, green and blue gradient. 71481 * 71482 */ 71483p5.prototype.model = function(model) { 71484 this._assert3d('model'); 71485 p5._validateParameters('model', arguments); 71486 if (model.vertices.length > 0) { 71487 if (!this._renderer.geometryInHash(model.gid)) { 71488 model._makeTriangleEdges()._edgesToVertices(); 71489 this._renderer.createBuffers(model.gid, model); 71490 } 71491 71492 this._renderer.drawBuffers(model.gid); 71493 } 71494}; 71495 71496module.exports = p5; 71497 71498},{"../core/core":22,"./p5.Geometry":68}],67:[function(_dereq_,module,exports){ 71499/** 71500 * @module Lights, Camera 71501 * @submodule Material 71502 * @for p5 71503 * @requires core 71504 */ 71505 71506'use strict'; 71507 71508var p5 = _dereq_('../core/core'); 71509var constants = _dereq_('../core/constants'); 71510_dereq_('./p5.Texture'); 71511 71512/** 71513 * Loads a custom shader from the provided vertex and fragment 71514 * shader paths. The shader files are loaded asynchronously in the 71515 * background, so this method should be used in preload(). 71516 * 71517 * For now, there are three main types of shaders. p5 will automatically 71518 * supply appropriate vertices, normals, colors, and lighting attributes 71519 * if the parameters defined in the shader match the names. 71520 * 71521 * @method loadShader 71522 * @param {String} [vertFilename] path to file containing vertex shader 71523 * source code 71524 * @param {String} [fragFilename] path to file containing fragment shader 71525 * source code 71526 * @return {p5.Shader} a shader object created from the provided 71527 * vertex and fragment shader files. 71528 */ 71529p5.prototype.loadShader = function(vertFilename, fragFilename) { 71530 p5._validateParameters('loadShader', arguments); 71531 var loadedShader = new p5.Shader(); 71532 71533 var self = this; 71534 var loadedFrag = false; 71535 var loadedVert = false; 71536 71537 this.loadStrings(fragFilename, function(result) { 71538 loadedShader._fragSrc = result.join('\n'); 71539 loadedFrag = true; 71540 if (loadedVert) { 71541 self._decrementPreload(); 71542 } 71543 }); 71544 this.loadStrings(vertFilename, function(result) { 71545 loadedShader._vertSrc = result.join('\n'); 71546 loadedVert = true; 71547 if (loadedFrag) { 71548 self._decrementPreload(); 71549 } 71550 }); 71551 71552 return loadedShader; 71553}; 71554 71555/** 71556 * @method createShader 71557 * @param {String} vertSrc source code for the vertex shader 71558 * @param {String} fragSrc source code for the fragment shader 71559 * @returns {p5.Shader} a shader object created from the provided 71560 * vertex and fragment shaders. 71561 * 71562 * @example 71563 * <div modernizr='webgl'> 71564 * <code> 71565 * // the 'varying's are shared between both vertex & fragment shaders 71566 * var varying = 'precision highp float; varying vec2 vPos;'; 71567 * 71568 * // the vertex shader is called for each vertex 71569 * var vs = 71570 * varying + 71571 * 'attribute vec3 aPosition;' + 71572 * 'void main() { vPos = (gl_Position = vec4(aPosition,1.0)).xy; }'; 71573 * 71574 * // the fragment shader is called for each pixel 71575 * var fs = 71576 * varying + 71577 * 'uniform vec2 p;' + 71578 * 'uniform float r;' + 71579 * 'const int I = 500;' + 71580 * 'void main() {' + 71581 * ' vec2 c = p + vPos * r, z = c;' + 71582 * ' float n = 0.0;' + 71583 * ' for (int i = I; i > 0; i --) {' + 71584 * ' if(z.x*z.x+z.y*z.y > 4.0) {' + 71585 * ' n = float(i)/float(I);' + 71586 * ' break;' + 71587 * ' }' + 71588 * ' z = vec2(z.x*z.x-z.y*z.y, 2.0*z.x*z.y) + c;' + 71589 * ' }' + 71590 * ' gl_FragColor = vec4(0.5-cos(n*17.0)/2.0,0.5-cos(n*13.0)/2.0,0.5-cos(n*23.0)/2.0,1.0);' + 71591 * '}'; 71592 * 71593 * var mandel; 71594 * function setup() { 71595 * createCanvas(100, 100, WEBGL); 71596 * 71597 * // create and initialize the shader 71598 * mandel = createShader(vs, fs); 71599 * shader(mandel); 71600 * noStroke(); 71601 * 71602 * // 'p' is the center point of the Mandelbrot image 71603 * mandel.setUniform('p', [-0.74364388703, 0.13182590421]); 71604 * } 71605 * 71606 * function draw() { 71607 * // 'r' is the size of the image in Mandelbrot-space 71608 * mandel.setUniform('r', 1.5 * exp(-6.5 * (1 + sin(millis() / 2000)))); 71609 * quad(-1, -1, 1, -1, 1, 1, -1, 1); 71610 * } 71611 * </code> 71612 * </div> 71613 * 71614 * @alt 71615 * zooming Mandelbrot set. a colorful, infinitely detailed fractal. 71616 */ 71617p5.prototype.createShader = function(vertSrc, fragSrc) { 71618 this._assert3d('createShader'); 71619 p5._validateParameters('createShader', arguments); 71620 return new p5.Shader(this._renderer, vertSrc, fragSrc); 71621}; 71622 71623/** 71624 * The shader() function lets the user provide a custom shader 71625 * to fill in shapes in WEBGL mode. Users can create their 71626 * own shaders by loading vertex and fragment shaders with 71627 * loadShader(). 71628 * 71629 * @method shader 71630 * @chainable 71631 * @param {p5.Shader} [s] the desired p5.Shader to use for rendering 71632 * shapes. 71633 */ 71634p5.prototype.shader = function(s) { 71635 this._assert3d('shader'); 71636 p5._validateParameters('shader', arguments); 71637 if (s._renderer === undefined) { 71638 s._renderer = this._renderer; 71639 } 71640 if (s.isStrokeShader()) { 71641 this._renderer.setStrokeShader(s); 71642 } else { 71643 this._renderer.setFillShader(s); 71644 } 71645 return this; 71646}; 71647 71648/** 71649 * Normal material for geometry. You can view all 71650 * possible materials in this 71651 * <a href="https://p5js.org/examples/3d-materials.html">example</a>. 71652 * @method normalMaterial 71653 * @chainable 71654 * @example 71655 * <div> 71656 * <code> 71657 * function setup() { 71658 * createCanvas(100, 100, WEBGL); 71659 * } 71660 * 71661 * function draw() { 71662 * background(200); 71663 * normalMaterial(); 71664 * sphere(50); 71665 * } 71666 * </code> 71667 * </div> 71668 * 71669 * @alt 71670 * Red, green and blue gradient. 71671 * 71672 */ 71673p5.prototype.normalMaterial = function() { 71674 this._assert3d('normalMaterial'); 71675 p5._validateParameters('normalMaterial', arguments); 71676 this._renderer.drawMode = constants.FILL; 71677 this._renderer.setFillShader(this._renderer._getNormalShader()); 71678 this._renderer.curFillColor = [1, 1, 1, 1]; 71679 this.noStroke(); 71680 return this; 71681}; 71682 71683/** 71684 * Texture for geometry. You can view other possible materials in this 71685 * <a href="https://p5js.org/examples/3d-materials.html">example</a>. 71686 * @method texture 71687 * @param {p5.Image|p5.MediaElement|p5.Graphics} tex 2-dimensional graphics 71688 * to render as texture 71689 * @chainable 71690 * @example 71691 * <div> 71692 * <code> 71693 * var img; 71694 * function preload() { 71695 * img = loadImage('assets/laDefense.jpg'); 71696 * } 71697 * 71698 * function setup() { 71699 * createCanvas(100, 100, WEBGL); 71700 * } 71701 * 71702 * function draw() { 71703 * background(0); 71704 * rotateZ(frameCount * 0.01); 71705 * rotateX(frameCount * 0.01); 71706 * rotateY(frameCount * 0.01); 71707 * //pass image as texture 71708 * texture(img); 71709 * box(200, 200, 200); 71710 * } 71711 * </code> 71712 * </div> 71713 * 71714 * <div> 71715 * <code> 71716 * var pg; 71717 * function setup() { 71718 * createCanvas(100, 100, WEBGL); 71719 * pg = createGraphics(200, 200); 71720 * pg.textSize(100); 71721 * } 71722 * 71723 * function draw() { 71724 * background(0); 71725 * pg.background(255); 71726 * pg.text('hello!', 0, 100); 71727 * //pass image as texture 71728 * texture(pg); 71729 * plane(200); 71730 * } 71731 * </code> 71732 * </div> 71733 * 71734 * <div> 71735 * <code> 71736 * var vid; 71737 * function preload() { 71738 * vid = createVideo('assets/fingers.mov'); 71739 * vid.hide(); 71740 * vid.loop(); 71741 * } 71742 * function setup() { 71743 * createCanvas(100, 100, WEBGL); 71744 * } 71745 * 71746 * function draw() { 71747 * background(0); 71748 * //pass video frame as texture 71749 * texture(vid); 71750 * plane(200); 71751 * } 71752 * </code> 71753 * </div> 71754 * 71755 * @alt 71756 * Rotating view of many images umbrella and grid roof on a 3d plane 71757 * black canvas 71758 * black canvas 71759 * 71760 */ 71761p5.prototype.texture = function(tex) { 71762 this._assert3d('texture'); 71763 p5._validateParameters('texture', arguments); 71764 this._renderer.drawMode = constants.TEXTURE; 71765 var shader = this._renderer._useLightShader(); 71766 shader.setUniform('uSpecular', false); 71767 shader.setUniform('isTexture', true); 71768 shader.setUniform('uSampler', tex); 71769 this.noStroke(); 71770 return this; 71771}; 71772 71773/** 71774 * Ambient material for geometry with a given color. You can view all 71775 * possible materials in this 71776 * <a href="https://p5js.org/examples/3d-materials.html">example</a>. 71777 * @method ambientMaterial 71778 * @param {Number} v1 gray value, red or hue value 71779 * (depending on the current color mode), 71780 * @param {Number} [v2] green or saturation value 71781 * @param {Number} [v3] blue or brightness value 71782 * @param {Number} [a] opacity 71783 * @chainable 71784 * @example 71785 * <div> 71786 * <code> 71787 * function setup() { 71788 * createCanvas(100, 100, WEBGL); 71789 * } 71790 * function draw() { 71791 * background(0); 71792 * ambientLight(100); 71793 * pointLight(250, 250, 250, 100, 100, 0); 71794 * ambientMaterial(250); 71795 * sphere(50); 71796 * } 71797 * </code> 71798 * </div> 71799 * 71800 * @alt 71801 * radiating light source from top right of canvas 71802 * 71803 */ 71804/** 71805 * @method ambientMaterial 71806 * @param {Number[]|String|p5.Color} color color, color Array, or CSS color string 71807 * @chainable 71808 */ 71809p5.prototype.ambientMaterial = function(v1, v2, v3, a) { 71810 this._assert3d('ambientMaterial'); 71811 p5._validateParameters('ambientMaterial', arguments); 71812 var color = p5.prototype.color.apply(this, arguments); 71813 this._renderer.curFillColor = color._array; 71814 71815 var shader = this._renderer._useLightShader(); 71816 shader.setUniform('uMaterialColor', this._renderer.curFillColor); 71817 shader.setUniform('uSpecular', false); 71818 shader.setUniform('isTexture', false); 71819 return this; 71820}; 71821 71822/** 71823 * Specular material for geometry with a given color. You can view all 71824 * possible materials in this 71825 * <a href="https://p5js.org/examples/3d-materials.html">example</a>. 71826 * @method specularMaterial 71827 * @param {Number} v1 gray value, red or hue value 71828 * (depending on the current color mode), 71829 * @param {Number} [v2] green or saturation value 71830 * @param {Number} [v3] blue or brightness value 71831 * @param {Number} [a] opacity 71832 * @chainable 71833 * @example 71834 * <div> 71835 * <code> 71836 * function setup() { 71837 * createCanvas(100, 100, WEBGL); 71838 * } 71839 * function draw() { 71840 * background(0); 71841 * ambientLight(100); 71842 * pointLight(250, 250, 250, 100, 100, 0); 71843 * specularMaterial(250); 71844 * sphere(50); 71845 * } 71846 * </code> 71847 * </div> 71848 * 71849 * @alt 71850 * diffused radiating light source from top right of canvas 71851 * 71852 */ 71853/** 71854 * @method specularMaterial 71855 * @param {Number[]|String|p5.Color} color color Array, or CSS color string 71856 * @chainable 71857 */ 71858p5.prototype.specularMaterial = function(v1, v2, v3, a) { 71859 this._assert3d('specularMaterial'); 71860 p5._validateParameters('specularMaterial', arguments); 71861 var color = p5.prototype.color.apply(this, arguments); 71862 this._renderer.curFillColor = color._array; 71863 71864 var shader = this._renderer._useLightShader(); 71865 shader.setUniform('uMaterialColor', this._renderer.curFillColor); 71866 shader.setUniform('uSpecular', true); 71867 shader.setUniform('isTexture', false); 71868 return this; 71869}; 71870 71871/** 71872 * @private blends colors according to color components. 71873 * If alpha value is less than 1, we need to enable blending 71874 * on our gl context. Otherwise opaque objects need to a depthMask. 71875 * @param {Number[]} color [description] 71876 * @return {Number[]]} Normalized numbers array 71877 */ 71878p5.RendererGL.prototype._applyColorBlend = function(colors) { 71879 var gl = this.GL; 71880 71881 var isTexture = this.drawMode === constants.TEXTURE; 71882 if (isTexture || colors[colors.length - 1] < 1.0) { 71883 gl.depthMask(isTexture); 71884 gl.enable(gl.BLEND); 71885 gl.blendEquation(gl.FUNC_ADD); 71886 gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); 71887 } else { 71888 gl.depthMask(true); 71889 gl.disable(gl.BLEND); 71890 } 71891 return colors; 71892}; 71893 71894module.exports = p5; 71895 71896},{"../core/constants":21,"../core/core":22,"./p5.Texture":74}],68:[function(_dereq_,module,exports){ 71897//some of the functions are adjusted from Three.js(http://threejs.org) 71898 71899'use strict'; 71900 71901var p5 = _dereq_('../core/core'); 71902/** 71903 * p5 Geometry class 71904 * @class p5.Geometry 71905 * @constructor 71906 * @param {function | Object} vertData callback function or Object 71907 * containing routine(s) for vertex data generation 71908 * @param {Integer} [detailX] number of vertices on horizontal surface 71909 * @param {Integer} [detailY] number of vertices on horizontal surface 71910 * @param {function} [callback] function to call upon object instantiation. 71911 * 71912 */ 71913p5.Geometry = function(detailX, detailY, callback) { 71914 //an array containing every vertex 71915 //@type [p5.Vector] 71916 this.vertices = []; 71917 71918 //an array containing every vertex for stroke drawing 71919 this.lineVertices = []; 71920 71921 //an array 1 normal per lineVertex with 71922 //final position representing which direction to 71923 //displace for strokeWeight 71924 //[[0,0,-1,1], [0,1,0,-1] ...]; 71925 this.lineNormals = []; 71926 71927 //an array containing 1 normal per vertex 71928 //@type [p5.Vector] 71929 //[p5.Vector, p5.Vector, p5.Vector,p5.Vector, p5.Vector, p5.Vector,...] 71930 this.vertexNormals = []; 71931 //an array containing each three vertex indices that form a face 71932 //[[0, 1, 2], [2, 1, 3], ...] 71933 this.faces = []; 71934 //a 2D array containing uvs for every vertex 71935 //[[0.0,0.0],[1.0,0.0], ...] 71936 this.uvs = []; 71937 // a 2D array containing edge connectivity pattern for create line vertices 71938 //based on faces for most objects; 71939 this.edges = []; 71940 this.detailX = detailX !== undefined ? detailX : 1; 71941 this.detailY = detailY !== undefined ? detailY : 1; 71942 if (callback instanceof Function) { 71943 callback.call(this); 71944 } 71945 return this; // TODO: is this a constructor? 71946}; 71947 71948/** 71949 * @method computeFaces 71950 * @chainable 71951 */ 71952p5.Geometry.prototype.computeFaces = function() { 71953 this.faces.length = 0; 71954 var sliceCount = this.detailX + 1; 71955 var a, b, c, d; 71956 for (var i = 0; i < this.detailY; i++) { 71957 for (var j = 0; j < this.detailX; j++) { 71958 a = i * sliceCount + j; // + offset; 71959 b = i * sliceCount + j + 1; // + offset; 71960 c = (i + 1) * sliceCount + j + 1; // + offset; 71961 d = (i + 1) * sliceCount + j; // + offset; 71962 this.faces.push([a, b, d]); 71963 this.faces.push([d, b, c]); 71964 } 71965 } 71966 return this; 71967}; 71968
71969p5.Geometry.prototype._getFaceNormal = function(faceId) { 71970 //This assumes that vA->vB->vC is a counter-clockwise ordering 71971 var face = this.faces[faceId]; 71972 var vA = this.vertices[face[0]]; 71973 var vB = this.vertices[face[1]]; 71974 var vC = this.vertices[face[2]]; 71975 var ab = p5.Vector.sub(vB, vA); 71976 var ac = p5.Vector.sub(vC, vA); 71977 var n = p5.Vector.cross(ab, ac); 71978 var ln = p5.Vector.mag(n); 71979 var sinAlpha = ln / (p5.Vector.mag(ab) * p5.Vector.mag(ac)); 71980 if (sinAlpha === 0 || isNaN(sinAlpha)) { 71981 console.warn( 71982 'p5.Geometry.prototype._getFaceNormal:', 71983 'face has colinear sides or a repeated vertex' 71984 ); 71985 return n; 71986 } 71987 if (sinAlpha > 1) sinAlpha = 1; // handle float rounding error 71988 return n.mult(Math.asin(sinAlpha) / ln); 71989}; 71990/** 71991 * computes smooth normals per vertex as an average of each 71992 * face. 71993 * @method computeNormals 71994 * @chainable 71995 */ 71996p5.Geometry.prototype.computeNormals = function() { 71997 var vertexNormals = this.vertexNormals; 71998 var vertices = this.vertices; 71999 var faces = this.faces; 72000 var iv; 72001 72002 // initialize the vertexNormals array with empty vectors 72003 vertexNormals.length = 0; 72004 for (iv = 0; iv < vertices.length; ++iv) { 72005 vertexNormals.push(new p5.Vector()); 72006 } 72007 72008 // loop through all the faces adding its normal to the normal 72009 // of each of its vertices 72010 for (var f = 0; f < faces.length; ++f) { 72011 var face = faces[f]; 72012 var faceNormal = this._getFaceNormal(f); 72013 72014 // all three vertices get the normal added 72015 for (var fv = 0; fv < 3; ++fv) { 72016 var vertexIndex = face[fv]; 72017 vertexNormals[vertexIndex].add(faceNormal); 72018 } 72019 } 72020 72021 // normalize the normals 72022 for (iv = 0; iv < vertices.length; ++iv) { 72023 vertexNormals[iv].normalize(); 72024 } 72025 72026 return this; 72027}; 72028 72029/** 72030 * Averages the vertex normals. Used in curved 72031 * surfaces 72032 * @method averageNormals 72033 * @chainable 72034 */ 72035p5.Geometry.prototype.averageNormals = function() { 72036 for (var i = 0; i <= this.detailY; i++) { 72037 var offset = this.detailX + 1; 72038 var temp = p5.Vector.add( 72039 this.vertexNormals[i * offset], 72040 this.vertexNormals[i * offset + this.detailX] 72041 ); 72042 72043 temp = p5.Vector.div(temp, 2); 72044 this.vertexNormals[i * offset] = temp; 72045 this.vertexNormals[i * offset + this.detailX] = temp; 72046 } 72047 return this; 72048}; 72049 72050/** 72051 * Averages pole normals. Used in spherical primitives 72052 * @method averagePoleNormals 72053 * @chainable 72054 */ 72055p5.Geometry.prototype.averagePoleNormals = function() { 72056 //average the north pole 72057 var sum = new p5.Vector(0, 0, 0); 72058 for (var i = 0; i < this.detailX; i++) { 72059 sum.add(this.vertexNormals[i]); 72060 } 72061 sum = p5.Vector.div(sum, this.detailX); 72062 72063 for (i = 0; i < this.detailX; i++) { 72064 this.vertexNormals[i] = sum; 72065 } 72066 72067 //average the south pole 72068 sum = new p5.Vector(0, 0, 0); 72069 for ( 72070 i = this.vertices.length - 1; 72071 i > this.vertices.length - 1 - this.detailX; 72072 i-- 72073 ) { 72074 sum.add(this.vertexNormals[i]); 72075 } 72076 sum = p5.Vector.div(sum, this.detailX); 72077 72078 for ( 72079 i = this.vertices.length - 1; 72080 i > this.vertices.length - 1 - this.detailX; 72081 i-- 72082 ) { 72083 this.vertexNormals[i] = sum; 72084 } 72085 return this; 72086}; 72087 72088/** 72089 * Create a 2D array for establishing stroke connections 72090 * @private 72091 * @chainable 72092 */ 72093p5.Geometry.prototype._makeTriangleEdges = function() { 72094 this.edges.length = 0; 72095 if (Array.isArray(this.strokeIndices)) { 72096 for (var i = 0, max = this.strokeIndices.length; i < max; i++) { 72097 this.edges.push(this.strokeIndices[i]); 72098 } 72099 } else { 72100 for (var j = 0; j < this.faces.length; j++) { 72101 this.edges.push([this.faces[j][0], this.faces[j][1]]); 72102 this.edges.push([this.faces[j][1], this.faces[j][2]]); 72103 this.edges.push([this.faces[j][2], this.faces[j][0]]); 72104 } 72105 } 72106 return this; 72107}; 72108 72109/** 72110 * Create 4 vertices for each stroke line, two at the beginning position 72111 * and two at the end position. These vertices are displaced relative to 72112 * that line's normal on the GPU 72113 * @private 72114 * @chainable 72115 */ 72116p5.Geometry.prototype._edgesToVertices = function() { 72117 this.lineVertices.length = 0; 72118 this.lineNormals.length = 0; 72119 72120 for (var i = 0; i < this.edges.length; i++) { 72121 var begin = this.vertices[this.edges[i][0]]; 72122 var end = this.vertices[this.edges[i][1]]; 72123 var dir = end 72124 .copy() 72125 .sub(begin) 72126 .normalize(); 72127 var a = begin.array(); 72128 var b = begin.array(); 72129 var c = end.array(); 72130 var d = end.array(); 72131 var dirAdd = dir.array(); 72132 var dirSub = dir.array(); 72133 // below is used to displace the pair of vertices at beginning and end 72134 // in opposite directions 72135 dirAdd.push(1); 72136 dirSub.push(-1); 72137 this.lineNormals.push(dirAdd, dirSub, dirAdd, dirAdd, dirSub, dirSub); 72138 this.lineVertices.push(a, b, c, c, b, d); 72139 } 72140 return this; 72141}; 72142 72143/** 72144 * Modifies all vertices to be centered within the range -100 to 100. 72145 * @method normalize 72146 * @chainable 72147 */ 72148p5.Geometry.prototype.normalize = function() { 72149 if (this.vertices.length > 0) { 72150 // Find the corners of our bounding box 72151 var maxPosition = this.vertices[0].copy(); 72152 var minPosition = this.vertices[0].copy(); 72153 72154 for (var i = 0; i < this.vertices.length; i++) { 72155 maxPosition.x = Math.max(maxPosition.x, this.vertices[i].x); 72156 minPosition.x = Math.min(minPosition.x, this.vertices[i].x); 72157 maxPosition.y = Math.max(maxPosition.y, this.vertices[i].y); 72158 minPosition.y = Math.min(minPosition.y, this.vertices[i].y); 72159 maxPosition.z = Math.max(maxPosition.z, this.vertices[i].z); 72160 minPosition.z = Math.min(minPosition.z, this.vertices[i].z); 72161 } 72162 72163 var center = p5.Vector.lerp(maxPosition, minPosition, 0.5); 72164 var dist = p5.Vector.sub(maxPosition, minPosition); 72165 var longestDist = Math.max(Math.max(dist.x, dist.y), dist.z); 72166 var scale = 200 / longestDist; 72167 72168 for (i = 0; i < this.vertices.length; i++) { 72169 this.vertices[i].sub(center); 72170 this.vertices[i].mult(scale); 72171 } 72172 } 72173 return this; 72174}; 72175 72176module.exports = p5.Geometry; 72177 72178},{"../core/core":22}],69:[function(_dereq_,module,exports){ 72179/** 72180 * @requires constants 72181 * @todo see methods below needing further implementation. 72182 * future consideration: implement SIMD optimizations 72183 * when browser compatibility becomes available 72184 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/ 72185 * Reference/Global_Objects/SIMD 72186 */ 72187 72188'use strict'; 72189 72190var p5 = _dereq_('../core/core'); 72191 72192var GLMAT_ARRAY_TYPE = Array; 72193var isMatrixArray = function(x) { 72194 return x instanceof Array; 72195}; 72196if (typeof Float32Array !== 'undefined') { 72197 GLMAT_ARRAY_TYPE = Float32Array; 72198 isMatrixArray = function(x) { 72199 return x instanceof Array || x instanceof Float32Array; 72200 }; 72201} 72202 72203/** 72204 * A class to describe a 4x4 matrix 72205 * for model and view matrix manipulation in the p5js webgl renderer. 72206 * @class p5.Matrix 72207 * @private 72208 * @constructor 72209 * @param {Array} [mat4] array literal of our 4x4 matrix 72210 */ 72211p5.Matrix = function() { 72212 var args = new Array(arguments.length); 72213 for (var i = 0; i < args.length; ++i) { 72214 args[i] = arguments[i]; 72215 } 72216 72217 // This is default behavior when object 72218 // instantiated using createMatrix() 72219 // @todo implement createMatrix() in core/math.js 72220 if (args.length && args[args.length - 1] instanceof p5) { 72221 this.p5 = args[args.length - 1]; 72222 } 72223 72224 if (args[0] === 'mat3') { 72225 this.mat3 = Array.isArray(args[1]) 72226 ? args[1] 72227 : new GLMAT_ARRAY_TYPE([1, 0, 0, 0, 1, 0, 0, 0, 1]); 72228 } else { 72229 this.mat4 = Array.isArray(args[0]) 72230 ? args[0] 72231 : new GLMAT_ARRAY_TYPE([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]); 72232 } 72233 return this; 72234}; 72235 72236/** 72237 * Sets the x, y, and z component of the vector using two or three separate 72238 * variables, the data from a p5.Matrix, or the values from a float array. 72239 * 72240 * @method set 72241 * @param {p5.Matrix|Float32Array|Number[]} [inMatrix] the input p5.Matrix or 72242 * an Array of length 16 72243 * @chainable 72244 */ 72245/** 72246 * @method set 72247 * @param {Number[]} elements 16 numbers passed by value to avoid 72248 * array copying. 72249 * @chainable 72250 */ 72251p5.Matrix.prototype.set = function(inMatrix) { 72252 if (inMatrix instanceof p5.Matrix) { 72253 this.mat4 = inMatrix.mat4; 72254 return this; 72255 } else if (isMatrixArray(inMatrix)) { 72256 this.mat4 = inMatrix; 72257 return this; 72258 } else if (arguments.length === 16) { 72259 this.mat4[0] = arguments[0]; 72260 this.mat4[1] = arguments[1]; 72261 this.mat4[2] = arguments[2]; 72262 this.mat4[3] = arguments[3]; 72263 this.mat4[4] = arguments[4]; 72264 this.mat4[5] = arguments[5]; 72265 this.mat4[6] = arguments[6]; 72266 this.mat4[7] = arguments[7]; 72267 this.mat4[8] = arguments[8]; 72268 this.mat4[9] = arguments[9]; 72269 this.mat4[10] = arguments[10]; 72270 this.mat4[11] = arguments[11]; 72271 this.mat4[12] = arguments[12]; 72272 this.mat4[13] = arguments[13]; 72273 this.mat4[14] = arguments[14]; 72274 this.mat4[15] = arguments[15]; 72275 } 72276 return this; 72277}; 72278 72279/** 72280 * Gets a copy of the vector, returns a p5.Matrix object. 72281 * 72282 * @method get 72283 * @return {p5.Matrix} the copy of the p5.Matrix object 72284 */ 72285p5.Matrix.prototype.get = function() { 72286 return new p5.Matrix(this.mat4, this.p5); 72287}; 72288 72289/** 72290 * return a copy of a matrix 72291 * @method copy 72292 * @return {p5.Matrix} the result matrix 72293 */ 72294p5.Matrix.prototype.copy = function() { 72295 var copied = new p5.Matrix(this.p5); 72296 copied.mat4[0] = this.mat4[0]; 72297 copied.mat4[1] = this.mat4[1]; 72298 copied.mat4[2] = this.mat4[2]; 72299 copied.mat4[3] = this.mat4[3]; 72300 copied.mat4[4] = this.mat4[4]; 72301 copied.mat4[5] = this.mat4[5]; 72302 copied.mat4[6] = this.mat4[6]; 72303 copied.mat4[7] = this.mat4[7]; 72304 copied.mat4[8] = this.mat4[8]; 72305 copied.mat4[9] = this.mat4[9]; 72306 copied.mat4[10] = this.mat4[10]; 72307 copied.mat4[11] = this.mat4[11]; 72308 copied.mat4[12] = this.mat4[12]; 72309 copied.mat4[13] = this.mat4[13]; 72310 copied.mat4[14] = this.mat4[14]; 72311 copied.mat4[15] = this.mat4[15]; 72312 return copied; 72313}; 72314 72315/** 72316 * return an identity matrix 72317 * @method identity 72318 * @return {p5.Matrix} the result matrix 72319 */ 72320p5.Matrix.identity = function(pInst) { 72321 return new p5.Matrix(pInst); 72322}; 72323 72324/** 72325 * transpose according to a given matrix 72326 * @method transpose 72327 * @param {p5.Matrix|Float32Array|Number[]} a the matrix to be 72328 * based on to transpose 72329 * @chainable 72330 */ 72331p5.Matrix.prototype.transpose = function(a) { 72332 var a01, a02, a03, a12, a13, a23; 72333 if (a instanceof p5.Matrix) { 72334 a01 = a.mat4[1]; 72335 a02 = a.mat4[2]; 72336 a03 = a.mat4[3]; 72337 a12 = a.mat4[6]; 72338 a13 = a.mat4[7]; 72339 a23 = a.mat4[11]; 72340 72341 this.mat4[0] = a.mat4[0]; 72342 this.mat4[1] = a.mat4[4]; 72343 this.mat4[2] = a.mat4[8]; 72344 this.mat4[3] = a.mat4[12]; 72345 this.mat4[4] = a01; 72346 this.mat4[5] = a.mat4[5]; 72347 this.mat4[6] = a.mat4[9]; 72348 this.mat4[7] = a.mat4[13]; 72349 this.mat4[8] = a02; 72350 this.mat4[9] = a12; 72351 this.mat4[10] = a.mat4[10]; 72352 this.mat4[11] = a.mat4[14]; 72353 this.mat4[12] = a03; 72354 this.mat4[13] = a13; 72355 this.mat4[14] = a23; 72356 this.mat4[15] = a.mat4[15]; 72357 } else if (isMatrixArray(a)) { 72358 a01 = a[1]; 72359 a02 = a[2]; 72360 a03 = a[3]; 72361 a12 = a[6]; 72362 a13 = a[7]; 72363 a23 = a[11]; 72364 72365 this.mat4[0] = a[0]; 72366 this.mat4[1] = a[4]; 72367 this.mat4[2] = a[8]; 72368 this.mat4[3] = a[12]; 72369 this.mat4[4] = a01; 72370 this.mat4[5] = a[5]; 72371 this.mat4[6] = a[9]; 72372 this.mat4[7] = a[13]; 72373 this.mat4[8] = a02; 72374 this.mat4[9] = a12; 72375 this.mat4[10] = a[10]; 72376 this.mat4[11] = a[14]; 72377 this.mat4[12] = a03; 72378 this.mat4[13] = a13; 72379 this.mat4[14] = a23; 72380 this.mat4[15] = a[15]; 72381 } 72382 return this; 72383}; 72384 72385/** 72386 * invert matrix according to a give matrix 72387 * @method invert 72388 * @param {p5.Matrix|Float32Array|Number[]} a the matrix to be 72389 * based on to invert 72390 * @chainable 72391 */ 72392p5.Matrix.prototype.invert = function(a) { 72393 var a00, a01, a02, a03, a10, a11, a12, a13; 72394 var a20, a21, a22, a23, a30, a31, a32, a33; 72395 if (a instanceof p5.Matrix) { 72396 a00 = a.mat4[0]; 72397 a01 = a.mat4[1]; 72398 a02 = a.mat4[2]; 72399 a03 = a.mat4[3]; 72400 a10 = a.mat4[4]; 72401 a11 = a.mat4[5]; 72402 a12 = a.mat4[6]; 72403 a13 = a.mat4[7]; 72404 a20 = a.mat4[8]; 72405 a21 = a.mat4[9]; 72406 a22 = a.mat4[10]; 72407 a23 = a.mat4[11]; 72408 a30 = a.mat4[12]; 72409 a31 = a.mat4[13]; 72410 a32 = a.mat4[14]; 72411 a33 = a.mat4[15]; 72412 } else if (isMatrixArray(a)) { 72413 a00 = a[0]; 72414 a01 = a[1]; 72415 a02 = a[2]; 72416 a03 = a[3]; 72417 a10 = a[4]; 72418 a11 = a[5]; 72419 a12 = a[6]; 72420 a13 = a[7]; 72421 a20 = a[8]; 72422 a21 = a[9]; 72423 a22 = a[10]; 72424 a23 = a[11]; 72425 a30 = a[12]; 72426 a31 = a[13]; 72427 a32 = a[14]; 72428 a33 = a[15]; 72429 } 72430 var b00 = a00 * a11 - a01 * a10; 72431 var b01 = a00 * a12 - a02 * a10; 72432 var b02 = a00 * a13 - a03 * a10; 72433 var b03 = a01 * a12 - a02 * a11; 72434 var b04 = a01 * a13 - a03 * a11; 72435 var b05 = a02 * a13 - a03 * a12; 72436 var b06 = a20 * a31 - a21 * a30; 72437 var b07 = a20 * a32 - a22 * a30; 72438 var b08 = a20 * a33 - a23 * a30; 72439 var b09 = a21 * a32 - a22 * a31; 72440 var b10 = a21 * a33 - a23 * a31; 72441 var b11 = a22 * a33 - a23 * a32; 72442 72443 // Calculate the determinant 72444 var det = 72445 b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; 72446 72447 if (!det) { 72448 return null; 72449 } 72450 det = 1.0 / det; 72451 72452 this.mat4[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det; 72453 this.mat4[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det; 72454 this.mat4[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det; 72455 this.mat4[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det; 72456 this.mat4[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det; 72457 this.mat4[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det; 72458 this.mat4[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det; 72459 this.mat4[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det; 72460 this.mat4[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det; 72461 this.mat4[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det; 72462 this.mat4[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det; 72463 this.mat4[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det; 72464 this.mat4[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det; 72465 this.mat4[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det; 72466 this.mat4[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det; 72467 this.mat4[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det; 72468 72469 return this; 72470}; 72471 72472/** 72473 * Inverts a 3x3 matrix 72474 * @method invert3x3 72475 * @chainable 72476 */ 72477p5.Matrix.prototype.invert3x3 = function() { 72478 var a00 = this.mat3[0]; 72479 var a01 = this.mat3[1]; 72480 var a02 = this.mat3[2]; 72481 var a10 = this.mat3[3]; 72482 var a11 = this.mat3[4]; 72483 var a12 = this.mat3[5]; 72484 var a20 = this.mat3[6]; 72485 var a21 = this.mat3[7]; 72486 var a22 = this.mat3[8]; 72487 var b01 = a22 * a11 - a12 * a21; 72488 var b11 = -a22 * a10 + a12 * a20; 72489 var b21 = a21 * a10 - a11 * a20; 72490 72491 // Calculate the determinant 72492 var det = a00 * b01 + a01 * b11 + a02 * b21; 72493 if (!det) { 72494 return null; 72495 } 72496 det = 1.0 / det; 72497 this.mat3[0] = b01 * det; 72498 this.mat3[1] = (-a22 * a01 + a02 * a21) * det; 72499 this.mat3[2] = (a12 * a01 - a02 * a11) * det; 72500 this.mat3[3] = b11 * det; 72501 this.mat3[4] = (a22 * a00 - a02 * a20) * det; 72502 this.mat3[5] = (-a12 * a00 + a02 * a10) * det; 72503 this.mat3[6] = b21 * det; 72504 this.mat3[7] = (-a21 * a00 + a01 * a20) * det; 72505 this.mat3[8] = (a11 * a00 - a01 * a10) * det; 72506 return this; 72507}; 72508 72509/** 72510 * transposes a 3x3 p5.Matrix by a mat3 72511 * @method transpose3x3 72512 * @param {Number[]} mat3 1-dimensional array 72513 * @chainable 72514 */ 72515p5.Matrix.prototype.transpose3x3 = function(mat3) { 72516 var a01 = mat3[1], 72517 a02 = mat3[2], 72518 a12 = mat3[5]; 72519 this.mat3[1] = mat3[3]; 72520 this.mat3[2] = mat3[6]; 72521 this.mat3[3] = a01; 72522 this.mat3[5] = mat3[7]; 72523 this.mat3[6] = a02; 72524 this.mat3[7] = a12; 72525 return this; 72526}; 72527 72528/** 72529 * converts a 4x4 matrix to its 3x3 inverse tranform 72530 * commonly used in MVMatrix to NMatrix conversions. 72531 * @method invertTranspose 72532 * @param {p5.Matrix} mat4 the matrix to be based on to invert 72533 * @chainable 72534 * @todo finish implementation 72535 */ 72536p5.Matrix.prototype.inverseTranspose = function(matrix) { 72537 if (this.mat3 === undefined) { 72538 console.error('sorry, this function only works with mat3'); 72539 } else { 72540 //convert mat4 -> mat3 72541 this.mat3[0] = matrix.mat4[0]; 72542 this.mat3[1] = matrix.mat4[1]; 72543 this.mat3[2] = matrix.mat4[2]; 72544 this.mat3[3] = matrix.mat4[4]; 72545 this.mat3[4] = matrix.mat4[5]; 72546 this.mat3[5] = matrix.mat4[6]; 72547 this.mat3[6] = matrix.mat4[8]; 72548 this.mat3[7] = matrix.mat4[9]; 72549 this.mat3[8] = matrix.mat4[10]; 72550 } 72551 72552 var inverse = this.invert3x3(); 72553 // check inverse succeded 72554 if (inverse) { 72555 inverse.transpose3x3(this.mat3); 72556 } else { 72557 // in case of singularity, just zero the matrix 72558 for (var i = 0; i < 9; i++) { 72559 this.mat
725593[i] = 0; 72560 } 72561 } 72562 return this; 72563}; 72564 72565/** 72566 * inspired by Toji's mat4 determinant 72567 * @method determinant 72568 * @return {Number} Determinant of our 4x4 matrix 72569 */ 72570p5.Matrix.prototype.determinant = function() { 72571 var d00 = this.mat4[0] * this.mat4[5] - this.mat4[1] * this.mat4[4], 72572 d01 = this.mat4[0] * this.mat4[6] - this.mat4[2] * this.mat4[4], 72573 d02 = this.mat4[0] * this.mat4[7] - this.mat4[3] * this.mat4[4], 72574 d03 = this.mat4[1] * this.mat4[6] - this.mat4[2] * this.mat4[5], 72575 d04 = this.mat4[1] * this.mat4[7] - this.mat4[3] * this.mat4[5], 72576 d05 = this.mat4[2] * this.mat4[7] - this.mat4[3] * this.mat4[6], 72577 d06 = this.mat4[8] * this.mat4[13] - this.mat4[9] * this.mat4[12], 72578 d07 = this.mat4[8] * this.mat4[14] - this.mat4[10] * this.mat4[12], 72579 d08 = this.mat4[8] * this.mat4[15] - this.mat4[11] * this.mat4[12], 72580 d09 = this.mat4[9] * this.mat4[14] - this.mat4[10] * this.mat4[13], 72581 d10 = this.mat4[9] * this.mat4[15] - this.mat4[11] * this.mat4[13], 72582 d11 = this.mat4[10] * this.mat4[15] - this.mat4[11] * this.mat4[14]; 72583 72584 // Calculate the determinant 72585 return d00 * d11 - d01 * d10 + d02 * d09 + d03 * d08 - d04 * d07 + d05 * d06; 72586}; 72587 72588/** 72589 * multiply two mat4s 72590 * @method mult 72591 * @param {p5.Matrix|Float32Array|Number[]} multMatrix The matrix 72592 * we want to multiply by 72593 * @chainable 72594 */ 72595p5.Matrix.prototype.mult = function(multMatrix) { 72596 var _src; 72597 72598 if (multMatrix === this || multMatrix === this.mat4) { 72599 _src = this.copy().mat4; // only need to allocate in this rare case 72600 } else if (multMatrix instanceof p5.Matrix) { 72601 _src = multMatrix.mat4; 72602 } else if (isMatrixArray(multMatrix)) { 72603 _src = multMatrix; 72604 } else { 72605 return; // nothing to do. 72606 } 72607 72608 // each row is used for the multiplier 72609 var b0 = this.mat4[0], 72610 b1 = this.mat4[1], 72611 b2 = this.mat4[2], 72612 b3 = this.mat4[3]; 72613 this.mat4[0] = b0 * _src[0] + b1 * _src[4] + b2 * _src[8] + b3 * _src[12]; 72614 this.mat4[1] = b0 * _src[1] + b1 * _src[5] + b2 * _src[9] + b3 * _src[13]; 72615 this.mat4[2] = b0 * _src[2] + b1 * _src[6] + b2 * _src[10] + b3 * _src[14]; 72616 this.mat4[3] = b0 * _src[3] + b1 * _src[7] + b2 * _src[11] + b3 * _src[15]; 72617 72618 b0 = this.mat4[4]; 72619 b1 = this.mat4[5]; 72620 b2 = this.mat4[6]; 72621 b3 = this.mat4[7]; 72622 this.mat4[4] = b0 * _src[0] + b1 * _src[4] + b2 * _src[8] + b3 * _src[12]; 72623 this.mat4[5] = b0 * _src[1] + b1 * _src[5] + b2 * _src[9] + b3 * _src[13]; 72624 this.mat4[6] = b0 * _src[2] + b1 * _src[6] + b2 * _src[10] + b3 * _src[14]; 72625 this.mat4[7] = b0 * _src[3] + b1 * _src[7] + b2 * _src[11] + b3 * _src[15]; 72626 72627 b0 = this.mat4[8]; 72628 b1 = this.mat4[9]; 72629 b2 = this.mat4[10]; 72630 b3 = this.mat4[11]; 72631 this.mat4[8] = b0 * _src[0] + b1 * _src[4] + b2 * _src[8] + b3 * _src[12]; 72632 this.mat4[9] = b0 * _src[1] + b1 * _src[5] + b2 * _src[9] + b3 * _src[13]; 72633 this.mat4[10] = b0 * _src[2] + b1 * _src[6] + b2 * _src[10] + b3 * _src[14]; 72634 this.mat4[11] = b0 * _src[3] + b1 * _src[7] + b2 * _src[11] + b3 * _src[15]; 72635 72636 b0 = this.mat4[12]; 72637 b1 = this.mat4[13]; 72638 b2 = this.mat4[14]; 72639 b3 = this.mat4[15]; 72640 this.mat4[12] = b0 * _src[0] + b1 * _src[4] + b2 * _src[8] + b3 * _src[12]; 72641 this.mat4[13] = b0 * _src[1] + b1 * _src[5] + b2 * _src[9] + b3 * _src[13]; 72642 this.mat4[14] = b0 * _src[2] + b1 * _src[6] + b2 * _src[10] + b3 * _src[14]; 72643 this.mat4[15] = b0 * _src[3] + b1 * _src[7] + b2 * _src[11] + b3 * _src[15]; 72644 72645 return this; 72646}; 72647 72648/** 72649 * scales a p5.Matrix by scalars or a vector 72650 * @method scale 72651 * @param {p5.Vector|Float32Array|Number[]} s vector to scale by 72652 * @chainable 72653 */ 72654p5.Matrix.prototype.scale = function(x, y, z) { 72655 if (x instanceof p5.Vector) { 72656 // x is a vector, extract the components from it. 72657 y = x.y; 72658 z = x.z; 72659 x = x.x; // must be last 72660 } else if (x instanceof Array) { 72661 // x is an array, extract the components from it. 72662 y = x[1]; 72663 z = x[2]; 72664 x = x[0]; // must be last 72665 } 72666 72667 this.mat4[0] *= x; 72668 this.mat4[1] *= x; 72669 this.mat4[2] *= x; 72670 this.mat4[3] *= x; 72671 this.mat4[4] *= y; 72672 this.mat4[5] *= y; 72673 this.mat4[6] *= y; 72674 this.mat4[7] *= y; 72675 this.mat4[8] *= z; 72676 this.mat4[9] *= z; 72677 this.mat4[10] *= z; 72678 this.mat4[11] *= z; 72679 72680 return this; 72681}; 72682 72683/** 72684 * rotate our Matrix around an axis by the given angle. 72685 * @method rotate 72686 * @param {Number} a The angle of rotation in radians 72687 * @param {p5.Vector|Number[]} axis the axis(es) to rotate around 72688 * @chainable 72689 * inspired by Toji's gl-matrix lib, mat4 rotation 72690 */ 72691p5.Matrix.prototype.rotate = function(a, x, y, z) { 72692 var _a = this.p5 ? this.p5._toRadians(a) : a; 72693 72694 if (x instanceof p5.Vector) { 72695 // x is a vector, extract the components from it. 72696 y = x.y; 72697 z = x.z; 72698 x = x.x; //must be last 72699 } else if (x instanceof Array) { 72700 // x is an array, extract the components from it. 72701 y = x[1]; 72702 z = x[2]; 72703 x = x[0]; //must be last 72704 } 72705 72706 var len = Math.sqrt(x * x + y * y + z * z); 72707 x *= 1 / len; 72708 y *= 1 / len; 72709 z *= 1 / len; 72710 72711 var a00 = this.mat4[0]; 72712 var a01 = this.mat4[1]; 72713 var a02 = this.mat4[2]; 72714 var a03 = this.mat4[3]; 72715 var a10 = this.mat4[4]; 72716 var a11 = this.mat4[5]; 72717 var a12 = this.mat4[6]; 72718 var a13 = this.mat4[7]; 72719 var a20 = this.mat4[8]; 72720 var a21 = this.mat4[9]; 72721 var a22 = this.mat4[10]; 72722 var a23 = this.mat4[11]; 72723 72724 //sin,cos, and tan of respective angle 72725 var sA = Math.sin(_a);
72726 var cA = Math.cos(_a); 72727 var tA = 1 - cA; 72728 // Construct the elements of the rotation matrix 72729 var b00 = x * x * tA + cA; 72730 var b01 = y * x * tA + z * sA; 72731 var b02 = z * x * tA - y * sA; 72732 var b10 = x * y * tA - z * sA; 72733 var b11 = y * y * tA + cA; 72734 var b12 = z * y * tA + x * sA; 72735 var b20 = x * z * tA + y * sA; 72736 var b21 = y * z * tA - x * sA; 72737 var b22 = z * z * tA + cA; 72738 72739 // rotation-specific matrix multiplication 72740 this.mat4[0] = a00 * b00 + a10 * b01 + a20 * b02; 72741 this.mat4[1] = a01 * b00 + a11 * b01 + a21 * b02; 72742 this.mat4[2] = a02 * b00 + a12 * b01 + a22 * b02; 72743 this.mat4[3] = a03 * b00 + a13 * b01 + a23 * b02; 72744 this.mat4[4] = a00 * b10 + a10 * b11 + a20 * b12; 72745 this.mat4[5] = a01 * b10 + a11 * b11 + a21 * b12; 72746 this.mat4[6] = a02 * b10 + a12 * b11 + a22 * b12; 72747 this.mat4[7] = a03 * b10 + a13 * b11 + a23 * b12; 72748 this.mat4[8] = a00 * b20 + a10 * b21 + a20 * b22; 72749 this.mat4[9] = a01 * b20 + a11 * b21 + a21 * b22; 72750 this.mat4[10] = a02 * b20 + a12 * b21 + a22 * b22; 72751 this.mat4[11] = a03 * b20 + a13 * b21 + a23 * b22; 72752 72753 return this; 72754}; 72755 72756/** 72757 * @todo finish implementing this method! 72758 * translates 72759 * @method translate 72760 * @param {Number[]} v vector to translate by 72761 * @chainable 72762 */ 72763p5.Matrix.prototype.translate = function(v) { 72764 var x = v[0], 72765 y = v[1], 72766 z = v[2] || 0; 72767 this.mat4[12] += this.mat4[0] * x + this.mat4[4] * y + this.mat4[8] * z; 72768 this.mat4[13] += this.mat4[1] * x + this.mat4[5] * y + this.mat4[9] * z; 72769 this.mat4[14] += this.mat4[2] * x + this.mat4[6] * y + this.mat4[10] * z; 72770 this.mat4[15] += this.mat4[3] * x + this.mat4[7] * y + this.mat4[11] * z; 72771}; 72772 72773p5.Matrix.prototype.rotateX = function(a) { 72774 this.rotate(a, 1, 0, 0); 72775}; 72776p5.Matrix.prototype.rotateY = function(a) { 72777 this.rotate(a, 0, 1, 0); 72778}; 72779p5.Matrix.prototype.rotateZ = function(a) { 72780 this.rotate(a, 0, 0, 1); 72781}; 72782 72783/** 72784 * sets the perspective matrix 72785 * @method perspective 72786 * @param {Number} fovy [description] 72787 * @param {Number} aspect [description] 72788 * @param {Number} near near clipping plane 72789 * @param {Number} far far clipping plane 72790 * @chainable 72791 */ 72792p5.Matrix.prototype.perspective = function(fovy, aspect, near, far) { 72793 var f = 1.0 / Math.tan(fovy / 2), 72794 nf = 1 / (near - far); 72795 72796 this.mat4[0] = f / aspect; 72797 this.mat4[1] = 0; 72798 this.mat4[2] = 0; 72799 this.mat4[3] = 0; 72800 this.mat4[4] = 0; 72801 this.mat4[5] = f; 72802 this.mat4[6] = 0; 72803 this.mat4[7] = 0; 72804 this.mat4[8] = 0; 72805 this.mat4[9] = 0; 72806 this.mat4[10] = (far + near) * nf; 72807 this.mat4[11] = -1; 72808 this.mat4[12] = 0; 72809 this.mat4[13] = 0; 72810 this.mat4[14] = 2 * far * near * nf; 72811 this.mat4[15] = 0; 72812 72813 return this; 72814}; 72815 72816/** 72817 * sets the ortho matrix 72818 * @method ortho 72819 * @param {Number} left [description] 72820 * @param {Number} right [description] 72821 * @param {Number} bottom [description] 72822 * @param {Number} top [description] 72823 * @param {Number} near near clipping plane 72824 * @param {Number} far far clipping plane 72825 * @chainable 72826 */ 72827p5.Matrix.prototype.ortho = function(left, right, bottom, top, near, far) { 72828 var lr = 1 / (left - right), 72829 bt = 1 / (bottom - top), 72830 nf = 1 / (near - far); 72831 this.mat4[0] = -2 * lr; 72832 this.mat4[1] = 0; 72833 this.mat4[2] = 0; 72834 this.mat4[3] = 0; 72835 this.mat4[4] = 0; 72836 this.mat4[5] = -2 * bt; 72837 this.mat4[6] = 0; 72838 this.mat4[7] = 0; 72839 this.mat4[8] = 0; 72840 this.mat4[9] = 0; 72841 this.mat4[10] = 2 * nf; 72842 this.mat4[11] = 0; 72843 this.mat4[12] = (left + right) * lr; 72844 this.mat4[13] = (top + bottom) * bt; 72845 this.mat4[14] = (far + near) * nf; 72846 this.mat4[15] = 1; 72847 72848 return this; 72849}; 72850 72851/** 72852 * PRIVATE 72853 */ 72854// matrix methods adapted from: 72855// https://developer.mozilla.org/en-US/docs/Web/WebGL/ 72856// gluPerspective 72857// 72858// function _makePerspective(fovy, aspect, znear, zfar){ 72859// var ymax = znear * Math.tan(fovy * Math.PI / 360.0); 72860// var ymin = -ymax; 72861// var xmin = ymin * aspect; 72862// var xmax = ymax * aspect; 72863// return _makeFrustum(xmin, xmax, ymin, ymax, znear, zfar); 72864// } 72865 72866//// 72867//// glFrustum 72868//// 72869//function _makeFrustum(left, right, bottom, top, znear, zfar){ 72870// var X = 2*znear/(right-left); 72871// var Y = 2*znear/(top-bottom); 72872// var A = (right+left)/(right-left); 72873// var B = (top+bottom)/(top-bottom); 72874// var C = -(zfar+znear)/(zfar-znear); 72875// var D = -2*zfar*znear/(zfar-znear); 72876// var frustrumMatrix =[
72877// X, 0, A, 0, 72878// 0, Y, B, 0, 72879// 0, 0, C, D, 72880// 0, 0, -1, 0 72881//]; 72882//return frustrumMatrix; 72883// } 72884 72885// function _setMVPMatrices(){ 72886////an identity matrix 72887////@TODO use the p5.Matrix class to abstract away our MV matrices and 72888///other math 72889//var _mvMatrix = 72890//[ 72891// 1.0,0.0,0.0,0.0, 72892// 0.0,1.0,0.0,0.0, 72893// 0.0,0.0,1.0,0.0, 72894// 0.0,0.0,0.0,1.0 72895//]; 72896 72897module.exports = p5.Matrix; 72898 72899},{"../core/core":22}],70:[function(_dereq_,module,exports){ 72900/** 72901 * Welcome to RendererGL Immediate Mode. 72902 * Immediate mode is used for drawing custom shapes 72903 * from a set of vertices. Immediate Mode is activated 72904 * when you call beginShape() & de-activated when you call endShape(). 72905 * Immediate mode is a style of programming borrowed 72906 * from OpenGL's (now-deprecated) immediate mode. 72907 * It differs from p5.js' default, Retained Mode, which caches 72908 * geometries and buffers on the CPU to reduce the number of webgl 72909 * draw calls. Retained mode is more efficient & performative, 72910 * however, Immediate Mode is useful for sketching quick 72911 * geometric ideas. 72912 */ 72913'use strict'; 72914 72915var p5 = _dereq_('../core/core'); 72916var constants = _dereq_('../core/constants'); 72917 72918/** 72919 * Begin shape drawing. This is a helpful way of generating 72920 * custom shapes quickly. However in WEBGL mode, application 72921 * performance will likely drop as a result of too many calls to 72922 * beginShape() / endShape(). As a high performance alternative, 72923 * please use p5.js geometry primitives. 72924 * @private 72925 * @method beginShape 72926 * @param {Number} mode webgl primitives mode. beginShape supports the 72927 * following modes: 72928 * POINTS,LINES,LINE_STRIP,LINE_LOOP,TRIANGLES, 72929 * TRIANGLE_STRIP,and TRIANGLE_FAN. 72930 * @chainable 72931 */ 72932p5.RendererGL.prototype.beginShape = function(mode) { 72933 //default shape mode is line_strip 72934 this.immediateMode.shapeMode = 72935 mode !== undefined ? mode : constants.LINE_STRIP; 72936 //if we haven't yet initialized our 72937 //immediateMode vertices & buffers, create them now! 72938 if (this.immediateMode.vertices === undefined) { 72939 this.immediateMode.vertices = []; 72940 this.immediateMode.edges = []; 72941 this.immediateMode.lineVertices = []; 72942 this.immediateMode.vertexColors = []; 72943 this.immediateMode.lineNormals = []; 72944 this.immediateMode.uvCoords = []; 72945 this.immediateMode.vertexBuffer = this.GL.createBuffer(); 72946 this.immediateMode.colorBuffer = this.GL.createBuffer(); 72947 this.immediateMode.uvBuffer = this.GL.createBuffer(); 72948 this.immediateMode.lineVertexBuffer = this.GL.createBuffer(); 72949 this.immediateMode.lineNormalBuffer = this.GL.createBuffer(); 72950 } else { 72951 this.immediateMode.vertices.length = 0; 72952 this.immediateMode.edges.length = 0; 72953 this.immediateMode.lineVertices.length = 0; 72954 this.immediateMode.lineNormals.length = 0; 72955 this.immediateMode.vertexColors.length = 0; 72956 this.immediateMode.uvCoords.length = 0; 72957 } 72958 this.isImmediateDrawing = true; 72959 return this; 72960}; 72961/** 72962 * adds a vertex to be drawn in a custom Shape. 72963 * @private 72964 * @method vertex 72965 * @param {Number} x x-coordinate of vertex 72966 * @param {Number} y y-coordinate of vertex 72967 * @param {Number} z z-coordinate of vertex 72968 * @chainable 72969 * @TODO implement handling of p5.Vector args 72970 */ 72971p5.RendererGL.prototype.vertex = function(x, y) { 72972 var z, u, v; 72973 72974 // default to (x, y) mode: all other arugments assumed to be 0. 72975 z = u = v = 0; 72976 72977 if (arguments.length === 3) { 72978 // (x, y, z) mode: (u, v) assumed to be 0. 72979 z = arguments[2]; 72980 } else if (arguments.length === 4) { 72981 // (x, y, u, v) mode: z assumed to be 0. 72982 u = arguments[2]; 72983 v = arguments[3]; 72984 } else if (arguments.length === 5) { 72985 // (x, y, z, u, v) mode 72986 z = arguments[2]; 72987 u = arguments[3]; 72988 v = arguments[4]; 72989 } 72990 var vert = new p5.Vector(x, y, z); 72991 this.immediateMode.vertices.push(vert); 72992 var vertexColor = this.curFillColor || [0.5, 0.5, 0.5, 1.0]; 72993 this.immediateMode.vertexColors.push( 72994 vertexColor[0], 72995 vertexColor[1], 72996 vertexColor[2], 72997 vertexColor[3] 72998 ); 72999 73000 this.immediateMode.uvCoords.push(u, v); 73001 73002 return this; 73003}; 73004 73005/** 73006 * End shape drawing and render vertices to screen. 73007 * @chainable 73008 */ 73009p5.RendererGL.prototype.endShape = function( 73010 mode, 73011 isCurve, 73012 isBezier, 73013 isQuadratic, 73014 isContour, 73015 shapeKind 73016) { 73017 this._useImmediateModeShader(); 73018 73019 if (this._doStroke && this.drawMode !== constants.TEXTURE) { 73020 for (var i = 0; i < this.immediateMode.vertices.length - 1; i++) { 73021 this.immediateMode.edges.push([i, i + 1]); 73022 } 73023 if (mode === constants.CLOSE) { 73024 this.immediateMode.edges.push([ 73025 this.immediateMode.vertices.length - 1, 73026 0 73027 ]); 73028 } 73029 73030 p5.Geometry.prototype._edgesToVertices.call(this.immediateMode); 73031 this._drawStrokeImmediateMode(); 73032 } 73033 if (this._doFill) { 73034 this._drawFillImmediateMode( 73035 mode, 73036 isCurve, 73037 isBezier, 73038 isQuadratic, 73039 isContour, 73040 shapeKind 73041 ); 73042 } 73043 //clear out our vertexPositions & colors arrays 73044 //after rendering 73045 this.immediateMode.vertices.length = 0; 73046 this.immediateMode.vertexColors.length = 0; 73047 this.immediateMode.uvCoords.length = 0; 73048 this.isImmediateDrawing = false;
73049 73050 return this; 73051}; 73052 73053p5.RendererGL.prototype._drawFillImmediateMode = function( 73054 mode, 73055 isCurve, 73056 isBezier, 73057 isQuadratic, 73058 isContour, 73059 shapeKind 73060) { 73061 var gl = this.GL; 73062 this.curFillShader.bindShader(); 73063 73064 // initialize the fill shader's 'aPosition' buffer 73065 if (this.curFillShader.attributes.aPosition) { 73066 //vertex position Attribute 73067 this._bindBuffer( 73068 this.immediateMode.vertexBuffer, 73069 gl.ARRAY_BUFFER, 73070 this._vToNArray(this.immediateMode.vertices), 73071 Float32Array, 73072 gl.DYNAMIC_DRAW 73073 ); 73074 73075 this.curFillShader.enableAttrib( 73076 this.curFillShader.attributes.aPosition.location, 73077 3, 73078 gl.FLOAT, 73079 false, 73080 0, 73081 0 73082 ); 73083 } 73084 73085 // initialize the fill shader's 'aVertexColor' buffer 73086 if ( 73087 this.drawMode === constants.FILL && 73088 this.curFillShader.attributes.aVertexColor 73089 ) { 73090 this._bindBuffer( 73091 this.immediateMode.colorBuffer, 73092 gl.ARRAY_BUFFER, 73093 this.immediateMode.vertexColors, 73094 Float32Array, 73095 gl.DYNAMIC_DRAW 73096 ); 73097 73098 this.curFillShader.enableAttrib( 73099 this.curFillShader.attributes.aVertexColor.location, 73100 4, 73101 gl.FLOAT, 73102 false, 73103 0, 73104 0 73105 ); 73106 } 73107 73108 // initialize the fill shader's 'aTexCoord' buffer 73109 if ( 73110 this.drawMode === constants.TEXTURE && 73111 this.curFillShader.attributes.aTexCoord 73112 ) { 73113 //texture coordinate Attribute 73114 this._bindBuffer( 73115 this.immediateMode.uvBuffer, 73116 gl.ARRAY_BUFFER, 73117 this.immediateMode.uvCoords, 73118 Float32Array, 73119 gl.DYNAMIC_DRAW 73120 ); 73121 73122 this.curFillShader.enableAttrib( 73123 this.curFillShader.attributes.aTexCoord.location, 73124 2, 73125 gl.FLOAT, 73126 false, 73127 0, 73128 0 73129 ); 73130 } 73131 73132 //if (true || mode) { 73133 if (this.drawMode === constants.FILL || this.drawMode === constants.TEXTURE) { 73134 switch (this.immediateMode.shapeMode) { 73135 case constants.LINE_STRIP: 73136 case constants.LINES: 73137 case constants.TRIANGLES: 73138 this.immediateMode.shapeMode = constants.TRIANGLE_FAN; 73139 break; 73140 } 73141 } else { 73142 switch (this.immediateMode.shapeMode) { 73143 case constants.LINE_STRIP: 73144 case constants.LINES: 73145 this.immediateMode.shapeMode = constants.LINE_LOOP; 73146 break; 73147 } 73148 } 73149 //} 73150 //QUADS & QUAD_STRIP are not supported primitives modes 73151 //in webgl. 73152 if ( 73153 this.immediateMode.shapeMode === constants.QUADS || 73154 this.immediateMode.shapeMode === constants.QUAD_STRIP 73155 ) { 73156 throw new Error( 73157 'sorry, ' + 73158 this.immediateMode.shapeMode + 73159 ' not yet implemented in webgl mode.' 73160 ); 73161 } else { 73162 this._applyColorBlend(this.curFillColor); 73163 gl.enable(gl.BLEND); 73164 gl.drawArrays( 73165 this.immediateMode.shapeMode, 73166 0, 73167 this.immediateMode.vertices.length 73168 ); 73169 } 73170 // todo / optimizations? leave bound until another shader is set? 73171 this.curFillShader.unbindShader(); 73172}; 73173 73174p5.RendererGL.prototype._drawStrokeImmediateMode = function() { 73175 var gl = this.GL; 73176 this.curStrokeShader.bindShader(); 73177 73178 // initialize the stroke shader's 'aPosition' buffer 73179 if (this.curStrokeShader.attributes.aPosition) { 73180 this._bindBuffer( 73181 this.immediateMode.lineVertexBuffer, 73182 gl.ARRAY_BUFFER, 73183 this._flatten(this.immediateMode.lineVertices), 73184 Float32Array, 73185 gl.STATIC_DRAW 73186 ); 73187 73188 this.curStrokeShader.enableAttrib( 73189 this.curStrokeShader.attributes.aPosition.location, 73190 3, 73191 gl.FLOAT, 73192 false, 73193 0, 73194 0 73195 ); 73196 } 73197 73198 // initialize the stroke shader's 'aDirection' buffer 73199 if (this.curStrokeShader.attributes.aDirection) { 73200 this._bindBuffer( 73201 this.immediateMode.lineNormalBuffer, 73202 gl.ARRAY_BUFFER, 73203 this._flatten(this.immediateMode.lineNormals), 73204 Float32Array, 73205 gl.STATIC_DRAW 73206 ); 73207 this.curStrokeShader.enableAttrib( 73208 this.curStrokeShader.attributes.aDirection.location, 73209 4, 73210 gl.FLOAT, 73211 false, 73212 0, 73213 0 73214 ); 73215 } 73216 73217 this._applyColorBlend(this.curStrokeColor); 73218 gl.drawArrays(gl.TRIANGLES, 0, this.immediateMode.lineVertices.length); 73219 73220 // todo / optimizations? leave bound until another shader is set? 73221 this.curStrokeShader.unbindShader(); 73222}; 73223 73224module.exports = p5.RendererGL; 73225 73226},{"../core/constants":21,"../core/core":22}],71:[function(_dereq_,module,exports){ 73227//Retained Mode. The default mode for rendering 3D primitives 73228//in WEBGL. 73229'use strict'; 73230 73231var p5 = _dereq_('../core/core'); 73232 73233var hashCount = 0; 73234/** 73235 * _initBufferDefaults 73236 * @private 73237 * @description initializes buffer defaults. runs each time a new geometry is 73238 * registered 73239 * @param {String} gId key of the geometry object 73240 */ 73241p5.RendererGL.prototype._initBufferDefaults = function(gId) { 73242 this._freeBuffers(gId); 73243 73244 //@TODO remove this limit on hashes in gHash 73245 hashCount++; 73246 if (hashCount > 1000) { 73247 var key = Object.keys(this.gHash)[0]; 73248 delete this.gHash[key]; 73249 hashCount--; 73250 } 73251 73252 //create a new entry in our gHash 73253 this.gHash[gId] = {}; 73254}; 73255 73256p5.RendererGL.prototype._freeBuffers = function(gId) { 73257 var geometry = this.gHash[gId]; 73258 if (!geometry) { 73259 return; 73260 } 73261 73262 delete this.gHash[gId]; 73263 hashCount--; 73264 73265 var gl = this.GL; 73266 geometry.vertexBuffer && gl.deleteBuffer(geometry.vertexBuffer); 73267 geometry.normalBuffer && gl.deleteBuffer(geometry.normalBuffer); 73268 geometry.lineNormalBuffer && gl.deleteBuffer(geometry.lineNormalBuffer); 73269 geometry.uvBuffer && gl.deleteBuffer(geometry.uvBuffer); 73270 geometry.indexBuffer && gl.deleteBuffer(geometry.indexBuffer); 73271 geometry.lineVertexBuffer && gl.deleteBuffer(geometry.lineVertexBuffer); 73272}; 73273/** 73274 * createBuffers description 73275 * @private 73276 * @param {String} gId key of the geometry object 73277 * @param {p5.Geometry} obj contains geometry data 73278 */ 73279p5.RendererGL.prototype.createBuffers = function(gId, obj) { 73280 var gl = this.GL; 73281 this._setDefaultCamera(); 73282 //initialize the gl buffers for our geom groups 73283 this._initBufferDefaults(gId); 73284 73285 var geometry = this.gHash[gId]; 73286 73287 geometry.numberOfItems = obj.faces.length * 3; 73288 geometry.lineVertexCount = obj.lineVertices.length; 73289 73290 this._useColorShader(); 73291 73292 // initialize the stroke shader's 'aPosition' buffer, if used 73293 if (this.curStrokeShader.attributes.aPosition) { 73294 geometry.lineVertexBuffer = gl.createBuffer(); 73295 73296 this._bindBuffer( 73297 geometry.lineVertexBuffer, 73298 gl.ARRAY_BUFFER, 73299 this._flatten(obj.lineVertices), 73300 Float32Array, 73301 gl.STATIC_DRAW 73302 ); 73303 73304 this.curStrokeShader.enableAttrib( 73305 this.curStrokeShader.attributes.aPosition.location, 73306 3, 73307 gl.FLOAT, 73308 false, 73309 0, 73310 0 73311 ); 73312 } 73313 73314 // initialize the stroke shader's 'aDirection' buffer, if used 73315 if (this.curStrokeShader.attributes.aDirection) { 73316 geometry.lineNormalBuffer = gl.createBuffer(); 73317 73318 this._bindBuffer( 73319 geometry.lineNormalBuffer, 73320 gl.ARRAY_BUFFER, 73321 this._flatten(obj.lineNormals), 73322 Float32Array, 73323 gl.STATIC_DRAW 73324 ); 73325 73326 this.curStrokeShader.enableAttrib( 73327 this.curStrokeShader.attributes.aDirection.location, 73328 4, 73329 gl.FLOAT, 73330 false, 73331 0, 73332 0 73333 ); 73334 } 73335 73336 // initialize the fill shader's 'aPosition' buffer, if used 73337 if (this.curFillShader.attributes.aPosition) { 73338 geometry.vertexBuffer = gl.createBuffer(); 73339 73340 // allocate space for vertex positions 73341 this._bindBuffer( 73342 geometry.vertexBuffer, 73343 gl.ARRAY_BUFFER, 73344 this._vToNArray(obj.vertices), 73345 Float32Array, 73346 gl.STATIC_DRAW 73347 ); 73348 73349 this.curFillShader.enableAttrib( 73350 this.curFillShader.attributes.aPosition.location, 73351 3, 73352 gl.FLOAT, 73353 false, 73354 0, 73355 0 73356 ); 73357 } 73358 73359 // allocate space for faces 73360 geometry.indexBuffer = gl.createBuffer(); 73361 this._bindBuffer( 73362 geometry.indexBuffer, 73363 gl.ELEMENT_ARRAY_BUFFER, 73364 this._flatten(obj.faces), 73365 Uint16Array, 73366 gl.STATIC_DRAW 73367 ); 73368 73369 // initialize the fill shader's 'aNormal' buffer, if used 73370 if (this.curFillShader.attributes.aNormal) { 73371 geometry.normalBuffer = gl.createBuffer(); 73372 73373 // allocate space for normals 73374 this._bindBuffer( 73375 geometry.normalBuffer, 73376 gl.ARRAY_BUFFER, 73377 this._vToNArray(obj.vertexNormals), 73378 Float32Array, 73379 gl.STATIC_DRAW 73380 ); 73381 73382 this.curFillShader.enableAttrib( 73383 this.curFillShader.attributes.aNormal.location, 73384 3, 73385 gl.FLOAT, 73386 false, 73387 0, 73388 0 73389 ); 73390 } 73391 73392 // initialize the fill shader's 'aTexCoord' buffer, if used 73393 if (this.curFillShader.attributes.aTexCoord) { 73394 geometry.uvBuffer = gl.createBuffer(); 73395 73396 // tex coords 73397 this._bindBuffer( 73398 geometry.uvBuffer, 73399 gl.ARRAY_BUFFER, 73400 this._flatten(obj.uvs), 73401 Float32Array, 73402 gl.STATIC_DRAW 73403 ); 73404 73405 this.curFillShader.enableAttrib( 73406 this.curFillShader.attributes.aTexCoord.location, 73407 2, 73408 gl.FLOAT, 73409 false, 73410 0, 73411 0 73412 ); 73413 } 73414 //} 73415}; 73416 73417/** 73418 * Draws buffers given a geometry key ID 73419 * @private 73420 * @param {String} gId ID in our geom hash 73421 * @chainable 73422 */ 73423p5.RendererGL.prototype.drawBuffers = function(gId) { 73424 this._setDefaultCamera(); 73425 var gl = this.GL; 73426 this._useColorShader(); 73427 var geometry = this.gHash[gId]; 73428 73429 if (this._doStroke && geometry.lineVertexCount > 0) { 73430 this.curStrokeShader.bindShader(); 73431 73432 // bind the stroke shader's 'aPosition' buffer 73433 if (geometry.lineVertexBuffer) { 73434 this._bindBuffer(geometry.lineVertexBuffer, gl.ARRAY_BUFFER); 73435 this.curStrokeShader.enableAttrib( 73436 this.curStrokeShader.attributes.aPosition.location, 73437 3, 73438 gl.FLOAT, 73439 false, 73440 0, 73441 0 73442 ); 73443 } 73444 73445 // bind the stroke shader's 'aDirection' buffer 73446 if (geometry.lineNormalBuffer) { 73447 this._bindBuffer(geometry.lineNormalBuffer, gl.ARRAY_BUFFER); 73448 this.curStrokeShader.enableAttrib( 73449 this.curStrokeShader.attributes.aDirection.location, 73450 4, 73451 gl.FLOAT, 73452 false, 73453 0, 73454 0 73455 ); 73456 } 73457 73458 this._applyColorBlend(this.curStrokeColor); 73459 this._drawArrays(gl.TRIANGLES, gId); 73460 this.curStrokeShader.unbindShader(); 73461 } 73462 73463 if (this._doFill !== false) { 73464 this.curFillShader.bindShader(); 73465 73466 // bind the fill shader's 'aPosition' buffer 73467 if (geometry.vertexBuffer) { 73468 //vertex position buffer 73469 this._bindBuffer(geometry.vertexBuffer, gl.ARRAY_BUFFER); 73470 this.curFillShader.enableAttrib( 73471 this.curFillShader.attributes.aPosition.location, 73472 3, 73473 gl.FLOAT, 73474 false, 73475 0, 73476 0 73477 ); 73478 } 73479 73480 if (geometry.indexBuffer) { 73481 //vertex index buffer 73482 this._bindBuffer(geometry.indexBuffer, gl.ELEMENT_ARRAY_BUFFER); 73483 } 73484 73485 // bind the fill shader's 'aNormal' buffer 73486 if (geometry.normalBuffer) { 73487 this._bindBuffer(geometry.normalBuffer, gl.ARRAY_BUFFER); 73488 this.curFillShader.enableAttrib( 73489 this.curFillShader.attributes.aNormal.location, 73490 3, 73491 gl.FLOAT, 73492 false, 73493 0, 73494 0 73495 ); 73496 } 73497 73498 // bind the fill shader's 'aTexCoord' buffer 73499 if (geometry.uvBuffer) { 73500 // uv buffer 73501 this._bindBuffer(geometry.uvBuffer, gl.ARRAY_BUFFER); 73502 this.curFillShader.enableAttrib( 73503 this.curFillShader.attributes.aTexCoord.location, 73504 2, 73505 gl.FLOAT, 73506 false, 73507 0, 73508 0 73509 ); 73510 } 73511 73512 this._applyColorBlend(this.curFillColor); 73513 this._drawElements(gl.TRIANGLES, gId); 73514 this.curFillShader.unbindShader(); 73515 } 73516 return this; 73517}; 73518 73519/** 73520 * Calls drawBuffers() with a scaled model/view matrix. 73521 * 73522 * This is used by various 3d primitive methods (in primitives.js, eg. plane, 73523 * box, torus, etc...) to allow caching of un-scaled geometries. Those 73524 * geometries are generally created with unit-length dimensions, cached as 73525 * such, and then scaled appropriately in this method prior to rendering. 73526 * 73527 * @private 73528 * @method drawBuffersScaled 73529 * @param {String} gId ID in our geom hash 73530 * @param {Number} scaleX the amount to scale in the X direction 73531 * @param {Number} scaleY the amount to scale in the Y direction 73532 * @param {Number} scaleZ the amount to scale in the Z direction 73533 */ 73534p5.RendererGL.prototype.drawBuffersScaled = function( 73535 gId, 73536 scaleX, 73537 scaleY, 73538 scaleZ 73539) { 73540 var uMVMatrix = this.uMVMatrix.copy(); 73541 try { 73542 this.uMVMatrix.scale(scaleX, scaleY, scaleZ); 73543 this.drawBuffers(gId); 73544 } finally { 73545 this.uMVMatrix = uMVMatrix; 73546 } 73547}; 73548 73549p5.RendererGL.prototype._drawArrays = function(drawMode, gId) { 73550 this.GL.drawArrays(drawMode, 0, this.gHash[gId].lineVertexCount); 73551 return this; 73552}; 73553 73554p5.RendererGL.prototype._drawElements = function(drawMode, gId) { 73555 this.GL.drawElements( 73556 drawMode, 73557 this.gHash[gId].numberOfItems, 73558 this.GL.UNSIGNED_SHORT, 73559 0 73560 ); 73561}; 73562 73563module.exports = p5.RendererGL; 73564 73565},{"../core/core":22}],72:[function(_dereq_,module,exports){ 73566'use strict'; 73567 73568var p5 = _dereq_('../core/core'); 73569var constants = _dereq_('../core/constants'); 73570_dereq_('./p5.Shader'); 73571_dereq_('../core/p5.Renderer'); 73572_dereq_('./p5.Matrix'); 73573 73574 73575var defaultShaders = { 73576 immediateVert: "attribute vec3 aPosition;\nattribute vec4 aVertexColor;\n\nuniform mat4 uModelViewMatrix;\nuniform mat4 uProjectionMatrix;\nuniform float uResolution;\nuniform float uPointSize;\n\nvarying vec4 vColor;
73576\nvoid main(void) {\n vec4 positionVec4 = vec4(aPosition, 1.0);\n gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;\n vColor = aVertexColor;\n gl_PointSize = uPointSize;\n}\n", 73577 vertexColorVert: "attribute vec3 aPosition;\nattribute vec4 aVertexColor;\n\nuniform mat4 uModelViewMatrix;\nuniform mat4 uProjectionMatrix;\n\nvarying vec4 vColor;\n\nvoid main(void) {\n vec4 positionVec4 = vec4(aPosition, 1.0);\n gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;\n vColor = aVertexColor;\n}\n", 73578 vertexColorFrag: "precision mediump float;\nvarying vec4 vColor;\nvoid main(void) {\n gl_FragColor = vColor;\n}", 73579 normalVert: "attribute vec3 aPosition;\nattribute vec3 aNormal;\nattribute vec2 aTexCoord;\n\nuniform mat4 uModelViewMatrix;\nuniform mat4 uProjectionMatrix;\nuniform mat3 uNormalMatrix;\n\nvarying vec3 vVertexNormal;\nvarying highp vec2 vVertTexCoord;\n\nvoid main(void) {\n vec4 positionVec4 = vec4(aPosition, 1.0);\n gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;\n vVertexNormal = normalize(vec3( uNormalMatrix * aNormal ));\n vVertTexCoord = aTexCoord;\n}\n", 73580 normalFrag: "precision mediump float;\nvarying vec3 vVertexNormal;\nvoid main(void) {\n gl_FragColor = vec4(vVertexNormal, 1.0);\n}", 73581 basicFrag: "precision mediump float;\nvarying vec3 vVertexNormal;\nuniform vec4 uMaterialColor;\nvoid main(void) {\n gl_FragColor = uMaterialColor;\n}", 73582 lightVert: "attribute vec3 aPosition;\nattribute vec3 aNormal;\nattribute vec2 aTexCoord;\n\nuniform mat4 uViewMatrix;\nuniform mat4 uModelViewMatrix;\nuniform mat4 uProjectionMatrix;\nuniform mat3 uNormalMatrix;\nuniform int uAmbientLightCount;\nuniform int uDirectionalLightCount;\nuniform int uPointLightCount;\n\nuniform vec3 uAmbientColor[8];\nuniform vec3 uLightingDirection[8];\nuniform vec3 uDirectionalColor[8];\nuniform vec3 uPointLightLocation[8];\nuniform vec3 uPointLightColor[8];\nuniform bool uSpecular;\n\nvarying vec3 vVertexNormal;\nvarying vec2 vVertTexCoord;\nvarying vec3 vLightWeighting;\n\nvoid main(void){\n\n vec4 positionVec4 = vec4(aPosition, 1.0
73582);\n gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;\n\n vec3 vertexNormal = normalize(vec3( uNormalMatrix * aNormal ));\n vVertexNormal = vertexNormal;\n vVertTexCoord = aTexCoord;\n\n vec4 mvPosition = uModelViewMatrix * vec4(aPosition, 1.0);\n vec3 eyeDirection = normalize(-mvPosition.xyz);\n\n float shininess = 32.0;\n float specularFactor = 2.0;\n float diffuseFactor = 0.3;\n\n vec3 ambientLightFactor = vec3(0.0);\n\n for (int i = 0; i < 8; i++) {\n if (uAmbientLightCount == i) break;\n ambientLightFactor += uAmbientColor[i];\n }\n\n\n vec3 directionalLightFactor = vec3(0.0);\n\n for (int j = 0; j < 8; j++) {\n if (uDirectionalLightCount == j) break;\n vec3 dir = uLightingDirection[j];\n float directionalLightWeighting = max(dot(vertexNormal, -dir), 0.0);\n directionalLightFactor += uDirectionalColor[j] * directionalLightWeighting;\n }\n\n\n vec3 pointLightFactor = vec3(0.0);\n\n for (int k = 0; k < 8; k++) {\n if (uPointLightCount == k) break;\n vec3 loc = (uViewMatrix * vec4(uPointLightLocation[k], 1.0)).xyz;\n vec3 lightDirection = normalize(loc - mvPosition.xyz);\n\n float directionalLightWeighting = max(dot(vertexNormal, lightDirection), 0.0);\n\n float specularLightWeighting = 0.0;\n if (uSpecular ){\n vec3 reflectionDirection = reflect(-lightDirection, vertexNormal);\n specularLightWeighting = pow(max(dot(reflectionDirection, eyeDirection), 0.0), shininess);\n }\n\n pointLightFactor += uPointLightColor[k] * (specularFactor * specularLightWeighting\n + directionalLightWeighting * diffuseFactor);\n }\n\n vLightWeighting = ambientLightFactor + directionalLightFactor + pointLightFactor;\n}\n", 73583 lightTextureFrag: "precision mediump float;\n\nuniform vec4 uMaterialColor;\nuniform sampler2D uSampler;\nuniform bool isTexture;\nuniform bool uUseLighting;\n\nvarying vec3 vLightWeighting;\nvarying highp vec2 vVertTexCoord;\n\nvoid main(void) {\n gl_FragColor = isTexture ? texture2D(uSampler, vVertTexCoord) : uMaterialColor;\n if (uUseLighting)\n gl_FragColor.rgb *= vLightWeighting;\n}", 73584 phongVert: "precision mediump float;\n\nattribute vec3 aPosition;\nattribute vec3 aNormal;\nattribute vec2 aTexCoord;\n\nuniform vec3 uAmbientColor[8];\n\nuniform mat4 uModelViewMatrix;\nuniform mat4 uProjectionMatrix;\nuniform mat3 uNormalMatrix;\nuniform int uAmbientLightCount;\n\nvarying vec3 vNormal;\nvarying vec2 vTexCoord;\nvarying vec3 vViewPosition;\nvarying vec3 vAmbientColor;\n\nvoid main(void){\n\n vec4 viewModelPosition = uModelViewMatrix * vec4(aPosition, 1.0
73584);\n\n // Pass varyings to fragment shader\n vViewPosition = viewModelPosition.xyz;\n gl_Position = uProjectionMatrix * viewModelPosition; \n\n vNormal = normalize(uNormalMatrix * normalize(aNormal));\n vTexCoord = aTexCoord;\n\n vAmbientColor = vec3(0.0);\n for (int i = 0; i < 8; i++) {\n if (uAmbientLightCount == i) break;\n vAmbientColor += uAmbientColor[i];\n }\n}\n", 73585 phongFrag: "precision mediump float;\n\n//uniform mat4 uModelViewMatrix;\nuniform mat4 uViewMatrix;\n\nuniform vec4 uMaterialColor;\nuniform sampler2D uSampler;\nuniform bool isTexture;\nuniform bool uUseLighting;\n\nuniform vec3 uLightingDirection[8];\nuniform vec3 uDirectionalColor[8];\nuniform vec3 uPointLightLocation[8];\nuniform vec3 uPointLightColor[8];\nuniform bool uSpecular;\n\nuniform int uDirectionalLightCount;\nuniform int uPointLightCount;\n\nvarying vec3 vNormal;\nvarying vec2 vTexCoord;\nvarying vec3 vViewPosition;\nvarying vec3 vAmbientColor;\n\nvec3 V;\nvec3 N;\n\nconst float shininess = 32.0;\nconst float specularFactor = 2.0;\nconst float diffuseFactor = 0.73;\n\nstruct LightResult {\n\tfloat specular;\n\tfloat diffuse;\n};\n\nfloat phongSpecular(\n vec3 lightDirection,\n vec3 viewDirection,\n vec3 surfaceNormal,\n float shininess) {\n\n vec3 R = normalize(reflect(-lightDirection, surfaceNormal)); \n return pow(max(0.0, dot(R, viewDirection)), shininess);\n}\n\nfloat lambertDiffuse(\n vec3 lightDirection,\n vec3 surfaceNormal) {\n return max(0.0, dot(-lightDirection, surfaceNormal));\n}\n\nLightResult light(vec3 lightVector) {\n\n vec3 L = normalize(lightVector);\n\n //compute our diffuse & specular terms\n LightResult lr;\n if (uSpecular)\n lr.specular = phongSpecular(L, V, N, shininess);\n lr.diffuse = lambertDiffuse(L, N);\n return lr;\n}\n\nvoid main(void) {\n\n V = normalize(vViewPosition);\n N = vNormal;\n\n vec3 diffuse = vec3(0.0);\n float specular = 0.0;\n\n for (int j = 0; j < 8; j++) {\n if (uDirectionalLightCount == j) break;\n\n LightResult result = light(uLightingDirection[j]);\n diffuse += result.diffuse * uDirectionalColor[j];\n specular += result.specular;\n }\n\n for (int k = 0; k < 8; k++) {\n if (uPointLightCount == k) break;\n\n vec3 lightPosition = (uViewMatrix * vec4(uPointLightLocation[k], 1.0)).xyz;\n vec3 lightVector = vViewPosition - lightPosition;\n\t\n //calculate attenuation\n float lightDistance = length(lightVector);\n float falloff = 500.0 / (lightDistance + 500.0);\n\n LightResult result = light(lightVector);\n diffuse += result.diffuse * falloff * uPointLightColor[k];\n specular += result.specular * falloff;\n }\n\n gl_FragColor = isTexture ? texture2D(uSampler, vTexCoord) : uMaterialColor;\n gl_FragColor.rgb = gl_FragColor.rgb * (diffuse * diffuseFactor + vAmbientColor) + specular * specularFactor;\n}", 73586 lineVert: "/*\n Part of the Processing project - http://processing.org\n Copyright (c) 2012-15 The Processing Foundation\n Copyright (c) 2004-12 Ben Fry and Casey Reas\n Copyright (c) 2001-04 Massachusetts Institute of Technology\n This library is free software; you can redistribute it and/or\n modify it under the terms of the GNU Lesser General Public\n License as published by the Free Software Foundation, version 2.1.\n This library is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n Lesser General Public License for more details.\n You should have received a copy of the GNU Lesser General\n Public License along with this library; if not, write to the\n Free Software Foundation, Inc., 59 Temple Place, Suite 330,\n Boston, MA 02111-1307 USA\n*/\n\n#define PROCESSING_LINE_SHADER\n\nuniform mat4 uModelViewMatrix;\nuniform mat4 uProjectionMatrix;\nuniform float uStrokeWeight;\n\nuniform vec4 uViewport;\nvec3 scale = vec3(1.0);\n\nattribute vec4 aPosition;\nattribute vec4 aDirection;\n \nvoid main() {\n vec4 posp = uModelViewMatrix * aPosition;\n vec4 posq = uModelViewMatrix * (aPosition + vec4(aDirection.xyz, 0));\n\n // Moving vertices slightly toward the camera\n // to avoid depth-fighting with the fill triangles.\n // Discussed here:\n // http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=252848 \n posp.xyz = posp.xyz * scale;\n posq.xyz = posq.xyz * scale;\n\n vec4 p = uProjectionMatrix * posp;\n vec4 q = uProjectionMatrix * posq;\n\n // formula to convert from clip space (range -1..1) to screen space (range 0..[width or height])\n // screen_p = (p.xy/p.w + <1,1>) * 0.5 * uViewport.zw\n\n // prevent division by W by transforming the tangent formula (div by 0 causes\n // the line to disappear, see https://github.com/processing/processing/issues/5183)\n // t = screen_q - screen_p\n //\n // tangent is normalized and we don't care which aDirection it points to (+-)\n // t = +- normalize( screen_q - screen_p )\n // t = +- normalize( (q.xy/q.w+<1,1>)*0.5*uViewport.zw - (p.xy/p.w+<1,1>)*0.5*uViewport.zw )\n //\n // extract common factor, <1,1> - <1,1> cancels out\n // t = +- normalize( (q.xy/q.w - p.xy/p.w) * 0.5 * uViewport.zw )\n //\n // convert to common divisor\n // t = +- normalize( ((q.xy*p.w - p.xy*q.w) / (p.w*q.w)) * 0.5 * uViewport.zw )\n //\n // remove the common scalar divisor/factor, not needed due to normalize and +-\n // (keep uViewport - can't remove because it has different c
73586omponents for x and y\n // and corrects for aspect ratio, see https://github.com/processing/processing/issues/5181)\n // t = +- normalize( (q.xy*p.w - p.xy*q.w) * uViewport.zw )\n\n vec2 tangent = normalize((q.xy*p.w - p.xy*q.w) * uViewport.zw);\n\n // flip tangent to normal (it's already normalized)\n vec2 normal = vec2(-tangent.y, tangent.x);\n\n float thickness = aDirection.w * uStrokeWeight;\n vec2 offset = normal * thickness / 2.0;\n\n // Perspective ---\n // convert from world to clip by multiplying with projection scaling factor\n // to get the right thickness (see https://github.com/processing/processing/issues/5182)\n // invert Y, projections in Processing invert Y\n vec2 perspScale = (uProjectionMatrix * vec4(1, -1, 0, 0)).xy;\n\n // No Perspective ---\n // multiply by W (to cancel out division by W later in the pipeline) and\n // convert from screen to clip (derived from clip to screen above)\n vec2 noPerspScale = p.w / (0.5 * uViewport.zw);\n\n //gl_Position.xy = p.xy + offset.xy * mix(noPerspScale, perspScale, float(perspective > 0));\n gl_Position.xy = p.xy + offset.xy * perspScale;\n gl_Position.zw = p.zw;\n}\n", 73587 lineFrag: "precision mediump float;\nprecision mediump int;\n\nuniform vec4 uMaterialColor;\n\nvoid main() {\n gl_FragColor = uMaterialColor;\n}" 73588}; 73589 73590/** 73591 * 3D graphics class 73592 * @private 73593 * @class p5.RendererGL 73594 * @constructor 73595 * @extends p5.Renderer 73596 * @todo extend class to include public method for offscreen 73597 * rendering (FBO). 73598 * 73599 */ 73600p5.RendererGL = function(elt, pInst, isMainCanvas, attr) { 73601 p5.Renderer.call(this, elt, pInst, isMainCanvas); 73602 this.attributes = {}; 73603 attr = attr || {}; 73604 this.attributes.alpha = attr.alpha === undefined ? true : attr.alpha; 73605 this.attributes.depth = attr.depth === undefined ? true : attr.depth; 73606 this.attributes.stencil = attr.stencil === undefined ? true : attr.stencil; 73607 this.attributes.antialias = 73608 attr.antialias === undefined ? false : attr.antialias; 73609 this.attributes.premultipliedAlpha = 73610 attr.premultipliedAlpha === undefined ? false : attr.premultipliedAlpha; 73611 this.attributes.preserveDrawingBuffer = 73612 attr.preserveDrawingBuffer === undefined 73613 ? true 73614 : attr.preserveDrawingBuffer; 73615 this.attributes.perPixelLighting = 73616 attr.perPixelLighting === undefined ? false : attr.perPixelLighting; 73617 this._initContext(); 73618 this.isP3D = true; //lets us know we're in 3d mode 73619 this.GL = this.drawingContext; 73620 73621 // lights 73622 73623 this.ambientLightColors = []; 73624 this.directionalLightDirections = []; 73625 this.directionalLightColors = []; 73626 73627 this.pointLightPositions = []; 73628 this.pointLightColors = []; 73629 73630 /** 73631 * model view, projection, & normal 73632 * matrices 73633 */ 73634 this.uMVMatrix = new p5.Matrix(); 73635 this.uPMatrix = new p5.Matrix(); 73636 this.uNMatrix = new p5.Matrix('mat3'); 73637 73638 // Camera 73639 this._curCamera = null; 73640 // default camera settings, then use those to populate camera fields. 73641 this._computeCameraDefaultSettings(); 73642 this.cameraFOV = this.defaultCameraFOV; 73643 this.cameraAspect = this.defaultAspect; 73644 this.cameraX = this.defaultCameraX; 73645 this.cameraY = this.defaultCameraY; 73646 this.cameraZ = this.defaultCameraZ; 73647 this.cameraNear = this.defaultCameraNear; 73648 this.cameraFar = this.defaultCameraFar; 73649 this.cameraMatrix = new p5.Matrix(); 73650 this.camera(); // set default camera matrices 73651 73652 //Geometry & Material hashes 73653 this.gHash = {}; 73654 73655 this._defaultLightShader = undefined; 73656 this._defaultImmediateModeShader = undefined; 73657 this._defaultNormalShader = undefined; 73658 this._defaultColorShader = undefined; 73659 73660 this.curFillShader = undefined; 73661 this.curStrokeShader = undefined; 73662 73663 this._useColorShader(); 73664 this.setStrokeShader(this._getLineShader()); 73665 73666 //Imediate Mode 73667 //default drawing is done in Retained Mode 73668 this.isImmediateDrawing = false; 73669 this.immediateMode = {}; 73670 73671 // note: must call fill() and stroke () AFTER 73672 // default shader has been set. 73673 this.fill(255, 255, 255, 255); 73674 //this.stroke(0, 0, 0, 255); 73675 this.pointSize = 5.0; //default point size 73676 this.strokeWeight(2); 73677 this.stroke(0, 0, 0); 73678 // array of textures created in this gl context via this.getTexture(src) 73679 this.textures = []; 73680 return this; 73681}; 73682 73683p5.RendererGL.prototype = Object.create(p5.Renderer.prototype); 73684 73685////////////////////////////////////////////// 73686// Setting 73687////////////////////////////////////////////// 73688 73689p5.RendererGL.prototype._initContext = function() { 73690 try { 73691 this.drawingContext = 73692 this.canvas.getContext('webgl', this.attributes) || 73693 this.canvas.getContext('experimental-webgl', this.attributes); 73694 if (this.drawingContext === null) { 73695 throw new Error('Error creating webgl context'); 73696 } else { 73697 console.log('p5.RendererGL: enabled webgl context'); 73698 var gl = this.drawingContext; 73699 gl.enable(gl.DEPTH_TEST); 73700 gl.depthFunc(gl.LEQUAL); 73701 gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); 73702 this._viewport = this.drawingContext.getParameter( 73703 this.drawingContext.VIEWPORT 73704 ); 73705 } 73706 } catch (er) { 73707 throw new Error(er); 73708 } 73709}; 73710 73711//This is helper function to reset the context anytime the attributes 73712//are changed with setAttributes() 73713 73714p5.RendererGL.prototype._resetContext = function(attr, options, callback) { 73715 var w = this.width;
73716 var h = this.height; 73717 var defaultId = this.canvas.id; 73718 var c = this.canvas; 73719 if (c) { 73720 c.parentNode.removeChild(c); 73721 } 73722 c = document.createElement('canvas'); 73723 c.id = defaultId; 73724 if (this._pInst._userNode) { 73725 this._pInst._userNode.appendChild(c); 73726 } else { 73727 document.body.appendChild(c); 73728 } 73729 this._pInst.canvas = c; 73730 73731 var renderer = new p5.RendererGL(this._pInst.canvas, this._pInst, true, attr); 73732 this._pInst._setProperty('_renderer', renderer); 73733 renderer.resize(w, h); 73734 renderer._applyDefaults(); 73735 this._pInst._elements.push(renderer); 73736 73737 if (typeof callback === 'function') { 73738 //setTimeout with 0 forces the task to the back of the queue, this ensures that 73739 //we finish switching out the renderer 73740 setTimeout(function() { 73741 callback.apply(window._renderer, options); 73742 }, 0); 73743 } 73744}; 73745/** 73746 * @module Rendering 73747 * @submodule Rendering 73748 * @for p5 73749 */ 73750/** 73751 * Set attributes for the WebGL Drawing context. 73752 * This is a way of adjusting ways that the WebGL 73753 * renderer works to fine-tune the display and performance. 73754 * This should be put in setup(). 73755 * The available attributes are: 73756 * <br> 73757 * alpha - indicates if the canvas contains an alpha buffer 73758 * default is true 73759 * <br><br> 73760 * depth - indicates whether the drawing buffer has a depth buffer 73761 * of at least 16 bits - default is true 73762 * <br><br> 73763 * stencil - indicates whether the drawing buffer has a stencil buffer 73764 * of at least 8 bits 73765 * <br><br> 73766 * antialias - indicates whether or not to perform anti-aliasing 73767 * default is false 73768 * <br><br> 73769 * premultipliedAlpha - indicates that the page compositor will assume 73770 * the drawing buffer contains colors with pre-multiplied alpha 73771 * default is false 73772 * <br><br> 73773 * preserveDrawingBuffer - if true the buffers will not be cleared and 73774 * and will preserve their values until cleared or overwritten by author 73775 * (note that p5 clears automatically on draw loop) 73776 * default is true 73777 * <br><br> 73778 * perPixelLighting - if true, per-pixel lighting will be used in the 73779 * lighting shader. 73780 * default is false 73781 * <br><br> 73782 * @method setAttributes 73783 * @for p5 73784 * @param {String} key Name of attribute 73785 * @param {Boolean} value New value of named attribute 73786 * @example 73787 * <div> 73788 * <code> 73789 * function setup() { 73790 * createCanvas(100, 100, WEBGL); 73791 * } 73792 * 73793 * function draw() { 73794 * background(255); 73795 * push(); 73796 * rotateZ(frameCount * 0.02); 73797 * rotateX(frameCount * 0.02); 73798 * rotateY(frameCount * 0.02); 73799 * fill(0, 0, 0); 73800 * box(50); 73801 * pop(); 73802 * } 73803 * </code> 73804 * </div> 73805 * <br> 73806 * Now with the antialias attribute set to true. 73807 * <br> 73808 * <div> 73809 * <code> 73810 * function setup() { 73811 * createCanvas(100, 100, WEBGL); 73812 * setAttributes('antialias', true); 73813 * } 73814 * 73815 * function draw() { 73816 * background(255); 73817 * push(); 73818 * rotateZ(frameCount * 0.02); 73819 * rotateX(frameCount * 0.02); 73820 * rotateY(frameCount * 0.02); 73821 * fill(0, 0, 0); 73822 * box(50); 73823 * pop(); 73824 * } 73825 * </code> 73826 * </div> 73827 * 73828 * <div> 73829 * <code> 73830 * // press the mouse button to enable perPixelLighting 73831 * function setup() { 73832 * createCanvas(100, 100, WEBGL); 73833 * noStroke(); 73834 * fill(255); 73835 * } 73836 * 73837 * var lights = [ 73838 * { c: '#f00', t: 1.12, p: 1.91, r: 0.2 }, 73839 * { c: '#0f0', t: 1.21, p: 1.31, r: 0.2 }, 73840 * { c: '#00f', t: 1.37, p: 1.57, r: 0.2 }, 73841 * { c: '#ff0', t: 1.12, p: 1.91, r: 0.7 }, 73842 * { c: '#0ff', t: 1.21, p: 1.31, r: 0.7 }, 73843 * { c: '#f0f', t: 1.37, p: 1.57, r: 0.7 } 73844 * ]; 73845 * 73846 * function draw() { 73847 * var t = millis() / 1000 + 1000; 73848 * background(0); 73849 * directionalLight(color('#222'), 1, 1, 1); 73850 * 73851 * for (var i = 0; i < lights.length; i++) { 73852 * var light = lights[i]; 73853 * pointLight( 73854 * color(light.c), 73855 * p5.Vector.fromAngles(t * light.t, t * light.p, width * light.r) 73856 * ); 73857 * } 73858 * 73859 * specularMaterial(255); 73860 * sphere(width * 0.1); 73861 * 73862 * rotateX(t * 0.77); 73863 * rotateY(t * 0.83); 73864 * rotateZ(t * 0.91); 73865 * torus(width * 0.3, width * 0.07, 30, 10); 73866 * } 73867 * 73868 * function mousePressed() { 73869 * setAttributes('perPixelLighting', true); 73870 * noStroke(); 73871 * fill(255); 73872 * } 73873 * function mouseReleased() { 73874 * setAttributes('perPixelLighting', false); 73875 * noStroke(); 73876 * fill(255); 73877 * } 73878 * </code> 73879 * </div> 73880 * 73881 * @alt a rotating cube with smoother edges 73882 */ 73883/** 73884 * @method setAttributes 73885 * @for p5 73886 * @param {Object} obj object with key-value pairs 73887 */ 73888 73889p5.prototype.setAttributes = function(key, value) { 73890 this._assert3d('setAttributes'); 73891 //@todo_FES 73892 var attr; 73893 if (typeof value !== 'undefined') { 73894 attr = {}; 73895 attr[key] = value; 73896 } else if (key instanceof Object) { 73897 attr = key; 73898 } 73899 this.push(); 73900 this._renderer._resetContext(attr); 73901 this.pop(); 73902}; 73903 73904/** 73905 * @class p5.RendererGL 73906 */ 73907 73908p5.RendererGL.prototype._computeCameraDefaultSettings = function() { 73909 this.defaultCameraFOV = 60 / 180 * Math.PI; 73910 this.defaultCameraAspect = this.width / this.height; 73911 this.defaultCameraX = 0; 73912 this.defaultCameraY = 0; 73913 this.defaultCameraZ = 73914 this.height / 2.0 / Math.tan(this.defaultCameraFOV / 2.0); 73915 this.defaultCameraNear = this.defaultCameraZ * 0.1; 73916 this.defaultCameraFar = this.defaultCameraZ * 10; 73917}; 73918 73919//detect if user didn't set the camera 73920//then call this function below 73921p5.RendererGL.prototype._setDefaultCamera = function() { 73922 if (this._curCamera === null) { 73923 this._computeCameraDefaultSettings(); 73924 this.cameraFOV = this.defaultCameraFOV; 73925 this.cameraAspect = this.defaultAspect; 73926 this.cameraX = this.defaultCameraX; 73927 this.cameraY = this.defaultCameraY; 73928 this.cameraZ = this.defaultCameraZ; 73929 this.cameraNear = this.defaultCameraNear; 73930 this.cameraFar = this.defaultCameraFar; 73931 73932 this.perspective(); 73933 this.camera(); 73934 this._curCamera = 'default'; 73935 } 73936}; 73937 73938p5.RendererGL.prototype._update = function() { 73939 // reset model view and apply initial camera transform 73940 // (containing only look at info; no projection). 73941 this.uMVMatrix.set( 73942 this.cameraMatrix.mat4[0], 73943 this.cameraMatrix.mat4[1], 73944 this.cameraMatrix.mat4[2], 73945 this.cameraMatrix.mat4[3], 73946 this.cameraMatrix.mat4[4], 73947 this.cameraMatrix.mat4[5], 73948 this.cameraMatrix.mat4[6], 73949 this.cameraMatrix.mat4[7], 73950 this.cameraMatrix.mat4[8], 73951 this.cameraMatrix.mat4[9], 73952 this.cameraMatrix.mat4[10], 73953 this.cameraMatrix.mat4[11], 73954 this.cameraMatrix.mat4[12], 73955 this.cameraMatrix.mat4[13], 73956 this.cameraMatrix.mat4[14], 73957 this.cameraMatrix.mat4[15] 73958 ); 73959 73960 // reset light data for new frame. 73961 73962 this.ambientLightColors.length = 0; 73963 this.directionalLightDirections.length = 0; 73964 this.directionalLightColors.length = 0; 73965 73966 this.pointLightPositions.length = 0; 73967 this.pointLightColors.length = 0; 73968}; 73969 73970/** 73971 * [background description] 73972 */ 73973p5.RendererGL.prototype.background = function() { 73974 var _col = this._pInst.color.apply(this._pInst, arguments); 73975 var _r = _col.levels[0] / 255; 73976 var _g = _col.levels[1] / 255; 73977 var _b = _col.levels[2] / 255; 73978 var _a = _col.levels[3] / 255; 73979 this.GL.clearColor(_r, _g, _b, _a); 73980 this.GL.depthMask(true); 73981 this.GL.clear(this.GL.COLOR_BUFFER_BIT | this.GL.DEPTH_BUFFER_BIT); 73982}; 73983 73984//@TODO implement this 73985// p5.RendererGL.prototype.clear = function() { 73986//@TODO 73987// }; 73988 73989////////////////////////////////////////////// 73990// COLOR 73991////////////////////////////////////////////// 73992/** 73993 * Basic fill material for geometry with a given color 73994 * @method fill 73995 * @class p5.RendererGL 73996 * @param {Number|Number[]|String|p5.Color} v1 gray value, 73997 * red or hue value (depending on the current color mode),
73998 * or color Array, or CSS color string 73999 * @param {Number} [v2] green or saturation value 74000 * @param {Number} [v3] blue or brightness value 74001 * @param {Number} [a] opacity 74002 * @chainable 74003 * @example 74004 * <div> 74005 * <code> 74006 * function setup() { 74007 * createCanvas(200, 200, WEBGL); 74008 * } 74009 * 74010 * function draw() { 74011 * background(0); 74012 * noStroke(); 74013 * fill(100, 100, 240); 74014 * rotateX(frameCount * 0.01); 74015 * rotateY(frameCount * 0.01); 74016 * box(75, 75, 75); 74017 * } 74018 * </code> 74019 * </div> 74020 * 74021 * @alt 74022 * black canvas with purple cube spinning 74023 * 74024 */ 74025p5.RendererGL.prototype.fill = function(v1, v2, v3, a) { 74026 //see material.js for more info on color blending in webgl 74027 var color = p5.prototype.color.apply(this._pInst, arguments); 74028 this.curFillColor = color._array; 74029 74030 if (this.isImmediateDrawing) { 74031 this.setFillShader(this._getImmediateModeShader()); 74032 } else { 74033 this.setFillShader(this._getColorShader()); 74034 } 74035 this.drawMode = constants.FILL; 74036 this.curFillShader.setUniform('uMaterialColor', this.curFillColor); 74037}; 74038 74039/** 74040 * Basic stroke material for geometry with a given color 74041 * @method stroke 74042 * @param {Number|Number[]|String|p5.Color} v1 gray value, 74043 * red or hue value (depending on the current color mode), 74044 * or color Array, or CSS color string 74045 * @param {Number} [v2] green or saturation value 74046 * @param {Number} [v3] blue or brightness value 74047 * @param {Number} [a] opacity 74048 * @example 74049 * <div> 74050 * <code> 74051 * function setup() { 74052 * createCanvas(200, 200, WEBGL); 74053 * } 74054 * 74055 * function draw() { 74056 * background(0); 74057 * stroke(240, 150, 150); 74058 * fill(100, 100, 240); 74059 * rotateX(frameCount * 0.01); 74060 * rotateY(frameCount * 0.01); 74061 * box(75, 75, 75); 74062 * } 74063 * </code> 74064 * </div> 74065 * 74066 * @alt 74067 * black canvas with purple cube with pink outline spinning 74068 * 74069 */ 74070p5.RendererGL.prototype.stroke = function(r, g, b, a) { 74071 //@todo allow transparency in stroking currently doesn't have 74072 //any impact and causes problems with specularMaterial 74073 arguments[3] = 255; 74074 var color = p5.prototype.color.apply(this._pInst, arguments); 74075 this.curStrokeColor = color._array; 74076 this.curStrokeShader.setUniform('uMaterialColor', this.curStrokeColor); 74077}; 74078 74079/** 74080 * Change weight of stroke 74081 * @method strokeWeight 74082 * @param {Number} stroke weight to be used for drawing 74083 * @example 74084 * <div> 74085 * <code> 74086 * function setup() { 74087 * createCanvas(200, 400, WEBGL); 74088 * setAttributes('antialias', true); 74089 * } 74090 * 74091 * function draw() { 74092 * background(0); 74093 * noStroke(); 74094 * translate(0, -100, 0); 74095 * stroke(240, 150, 150); 74096 * fill(100, 100, 240); 74097 * push(); 74098 * strokeWeight(8); 74099 * rotateX(frameCount * 0.01); 74100 * rotateY(frameCount * 0.01); 74101 * sphere(75); 74102 * pop(); 74103 * push(); 74104 * translate(0, 200, 0); 74105 * strokeWeight(1); 74106 * rotateX(frameCount * 0.01); 74107 * rotateY(frameCount * 0.01); 74108 * sphere(75); 74109 * pop(); 74110 * } 74111 * </code> 74112 * </div> 74113 * 74114 * @alt 74115 * black canvas with two purple rotating spheres with pink 74116 * outlines the sphere on top has much heavier outlines, 74117 * 74118 */ 74119p5.RendererGL.prototype.strokeWeight = function(w) { 74120 if (this.curStrokeWeight !== w) { 74121 this.pointSize = w; 74122 this.curStrokeWeight = w; 74123 this.curStrokeShader.setUniform('uStrokeWeight', w); 74124 } 74125}; 74126 74127/** 74128 * Returns an array of [R,G,B,A] values for any pixel or grabs a section of 74129 * an image. If no parameters are specified, the entire image is returned. 74130 * Use the x and y parameters to get the value of one pixel. Get a section of 74131 * the display window by specifying additional w and h parameters. When 74132 * getting an image, the x and y parameters define the coordinates for the 74133 * upper-left corner of the image, regardless of the current imageMode(). 74134 * <br><br> 74135 * If the pixel requested is outside of the image window, [0,0,0,255] is 74136 * returned. 74137 * <br><br> 74138 * Getting the color of a single pixel with get(x, y) is easy, but not as fast 74139 * as grabbing the data directly from pixels[]. The equivalent statement to 74140 * get(x, y) is using pixels[] with pixel density d 74141 * 74142 * @private 74143 * @method get 74144 * @param {Number} [x] x-coordinate of the pixel 74145 * @param {Number} [y] y-coordinate of the pixel 74146 * @param {Number} [w] width 74147 * @param {Number} [h] height 74148 * @return {Number[]|Color|p5.Image} color of pixel at x,y in array format 74149 * [R, G, B, A] or p5.Image 74150 */ 74151p5.RendererGL.prototype.get = function(x, y, w, h) { 74152 return p5.Renderer2D.prototype.get.apply(this, [x, y, w, h]); 74153}; 74154 74155/** 74156 * Loads the pixels data for this canvas into the pixels[] attribute. 74157 * Note that updatePixels() and set() do not work. 74158 * Any pixel manipulation must be done directly to the pixels[] array.
74159 * 74160 * @private 74161 * @method loadPixels 74162 * 74163 */ 74164 74165p5.RendererGL.prototype.loadPixels = function() { 74166 //@todo_FES 74167 if (this.attributes.preserveDrawingBuffer !== true) { 74168 console.log( 74169 'loadPixels only works in WebGL when preserveDrawingBuffer ' + 'is true.' 74170 ); 74171 return; 74172 } 74173 var pd = this._pInst._pixelDensity; 74174 var x = 0; 74175 var y = 0; 74176 var w = this.width; 74177 var h = this.height; 74178 w *= pd; 74179 h *= pd; 74180 //if there isn't a renderer-level temporary pixels buffer 74181 //make a new one 74182 if (typeof this.pixels === 'undefined') { 74183 this.pixels = new Uint8Array( 74184 this.GL.drawingBufferWidth * this.GL.drawingBufferHeight * 4 74185 ); 74186 } 74187 this.GL.readPixels( 74188 x, 74189 y, 74190 w, 74191 h, 74192 this.GL.RGBA, 74193 this.GL.UNSIGNED_BYTE, 74194 this.pixels 74195 ); 74196 this._pInst._setProperty('pixels', this.pixels); 74197}; 74198 74199////////////////////////////////////////////// 74200// HASH | for geometry 74201////////////////////////////////////////////// 74202 74203p5.RendererGL.prototype.geometryInHash = function(gId) { 74204 return this.gHash[gId] !== undefined; 74205}; 74206 74207/** 74208 * [resize description] 74209 * @private 74210 * @param {Number} w [description] 74211 * @param {Number} h [description] 74212 */ 74213p5.RendererGL.prototype.resize = function(w, h) { 74214 p5.Renderer.prototype.resize.call(this, w, h); 74215 this.GL.viewport( 74216 0, 74217 0, 74218 this.GL.drawingBufferWidth, 74219 this.GL.drawingBufferHeight 74220 ); 74221 this._viewport = this.GL.getParameter(this.GL.VIEWPORT); 74222 // If we're using the default camera, update the aspect ratio 74223 if (this._curCamera === null || this._curCamera === 'default') { 74224 this._curCamera = null; 74225 // camera defaults are dependent on the width & height of the screen, 74226 // so we'll want to update them if the size of the screen changes. 74227 this._setDefaultCamera(); 74228 } 74229 //resize pixels buffer 74230 if (typeof this.pixels !== 'undefined') { 74231 this.pixels = new Uint8Array( 74232 this.GL.drawingBufferWidth * this.GL.drawingBufferHeight * 4 74233 ); 74234 } 74235}; 74236 74237/** 74238 * clears color and depth buffers 74239 * with r,g,b,a 74240 * @private 74241 * @param {Number} r normalized red val. 74242 * @param {Number} g normalized green val. 74243 * @param {Number} b normalized blue val. 74244 * @param {Number} a normalized alpha val. 74245 */ 74246p5.RendererGL.prototype.clear = function() { 74247 var _r = arguments[0] || 0; 74248 var _g = arguments[1] || 0; 74249 var _b = arguments[2] || 0; 74250 var _a = arguments[3] || 0; 74251 this.GL.clearColor(_r, _g, _b, _a); 74252 this.GL.clear(this.GL.COLOR_BUFFER_BIT | this.GL.DEPTH_BUFFER_BIT); 74253}; 74254 74255/** 74256 * [translate description] 74257 * @private 74258 * @param {Number} x [description] 74259 * @param {Number} y [description] 74260 * @param {Number} z [description] 74261 * @chainable 74262 * @todo implement handle for components or vector as args 74263 */ 74264p5.RendererGL.prototype.translate = function(x, y, z) { 74265 if (x instanceof p5.Vector) { 74266 z = x.z; 74267 y = x.y; 74268 x = x.x; 74269 } 74270 this.uMVMatrix.translate([x, y, z]); 74271 return this; 74272}; 74273 74274/** 74275 * Scales the Model View Matrix by a vector 74276 * @private 74277 * @param {Number | p5.Vector | Array} x [description] 74278 * @param {Number} [y] y-axis scalar 74279 * @param {Number} [z] z-axis scalar 74280 * @chainable 74281 */ 74282p5.RendererGL.prototype.scale = function(x, y, z) { 74283 this.uMVMatrix.scale(x, y, z); 74284 return this; 74285}; 74286 74287p5.RendererGL.prototype.rotate = function(rad, axis) { 74288 if (typeof axis === 'undefined') { 74289 return this.rotateZ(rad); 74290 } 74291 p5.Matrix.prototype.rotate.apply(this.uMVMatrix, arguments); 74292 return this; 74293}; 74294 74295p5.RendererGL.prototype.rotateX = function(rad) { 74296 this.rotate(rad, 1, 0, 0); 74297 return this; 74298}; 74299 74300p5.RendererGL.prototype.rotateY = function(rad) { 74301 this.rotate(rad, 0, 1, 0); 74302 return this; 74303}; 74304 74305p5.RendererGL.prototype.rotateZ = function(rad) { 74306 this.rotate(rad, 0, 0, 1); 74307 return this; 74308}; 74309 74310p5.RendererGL.prototype.push = function() { 74311 // get the base renderer style 74312 var style = p5.Renderer.prototype.push.apply(this); 74313 74314 // add webgl-specific style properties 74315 var properties = style.properties; 74316 74317 properties.uMVMatrix = this.uMVMatrix.copy(); 74318 properties.cameraMatrix = this.cameraMatrix.copy(); 74319 74320 return style; 74321}; 74322 74323p5.RendererGL.prototype.resetMatrix = function() { 74324 this.uMVMatrix = p5.Matrix.identity(this._pInst); 74325 return this; 74326}; 74327 74328// Text/Typography 74329// @TODO: 74330p5.RendererGL.prototype._applyTextProperties = function() { 74331 //@TODO finish implementation 74332 console.error('text commands not yet implemented in webgl'); 74333}; 74334 74335////////////////////////////////////////////// 74336// SHADER 74337////////////////////////////////////////////// 74338 74339/* 74340 * Initializes and uses the specified shader, then returns 74341 * that shader. Note: initialization and resetting the program 74342 * is only used if needed (say, if a new value is provided) 74343 * so it is safe to call this method with the same shader multiple 74344 * times without a signficant performance hit). 74345 * 74346 * @method setFillShader 74347 * @param {p5.Shader} [s] a p5.Shader object 74348 * @return {p5.Shader} the current, updated fill shader 74349 */ 74350p5.RendererGL.prototype.setFillShader = function(s) { 74351 if (this.curFillShader !== s) { 74352 // only do setup etc. if shader is actually new. 74353 this.curFillShader = s; 74354 74355 // safe to do this multiple times; 74356 // init() will bail early if has already been run. 74357 this.curFillShader.init(); 74358 //this.curFillShader.useProgram(); 74359 } 74360 // always return this.curFillShader, even if no change was made. 74361 return this.curFillShader; 74362}; 74363 74364/* 74365 * @method setStrokeShader 74366 * @param {p5.Shader} [s] a p5.Shader object 74367 * @return {p5.Shader} the current, updated stroke shader 74368 */ 74369p5.RendererGL.prototype.setStrokeShader = function(s) { 74370 if (this.curStrokeShader !== s) { 74371 // only do setup etc. if shader is actually new. 74372 this.curStrokeShader = s; 74373 // safe to do this multiple times; 74374 // init() will bail early if has already been run. 74375 this.curStrokeShader.init(); 74376 //this.curStrokeShader.useProgram(); 74377 } 74378 // always return this.curLineShader, even if no change was made. 74379 return this.curStrokeShader; 74380}; 74381 74382/* 74383 * shaders are created and cached on a per-renderer basis, 74384 * on the grounds that each renderer will have its own gl context 74385 * and the shader must be valid in that context. 74386 * 74387 * 74388 */ 74389 74390p5.RendererGL.prototype._useLightShader = function() { 74391 if (!this.curFillShader || !this.curFillShader.isLightShader()) { 74392 this.setFillShader(this._getLightShader()); 74393 } 74394 return this.curFillShader; 74395}; 74396 74397p5.RendererGL.prototype._useColorShader = function() { 74398 // looking at the code within the glsl files, I'm not really 74399 // sure why these are two different shaders. but, they are, 74400 // and if we're drawing in retain mode but the shader is the 74401 // immediate mode one, we need to switch. 74402 74403 // TODO: what if curFillShader is _any_ other shader? 74404 if ( 74405 !this.curFillShader || 74406 this.curFillShader === this._defaultImmediateModeShader 74407 ) { 74408 // there are different immediate mode and retain mode color shaders. 74409 // if we're using the immediate mode one, we need to switch to 74410 // one that works for retain mode. 74411 this.setFillShader(this._getColorShader()); 74412 } 74413 return this.curFillShader; 74414}; 74415 74416p5.RendererGL.prototype._useImmediateModeShader = function() { 74417 // TODO: what if curFillShader is _any_ other shader? 74418 if (!this.curFillShader || this.curFillShader === this._defaultColorShader) { 74419 // this is the fill/stroke shader for retain mode. 74420 // must switch to immediate mode shader before drawing! 74421 this.setFillShader(this._getImmediateModeShader()); 74422 // note that if we're using the texture shader... 74423 // this shouldn't change. :) 74424 } 74425 return this.curFillShader; 74426}; 74427 74428p5.RendererGL.prototype._getLightShader = function() { 74429 if (!this._defaultLightShader) { 74430 if (this.attributes.perPixelLighting) { 74431 this._defaultLightShader = new p5.Shader( 74432 this, 74433 defaultShaders.phongVert, 74434 defaultShaders.phongFrag 74435 ); 74436 } else { 74437 this._defaultLightShader = new p5.Shader( 74438 this, 74439 defaultShaders.lightVert, 74440 defaultShaders.lightTextureFrag 74441 ); 74442 } 74443 } 74444 //this.drawMode = constants.FILL; 74445 return this._defaultLightShader; 74446}; 74447 74448p5.RendererGL.prototype._getImmediateModeShader = function() { 74449 if (!this._defaultImmediateModeShader) { 74450 this._defaultImmediateModeShader = new p5.Shader( 74451 this, 74452 defaultShaders.immediateVert, 74453 defaultShaders.vertexColorFrag 74454 ); 74455 } 74456 //this.drawMode = constants.FILL; 74457 return this._defaultImmediateModeShader; 74458}; 74459 74460p5.RendererGL.prototype._getNormalShader = function() { 74461 if (!this._defaultNormalShader) { 74462 this._defaultNormalShader = new p5.Shader( 74463 this, 74464 defaultShaders.normalVert, 74465 defaultShaders.normalFrag 74466 ); 74467 } 74468 //this.drawMode = constants.FILL; 74469 return this._defaultNormalShader; 74470}; 74471 74472p5.RendererGL.prototype._getColorShader = function() { 74473 if (!this._defaultColorShader) { 74474 this._defaultColorShader = new p5.Shader( 74475 this, 74476 defaultShaders.normalVert, 74477 defaultShaders.basicFrag 74478 ); 74479 } 74480 //this.drawMode = constants.FILL; 74481 return this._defaultColorShader; 74482}; 74483 74484p5.RendererGL.prototype._getLineShader = function() { 74485 if (!this._defaultLineShader) { 74486 this._defaultLineShader = new p5.Shader( 74487 this, 74488 defaultShaders.lineVert, 74489 defaultShaders.lineFrag 74490 ); 74491 } 74492 //this.drawMode = constants.STROKE; 74493 return this._defaultLineShader; 74494}; 74495 74496p5.RendererGL.prototype._getEmptyTexture = function() { 74497 if (!this._emptyTexture) { 74498 // a plain white texture RGBA, full alpha, single pixel. 74499 var im = new p5.Image(1, 1); 74500 im.set(0, 0, 255); 74501 this._emptyTexture = new p5.Texture(this, im); 74502 } 74503 return this._emptyTexture; 74504}; 74505 74506p5.RendererGL.prototype.getTexture = function(img) { 74507 var checkSource = function(element) { 74508 return element.src === img; 74509 }; 74510 //this.drawMode = constants.TEXTURE; 74511 var tex = this.textures.find(checkSource); 74512 if (!tex) { 74513 tex = new p5.Texture(this, img); 74514 this.textures.push(tex); 74515 } 74516 74517 return tex; 74518}; 74519 74520//Binds a buffer to the drawing context 74521//when passed more than two arguments it also updates or initializes 74522//the data associated with the buffer 74523p5.RendererGL.prototype._bindBuffer = function( 74524 buffer, 74525 target, 74526 values, 74527 type, 74528 usage 74529) { 74530 this.GL.bindBuffer(target, buffer); 74531 if (values !== undefined) { 74532 var data = new type(values); 74533 this.GL.bufferData(target, data, usage); 74534 } 74535}; 74536 74537////////////////////////// 74538//// SMOOTHING 74539///////////////////////// 74540// @TODO: 74541p5.RendererGL.prototype.smooth = function() { 74542 //@TODO finish implementation 74543 console.log('smoothing not yet implemented in webgl'); 74544}; 74545 74546p5.RendererGL.prototype.noSmooth = function() { 74547 //@TODO finish implementation 74548 console.log('smoothing not yet implemented in webgl'); 74549}; 74550 74551/////////////////////////////// 74552//// UTILITY FUNCTIONS 74553////////////////////////////// 74554/** 74555 * turn a two dimensional array into one dimensional array 74556 * @private 74557 * @param {Array} arr 2-dimensional array 74558 * @return {Array} 1-dimensional array 74559 * [[1, 2, 3],[4, 5, 6]] -> [1, 2, 3, 4, 5, 6] 74560 */ 74561p5.RendererGL.prototype._flatten = function(arr) { 74562 //when empty, return empty 74563 if (arr.length === 0) { 74564 return []; 74565 } else if (arr.length > 20000) { 74566 //big models , load slower to avoid stack overflow 74567 //faster non-recursive flatten via axelduch 74568 //stackoverflow.com/questions/27266550/how-to-flatten-nested-array-in-javascript 74569 var toString = Object.prototype.toString; 74570 var arrayTypeStr = '[object Array]'; 74571 var result = []; 74572 var nodes = arr.slice(); 74573 var node; 74574 node = nodes.pop(); 74575 do { 74576 if (toString.call(node) === arrayTypeStr) { 74577 nodes.push.apply(nodes, node); 74578 } else { 74579 result.push(node); 74580 } 74581 } while (nodes.length && (node = nodes.pop()) !== undefined); 74582 result.reverse(); // we reverse result to restore the original order 74583 return result; 74584 } else { 74585 //otherwise if model within limits for browser 74586 //use faster recursive loading 74587 return [].concat.apply([], arr); 74588 } 74589}; 74590 74591/** 74592 * turn a p5.Vector Array into a one dimensional number array 74593 * @private 74594 * @param {p5.Vector[]} arr an array of p5.Vector 74595 * @return {Number[]} a one dimensional array of numbers
74596 * [p5.Vector(1, 2, 3), p5.Vector(4, 5, 6)] -> 74597 * [1, 2, 3, 4, 5, 6] 74598 */ 74599p5.RendererGL.prototype._vToNArray = function(arr) { 74600 return this._flatten( 74601 arr.map(function(item) { 74602 return [item.x, item.y, item.z]; 74603 }) 74604 ); 74605}; 74606 74607/** 74608 * ensures that p5 is using a 3d renderer. throws an error if not. 74609 */ 74610p5.prototype._assert3d = function(name) { 74611 if (!this._renderer.isP3D) 74612 throw new Error( 74613 name + 74614 "() is only supported in WEBGL mode. If you'd like to use 3D graphics" + 74615 ' and WebGL, see https://p5js.org/examples/form-3d-primitives.html' + 74616 ' for more information.' 74617 ); 74618}; 74619 74620module.exports = p5.RendererGL; 74621 74622},{"../core/constants":21,"../core/core":22,"../core/p5.Renderer":29,"./p5.Matrix":69,"./p5.Shader":73}],73:[function(_dereq_,module,exports){ 74623/** 74624 * This module defines the p5.Shader class 74625 * @module Lights, Camera 74626 * @submodule Shaders 74627 * @for p5 74628 * @requires core 74629 */ 74630 74631'use strict'; 74632 74633var p5 = _dereq_('../core/core'); 74634 74635/** 74636 * Shader class for WEBGL Mode 74637 * @class p5.Shader 74638 * @param {p5.RendererGL} renderer an instance of p5.RendererGL that 74639 * will provide the GL context for this new p5.Shader 74640 * @param {String} vertSrc source code for the vertex shader (as a string) 74641 * @param {String} fragSrc source code for the fragment shader (as a string) 74642 */ 74643p5.Shader = function(renderer, vertSrc, fragSrc) { 74644 // TODO: adapt this to not take ids, but rather, 74645 // to take the source for a vertex and fragment shader 74646 // to enable custom shaders at some later date 74647 this._renderer = renderer; 74648 this._vertSrc = vertSrc; 74649 this._fragSrc = fragSrc; 74650 this._vertShader = -1; 74651 this._fragShader = -1; 74652 this._glProgram = 0; 74653 this._loadedAttributes = false; 74654 this.attributes = {}; 74655 this._loadedUniforms = false; 74656 this.uniforms = {}; 74657 this._bound = false; 74658 this.samplers = []; 74659 74660 return this; 74661}; 74662 74663/** 74664 * Creates, compiles, and links the shader based on its 74665 * sources for the vertex and fragment shaders (provided 74666 * to the constructor). Populates known attributes and 74667 * uniforms from the shader. 74668 * @method init 74669 * @chainable 74670 * @private 74671 */ 74672p5.Shader.prototype.init = function() { 74673 if (this._glProgram === 0 /* or context is stale? */) { 74674 var gl = this._renderer.GL; 74675 74676 // @todo: once custom shading is allowed, 74677 // friendly error messages should be used here to share 74678 // compiler and linker errors. 74679 74680 //set up the shader by 74681 // 1. creating and getting a gl id for the shader program, 74682 // 2. compliling its vertex & fragment sources, 74683 // 3. linking the vertex and fragment shaders 74684 this._vertShader = gl.createShader(gl.VERTEX_SHADER); 74685 //load in our default vertex shader 74686 gl.shaderSource(this._vertShader, this._vertSrc); 74687 gl.compileShader(this._vertShader); 74688 // if our vertex shader failed compilation? 74689 if (!gl.getShaderParameter(this._vertShader, gl.COMPILE_STATUS)) { 74690 console.error( 74691 'Yikes! An error occurred compiling the vertex shader:' + 74692 gl.getShaderInfoLog(this._vertShader) 74693 ); 74694 return null; 74695 } 74696 74697 this._fragShader = gl.createShader(gl.FRAGMENT_SHADER); 74698 //load in our material frag shader 74699 gl.shaderSource(this._fragShader, this._fragSrc); 74700 gl.compileShader(this._fragShader); 74701 // if our frag shader failed compilation? 74702 if (!gl.getShaderParameter(this._fragShader, gl.COMPILE_STATUS)) { 74703 console.error( 74704 'Darn! An error occurred compiling the fragment shader:' + 74705 gl.getShaderInfoLog(this._fragShader) 74706 ); 74707 return null; 74708 } 74709 74710 this._glProgram = gl.createProgram(); 74711 gl.attachShader(this._glProgram, this._vertShader); 74712 gl.attachShader(this._glProgram, this._fragShader); 74713 gl.linkProgram(this._glProgram); 74714 if (!gl.getProgramParameter(this._glProgram, gl.LINK_STATUS)) { 74715 console.error( 74716 'Snap! Error linking shader program: ' + 74717 gl.getProgramInfoLog(this._glProgram) 74718 ); 74719 } 74720 74721 this._loadAttributes(); 74722 this._loadUniforms(); 74723 } 74724 return this; 74725}; 74726 74727/** 74728 * Queries the active attributes for this shader and loads 74729 * their names and locations into the attributes array. 74730 * @method _loadAttributes 74731 * @private 74732 */ 74733p5.Shader.prototype._loadAttributes = function() { 74734 if (this._loadedAttributes) { 74735 return; 74736 } 74737 74738 this.attributes = {}; 74739 74740 var gl = this._renderer.GL; 74741 74742 var numAttributes = gl.getProgramParameter( 74743 this._glProgram, 74744 gl.ACTIVE_ATTRIBUTES 74745 ); 74746 for (var i = 0; i < numAttributes; ++i) { 74747 var attributeInfo = gl.getActiveAttrib(this._glProgram, i); 74748 var name = attributeInfo.name; 74749 var location = gl.getAttribLocation(this._glProgram, name); 74750 var attribute = {}; 74751 attribute.name = name; 74752 attribute.location = location; 74753 attribute.type = attributeInfo.type; 74754 attribute.size = attributeInfo.size; 74755 this.attributes[name] = attribute; 74756 } 74757 74758 this._loadedAttributes = true; 74759}; 74760 74761/** 74762 * Queries the active uniforms for this shader and loads 74763 * their names and locations into the uniforms array. 74764 * @method _loadUniforms 74765 * @private 74766 */ 74767p5.Shader.prototype._loadUniforms = function() { 74768 if (this._loadedUniforms) { 74769 return; 74770 } 74771 74772 var gl = this._renderer.GL; 74773 74774 // Inspect shader and cache uniform info 74775 var numUniforms = gl.getProgramParameter(this._glProgram, gl.ACTIVE_UNIFORMS); 74776 74777 var samplerIndex = 0; 74778 for (var i = 0; i < numUniforms; ++i) { 74779 var uniformInfo = gl.getActiveUniform(this._glProgram, i); 74780 var uniform = {}; 74781 uniform.location = gl.getUniformLocation(this._glProgram, uniformInfo.name); 74782 uniform.size = uniformInfo.size; 74783 var uniformName = uniformInfo.name; 74784 //uniforms thats are arrays have their name returned as 74785 //someUniform[0] which is a bit silly so we trim it 74786 //off here. The size property tells us that its an array 74787 //so we dont lose any information by doing this 74788 if (uniformInfo.size > 1) { 74789 uniformName = uniformName.substring(0, uniformName.indexOf('[0]')); 74790 } 74791 uniform.name = uniformName; 74792 uniform.type = uniformInfo.type; 74793 if (uniform.type === gl.SAMPLER_2D) { 74794 uniform.samplerIndex = samplerIndex; 74795 samplerIndex++; 74796 this.samplers.push(uniform); 74797 } 74798 this.uniforms[uniformName] = uniform; 74799 } 74800 this._loadedUniforms = true; 74801}; 74802 74803p5.Shader.prototype.compile = function() { 74804 // TODO 74805}; 74806 74807/** 74808 * initializes (if needed) and binds the shader program. 74809 * @method bindShader 74810 * @private 74811 */ 74812p5.Shader.prototype.bindShader = function() { 74813 this.init(); 74814 if (!this._bound) { 74815 this.useProgram(); 74816 this._bound = true; 74817 this.bindTextures(); 74818 74819 this._loadAttributes(); 74820 this._loadUniforms(); 74821 74822 this._renderer._setDefaultCamera(); 74823 this._setMatrixUniforms(); 74824 if (this === this._renderer.curStrokeShader) {
74825 this._setViewportUniform(); 74826 } 74827 } 74828}; 74829 74830/** 74831 * @method unbindShader 74832 * @chainable 74833 * @private 74834 */ 74835p5.Shader.prototype.unbindShader = function() { 74836 if (this._bound) { 74837 this.unbindTextures(); 74838 //this._renderer.GL.useProgram(0); ?? 74839 this._bound = false; 74840 } 74841 return this; 74842}; 74843 74844p5.Shader.prototype.bindTextures = function() { 74845 var gl = this._renderer.GL; 74846 for (var i = 0; i < this.samplers.length; i++) { 74847 var uniform = this.samplers[i]; 74848 var tex = uniform.texture; 74849 if (tex === undefined) { 74850 // user hasn't yet supplied a texture for this slot. 74851 // (or there may not be one--maybe just lighting), 74852 // so we supply a default texture instead. 74853 tex = this._renderer._getEmptyTexture(); 74854 } 74855 gl.activeTexture(gl.TEXTURE0 + uniform.samplerIndex); 74856 tex.bindTexture(); 74857 tex.update(); 74858 gl.uniform1i(uniform.location, uniform.samplerIndex); 74859 } 74860}; 74861 74862p5.Shader.prototype.unbindTextures = function() { 74863 // TODO: migrate stuff from material.js here 74864 // - OR - have material.js define this function 74865}; 74866 74867p5.Shader.prototype._setMatrixUniforms = function() { 74868 this.setUniform('uProjectionMatrix', this._renderer.uPMatrix.mat4); 74869 this.setUniform('uModelViewMatrix', this._renderer.uMVMatrix.mat4); 74870 this.setUniform('uViewMatrix', this._renderer.cameraMatrix.mat4); 74871 if (this === this._renderer.curFillShader) { 74872 this._renderer.uNMatrix.inverseTranspose(this._renderer.uMVMatrix); 74873 this.setUniform('uNormalMatrix', this._renderer.uNMatrix.mat3); 74874 } 74875}; 74876 74877p5.Shader.prototype._setViewportUniform = function() { 74878 this.setUniform('uViewport', this._renderer._viewport); 74879}; 74880 74881/** 74882 * @method useProgram 74883 * @chainable 74884 * @private 74885 */ 74886p5.Shader.prototype.useProgram = function() { 74887 var gl = this._renderer.GL; 74888 gl.useProgram(this._glProgram); 74889 return this; 74890}; 74891 74892/** 74893 * Wrapper around gl.uniform functions. 74894 * As we store uniform info in the shader we can use that 74895 * to do type checking on the supplied data and call 74896 * the appropriate function. 74897 * @method setUniform 74898 * @chainable 74899 * @param {String} uniformName the name of the uniform in the 74900 * shader program 74901 * @param {Object|Number|Boolean|Number[]} data the data to be associated 74902 * with that uniform; type varies (could be a single numerical value, array, 74903 * matrix, or texture / sampler reference) 74904 */ 74905p5.Shader.prototype.setUniform = function(uniformName, data) { 74906 //@todo update all current gl.uniformXX calls 74907 74908 var uniform = this.uniforms[uniformName]; 74909 if (!uniform) { 74910 //@todo warning? 74911 return; 74912 } 74913 var location = uniform.location; 74914 74915 var gl = this._renderer.GL; 74916 // todo: is this safe to do here? 74917 // todo: store the values another way? 74918 this.useProgram(); 74919 74920 // TODO BIND? 74921 74922 switch (uniform.type) { 74923 case gl.BOOL: 74924 if (data === true) { 74925 gl.uniform1i(location, 1); 74926 } else { 74927 gl.uniform1i(location, 0); 74928 } 74929 break; 74930 case gl.INT: 74931 if (uniform.size > 1) { 74932 data.length && gl.uniform1iv(location, data); 74933 } else { 74934 gl.uniform1i(location, data); 74935 } 74936 break; 74937 case gl.FLOAT: 74938 if (uniform.size > 1) { 74939 data.length && gl.uniform1fv(location, data); 74940 } else { 74941 gl.uniform1f(location, data); 74942 } 74943 break; 74944 case gl.FLOAT_MAT3: 74945 gl.uniformMatrix3fv(location, false, data); 74946 break; 74947 case gl.FLOAT_MAT4: 74948 gl.uniformMatrix4fv(location, false, data); 74949 break; 74950 case gl.FLOAT_VEC2: 74951 if (uniform.size > 1) { 74952 data.length && gl.uniform2fv(location, data); 74953 } else { 74954 gl.uniform2f(location, data[0], data[1]); 74955 } 74956 break; 74957 case gl.FLOAT_VEC3: 74958 if (uniform.size > 1) { 74959 data.length && gl.uniform3fv(location, data); 74960 } else { 74961 gl.uniform3f(location, data[0], data[1], data[2]); 74962 } 74963 break; 74964 case gl.FLOAT_VEC4: 74965 if (uniform.size > 1) { 74966 data.length && gl.uniform4fv(location, data); 74967 } else { 74968 gl.uniform4f(location, data[0], data[1], data[2], data[3]); 74969 } 74970 break; 74971 case gl.SAMPLER_2D: 74972 gl.activeTexture(gl.TEXTURE0 + uniform.samplerIndex); 74973 uniform.texture = this._renderer.getTexture(data); 74974 gl.uniform1i(uniform.location, uniform.samplerIndex); 74975 break; 74976 //@todo complete all types 74977 } 74978 return this; 74979}; 74980 74981/* NONE OF THIS IS FAST OR EFFICIENT BUT BEAR WITH ME 74982 * 74983 * these shader "type" query methods are used by various 74984 * facilities of the renderer to determine if changing
74985 * the shader type for the required action (for example, 74986 * do we need to load the default lighting shader if the 74987 * current shader cannot handle lighting?) 74988 * 74989 **/ 74990 74991p5.Shader.prototype.isLightShader = function() { 74992 return ( 74993 this.uniforms.uUseLighting !== undefined || 74994 this.uniforms.uAmbientLightCount !== undefined || 74995 this.uniforms.uDirectionalLightCount !== undefined || 74996 this.uniforms.uPointLightCount !== undefined || 74997 this.uniforms.uAmbientColor !== undefined || 74998 this.uniforms.uDirectionalColor !== undefined || 74999 this.uniforms.uPointLightLocation !== undefined || 75000 this.uniforms.uPointLightColor !== undefined || 75001 this.uniforms.uLightingDirection !== undefined || 75002 this.uniforms.uSpecular !== undefined 75003 ); 75004}; 75005 75006p5.Shader.prototype.isTextureShader = function() { 75007 return this.samplerIndex > 0; 75008}; 75009 75010p5.Shader.prototype.isColorShader = function() { 75011 return ( 75012 this.attributes.aVertexColor !== undefined || 75013 this.uniforms.uMaterialColor !== undefined 75014 ); 75015}; 75016 75017p5.Shader.prototype.isTexLightShader = function() { 75018 return this.isLightShader() && this.isTextureShader(); 75019}; 75020 75021p5.Shader.prototype.isStrokeShader = function() { 75022 return this.uniforms.uStrokeWeight !== undefined; 75023}; 75024 75025/** 75026 * @method enableAttrib 75027 * @chainable 75028 * @private 75029 */ 75030p5.Shader.prototype.enableAttrib = function( 75031 loc, 75032 size, 75033 type, 75034 normalized, 75035 stride, 75036 offset 75037) { 75038 var gl = this._renderer.GL; 75039 if (loc !== -1) { 75040 gl.enableVertexAttribArray(loc); 75041 gl.vertexAttribPointer(loc, size, type, normalized, stride, offset); 75042 } 75043 return this; 75044}; 75045 75046module.exports = p5.Shader; 75047 75048},{"../core/core":22}],74:[function(_dereq_,module,exports){ 75049/** 75050 * This module defines the p5.Texture class 75051 * @module Lights, Camera 75052 * @submodule Material 75053 * @for p5 75054 * @requires core 75055 */ 75056 75057'use strict'; 75058 75059var p5 = _dereq_('../core/core'); 75060 75061/** 75062 * Texture class for WEBGL Mode 75063 * @private 75064 * @class p5.Texture 75065 * @param {p5.RendererGL} renderer an instance of p5.RendererGL that 75066 * will provide the GL context for this new p5.Texture 75067 * @param {p5.Image|p5.Graphics|p5.Element|p5.MediaElement} [obj] the
75068 * object containing the image data to store in the texture. 75069 */ 75070p5.Texture = function(renderer, obj) { 75071 this._renderer = renderer; 75072 75073 var gl = this._renderer.GL; 75074 75075 this.src = obj; 75076 this.glTex = undefined; 75077 this.glTarget = gl.TEXTURE_2D; 75078 this.glFormat = gl.RGBA; 75079 this.mipmaps = false; 75080 this.glMinFilter = gl.LINEAR; 75081 this.glMagFilter = gl.LINEAR; 75082 this.glWrapS = gl.CLAMP_TO_EDGE; 75083 this.glWrapT = gl.CLAMP_TO_EDGE; 75084 75085 // used to determine if this texture might need constant updating 75086 // because it is a video or gif. 75087 this.isSrcMediaElement = 75088 typeof p5.MediaElement !== 'undefined' && obj instanceof p5.MediaElement; 75089 this._videoPrevUpdateTime = 0; 75090 this.isSrcHTMLElement = 75091 typeof p5.Element !== 'undefined' && 75092 obj instanceof p5.Element && 75093 !(obj instanceof p5.Graphics); 75094 this.isSrcP5Image = obj instanceof p5.Image; 75095 this.isSrcP5Graphics = obj instanceof p5.Graphics; 75096 75097 var textureData = this._getTextureDataFromSource(); 75098 this.width = textureData.width; 75099 this.height = textureData.height; 75100 75101 this.init(textureData); 75102 return this; 75103}; 75104 75105p5.Texture.prototype._getTextureDataFromSource = function() { 75106 var textureData; 75107 if (this.isSrcP5Image) { 75108 // param is a p5.Image 75109 textureData = this.src.canvas; 75110 } else if ( 75111 this.isSrcMediaElement || 75112 this.isSrcP5Graphics || 75113 this.isSrcHTMLElement 75114 ) { 75115 // if param is a video HTML element 75116 textureData = this.src.elt; 75117 } 75118 return textureData; 75119}; 75120 75121/** 75122 * Initializes common texture parameters, creates a gl texture, 75123 * tries to upload the texture for the first time if data is 75124 * already available. 75125 * @private 75126 * @method init 75127 */ 75128p5.Texture.prototype.init = function(data) { 75129 var gl = this._renderer.GL; 75130 this.glTex = gl.createTexture(); 75131 this.bindTexture(); 75132 75133 //gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); 75134 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, this.glMagFilter); 75135 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, this.glMinFilter); 75136 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, this.glWrapS); 75137 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, this.glWrapT); 75138 75139 if ( 75140 this.width === 0 || 75141 this.height === 0 || 75142 (this.isSrcMediaElement && !this.src.loadedmetadata) 75143 ) { 75144 // assign a 1x1 empty texture initially, because data is not yet ready, 75145 // so that no errors occur in gl console! 75146 var tmpdata = new Uint8Array([1, 1, 1, 1]); 75147 gl.texImage2D( 75148 this.glTarget, 75149 0, 75150 gl.RGBA, 75151 1, 75152 1, 75153 0, 75154 this.glFormat, 75155 gl.UNSIGNED_BYTE, 75156 tmpdata 75157 ); 75158 } else { 75159 // data is ready: just push the texture! 75160 gl.texImage2D( 75161 this.glTarget, 75162 0, 75163 this.glFormat, 75164 this.glFormat, 75165 gl.UNSIGNED_BYTE, 75166 data 75167 ); 75168 } 75169}; 75170 75171/** 75172 * Checks if the source data for this texture has changed (if it's 75173 * easy to do so) and reuploads the texture if necessary. If it's not 75174 * possible or to expensive to do a calculation to determine wheter or 75175 * not the data has occurred, this method simply re-uploads the texture. 75176 * @method update 75177 */ 75178p5.Texture.prototype.update = function() { 75179 var data = this.src; 75180 if (data.width === 0 || data.height === 0) { 75181 return; // nothing to do! 75182 } 75183 75184 var textureData = this._getTextureDataFromSource(); 75185 75186 var gl = this._renderer.GL; 75187 // pull texture from data, make sure width & height are appropriate 75188 if (textureData.width !== this.width || textureData.height !== this.height) { 75189 // make sure that if the width and height of this.src have changed 75190 // for some reason, we update our metadata and upload the texture again 75191 this.width = textureData.width; 75192 this.height = textureData.height; 75193 75194 this.bindTexture(); 75195 gl.texImage2D( 75196 this.glTarget, 75197 0, 75198 this.glFormat, 75199 this.glFormat, 75200 gl.UNSIGNED_BYTE, 75201 textureData 75202 ); 75203 75204 if (this.isSrcP5Image) { 75205 data.setModified(false); 75206 } else if (this.isSrcMediaElement || this.isSrcHTMLElement) { 75207 // on the first frame the metadata comes in, the size will be changed 75208 // from 0 to actual size, but pixels may not be available. 75209 // flag for update in a future frame. 75210 // if we don't do this, a paused video, for example, may not
75211 // send the first frame to texture memory. 75212 data.setModified(true); 75213 } 75214 } else if (this.isSrcP5Image) { 75215 // for an image, we only update if the modified field has been set, 75216 // for example, by a call to p5.Image.set 75217 if (data.isModified()) { 75218 this.bindTexture(); 75219 gl.texImage2D( 75220 this.glTarget, 75221 0, 75222 this.glFormat, 75223 this.glFormat, 75224 gl.UNSIGNED_BYTE, 75225 textureData 75226 ); 75227 data.setModified(false); 75228 } 75229 } else if (this.isSrcMediaElement) { 75230 var shouldUpdate = false; 75231 75232 // for a media element (video), we'll check if the current time in 75233 // the video frame matches the last time. if it doesn't match, the 75234 // video has advanced or otherwise been taken to a new frame, 75235 // and we need to upload it. 75236 if (data.isModified()) { 75237 // p5.MediaElement may have also had set/updatePixels, etc. called 75238 // on it and should be updated, or may have been set for the first 75239 // time! 75240 shouldUpdate = true; 75241 data.setModified(false); 75242 } else if (data.loadedmetadata) { 75243 // if the meta data has been loaded, we can ask the video 75244 // what it's current position (in time) is. 75245 if (this._videoPrevUpdateTime !== data.time()) { 75246 // update the texture in gpu mem only if the current 75247 // video timestamp does not match the timestamp of the last 75248 // time we uploaded this texture (and update the time we 75249 // last uploaded, too) 75250 this._videoPrevUpdateTime = data.time(); 75251 shouldUpdate = true; 75252 } 75253 } 75254 75255 if (shouldUpdate) { 75256 this.bindTexture(); 75257 gl.texImage2D( 75258 this.glTarget, 75259 0, 75260 this.glFormat, 75261 this.glFormat, 75262 gl.UNSIGNED_BYTE, 75263 textureData 75264 ); 75265 } 75266 } else { 75267 /* data instanceof p5.Graphics, probably */ // there is not enough information to tell if the texture can be 75268 // conditionally updated; so to be safe, we just go ahead and upload it. 75269 gl.texImage2D( 75270 this.glTarget, 75271 0, 75272 this.glFormat, 75273 this.glFormat, 75274 gl.UNSIGNED_BYTE, 75275 textureData 75276 ); 75277 } 75278}; 75279 75280/** 75281 * Binds the texture to the appropriate GL target. 75282 * @method bindTexture 75283 */ 75284p5.Texture.prototype.bindTexture = function() { 75285 // bind texture using gl context + glTarget and 75286 // generated gl texture object 75287 var gl = this._renderer.GL; 75288 gl.bindTexture(this.glTarget, this.glTex); 75289 75290 return this; 75291}; 75292 75293/** 75294 * Unbinds the texture from the appropriate GL target. 75295 * @method unbindTexture 75296 */ 75297p5.Texture.prototype.unbindTexture = function() { 75298 // unbind per above, disable texturing on glTarget 75299 var gl = this._renderer.GL; 75300 gl.bindTexture(this.glTarget, null); 75301}; 75302 75303module.exports = p5.Texture; 75304 75305},{"../core/core":22}],75:[function(_dereq_,module,exports){ 75306/** 75307 * @module Shape 75308 * @submodule 3D Primitives 75309 * @for p5 75310 * @requires core 75311 * @requires p5.Geometry 75312 */ 75313 75314'use strict'; 75315 75316var p5 = _dereq_('../core/core'); 75317_dereq_('./p5.Geometry'); 75318 75319/** 75320 * Draw a plane with given a width and height 75321 * @method plane 75322 * @param {Number} [width] width of the plane 75323 * @param {Number} [height] height of the plane 75324 * @param {Integer} [detailX] Optional number of triangle 75325 * subdivisions in x-dimension 75326 * @param {Integer} [detailY] Optional number of triangle 75327 * subdivisions in y-dimension 75328 * @chainable 75329 * @example 75330 * <div> 75331 * <code> 75332 * //draw a plane with width 50 and height 50 75333 * function setup() { 75334 * createCanvas(100, 100, WEBGL); 75335 * } 75336 * 75337 * function draw() { 75338 * background(200); 75339 * plane(50, 50); 75340 * } 75341 * </code> 75342 * </div> 75343 * 75344 * @alt 75345 * Nothing displayed on canvas 75346 * Rotating interior view of a box with sides that change color. 75347 * 3d red and green gradient. 75348 * Rotating interior view of a cylinder with sides that change color. 75349 * Rotating view of a cylinder with sides that change color. 75350 * 3d red and green gradient. 75351 * rotating view of a multi-colored cylinder with concave sides. 75352 */ 75353p5.prototype.plane = function(width, height, detailX, detailY) { 75354 this._assert3d('plane'); 75355 p5._validateParameters('plane', arguments); 75356 if (typeof width === 'undefined') { 75357 width = 50; 75358 } 75359 if (typeof height === 'undefined') { 75360 height = width; 75361 } 75362 75363 if (typeof detailX === 'undefined') { 75364 detailX = 1; 75365 } 75366 if (typeof detailY === 'undefined') { 75367 detailY = 1; 75368 } 75369 75370 var gId = 'plane|' + detailX + '|' + detailY; 75371 75372 if (!this._renderer.geometryInHash(gId)) { 75373 var _plane = function() { 75374 var u, v, p; 75375 for (var i = 0; i <= this.detailY; i++) { 75376 v = i / this.detailY; 75377 for (var j = 0; j <= this.detailX; j++) { 75378 u = j / this.detailX; 75379 p = new p5.Vector(u - 0.5, v - 0.5, 0); 75380 this.vertices.push(p); 75381 this.uvs.push(u, v); 75382 } 75383 } 75384 }; 75385 var planeGeom = new p5.Geometry(detailX, detailY, _plane); 75386 planeGeom.computeFaces().computeNormals(); 75387 if (detailX <= 1 && detailY <= 1) { 75388 planeGeom._makeTriangleEdges()._edgesToVertices(); 75389 } else { 75390 console.log( 75391 'Cannot draw stroke on plane objects with more' + 75392 ' than 1 detailX or 1 detailY' 75393 ); 75394 } 75395 this._renderer.createBuffers(gId, planeGeom); 75396 } 75397 75398 this._renderer.drawBuffersScaled(gId, width, height, 0); 75399}; 75400 75401/** 75402 * Draw a box with given width, height and depth 75403 * @method box 75404 * @param {Number} [width] width of the box 75405 * @param {Number} [Height] height of the box 75406 * @param {Number} [depth] depth of the box 75407 * @param {Integer} [detailX] Optional number of triangle 75408 * subdivisions in x-dimension 75409 * @param {Integer} [detailY] Optional number of triangle 75410 * subdivisions in y-dimension 75411 * @chainable 75412 * @example 75413 * <div> 75414 * <code> 75415 * //draw a spinning box with width, height and depth 200 75416 * function setup() { 75417 * createCanvas(100, 100, WEBGL); 75418 * } 75419 * 75420 * function draw() { 75421 * background(200); 75422 * rotateX(frameCount * 0.01); 75423 * rotateY(frameCount * 0.01); 75424 * box(50); 75425 * } 75426 * </code> 75427 * </div> 75428 */ 75429p5.prototype.box = function(width, height, depth, detailX, detailY) { 75430 this._assert3d('box'); 75431 p5._validateParameters('box', arguments); 75432 if (typeof width === 'undefined') { 75433 width = 50; 75434 } 75435 if (typeof height === 'undefined') { 75436 height = width; 75437 } 75438 if (typeof depth === 'undefined') { 75439 depth = height; 75440 } 75441 75442 var perPixelLighting = 75443 this._renderer.attributes && this._renderer.attributes.perPixelLighting; 75444 if (typeof detailX === 'undefined') { 75445 detailX = perPixelLighting ? 1 : 4; 75446 } 75447 if (typeof detailY === 'undefined') { 75448 detailY = perPixelLighting ? 1 : 4; 75449 } 75450 75451 var gId = 'box|' + detailX + '|' + detailY; 75452 if (!this._renderer.geometryInHash(gId)) { 75453 var _box = function() { 75454 var cubeIndices = [ 75455 [0, 4, 2, 6], // -1, 0, 0],// -x 75456 [1, 3, 5, 7], // +1, 0, 0],// +x 75457 [0, 1, 4, 5], // 0, -1, 0],// -y 75458 [2, 6, 3, 7], // 0, +1, 0],// +y 75459 [0, 2, 1, 3], // 0, 0, -1],// -z 75460 [4, 5, 6, 7] // 0, 0, +1] // +z 75461 ]; 75462 //using strokeIndices instead of faces for strokes 75463 //to avoid diagonal stroke lines across face of box 75464 this.strokeIndices = [ 75465 [0, 1], 75466 [1, 3], 75467 [3, 2], 75468 [6, 7], 75469 [8, 9], 75470 [9, 11], 75471 [14, 15], 75472 [16, 17], 75473 [17, 19], 75474 [18, 19], 75475 [20, 21], 75476 [22, 23] 75477 ]; 75478 for (var i = 0; i < cubeIndices.length; i++) { 75479 var cubeIndex = cubeIndices[i]; 75480 var v = i * 4; 75481 for (var j = 0; j < 4; j++) { 75482 var d = cubeIndex[j]; 75483 //inspired by lightgl: 75484 //https://github.com/evanw/lightgl.js 75485 //octants:https://en.wikipedia.org/wiki/Octant_(solid_geometry) 75486 var octant = new p5.Vector( 75487 ((d & 1) * 2 - 1) / 2, 75488 ((d & 2) - 1) / 2, 75489 ((d & 4) / 2 - 1) / 2 75490 ); 75491 this.vertices.push(octant); 75492 this.uvs.push(j & 1, (j & 2) / 2); 75493 } 75494 this.faces.push([v, v + 1, v + 2]); 75495 this.faces.push([v + 2, v + 1, v + 3]); 75496 } 75497 }; 75498 var boxGeom = new p5.Geometry(detailX, detailY, _box); 75499 boxGeom.computeNormals(); 75500 if (detailX <= 4 && detailY <= 4) { 75501 boxGeom._makeTriangleEdges()._edgesToVertices(); 75502 } else { 75503 console.log( 75504 'Cannot draw stroke on box objects with more' + 75505 ' than 4 detailX or 4 detailY' 75506 ); 75507 } 75508 //initialize our geometry buffer with 75509 //the key val pair: 75510 //geometry Id, Geom object 75511 this._renderer.createBuffers(gId, boxGeom); 75512 } 75513 this._renderer.drawBuffersScaled(gId, width, height, depth); 75514 75515 return this; 75516}; 75517 75518/** 75519 * Draw a sphere with given radius 75520 * @method sphere 75521 * @param {Number} [radius] radius of circle 75522 * @param {Integer} [detailX] number of segments, 75523 * the more segments the smoother geometry 75524 * default is 24 75525 * @param {Integer} [detailY] number of segments, 75526 * the more segments the smoother geometry 75527 * default is 16 75528 * @chainable 75529 * @example 75530 * <div> 75531 * <code> 75532 * // draw a sphere with radius 200 75533 * function setup() { 75534 * createCanvas(100, 100, WEBGL); 75535 * } 75536 * 75537 * function draw() { 75538 * background(200); 75539 * sphere(40); 75540 * } 75541 * </code> 75542 * </div> 75543 */ 75544p5.prototype.sphere = function(radius, detailX, detailY) { 75545 this._assert3d('sphere'); 75546 p5._validateParameters('sphere', arguments); 75547 if (typeof radius === 'undefined') { 75548 radius = 50; 75549 } 75550 if (typeof detailX === 'undefined') { 75551 detailX = 24; 75552 } 75553 if (typeof detailY === 'undefined') { 75554 detailY = 16; 75555 } 75556 75557 this.ellipsoid(radius, radius, radius, detailX, detailY); 75558 75559 return this; 75560}; 75561 75562/** 75563 * @private 75564 * Helper function for creating both cones and cyllinders 75565 * Will only generate well-defined geometry when bottomRadius, height > 0 75566 * and topRadius >= 0 75567 * If topRadius == 0, topCap should be false 75568 */ 75569var _truncatedCone = function( 75570 bottomRadius, 75571 topRadius, 75572 height, 75573 detailX, 75574 detailY, 75575 bottomCap, 75576 topCap 75577) { 75578 bottomRadius = bottomRadius <= 0 ? 1 : bottomRadius; 75579 topRadius = topRadius < 0 ? 0 : topRadius; 75580 height = height <= 0 ? bottomRadius : height; 75581 detailX = detailX < 3 ? 3 : detailX; 75582 detailY = detailY < 1 ? 1 : detailY; 75583 bottomCap = bottomCap === undefined ? true : bottomCap; 75584 topCap = topCap === undefined ? topRadius !== 0 : topCap; 75585 var start = bottomCap ? -2 : 0; 75586 var end = detailY + (topCap ? 2 : 0); 75587 var vertsOnLayer = {}; 75588 //ensure constant slant for interior vertex normals 75589 var slant = Math.atan2(bottomRadius - topRadius, height); 75590 var yy, ii, jj, nextii, nextjj; 75591 for (yy = start; yy <= end; ++yy) { 75592 var v = yy / detailY; 75593 var y = height * v; 75594 var ringRadius; 75595 if (yy < 0) { 75596 //for the bottomCap edge 75597 y = 0; 75598 v = 0; 75599 ringRadius = bottomRadius; 75600 } else if (yy > detailY) { 75601 //for the topCap edge 75602 y = height; 75603 v = 1; 75604 ringRadius = topRadius; 75605 } else { 75606 //for the middle 75607 ringRadius = bottomRadius + (topRadius - bottomRadius) * v; 75608 } 75609 if (yy === -2 || yy === detailY + 2) { 75610 //center of bottom or top caps 75611 ringRadius = 0; 75612 } 75613 75614 y -= height / 2; //shift coordiate origin to the center of object 75615 vertsOnLayer[yy] = ringRadius === 0 ? 1 : detailX; 75616 for (ii = 0; ii < vertsOnLayer[yy]; ++ii) { 75617 var u = ii / detailX; 75618 //VERTICES 75619 this.vertices.push( 75620 new p5.Vector( 75621 Math.sin(u * 2 * Math.PI) * ringRadius, 75622 y, 75623 Math.cos(u * 2 * Math.PI) * ringRadius 75624 ) 75625 ); 75626 //VERTEX NORMALS 75627 this.vertexNormals.push( 75628 new p5.Vector( 75629 yy < 0 || yy > detailY 75630 ? 0 75631 : Math.sin(u * 2 * Math.PI) * Math.cos(slant), 75632 yy < 0 ? -1 : yy > detailY ? 1 : Math.sin(slant), 75633 yy < 0 || yy > detailY 75634 ? 0
75635 : Math.cos(u * 2 * Math.PI) * Math.cos(slant) 75636 ) 75637 ); 75638 //UVs 75639 this.uvs.push(u, v); 75640 } 75641 } 75642 75643 var startIndex = 0; 75644 if (bottomCap) { 75645 for (jj = 0; jj < vertsOnLayer[-1]; ++jj) { 75646 nextjj = (jj + 1) % vertsOnLayer[-1]; 75647 this.faces.push([ 75648 startIndex, 75649 startIndex + 1 + nextjj, 75650 startIndex + 1 + jj 75651 ]); 75652 } 75653 startIndex += vertsOnLayer[-2] + vertsOnLayer[-1]; 75654 } 75655 for (yy = 0; yy < detailY; ++yy) { 75656 for (ii = 0; ii < vertsOnLayer[yy]; ++ii) { 75657 if (vertsOnLayer[yy + 1] === 1) { 75658 //top layer 75659 nextii = (ii + 1) % vertsOnLayer[yy]; 75660 this.faces.push([ 75661 startIndex + ii, 75662 startIndex + nextii, 75663 startIndex + vertsOnLayer[yy] 75664 ]); 75665 } else { 75666 //other side faces 75667 //should have vertsOnLayer[yy] === vertsOnLayer[yy + 1] 75668 nextii = (ii + 1) % vertsOnLayer[yy]; 75669 this.faces.push([ 75670 startIndex + ii, 75671 startIndex + nextii, 75672 startIndex + vertsOnLayer[yy] + nextii 75673 ]); 75674 this.faces.push([ 75675 startIndex + ii, 75676 startIndex + vertsOnLayer[yy] + nextii, 75677 startIndex + vertsOnLayer[yy] + ii 75678 ]); 75679 } 75680 } 75681 startIndex += vertsOnLayer[yy]; 75682 } 75683 if (topCap) { 75684 startIndex += vertsOnLayer[detailY]; 75685 for (ii = 0; ii < vertsOnLayer[detailY + 1]; ++ii) { 75686 nextii = (ii + 1) % vertsOnLayer[detailY + 1]; 75687 this.faces.push([ 75688 startIndex + ii, 75689 startIndex + nextii, 75690 startIndex + vertsOnLayer[detailY + 1] 75691 ]); 75692 } 75693 } 75694}; 75695 75696/** 75697 * Draw a cylinder with given radius and height 75698 * @method cylinder 75699 * @param {Number} [radius] radius of the surface 75700 * @param {Number} [height] height of the cylinder 75701 * @param {Integer} [detailX] number of segments, 75702 * the more segments the smoother geometry 75703 * default is 24 75704 * @param {Integer} [detailY] number of segments in y-dimension, 75705 * the more segments the smoother geometry 75706 * default is 1 75707 * @param {Boolean} [bottomCap] whether to draw the bottom of the cylinder 75708 * @param {Boolean} [topCap] whether to draw the top of the cylinder 75709 * @chainable 75710 * @example 75711 * <div> 75712 * <code> 75713 * //draw a spinning cylinder with radius 20 and height 50 75714 * function setup() { 75715 * createCanvas(100, 100, WEBGL); 75716 * } 75717 * 75718 * function draw() { 75719 * background(200); 75720 * rotateX(frameCount * 0.01); 75721 * rotateZ(frameCount * 0.01); 75722 * cylinder(20, 50); 75723 * } 75724 * </code> 75725 * </div> 75726 */ 75727p5.prototype.cylinder = function( 75728 radius, 75729 height, 75730 detailX, 75731 detailY, 75732 bottomCap, 75733 topCap 75734) { 75735 this._assert3d('cylinder'); 75736 p5._validateParameters('cylinder', arguments); 75737 if (typeof radius === 'undefined') { 75738 radius = 50; 75739 } 75740 if (typeof height === 'undefined') { 75741 height = radius; 75742 } 75743 if (typeof detailX === 'undefined') { 75744 detailX = 24; 75745 } 75746 if (typeof detailY === 'undefined') { 75747 detailY = 1; 75748 } 75749 if (typeof topCap === 'undefined') { 75750 topCap = true; 75751 } 75752 if (typeof bottomCap === 'undefined') { 75753 bottomCap = true; 75754 } 75755 75756 var gId = 75757 'cylinder|' + detailX + '|' + detailY + '|' + bottomCap + '|' + topCap; 75758 if (!this._renderer.geometryInHash(gId)) { 75759 var cylinderGeom = new p5.Geometry(detailX, detailY); 75760 _truncatedCone.call( 75761 cylinderGeom, 75762 1, 75763 1, 75764 1, 75765 detailX, 75766 detailY, 75767 bottomCap, 75768 topCap 75769 ); 75770 cylinderGeom.computeNormals(); 75771 if (detailX <= 24 && detailY <= 16) { 75772 cylinderGeom._makeTriangleEdges()._edgesToVertices(); 75773 } else { 75774 console.log( 75775 'Cannot draw stroke on cylinder objects with more' + 75776 ' than 24 detailX or 16 detailY' 75777 ); 75778 } 75779 this._renderer.createBuffers(gId, cylinderGeom); 75780 } 75781 75782 this._renderer.drawBuffersScaled(gId, radius, height, radius); 75783 75784 return this; 75785}; 75786 75787/** 75788 * Draw a cone with given radius and height 75789 * @method cone 75790 * @param {Number} [radius] radius of the bottom surface 75791 * @param {Number} [height] height of the cone 75792 * @param {Integer} [detailX] number of segments, 75793 * the more segments the smoother geometry 75794 * default is 24 75795 * @param {Integer} [detailY] number of segments, 75796 * the more segments the smoother geometry 75797 * default is 1 75798 * @param {Boolean} [cap] whether to draw the base of the cone 75799 * @chainable 75800 * @example 75801 * <div> 75802 * <code> 75803 * //draw a spinning cone with radius 40 and height 70 75804 * function setup() { 75805 * createCanvas(100, 100, WEBGL); 75806 * } 75807 * 75808 * function draw() { 75809 * background(200); 75810 * rotateX(frameCount * 0.01); 75811 * rotateZ(frameCount * 0.01); 75812 * cone(40, 70); 75813 * } 75814 * </code> 75815 * </div> 75816 */ 75817p5.prototype.cone = function(radius, height, detailX, detailY, cap) { 75818 this._assert3d('cone'); 75819 p5._validateParameters('cone', arguments); 75820 if (typeof radius === 'undefined') { 75821 radius = 50; 75822 } 75823 if (typeof height === 'undefined') { 75824 height = radius; 75825 } 75826 if (typeof detailX === 'undefined') { 75827 detailX = 24; 75828 } 75829 if (typeof detailY === 'undefined') { 75830 detailY = 1; 75831 } 75832 if (typeof cap === 'undefined') { 75833 cap = true; 75834 } 75835 75836 var gId = 'cone|' + detailX + '|' + detailY + '|' + cap; 75837 if (!this._renderer.geometryInHash(gId)) { 75838 var coneGeom = new p5.Geometry(detailX, detailY);
75839 _truncatedCone.call(coneGeom, 1, 0, 1, detailX, detailY, cap, false); 75840 //for cones we need to average Normals 75841 coneGeom.computeNormals(); 75842 if (detailX <= 24 && detailY <= 16) { 75843 coneGeom._makeTriangleEdges()._edgesToVertices(); 75844 } else { 75845 console.log( 75846 'Cannot draw stroke on cone objects with more' + 75847 ' than 24 detailX or 16 detailY' 75848 ); 75849 } 75850 this._renderer.createBuffers(gId, coneGeom); 75851 } 75852 75853 this._renderer.drawBuffersScaled(gId, radius, height, radius); 75854 75855 return this; 75856}; 75857 75858/** 75859 * Draw an ellipsoid with given radius 75860 * @method ellipsoid 75861 * @param {Number} [radiusx] xradius of circle 75862 * @param {Number} [radiusy] yradius of circle 75863 * @param {Number} [radiusz] zradius of circle 75864 * @param {Integer} [detailX] number of segments, 75865 * the more segments the smoother geometry 75866 * default is 24. Avoid detail number above 75867 * 150, it may crash the browser. 75868 * @param {Integer} [detailY] number of segments, 75869 * the more segments the smoother geometry 75870 * default is 16. Avoid detail number above 75871 * 150, it may crash the browser. 75872 * @chainable 75873 * @example 75874 * <div> 75875 * <code> 75876 * // draw an ellipsoid with radius 20, 30 and 40. 75877 * function setup() { 75878 * createCanvas(100, 100, WEBGL); 75879 * } 75880 * 75881 * function draw() { 75882 * background(200); 75883 * ellipsoid(20, 30, 40); 75884 * } 75885 * </code> 75886 * </div> 75887 */ 75888p5.prototype.ellipsoid = function(radiusX, radiusY, radiusZ, detailX, detailY) { 75889 this._assert3d('ellipsoid'); 75890 p5._validateParameters('ellipsoid', arguments); 75891 if (typeof radiusX === 'undefined') { 75892 radiusX = 50; 75893 } 75894 if (typeof radiusY === 'undefined') { 75895 radiusY = radiusX; 75896 } 75897 if (typeof radiusZ === 'undefined') { 75898 radiusZ = radiusX; 75899 } 75900 75901 if (typeof detailX === 'undefined') { 75902 detailX = 24; 75903 } 75904 if (typeof detailY === 'undefined') { 75905 detailY = 16; 75906 } 75907 75908 var gId = 'ellipsoid|' + detailX + '|' + detailY; 75909 75910 if (!this._renderer.geometryInHash(gId)) { 75911 var _ellipsoid = function() { 75912 for (var i = 0; i <= this.detailY; i++) { 75913 var v = i / this.detailY; 75914 var phi = Math.PI * v - Math.PI / 2; 75915 var cosPhi = Math.cos(phi); 75916 var sinPhi = Math.sin(phi); 75917 75918 for (var j = 0; j <= this.detailX; j++) { 75919 var u = j / this.detailX; 75920 var theta = 2 * Math.PI * u; 75921 var cosTheta = Math.cos(theta); 75922 var sinTheta = Math.sin(theta); 75923 var p = new p5.Vector(cosPhi * sinTheta, sinPhi, cosPhi * cosTheta); 75924 this.vertices.push(p); 75925 this.vertexNormals.push(p); 75926 this.uvs.push(u, v); 75927 } 75928 } 75929 }; 75930 var ellipsoidGeom = new p5.Geometry(detailX, detailY, _ellipsoid); 75931 ellipsoidGeom.computeFaces(); 75932 if (detailX <= 24 && detailY <= 24) { 75933 ellipsoidGeom._makeTriangleEdges()._edgesToVertices(); 75934 } else { 75935 console.log( 75936 'Cannot draw stroke on ellipsoids with more' + 75937 ' than 24 detailX or 24 detailY' 75938 ); 75939 } 75940 this._renderer.createBuffers(gId, ellipsoidGeom); 75941 } 75942 75943 this._renderer.drawBuffersScaled(gId, radiusX, radiusY, radiusZ); 75944 75945 return this; 75946}; 75947 75948/** 75949 * Draw a torus with given radius and tube radius 75950 * @method torus 75951 * @param {Number} [radius] radius of the whole ring 75952 * @param {Number} [tubeRadius] radius of the tube 75953 * @param {Integer} [detailX] number of segments in x-dimension, 75954 * the more segments the smoother geometry 75955 * default is 24 75956 * @param {Integer} [detailY] number of segments in y-dimension, 75957 * the more segments the smoother geometry 75958 * default is 16 75959 * @chainable 75960 * @example 75961 * <div> 75962 * <code> 75963 * //draw a spinning torus with radius 200 and tube radius 60 75964 * function setup() { 75965 * createCanvas(100, 100, WEBGL); 75966 * } 75967 * 75968 * function draw() { 75969 * background(200); 75970 * rotateX(frameCount * 0.01); 75971 * rotateY(frameCount * 0.01); 75972 * torus(50, 15); 75973 * } 75974 * </code> 75975 * </div> 75976 */ 75977p5.prototype.torus = function(radius, tubeRadius, detailX, detailY) { 75978 this._assert3d('torus'); 75979 p5._validateParameters('torus', arguments); 75980 if (typeof radius === 'undefined') { 75981 radius = 50; 75982 } else if (!radius) { 75983 return; // nothing to draw 75984 } 75985 75986 if (typeof tubeRadius === 'undefined') { 75987 tubeRadius = 10; 75988 } else if (!tubeRadius) { 75989 return; // nothing to draw 75990 } 75991 75992 if (typeof detailX === 'undefined') { 75993 detailX = 24; 75994 } 75995 if (typeof detailY === 'undefined') { 75996 detailY = 16; 75997 } 75998 75999 var tubeRatio = (tubeRadius / radius).toPrecision(4); 76000 var gId = 'torus|' + tubeRatio + '|' + detailX + '|' + detailY; 76001 76002 if (!this._renderer.geometryInHash(gId)) { 76003 var _torus = function() { 76004 for (var i = 0; i <= this.detailY; i++) { 76005 var v = i / this.detailY; 76006 var phi = 2 * Math.PI * v; 76007 var cosPhi = Math.cos(phi);
76008 var sinPhi = Math.sin(phi); 76009 var r = 1 + tubeRatio * cosPhi; 76010 76011 for (var j = 0; j <= this.detailX; j++) { 76012 var u = j / this.detailX; 76013 var theta = 2 * Math.PI * u; 76014 var cosTheta = Math.cos(theta); 76015 var sinTheta = Math.sin(theta); 76016 76017 var p = new p5.Vector(r * cosTheta, r * sinTheta, tubeRatio * sinPhi); 76018 76019 var n = new p5.Vector(cosPhi * cosTheta, cosPhi * sinTheta, sinPhi); 76020 76021 this.vertices.push(p); 76022 this.vertexNormals.push(n); 76023 this.uvs.push(u, v); 76024 } 76025 } 76026 }; 76027 var torusGeom = new p5.Geometry(detailX, detailY, _torus); 76028 torusGeom.computeFaces(); 76029 if (detailX <= 24 && detailY <= 16) { 76030 torusGeom._makeTriangleEdges()._edgesToVertices(); 76031 } else { 76032 console.log( 76033 'Cannot draw strokes on torus object with more' + 76034 ' than 24 detailX or 16 detailY' 76035 ); 76036 } 76037 this._renderer.createBuffers(gId, torusGeom); 76038 } 76039 this._renderer.drawBuffersScaled(gId, radius, radius, radius); 76040 76041 return this; 76042}; 76043 76044/////////////////////// 76045/// 2D primitives 76046///////////////////////// 76047 76048//@TODO 76049p5.RendererGL.prototype.point = function(x, y, z) { 76050 console.log('point not yet implemented in webgl'); 76051 return this; 76052}; 76053 76054p5.RendererGL.prototype.triangle = function(args) { 76055 var x1 = args[0], 76056 y1 = args[1]; 76057 var x2 = args[2], 76058 y2 = args[3]; 76059 var x3 = args[4], 76060 y3 = args[5]; 76061 76062 var gId = 'tri'; 76063 if (!this.geometryInHash(gId)) { 76064 var _triangle = function() { 76065 var vertices = []; 76066 vertices.push(new p5.Vector(0, 0, 0)); 76067 vertices.push(new p5.Vector(0, 1, 0)); 76068 vertices.push(new p5.Vector(1, 0, 0)); 76069 this.strokeIndices = [[0, 1], [1, 2], [2, 0]]; 76070 this.vertices = vertices; 76071 this.faces = [[0, 1, 2]]; 76072 this.uvs = [0, 0, 0, 1, 1, 1]; 76073 }; 76074 var triGeom = new p5.Geometry(1, 1, _triangle); 76075 triGeom._makeTriangleEdges()._edgesToVertices(); 76076 triGeom.computeNormals(); 76077 this.createBuffers(gId, triGeom); 76078 } 76079 76080 // only one triangle is cached, one point is at the origin, and the 76081 // two adjacent sides are tne unit vectors along the X & Y axes. 76082 // 76083 // this matrix multiplication transforms those two unit vectors 76084 // onto the required vector prior to rendering, and moves the 76085 // origin appropriately. 76086 var uMVMatrix = this.uMVMatrix.copy(); 76087 try { 76088 // prettier-ignore 76089 var mult = new p5.Matrix([ 76090 x2 - x1, y2 - y1, 0, 0, // the resulting unit X-axis 76091 x3 - x1, y3 - y1, 0, 0, // the resulting unit Y-axis 76092 0, 0, 1, 0, // the resulting unit Z-axis (unchanged) 76093 x1, y1, 0, 1 // the resulting origin 76094 ]).mult(this.uMVMatrix); 76095 76096 this.uMVMatrix = mult; 76097 76098 this.drawBuffers(gId); 76099 } finally { 76100 this.uMVMatrix = uMVMatrix; 76101 } 76102 76103 return this; 76104}; 76105 76106p5.RendererGL.prototype.ellipse = function(args) { 76107 var x = args[0]; 76108 var y = args[1]; 76109 var width = args[2]; 76110 var height = args[3]; 76111 //detailX and Y are optional 6th & 7th 76112 //arguments 76113 var detailX = args[4] || 24; 76114 var gId = 'ellipse|' + detailX; 76115 if (!this.geometryInHash(gId)) { 76116 var _ellipse = function() { 76117 this.vertices.push(new p5.Vector(0.5, 0.5, 0)); 76118 this.uvs.push([0.5, 0.5]); 76119 76120 for (var i = 0; i < this.detailX; i++) { 76121 var u = i / this.detailX; 76122 var theta = 2 * Math.PI * u; 76123 76124 var _x = 0.5 + Math.cos(theta) / 2; 76125 var _y = 0.5 + Math.sin(theta) / 2; 76126 76127 this.vertices.push(new p5.Vector(_x, _y, 0)); 76128 this.uvs.push(_x, _y); 76129 76130 this.faces.push([0, (i + 1) % this.detailX + 1, i + 1]); 76131 } 76132 }; 76133 var ellipseGeom = new p5.Geometry(detailX, 1, _ellipse); 76134 ellipseGeom.computeNormals(); 76135 if (detailX <= 50) { 76136 ellipseGeom._makeTriangleEdges()._edgesToVertices(); 76137 } else { 76138 console.log('Cannot stroke ellipse with more than 50 detailX'); 76139 } 76140 76141 this.createBuffers(gId, ellipseGeom); 76142 } 76143 76144 // only a single ellipse (of a given detail) is cached: a circle of 76145 // _diameter_ 1 (radius 0.5). 76146 // 76147 // before rendering, this circle is squished (technical term ;) 76148 // appropriately and moved to the required location. 76149 var uMVMatrix = this.uMVMatrix.copy(); 76150 try { 76151 this.uMVMatrix.translate([x, y, 0]); 76152 this.uMVMatrix.scale(width, height, 1); 76153 76154 this.drawBuffers(gId); 76155 } finally { 76156 this.uMVMatrix = uMVMatrix; 76157 } 76158 return this; 76159}; 76160 76161p5.RendererGL.prototype.rect = function(args) { 76162 var perPixelLighting = this.attributes.perPixelLighting; 76163 var x = args[0]; 76164 var y = args[1]; 76165 var width = args[2]; 76166 var height = args[3]; 76167 var detailX = args[4] || (perPixelLighting ? 1 : 24); 76168 var detailY = args[5] || (perPixelLighting ? 1 : 16); 76169 var gId = 'rect|' + detailX + '|' + detailY; 76170 if (!this.geometryInHash(gId)) { 76171 var _rect = function() { 76172 for (var i = 0; i <= this.detailY; i++) { 76173 var v = i / this.detailY; 76174 for (var j = 0; j <= this.detailX; j++) { 76175 var u = j / this.detailX; 76176 var p = new p5.Vector(u, v, 0); 76177 this.vertices.push(p); 76178 this.uvs.push(u, v); 76179 } 76180 } 76181 }; 76182 var rectGeom = new p5.Geometry(detailX, detailY, _rect); 76183 rectGeom 76184 .computeFaces() 76185 .computeNormals() 76186 ._makeTriangleEdges() 76187 ._edgesToVertices(); 76188 this.createBuffers(gId, rectGeom); 76189 } 76190 76191 // only a single rectangle (of a given detail) is cached: a square with 76192 // opposite corners at (0,0) & (1,1). 76193 // 76194 // before rendering, this square is scaled & moved to the required location. 76195 var uMVMatrix = this.uMVMatrix.copy(); 76196 try { 76197 this.uMVMatrix.translate([x, y, 0]); 76198 this.uMVMatrix.scale(width, height, 1); 76199 76200 this.drawBuffers(gId); 76201 } finally { 76202 this.uMVMatrix = uMVMatrix; 76203 } 76204 return this; 76205}; 76206 76207p5.RendererGL.prototype.quad = function(x1, y1, x2, y2, x3, y3, x4, y4) { 76208 var gId = 76209 'quad|' + 76210 x1 + 76211 '|' + 76212 y1 + 76213 '|' +
76214 x2 + 76215 '|' + 76216 y2 + 76217 '|' + 76218 x3 + 76219 '|' + 76220 y3 + 76221 '|' + 76222 x4 + 76223 '|' + 76224 y4; 76225 if (!this.geometryInHash(gId)) { 76226 var _quad = function() { 76227 this.vertices.push(new p5.Vector(x1, y1, 0)); 76228 this.vertices.push(new p5.Vector(x2, y2, 0)); 76229 this.vertices.push(new p5.Vector(x3, y3, 0)); 76230 this.vertices.push(new p5.Vector(x4, y4, 0)); 76231 this.uvs.push(0, 0, 1, 0, 1, 1, 0, 1); 76232 this.strokeIndices = [[0, 1], [1, 2], [2, 3], [3, 0]]; 76233 }; 76234 var quadGeom = new p5.Geometry(2, 2, _quad); 76235 quadGeom 76236 .computeNormals() 76237 ._makeTriangleEdges() 76238 ._edgesToVertices(); 76239 quadGeom.faces = [[0, 1, 2], [2, 3, 0]]; 76240 this.createBuffers(gId, quadGeom); 76241 } 76242 this.drawBuffers(gId); 76243 return this; 76244}; 76245 76246//this implementation of bezier curve 76247//is based on Bernstein polynomial 76248// pretier-ignore 76249p5.RendererGL.prototype.bezier = function( 76250 x1, 76251 y1, 76252 z1, // x2 76253 x2, // y2 76254 y2, // x3 76255 z2, // y3 76256 x3, // x4 76257 y3, // y4 76258 z3, 76259 x4, 76260 y4, 76261 z4 76262) { 76263 if (arguments.length === 8) { 76264 x4 = x3; 76265 y4 = y3; 76266 x3 = y2; 76267 y3 = x2; 76268 x2 = z1; 76269 y2 = x2; 76270 z1 = z2 = z3 = z4 = 0; 76271 } 76272 76273 var bezierDetail = this._pInst._bezierDetail || 20; //value of Bezier detail 76274 this.beginShape(); 76275 for (var i = 0; i <= bezierDetail; i++) { 76276 var c1 = Math.pow(1 - i / bezierDetail, 3); 76277 var c2 = 3 * (i / bezierDetail) * Math.pow(1 - i / bezierDetail, 2); 76278 var c3 = 3 * Math.pow(i / bezierDetail, 2) * (1 - i / bezierDetail); 76279 var c4 = Math.pow(i / bezierDetail, 3); 76280 this.vertex( 76281 x1 * c1 + x2 * c2 + x3 * c3 + x4 * c4, 76282 y1 * c1 + y2 * c2 + y3 * c3 + y4 * c4, 76283 z1 * c1 + z2 * c2 + z3 * c3 + z4 * c4 76284 ); 76285 } 76286 this.endShape(); 76287 return this; 76288}; 76289 76290// pretier-ignore 76291p5.RendererGL.prototype.curve = function( 76292 x1, 76293 y1, 76294 z1, // x2 76295 x2, // y2 76296 y2, // x3 76297 z2, // y3 76298 x3, // x4 76299 y3, // y4 76300 z3, 76301 x4, 76302 y4, 76303 z4 76304) { 76305 if (arguments.length === 8) { 76306 x4 = x3; 76307 y4 = y3; 76308 x3 = y2; 76309 y3 = x2; 76310 x2 = z1; 76311 y2 = x2; 76312 z1 = z2 = z3 = z4 = 0; 76313 } 76314 var curveDetail = this._pInst._curveDetail; 76315 this.beginShape(); 76316 for (var i = 0; i <= curveDetail; i++) { 76317 var c1 = Math.pow(i / curveDetail, 3) * 0.5; 76318 var c2 = Math.pow(i / curveDetail, 2) * 0.5; 76319 var c3 = i / curveDetail * 0.5; 76320 var c4 = 0.5; 76321 var vx = 76322 c1 * (-x1 + 3 * x2 - 3 * x3 + x4) + 76323 c2 * (2 * x1 - 5 * x2 + 4 * x3 - x4) + 76324 c3 * (-x1 + x3) + 76325 c4 * (2 * x2); 76326 var vy = 76327 c1 * (-y1 + 3 * y2 - 3 * y3 + y4) + 76328 c2 * (2 * y1 - 5 * y2 + 4 * y3 - y4) + 76329 c3 * (-y1 + y3) + 76330 c4 * (2 * y2); 76331 var vz = 76332 c1 * (-z1 + 3 * z2 - 3 * z3 + z4) + 76333 c2 * (2 * z1 - 5 * z2 + 4 * z3 - z4) + 76334 c3 * (-z1 + z3) + 76335 c4 * (2 * z2); 76336 this.vertex(vx, vy, vz); 76337 } 76338 this.endShape(); 76339 return this; 76340}; 76341 76342/** 76343 * Draw a line given two points 76344 * @private 76345 * @param {Number} x0 x-coordinate of first vertex 76346 * @param {Number} y0 y-coordinate of first vertex 76347 * @param {Number} z0 z-coordinate of first vertex 76348 * @param {Number} x1 x-coordinate of second vertex 76349 * @param {Number} y1 y-coordinate of second vertex 76350 * @param {Number} z1 z-coordinate of second vertex 76351 * @chainable 76352 * @example 76353 * <div> 76354 * <code> 76355 * //draw a line 76356 * function setup() { 76357 * createCanvas(100, 100, WEBGL); 76358 * } 76359 * 76360 * function draw() { 76361 * background(200); 76362 * rotateX(frameCount * 0.01); 76363 * rotateY(frameCount * 0.01); 76364 * // Use fill instead of stroke to change the color of shape. 76365 * fill(255, 0, 0); 76366 * line(10, 10, 0, 60, 60, 20); 76367 * } 76368 * </code> 76369 * </div> 76370 */ 76371p5.RendererGL.prototype.line = function() { 76372 if (arguments.length === 6) { 76373 this.beginShape(); 76374 this.vertex(arguments[0], arguments[1], arguments[2]); 76375 this.vertex(arguments[3], arguments[4], arguments[5]); 76376 this.endShape(); 76377 } else if (arguments.length === 4) { 76378 this.beginShape(); 76379 this.vertex(arguments[0], arguments[1], 0); 76380 this.vertex(arguments[2], arguments[3], 0); 76381 this.endShape(); 76382 } 76383 return this; 76384}; 76385 76386module.exports = p5; 76387 76388},{"../core/core":22,"./p5.Geometry":68}]},{},[13])(13) 76389});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.