Browse Source

initial import

lucaconte 3 years ago
commit
f98f791bbc

+ 4 - 0
README.md

@@ -0,0 +1,4 @@
+# udatinos
+
+For run it a local web server is neede to know how, for example, follow this link:
+https://github.com/processing/p5.js/wiki/Local-server#node-http-server

+ 135 - 0
asset/Oreto.svg

@@ -0,0 +1,135 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="Livello_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 2200 900" style="enable-background:new 0 0 2200 900;" xml:space="preserve">
+<polygon points="1915.2,77.9 1918.5,80.4 1922.9,85 1926.7,89.3 1929.6,93.3 1931,96.5 1931.3,98.7 1931.6,100.5 1931.2,101.3 
+	1926.6,104.2 1922,105.6 1916.5,108.4 1910,111.7 1906,115.5 1902,120.2 1900.5,121.5 1895.4,125.5 1889.7,129.4 1885,133.1 
+	1879.8,136.9 1874.3,141.5 1870.4,144.9 1868,147.1 1865.3,149.8 1861.6,154.3 1857.2,159.5 1853.6,163.8 1851.4,166.6 1848,170.5 
+	1846.3,173.5 1844.1,176.5 1842.4,178.8 1839.5,182.8 1836,187.1 1832.8,191.5 1831.6,192.9 1830.1,194.6 1826.6,197.8 
+	1824.1,201.1 1821.1,205.3 1818.3,208.4 1810.7,216.5 1802.6,225.1 1796.8,230.9 1788.9,238.7 1781.8,246.1 1773.4,254.5 
+	1772.2,256.9 1771.2,258.8 1767.3,262.3 1760.9,268.3 1756.9,272.7 1753.3,276.4 1748.5,281.5 1744.9,285.3 1742.2,288.4 
+	1739.6,291 1737.7,291.8 1734.7,292.2 1726,295.4 1716.1,299.1 1713.8,300.3 1710.9,301.4 1708.9,301.9 1703.8,303 1697.3,302.5 
+	1684.1,301.7 1682.4,301.5 1678.7,303.6 1675.7,305.7 1673.8,308.3 1667.4,320.1 1660.4,332.8 1659.7,333.5 1654,335.5 1652,336.2 
+	1647.8,336.2 1644.1,336.1 1642.3,335.2 1640.4,334.5 1636.7,334.1 1633.2,335 1631,336.9 1628.9,339.9 1628.4,342.1 1627.9,344.2 
+	1628.3,347.5 1628,349.7 1626.4,352.9 1624.1,354.7 1620.6,355.7 1617,356.4 1612.2,357.3 1609.7,356.4 1608.4,354.9 1607.2,351.8 
+	1606.9,346.6 1606.3,339.8 1605.5,334.3 1604.7,331.4 1603.1,328.2 1601.3,325.8 1599.2,322.9 1598,321.3 1596,321.3 1593.9,322.5 
+	1593.4,324.7 1593.9,328.1 1594.3,331.9 1593.7,334.3 1591.8,335.2 1583.4,337.5 1580,339.7 1576.8,342.3 1575.3,345.9 
+	1572.4,352.5 1569.9,357.7 1569.4,359.5 1569.9,361 1572.2,363.1 1577.1,368.8 1581,373.4 1584.2,377.3 1586.6,380.2 1587,382.2 
+	1586.6,384 1583.9,386.9 1577.7,391.4 1572.2,394.6 1568.1,396.6 1565.4,397.7 1560.9,396.2 1557.8,394.7 1554.7,392.1 
+	1550.5,388.8 1548.9,386.8 1548.8,385 1549.7,381.9 1552.3,378.1 1552.4,374.2 1552.4,372.1 1549.8,368.2 1548.5,366.4 
+	1545.5,365.5 1542.6,366.8 1538.6,370.3 1536.8,374.7 1534.9,380.3 1533.6,382.6 1532.2,386.5 1530.9,391.3 1530.9,394.7 
+	1532.4,399.8 1537.4,413.1 1539.2,415.4 1544.5,419.6 1548.5,423.4 1549.7,424.8 1549.1,426.5 1547.9,428.8 1539.7,436.2 
+	1529.7,444.8 1526.2,447.5 1522.6,449.5 1517.9,451 1516.9,450.2 1512.1,444.3 1507.1,438.3 1504.1,433.7 1501.6,428.3 
+	1499.5,424.4 1497.8,420.6 1496,417.4 1495.2,416.2 1492.7,414.6 1490.3,414.1 1487.1,415 1482.2,417 1476.5,421.8 1471.1,427 
+	1465.7,433 1460.3,437.1 1451.7,444.2 1446.2,448.7 1444.3,449.9 1443.1,451.6 1442.2,453.7 1440.6,455.3 1438.1,459.6 1435.9,463 
+	1434.9,468.9 1434.4,473.9 1434.6,476.4 1432.5,477.7 1428.3,478.6 1424.8,478.1 1420.1,476 1410.5,472.9 1403.3,470.9 
+	1396.6,470.3 1392.5,470.5 1389.1,471.6 1385.2,473.6 1381.2,476.7 1377.1,479.9 1374.1,482.7 1372.5,484.8 1370.5,486.9 
+	1367.9,489 1365.5,490.8 1362.8,490.9 1360.5,491.1 1358.2,490.9 1355.9,490.1 1353.7,491.4 1351.8,492.9 1351.7,495.5 
+	1352.5,499.2 1352.9,502.6 1351.9,504.4 1352.7,506.5 1351.6,510.5 1351.1,511.3 1347,512.9 1335.7,514.9 1333.1,515 1327.9,516.6 
+	1320.4,519.3 1313.9,522.3 1311.3,525.3 1304.5,532.9 1301.2,535.6 1296.2,539.3 1293.2,541.6 1289.6,546.6 1286,550.7 
+	1283.9,552.7 1278.5,557.5 1273.7,561 1265.4,565.8 1261.3,569.1 1255.9,574.3 1244.3,579.5 1235.3,583 1227,585.8 1220.9,588.5 
+	1217.2,590.1 1215.9,592 1215.3,594.3 1215.8,597.1 1216.2,598.9 1216.1,599.9 1214.9,601.2 1212.4,600.4 1206.8,598.7 
+	1203.7,597.9 1202.1,598.4 1199.5,599.2 1196.7,601.7 1195.7,603.2 1192.4,609.8 1188.9,616.5 1186.1,622.5 1183.7,626.5 
+	1181.9,630.3 1180.8,630.6 1179.4,629.9 1173.2,628 1167,625.7 1166.7,625.5 1157.9,625 1154.7,625 1149.2,625.6 1140.9,626.6 
+	1135.4,627.1 1132.3,627.6 1129.7,628.2 1127.9,629.7 1126.2,631.6 1125.2,634.6 1124.3,639.9 1123.2,645 1122.3,649.4 
+	1122.2,652.4 1122.5,655.8 1122.1,657.4 1121.3,660.1 1120.5,662 1119.8,664.1 1119.8,665.6 1118.9,667.5 1117.6,669.5 
+	1114.8,672.8 1112.7,674.4 1111.5,675.4 1110.1,676.6 1107.5,679.9 1105.3,681.9 1104.8,684.5 1104.1,689 1104.1,694.4 
+	1104.6,697.6 1105.8,700.1 1107.7,702.6 1109,704.6 1111.6,707 1113.7,708.7 1115.4,710.4 1117.4,712.4 1118.3,714 1119.6,717.1 
+	1120,719.5 1119.9,722.5 1119.7,724.5 1118.1,726.9 1116.6,728.9 1114.4,730.4 1111.5,733.1 1110.3,735.1 1109.5,737.9 1108.6,743 
+	1107.7,748 1106.7,753.5 1105.5,757.5 1103.8,762.2 1102.2,765.7 1100.4,768.8 1098.9,771 1097.2,773 1095.1,773.6 1090.8,774.3 
+	1087.4,774.8 1082.9,775.1 1078.3,775.1 1076.6,775.4 1073.1,776.6 1069,777.6 1064.3,778.8 1061.2,779.6 1058.8,783.2 
+	1057.5,786.9 1056,790.9 1054.8,793.9 1054.3,796.4 1053.7,800.6 1054,804.4 1053.8,807.7 1053.6,811.1 1053.6,813.9 1053.3,816.6 
+	1053.2,818 1051.7,820 1049.1,823.5 1045.8,826.2 1041.2,830.8 1036.9,835.6 1033.9,838.7 1030.7,842.1 1029.4,843.6 1026.8,845 
+	1023.5,845.1 1021.3,843.9 1019.5,843.1 1018.2,842.2 1016,842.8 1011.8,844.3 1010,845 1007.3,847.5 1006.1,848.4 1005.2,850.7 
+	1003.6,853.7 1002.1,855.8 1000.9,857.4 999.5,858.2 997.8,859.1 996.1,859.6 994.3,859.6 993.3,859.3 991.8,858.4 990.8,857 
+	989.6,855.9 988.7,853.8 988.1,850.4 986.9,848.8 985.6,847.7 984.6,845.6 984.1,844.7 983,843.6 981.6,842.6 980.5,841.4 
+	979,840.3 977.5,839.8 974.9,839 973.8,838 972.7,837.2 969,837.5 949.6,838.5 942.7,839.5 936.7,839.9 928.1,840.7 919.9,841.6 
+	915.1,842.1 913.5,843 912.7,844.1 911,844.1 908.9,843.1 905.5,839.3 903.9,837 901.4,834 898.8,831.6 895.5,830.6 889.7,830.1 
+	885.2,829.4 881.9,829.6 880.4,829.5 874.5,825.1 853,810.7 846.3,805.6 843.3,803.8 832.3,798.1 826,794.5 821.1,791 814.7,787.1 
+	813.2,785.7 811.4,783 809.1,780.2 806,778.2 802.2,776 792.7,771.5 788.5,770.1 785.5,769.3 781.1,767.9 776.2,766.6 772.5,765.8 
+	768.4,762 765,758.7 760.9,754.9 757.2,752 753.2,749.6 750.7,748 747.6,747.1 742.8,746.2 740,745.9 738.4,745 734.4,742.9 
+	731.8,741.9 726.9,741.5 711.6,740.6 706.5,740.4 702.1,739.5 696.4,738.7 695.9,737.9 695.3,736.3 692.3,734.2 686.3,730 
+	682,727.1 678.9,725 677.5,723.7 674.1,720.7 669.8,719.6 662.1,718.1 654.8,717.6 650.8,717.3 645.2,717.5 639.1,717.5 
+	637.5,717.6 628.6,715.4 626.1,714.9 623.4,713.6 621.2,712.4 618.5,712 615.7,711.9 612.8,712.1 611,713 608.6,715 607.1,716.6 
+	605.6,718.2 603.4,720.1 601.9,721.7 600.6,724.4 598.9,727.3 596.6,730 592.1,733.7 588.2,737.3 585.7,740.3 580.9,747.1 
+	575.8,753.8 570.7,761.2 566.4,763.2 564.9,764.2 561.1,765.2 554.1,766.7 550,763.7 543,758.9 539.4,756.2 535.2,754.2 532.3,753 
+	528.7,752.4 525,751.8 521.4,752 518.9,752 514.3,752.1 512.4,752.2 508.7,752 505.1,752.4 502.4,753.3 499.9,755 497.5,757.7 
+	494.9,760.6 491.7,764.4 488.7,768.3 487.5,770.4 484.4,771.2 480.1,772.5 476.8,774.1 473.4,777.3 471.2,779.3 469.5,782.5 
+	466.9,786.8 464.4,788.8 460.2,791.4 457,793.4 454.1,795.8 448.2,796.4 444.2,797.1 440.3,798.3 436.4,799.4 435.3,800.6 
+	434.2,802.6 429.8,804.2 427.6,806.2 423.5,808.1 417.2,810 410.5,811.9 404.5,812.9 399,813.7 393.9,814.2 391,814.7 389.2,816.2 
+	387.6,817.4 383.2,817.2 380.5,817.4 376.8,818 362.7,821.6 358.7,822.8 352.5,821.8 349.9,821.7 341.2,823.1 331.6,824.3 
+	323.8,825.3 313.1,825.8 308.3,826.2 300.9,827.6 293.3,829 269.7,831.5 263.1,832.9 257.5,833.6 239.2,836.1 231.6,837.5 
+	222.7,838.9 215.3,840.2 207.6,841.3 202.1,841.8 197.1,842.2 193.9,842.4 193,843 193.8,843.1 201.7,842.6 211.4,841.6 
+	219.9,840.1 230.1,838.5 237.7,837 241.9,836.5 250.9,835.4 256.2,834.6 261.6,834 266,833.4 269.5,832.7 274,832.2 280.4,831.4 
+	286,830.8 293.4,829.8 298.1,829.1 303.2,828 307,827.5 311,826.9 316.2,826.8 325.2,826 332,825.5 337.9,824.6 344.4,823.7 
+	348.7,822.9 350.6,822.7 355.3,823.2 359.2,823.7 363.1,822.9 367.4,821.5 373,820 378.2,818.9 382.6,818 386.6,818 387.8,818 
+	389.3,817 391.6,815.4 396.5,814.9 401.3,814.2 405.6,813.7 412.8,812.1 418.7,810.7 422.7,809.4 426.7,807.6 428.7,806.5 
+	430.2,805.2 431.2,804.5 433.7,803.8 434.8,803.2 436.4,800.8 437.3,800.1 439.9,799.1 442.5,798.3 445.4,797.7 448.4,797 
+	451.2,796.6 453.3,796.7 454.3,796.4 455.8,795.4 458.7,793.4 462.3,791.2 465.2,789.5 467.9,787.3 470.3,782.6 471.5,780.6 
+	473,778.9 475.5,776.5 477.5,774.9 480.5,773.3 482.8,772.7 486.3,771.7 487.6,771.5 488.6,770 489.7,768.1 491.2,766.1 
+	494.4,762.2 498.6,757.9 500.2,755.6 501.5,754.7 504.1,753.5 506.3,753.2 509.9,753 512.7,752.9 515.7,752.7 518.2,752.8 
+	521.3,752.8 523.2,752.7 525.3,752.7 527.1,753 531.6,753.6 534,754.6 538.8,756.7 541.7,759 545.5,761.7 552.3,766.4 553.6,767.3 
+	554.8,767.3 558.3,766.4 561.1,765.8 564.1,765.1 565.3,764.8 567.2,763.6 570.8,761.8 572.1,760.7 573.5,758.2 579.2,750.7 
+	583.3,744.9 586.6,740.6 588.1,738.5 589.8,736.6 592.3,734.5 595.3,732.1 598.5,729.3 599.8,727.3 601.1,725.1 602.3,722.3 
+	603.3,721.3 605.5,719.3 607.4,717.3 610.2,714.5 612.7,713.2 615.6,712.5 617.8,712.6 620.4,712.9 622.2,713.6 624.5,714.8 
+	627.2,715.9 629.5,716.3 634.4,717.4 637,718.1 640,718.4 643.9,718.5 648.8,718.2 654.1,718.6 659,718.8 663,719 665.7,719.4 
+	669.1,720.3 673.2,721.1 674.6,722.3 676.4,724.1 678.7,725.7 684.6,729.9 690.2,733.6 692.8,735.5 694.4,736.8 695.1,738.1 
+	696.2,739.2 697.6,739.7 704,740.7 706.8,741.3 711.2,741.7 719.5,741.8 726.2,742.2 730.2,742.8 731.7,742.9 734,744.2 737,745.6 
+	739.1,746.5 741.2,747 746.2,747.9 749.7,748.6 753.8,751 757.3,753 759.1,754.3 761.9,756.8 764.9,759.8 767.6,762.6 770.5,765.4 
+	771.9,766.4 774,767 779.4,768.3 785.1,770.3 789.6,771.4 793.2,772.7 796.9,774.3 800.6,776.2 802.8,777.2 805.9,779.2 
+	808.7,781.6 810.6,783.1 812.1,785.6 813.6,787.5 817.7,789.8 821.1,791.9 822.8,793.2 825.2,794.9 828.1,796.9 834.5,800 
+	838.7,802.2 842.6,804.4 845.4,806.1 848,808 852.7,811.3 856,813.8 861.4,817.3 865.3,819.7 868.5,822 871.4,824.3 875.2,826.7 
+	878.1,828.8 879.5,829.9 880.2,830.4 882.1,830.3 884.2,830.4 885.7,830.4 888.9,830.8 893,831.3 895.2,831.6 897,831.8 898,832.3 
+	899.2,833 901,835 903.9,838.3 905.8,840.9 906.9,842.1 908.3,843.7 910.1,844.7 912.4,845.1 913.8,844.4 915.4,843.1 918.5,842.6 
+	926,841.7 935.3,840.6 941.3,840 945,839.7 948.9,839.4 953.9,839 956.9,838.9 959,838.5 964.5,838.4 969.9,838 972.1,837.9 
+	973.1,838.4 973.7,839 974.9,839.6 977.1,840.3 978.5,840.9 979.6,841.8 980.8,842.8 982.4,844.1 983.4,845.1 984.1,846.1 
+	984.3,847.2 985.2,848.4 987,850.1 987.5,851.2 988,853.6 988.4,855.1 989.6,856.9 991.1,858.5 992.6,859.8 995.3,860.3 
+	996.7,860.3 999.3,859 1001.1,857.9 1002.9,855.7 1004.1,854.2 1005.1,852.8 1006.1,850.3 1007.1,848.2 1009.1,846.8 1009.8,846 
+	1012.8,844.8 1015.7,843.6 1018,843.1 1019.5,843.8 1021.3,844.7 1022.6,845.4 1024.5,845.8 1026.7,845.7 1029.2,844.5 
+	1030.1,843.7 1031.3,842.3 1037.2,836.5 1040,833.4 1044.6,828.4 1048.5,824.9 1050.2,823.2 1052.9,819.8 1054,818 1054.4,813.9 
+	1054.5,809.2 1054.6,804.7 1054.5,799.6 1054.9,796.3 1055.8,793.5 1058.4,787.2 1059.8,783.2 1060.6,781.8 1062,780.6 1064,779.6 
+	1066.7,779.1 1070.3,778.1 1073.1,777.4 1075.6,776.5 1077.1,776 1078.8,775.8 1081,775.8 1084.4,775.6 1087.5,775.4 1090.8,774.9 
+	1094.3,774.4 1096.9,773.8 1097.7,773.4 1098.9,771.9 1101.4,768.7 1102.6,767.1 1104.8,762.3 1106.3,757.2 1107.8,752 1109,744.1 
+	1109.9,740.2 1110.5,736.8 1111.8,734.6 1113.3,732.4 1116.1,730.1 1118.3,728.1 1119.1,726.3 1120.3,724.4 1120.5,722.8 
+	1120.5,719.3 1120.1,716.8 1119.4,715 1118.1,712.6 1115.7,709.5 1114.4,708.4 1112,706.5 1109.6,703.8 1107.2,700.7 1105.1,696.8 
+	1104.6,693.5 1104.8,690 1105,687 1105.6,683.7 1106.3,682.2 1108.1,680.3 1110.2,677.7 1111.3,676.6 1112.9,675.2 1115.1,673.7 
+	1117.6,671.1 1119.6,667.8 1120.4,665.6 1120.7,664 1121.6,661.6 1122.9,658.7 1123.3,656.5 1122.9,653.1 1122.8,650.8 
+	1123.3,648.3 1123.8,645.6 1124.3,643 1125,639.8 1125.4,637.3 1126.3,634.3 1126.8,632.2 1128.3,630.3 1129.8,628.9 1132.5,628.5 
+	1137.3,627.9 1143.7,627.1 1147.9,626.5 1153.6,625.8 1156.3,625.4 1160.4,625.7 1165.1,626 1166.6,626.2 1168.1,626.8 1171,628 
+	1173.5,629.1 1176.7,630.2 1179.6,630.9 1181,631.2 1180.1,632.2 1181.5,633.1 1183.2,630.2 1186.4,625 1189.1,621 1190.7,618.3 
+	1191.8,614.7 1193.4,610.3 1195.2,607 1197.2,603.6 1199.4,601.3 1201.6,600 1203.7,599.7 1205.7,599.9 1207.7,600.6 1209.2,601.5 
+	1210.1,602.3 1212.2,603.1 1213.6,603.1 1215.5,602.3 1217.3,600.6 1217.8,599.4 1217.9,597.4 1217.1,595.2 1217.5,593.3 1219,592 
+	1222,590.5 1226.1,588.6 1231.7,586.2 1235.1,584.5 1238.4,583.7 1244.1,581.7 1250.4,578.6 1254.8,576.5 1257.4,575.2 
+	1260.5,572.3 1264.8,568.9 1266.9,566.8 1268.6,565.7 1273.7,562.9 1277.2,560.2 1280.7,557.4 1284.5,553.7 1287.6,550.3 
+	1290.7,547.1 1293.5,544 1296.4,541.1 1299.1,538.5 1302,536.3 1305.7,533.1 1308,531 1310.2,528.6 1313.6,524.6 1315.8,523 
+	1322.3,520.2 1324.5,519.3 1327.3,518 1328.6,517.4 1332.8,516.8 1336.6,516 1340.2,515.6 1343.3,515 1348.5,513.9 1351,513.3 
+	1353,512.2 1354.1,510.4 1354.3,508.3 1354.7,501.2 1354.7,496.1 1354.7,493.2 1355,492.4 1356.3,491.9 1358.2,492.7 1360.8,493 
+	1365.1,492.6 1367.3,491.7 1371,488.7 1375.3,484.1 1379.4,480.5 1382.3,477.6 1387.5,475 1391.4,472.8 1395.1,472.4 1398.7,472.2 
+	1403.3,473 1406.5,473.5 1409.9,474.6 1413.8,476.4 1419.5,479.1 1423.1,480.6 1425.1,480.8 1429.3,480.5 1433,480.8 1435.8,479.3 
+	1437.3,477.1 1437.1,474.2 1436.8,471.3 1437.9,466.8 1439.3,462.5 1441.1,458.2 1442.9,456.2 1446.7,451.3 1448.8,448.5 
+	1453.2,445.7 1460.1,440.4 1462.5,438.7 1469.8,433.4 1472.1,431 1475.2,427 1479.5,422.7 1483.8,419.5 1486.7,418.1 1489.4,416.8 
+	1491.3,416.7 1492.3,417.5 1492.8,418.3 1492.8,419.6 1494,421.5 1497.6,426 1497.9,427.3 1498.5,429.7 1500.5,434 1501.5,436.1 
+	1504,440.2 1507.2,444.6 1509.1,446.9 1513.3,450.1 1514.3,451.4 1516.8,452.8 1518.4,452.9 1523,451.6 1527,449.6 1529.3,448.4 
+	1533.2,444.2 1536.9,440.6 1542.4,436 1547.4,431.5 1550,428.8 1550.7,427.7 1550.7,424.9 1550.4,422.9 1546.3,418.7 1543.9,416 
+	1541.8,412.5 1538.7,408.2 1536.8,406 1536.1,400.8 1535.1,396 1535.2,391.4 1535.1,385 1535.8,381.8 1536.7,379.4 1538.4,374.7 
+	1539.8,371.4 1541.5,369.4 1543.5,368 1545.5,367.7 1547.8,368.5 1549.2,370.3 1550.7,372.9 1550.8,375.3 1549.7,378.7 1547.6,382 
+	1546.5,385.5 1546.9,388.2 1549.7,391.6 1552.9,394.4 1557.1,397.4 1560.5,398.6 1564.6,399.4 1566.2,399.5 1569.9,397.8 
+	1574.6,395.3 1579.9,392.6 1583.4,390.3 1586.9,387 1588.8,383.7 1588.3,378.9 1586.7,375.2 1583.3,371.6 1580.9,368.2 
+	1578.3,365.6 1576.3,364.1 1574.2,361.9 1572.1,359.8 1571.6,357.9 1573.1,354.6 1576.9,347.9 1578.1,344.2 1579.1,342.4 
+	1583.5,339.4 1585.1,338.5 1587.9,337.5 1590.9,337 1594.2,335.9 1595.6,335 1596.1,332.1 1595.4,328.9 1594.9,325.7 1595.6,323.7 
+	1596.7,323.2 1598.2,324 1601.2,327.8 1603.5,333.8 1604.4,338.8 1604.5,341.8 1603.9,343.6 1604.1,346.1 1604.5,350.3 
+	1605.6,351.7 1605.8,353.6 1606.3,356.8 1608.5,359.2 1610.5,359.7 1615.3,359.8 1620.8,358.6 1626.9,355.2 1629.3,352.6 
+	1630,350.8 1630.5,346.9 1630.1,343.1 1632.4,338.9 1633.3,337.4 1634.7,336 1636.4,335.7 1639.6,337.2 1643.6,338.3 1648,338.7 
+	1652.1,338.8 1655.6,337.9 1660.6,335.4 1662,334.3 1667.3,325.2 1670.5,319.8 1676.6,308.9 1678.2,306.7 1680.2,305.4 
+	1683.7,304.2 1685,304 1687.7,304.1 1692.1,304.6 1694.2,304.8 1698,304.2 1701.2,304 1706.4,303.7 1711.7,303.3 1714.2,303.1 
+	1718.3,301.7 1724.6,299.1 1730.7,296.4 1735.2,294.4 1740.2,292.3 1742.7,289.8 1746.9,285.7 1753.4,279.1 1756.5,276.4 
+	1758.5,273.6 1762.1,268.9 1765.3,265.6 1767.8,263.2 1771.1,260 1773.1,257.5 1774.7,254.8 1777.8,251.3 1784.6,244.8 
+	1789.5,240.3 1792.5,237.5 1794.2,238.7 1798.3,234.5 1806.3,226.5 1810.8,221.5 1816.1,215.7 1823.8,205.7 1827.6,201 
+	1830.3,197.5 1833,194.8 1835.3,193.6 1839.7,188.8 1843,183.7 1845.7,180.4 1849.6,173.5 1850.9,170.3 1853.8,166.9 1857.3,163.4 
+	1861.8,158.7 1863.9,156 1865.5,155.3 1868.3,152 1869.5,149.3 1870.5,147.5 1873.4,144.9 1876.7,141 1881.7,138.3 1885.9,135.9 
+	1888.8,132.9 1890.4,131.1 1892.8,130 1895.5,127.4 1902.3,122.3 1905.6,119.1 1909.6,115.8 1913.9,111.7 1918.8,109.2 
+	1923.1,107.4 1925.9,106.1 1928.6,105.5 1930.6,102.8 1932.2,101.8 1932.7,102.5 1938.2,105.5 1943,108.6 1947.3,110.7 
+	1951.7,113.7 1957.3,118.5 1959,121.1 1961.8,125.5 1963.3,128.1 1965.5,130.4 1973.4,136.3 1977.9,138.5 1999,134.8 2007,87.6 
+	2000.2,59.3 1975.1,41.7 1944,40 1914.1,39.7 1898.8,49.2 1897.8,58.5 1907.9,69.8 "/>
+<polyline points="1897.8,58.5 1827.6,0 2200,0 2200,270 2094.5,219.1 1977.9,138.5 "/>
+</svg>

BIN
asset/UdatinosLogo-1.png


+ 1109 - 0
asset/uda.css

@@ -0,0 +1,1109 @@
+/*!
+Theme Name: udatinos
+Theme URI: http://underscores.me/
+Author: Salvatore Iaconesi
+Author URI: https://he-r.it
+Description: Udatinos project theme
+Version: 1.0.0
+License: GNU General Public License v2 or later
+License URI: LICENSE
+Text Domain: udatinos
+Tags: custom-background, custom-logo, custom-menu, featured-images, threaded-comments, translation-ready
+
+This theme, like WordPress, is licensed under the GPL.
+Use it to make something cool, have fun, and share what you've learned with others.
+
+udatinos is based on Underscores https://underscores.me/, (C) 2012-2017 Automattic, Inc.
+Underscores is distributed under the terms of the GNU GPL v2 or later.
+
+Normalizing styles have been helped along thanks to the fine work of
+Nicolas Gallagher and Jonathan Neal https://necolas.github.io/normalize.css/
+*/
+
+
+/* UDATINOS */
+
+
+body,html{
+	width:100%;
+	min-height:100%;
+	margin: 0px;
+	padding: 0px;
+	font: 22px Helvetica,sans-serif;
+	background: #FFFFFF;
+	color: #000000;
+}
+
+#mainoreto{
+	position: fixed;
+	top: 0px;
+	left: 0px;
+	z-index: 200;
+	width:100%;
+	min-height:100%;
+	margin: 0px;
+	padding: 0px;
+	background: url(asset/Oreto.svg) transparent;
+	background-repeat: no-repeat;
+	background-attachment: fixed;
+	background-position: 100% 0%;
+}
+
+#mainsub{
+	position: fixed;
+	top: 0px;
+	left: 0px;
+	z-index: 100;
+	width:100%;
+	min-height:100%;
+	margin: 0px;
+	padding: 0px;
+	background: linear-gradient(153deg, #f10d38, #f10ded, #0d0df1, #0dccf1, #0df111, #f1f10d);
+	background-size: 1200% 1200%;
+	-webkit-animation: backgroundanimation 17s ease infinite;
+	-moz-animation: backgroundanimation 17s ease infinite;
+	animation: backgroundanimation 17s ease infinite;
+}
+
+
+
+ 
+.site-branding{
+	text-align: center;
+}
+
+
+@-webkit-keyframes backgroundanimation {
+    0%{background-position:0% 50%}
+    50%{background-position:100% 50%}
+    100%{background-position:0% 50%}
+}
+@-moz-keyframes backgroundanimation {
+    0%{background-position:0% 50%}
+    50%{background-position:100% 50%}
+    100%{background-position:0% 50%}
+}
+@keyframes backgroundanimation {
+    0%{background-position:0% 50%}
+    50%{background-position:100% 50%}
+    100%{background-position:0% 50%}
+}
+
+
+#page{
+	position: relative;
+	z-index: 700;
+	padding: 30px;
+	margin: 0px;
+	margin-top: 30px;
+
+}
+
+
+
+
+/*--------------------------------------------------------------
+>>> TABLE OF CONTENTS:
+----------------------------------------------------------------
+# Normalize
+# Typography
+# Elements
+# Forms
+# Navigation
+	## Links
+	## Menus
+# Accessibility
+# Alignments
+# Clearings
+# Widgets
+# Content
+	## Posts and pages
+	## Comments
+# Infinite scroll
+# Media
+	## Captions
+	## Galleries
+--------------------------------------------------------------*/
+/*--------------------------------------------------------------
+# Normalize
+--------------------------------------------------------------*/
+/* normalize.css v8.0.0 | MIT License | github.com/necolas/normalize.css */
+
+/* Document
+	 ========================================================================== */
+
+/**
+ * 1. Correct the line height in all browsers.
+ * 2. Prevent adjustments of font size after orientation changes in iOS.
+ */
+
+html {
+	line-height: 1.15; /* 1 */
+	-webkit-text-size-adjust: 100%; /* 2 */
+}
+
+/* Sections
+	 ========================================================================== */
+
+/**
+ * Remove the margin in all browsers.
+ */
+
+body {
+	margin: 0;
+}
+
+/**
+ * Correct the font size and margin on `h1` elements within `section` and
+ * `article` contexts in Chrome, Firefox, and Safari.
+ */
+
+h1 {
+	font-size: 4em;
+	margin: 0.67em 0;
+}
+
+.entry-header h1{
+	color: #FFFFFF;
+}
+
+/* Grouping content
+	 ========================================================================== */
+
+/**
+ * 1. Add the correct box sizing in Firefox.
+ * 2. Show the overflow in Edge and IE.
+ */
+
+hr {
+	box-sizing: content-box; /* 1 */
+	height: 0; /* 1 */
+	overflow: visible; /* 2 */
+}
+
+/**
+ * 1. Correct the inheritance and scaling of font size in all browsers.
+ * 2. Correct the odd `em` font sizing in all browsers.
+ */
+
+pre {
+	font-family: monospace, monospace; /* 1 */
+	font-size: 1em; /* 2 */
+}
+
+/* Text-level semantics
+	 ========================================================================== */
+
+/**
+ * Remove the gray background on active links in IE 10.
+ */
+
+a {
+	background-color: transparent;
+}
+
+/**
+ * 1. Remove the bottom border in Chrome 57-
+ * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
+ */
+
+abbr[title] {
+	border-bottom: none; /* 1 */
+	text-decoration: underline; /* 2 */
+	text-decoration: underline dotted; /* 2 */
+}
+
+/**
+ * Add the correct font weight in Chrome, Edge, and Safari.
+ */
+
+b,
+strong {
+	font-weight: bolder;
+}
+
+/**
+ * 1. Correct the inheritance and scaling of font size in all browsers.
+ * 2. Correct the odd `em` font sizing in all browsers.
+ */
+
+code,
+kbd,
+samp {
+	font-family: monospace, monospace; /* 1 */
+	font-size: 1em; /* 2 */
+}
+
+/**
+ * Add the correct font size in all browsers.
+ */
+
+small {
+	font-size: 80%;
+}
+
+/**
+ * Prevent `sub` and `sup` elements from affecting the line height in
+ * all browsers.
+ */
+
+sub,
+sup {
+	font-size: 75%;
+	line-height: 0;
+	position: relative;
+	vertical-align: baseline;
+}
+
+sub {
+	bottom: -0.25em;
+}
+
+sup {
+	top: -0.5em;
+}
+
+/* Embedded content
+	 ========================================================================== */
+
+/**
+ * Remove the border on images inside links in IE 10.
+ */
+
+img {
+	border-style: none;
+}
+
+/* Forms
+	 ========================================================================== */
+
+/**
+ * 1. Change the font styles in all browsers.
+ * 2. Remove the margin in Firefox and Safari.
+ */
+
+button,
+input,
+optgroup,
+select,
+textarea {
+	font-family: inherit; /* 1 */
+	font-size: 100%; /* 1 */
+	line-height: 1.15; /* 1 */
+	margin: 0; /* 2 */
+}
+
+/**
+ * Show the overflow in IE.
+ * 1. Show the overflow in Edge.
+ */
+
+button,
+input { /* 1 */
+	overflow: visible;
+}
+
+/**
+ * Remove the inheritance of text transform in Edge, Firefox, and IE.
+ * 1. Remove the inheritance of text transform in Firefox.
+ */
+
+button,
+select { /* 1 */
+	text-transform: none;
+}
+
+/**
+ * Correct the inability to style clickable types in iOS and Safari.
+ */
+
+button,
+[type="button"],
+[type="reset"],
+[type="submit"] {
+	-webkit-appearance: button;
+}
+
+/**
+ * Remove the inner border and padding in Firefox.
+ */
+
+button::-moz-focus-inner,
+[type="button"]::-moz-focus-inner,
+[type="reset"]::-moz-focus-inner,
+[type="submit"]::-moz-focus-inner {
+	border-style: none;
+	padding: 0;
+}
+
+/**
+ * Restore the focus styles unset by the previous rule.
+ */
+
+button:-moz-focusring,
+[type="button"]:-moz-focusring,
+[type="reset"]:-moz-focusring,
+[type="submit"]:-moz-focusring {
+	outline: 1px dotted ButtonText;
+}
+
+/**
+ * Correct the padding in Firefox.
+ */
+
+fieldset {
+	padding: 0.35em 0.75em 0.625em;
+}
+
+/**
+ * 1. Correct the text wrapping in Edge and IE.
+ * 2. Correct the color inheritance from `fieldset` elements in IE.
+ * 3. Remove the padding so developers are not caught out when they zero out
+ *		`fieldset` elements in all browsers.
+ */
+
+legend {
+	box-sizing: border-box; /* 1 */
+	color: inherit; /* 2 */
+	display: table; /* 1 */
+	max-width: 100%; /* 1 */
+	padding: 0; /* 3 */
+	white-space: normal; /* 1 */
+}
+
+/**
+ * Add the correct vertical alignment in Chrome, Firefox, and Opera.
+ */
+
+progress {
+	vertical-align: baseline;
+}
+
+/**
+ * Remove the default vertical scrollbar in IE 10+.
+ */
+
+textarea {
+	overflow: auto;
+}
+
+/**
+ * 1. Add the correct box sizing in IE 10.
+ * 2. Remove the padding in IE 10.
+ */
+
+[type="checkbox"],
+[type="radio"] {
+	box-sizing: border-box; /* 1 */
+	padding: 0; /* 2 */
+}
+
+/**
+ * Correct the cursor style of increment and decrement buttons in Chrome.
+ */
+
+[type="number"]::-webkit-inner-spin-button,
+[type="number"]::-webkit-outer-spin-button {
+	height: auto;
+}
+
+/**
+ * 1. Correct the odd appearance in Chrome and Safari.
+ * 2. Correct the outline style in Safari.
+ */
+
+[type="search"] {
+	-webkit-appearance: textfield; /* 1 */
+	outline-offset: -2px; /* 2 */
+}
+
+/**
+ * Remove the inner padding in Chrome and Safari on macOS.
+ */
+
+[type="search"]::-webkit-search-decoration {
+	-webkit-appearance: none;
+}
+
+/**
+ * 1. Correct the inability to style clickable types in iOS and Safari.
+ * 2. Change font properties to `inherit` in Safari.
+ */
+
+::-webkit-file-upload-button {
+	-webkit-appearance: button; /* 1 */
+	font: inherit; /* 2 */
+}
+
+/* Interactive
+	 ========================================================================== */
+
+/*
+ * Add the correct display in Edge, IE 10+, and Firefox.
+ */
+
+details {
+	display: block;
+}
+
+/*
+ * Add the correct display in all browsers.
+ */
+
+summary {
+	display: list-item;
+}
+
+/* Misc
+	 ========================================================================== */
+
+/**
+ * Add the correct display in IE 10+.
+ */
+
+template {
+	display: none;
+}
+
+/**
+ * Add the correct display in IE 10.
+ */
+
+[hidden] {
+	display: none;
+}
+
+/*--------------------------------------------------------------
+# Typography
+--------------------------------------------------------------*/
+body,
+button,
+input,
+select,
+optgroup,
+textarea {
+	color: #404040;
+	font-family: 'Cousine', sans-serif;
+	font-size: 18px;
+	font-size: 1rem;
+	line-height: 1.5;
+}
+
+h1, h2, h3, h4, h5, h6 {
+	font-family: 'Cousine', sans-serif;
+	font-weight: 700;
+	clear: both;
+}
+
+p {
+	font-family: 'Cousine', sans-serif;
+	margin-bottom: 1.5em;
+	color: #FFFFFF;
+}
+
+dfn, cite, em, i {
+	font-style: italic;
+}
+
+blockquote {
+	margin: 0 1.5em;
+}
+
+address {
+	margin: 0 0 1.5em;
+}
+
+pre {
+	background: #eee;
+	font-family: "Courier 10 Pitch", Courier, monospace;
+	font-size: 15px;
+	font-size: 0.9375rem;
+	line-height: 1.6;
+	margin-bottom: 1.6em;
+	max-width: 100%;
+	overflow: auto;
+	padding: 1.6em;
+}
+
+code, kbd, tt, var {
+	font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace;
+	font-size: 15px;
+	font-size: 0.9375rem;
+}
+
+abbr, acronym {
+	border-bottom: 1px dotted #666;
+	cursor: help;
+}
+
+mark, ins {
+	background: #fff9c0;
+	text-decoration: none;
+}
+
+big {
+	font-size: 125%;
+}
+
+/*--------------------------------------------------------------
+# Elements
+--------------------------------------------------------------*/
+html {
+	box-sizing: border-box;
+}
+
+*,
+*:before,
+*:after {
+	/* Inherit box-sizing to make it easier to change the property for components that leverage other behavior; see https://css-tricks.com/inheriting-box-sizing-probably-slightly-better-best-practice/ */
+	box-sizing: inherit;
+}
+
+body {
+	background: #fff;
+	/* Fallback for when there is no custom background color defined. */
+}
+
+hr {
+	background-color: #ccc;
+	border: 0;
+	height: 1px;
+	margin-bottom: 1.5em;
+}
+
+ul, ol {
+	margin: 0 0 1.5em 3em;
+}
+
+ul {
+	list-style: disc;
+}
+
+ol {
+	list-style: decimal;
+}
+
+li > ul,
+li > ol {
+	margin-bottom: 0;
+	margin-left: 1.5em;
+}
+
+dt {
+	font-weight: bold;
+}
+
+dd {
+	margin: 0 1.5em 1.5em;
+}
+
+img {
+	height: auto;
+	/* Make sure images are scaled correctly. */
+	max-width: 100%;
+	/* Adhere to container width. */
+}
+
+figure {
+	margin: 1em 0;
+	/* Extra wide images within figure tags don't overflow the content area. */
+}
+
+table {
+	margin: 0 0 1.5em;
+	width: 100%;
+}
+
+/*--------------------------------------------------------------
+# Forms
+--------------------------------------------------------------*/
+button,
+input[type="button"],
+input[type="reset"],
+input[type="submit"] {
+	border: 1px solid;
+	border-color: #ccc #ccc #bbb;
+	border-radius: 3px;
+	background: #e6e6e6;
+	color: rgba(0, 0, 0, 0.8);
+	font-size: 12px;
+	font-size: 0.75rem;
+	line-height: 1;
+	padding: .6em 1em .4em;
+}
+
+button:hover,
+input[type="button"]:hover,
+input[type="reset"]:hover,
+input[type="submit"]:hover {
+	border-color: #ccc #bbb #aaa;
+}
+
+button:active, button:focus,
+input[type="button"]:active,
+input[type="button"]:focus,
+input[type="reset"]:active,
+input[type="reset"]:focus,
+input[type="submit"]:active,
+input[type="submit"]:focus {
+	border-color: #aaa #bbb #bbb;
+}
+
+input[type="text"],
+input[type="email"],
+input[type="url"],
+input[type="password"],
+input[type="search"],
+input[type="number"],
+input[type="tel"],
+input[type="range"],
+input[type="date"],
+input[type="month"],
+input[type="week"],
+input[type="time"],
+input[type="datetime"],
+input[type="datetime-local"],
+input[type="color"],
+textarea {
+	color: #666;
+	border: 1px solid #ccc;
+	border-radius: 3px;
+	padding: 3px;
+}
+
+input[type="text"]:focus,
+input[type="email"]:focus,
+input[type="url"]:focus,
+input[type="password"]:focus,
+input[type="search"]:focus,
+input[type="number"]:focus,
+input[type="tel"]:focus,
+input[type="range"]:focus,
+input[type="date"]:focus,
+input[type="month"]:focus,
+input[type="week"]:focus,
+input[type="time"]:focus,
+input[type="datetime"]:focus,
+input[type="datetime-local"]:focus,
+input[type="color"]:focus,
+textarea:focus {
+	color: #111;
+}
+
+select {
+	border: 1px solid #ccc;
+}
+
+textarea {
+	width: 100%;
+}
+
+/*--------------------------------------------------------------
+# Navigation
+--------------------------------------------------------------*/
+/*--------------------------------------------------------------
+## Links
+--------------------------------------------------------------*/
+.entry-content a {
+	color: #FFFFFF;
+	padding: 5px;
+}
+
+.entry-content a:visited {
+	color: #FFFF00;
+}
+
+.entry-content a:hover, a:focus, a:active {
+	color: #FFFFFF;
+	background: #000000;
+}
+
+.entry-content a:focus {
+	outline: thin dotted;
+}
+
+.entry-content a:hover, a:active {
+	outline: 0;
+}
+
+/*--------------------------------------------------------------
+## Menus
+--------------------------------------------------------------*/
+
+
+#hamburgerbox{
+	clear: both;
+	display: block;
+	position: fixed;
+	z-index: 999;
+	top: 0px;
+	left: 0px;
+}
+
+
+.main-navigation {
+	display: none;
+	position: fixed;
+	z-index: 800;
+	width: 100%;
+	height: 100%;
+	background: #FF00FF;
+	top: 0px;
+	left: 0px;
+}
+
+.main-navigation ul {
+	display: none;
+	list-style: none;
+	margin: 0;
+	padding-left: 0;
+}
+
+.main-navigation ul ul {
+	box-shadow: 0 3px 3px rgba(0, 0, 0, 0.2);
+	float: left;
+	position: absolute;
+	top: 100%;
+	left: -999em;
+	z-index: 99999;
+}
+
+.main-navigation ul ul ul {
+	left: -999em;
+	top: 0;
+}
+
+.main-navigation ul ul li:hover > ul,
+.main-navigation ul ul li.focus > ul {
+	left: 100%;
+}
+
+.main-navigation ul ul a {
+	width: 200px;
+}
+
+.main-navigation ul li:hover > ul,
+.main-navigation ul li.focus > ul {
+	left: auto;
+}
+
+#primary-menu{
+	margin-top: 70px;
+}
+
+.main-navigation li {
+	position: relative;
+	margin: 20px;
+	text-align: center;
+}
+
+.main-navigation a, .main-navigation a:visited {
+	display: block;
+	text-decoration: none;
+	padding: 10px;
+	background: transparent;
+	color: #FFFFFF;
+	font-size: 0.8rem;
+}
+
+.main-navigation a:hover{
+	background: #000000;
+}
+
+/* Small menu. */
+.menu-toggle,
+.main-navigation.toggled ul {
+	display: block;
+}
+
+@media screen and (min-width: 37.5em) {
+	.menu-toggle {
+		display: none;
+	}
+	.main-navigation ul {
+		display: block;
+	}
+}
+
+.site-main .comment-navigation, .site-main
+.posts-navigation, .site-main
+.post-navigation {
+	margin: 0 0 1.5em;
+	overflow: hidden;
+}
+
+.comment-navigation .nav-previous,
+.posts-navigation .nav-previous,
+.post-navigation .nav-previous {
+	float: left;
+	width: 50%;
+}
+
+.comment-navigation .nav-next,
+.posts-navigation .nav-next,
+.post-navigation .nav-next {
+	float: right;
+	text-align: right;
+	width: 50%;
+}
+
+/*--------------------------------------------------------------
+# Accessibility
+--------------------------------------------------------------*/
+/* Text meant only for screen readers. */
+.screen-reader-text {
+	border: 0;
+	clip: rect(1px, 1px, 1px, 1px);
+	clip-path: inset(50%);
+	height: 1px;
+	margin: -1px;
+	overflow: hidden;
+	padding: 0;
+	position: absolute !important;
+	width: 1px;
+	word-wrap: normal !important; /* Many screen reader and browser combinations announce broken words as they would appear visually. */
+}
+
+.screen-reader-text:focus {
+	background-color: #f1f1f1;
+	border-radius: 3px;
+	box-shadow: 0 0 2px 2px rgba(0, 0, 0, 0.6);
+	clip: auto !important;
+	clip-path: none;
+	color: #21759b;
+	display: block;
+	font-size: 14px;
+	font-size: 0.875rem;
+	font-weight: bold;
+	height: auto;
+	left: 5px;
+	line-height: normal;
+	padding: 15px 23px 14px;
+	text-decoration: none;
+	top: 5px;
+	width: auto;
+	z-index: 100000;
+	/* Above WP toolbar. */
+}
+
+/* Do not show the outline on the skip link target. */
+#content[tabindex="-1"]:focus {
+	outline: 0;
+}
+
+/*--------------------------------------------------------------
+# Alignments
+--------------------------------------------------------------*/
+.alignleft {
+	display: inline;
+	float: left;
+	margin-right: 1.5em;
+}
+
+.alignright {
+	display: inline;
+	float: right;
+	margin-left: 1.5em;
+}
+
+.aligncenter {
+	clear: both;
+	display: block;
+	margin-left: auto;
+	margin-right: auto;
+}
+
+/*--------------------------------------------------------------
+# Clearings
+--------------------------------------------------------------*/
+.clear:before,
+.clear:after,
+.entry-content:before,
+.entry-content:after,
+.comment-content:before,
+.comment-content:after,
+.site-header:before,
+.site-header:after,
+.site-content:before,
+.site-content:after,
+.site-footer:before,
+.site-footer:after {
+	content: "";
+	display: table;
+	table-layout: fixed;
+}
+
+.clear:after,
+.entry-content:after,
+.comment-content:after,
+.site-header:after,
+.site-content:after,
+.site-footer:after {
+	clear: both;
+}
+
+/*--------------------------------------------------------------
+# Widgets
+--------------------------------------------------------------*/
+.widget {
+	margin: 0 0 1.5em;
+	/* Make sure select elements fit in widgets. */
+}
+
+.widget select {
+	max-width: 100%;
+}
+
+/*--------------------------------------------------------------
+# Content
+--------------------------------------------------------------*/
+/*--------------------------------------------------------------
+## Posts and pages
+--------------------------------------------------------------*/
+.sticky {
+	display: block;
+}
+
+.post,
+.page {
+	margin: 0 0 1.5em;
+}
+
+.updated:not(.published) {
+	display: none;
+}
+
+.page-content,
+.entry-content,
+.entry-summary {
+	margin: 1.5em 0 0;
+	max-width: 800px;
+
+}
+
+.page-links {
+	clear: both;
+	margin: 0 0 1.5em;
+}
+
+/*--------------------------------------------------------------
+## Comments
+--------------------------------------------------------------*/
+.comment-content a {
+	word-wrap: break-word;
+}
+
+.bypostauthor {
+	display: block;
+}
+
+/*--------------------------------------------------------------
+# Infinite scroll
+--------------------------------------------------------------*/
+/* Globally hidden elements when Infinite Scroll is supported and in use. */
+.infinite-scroll .posts-navigation,
+.infinite-scroll.neverending .site-footer {
+	/* Theme Footer (when set to scrolling) */
+	display: none;
+}
+
+/* When Infinite Scroll has reached its end we need to re-display elements that were hidden (via .neverending) before. */
+.infinity-end.neverending .site-footer {
+	display: block;
+}
+
+/*--------------------------------------------------------------
+# Media
+--------------------------------------------------------------*/
+.page-content .wp-smiley,
+.entry-content .wp-smiley,
+.comment-content .wp-smiley {
+	border: none;
+	margin-bottom: 0;
+	margin-top: 0;
+	padding: 0;
+}
+
+/* Make sure embeds and iframes fit their containers. */
+embed,
+iframe,
+object {
+	max-width: 100%;
+}
+
+/* Make sure logo link wraps around logo image. */
+.custom-logo-link {
+	display: inline-block;
+}
+
+/*--------------------------------------------------------------
+## Captions
+--------------------------------------------------------------*/
+.wp-caption {
+	margin-bottom: 1.5em;
+	max-width: 100%;
+}
+
+.wp-caption img[class*="wp-image-"] {
+	display: block;
+	margin-left: auto;
+	margin-right: auto;
+}
+
+.wp-caption .wp-caption-text {
+	margin: 0.8075em 0;
+}
+
+.wp-caption-text {
+	text-align: center;
+}
+
+/*--------------------------------------------------------------
+## Galleries
+--------------------------------------------------------------*/
+.gallery {
+	margin-bottom: 1.5em;
+}
+
+.gallery-item {
+	display: inline-block;
+	text-align: center;
+	vertical-align: top;
+	width: 100%;
+}
+
+.gallery-columns-2 .gallery-item {
+	max-width: 50%;
+}
+
+.gallery-columns-3 .gallery-item {
+	max-width: 33.33%;
+}
+
+.gallery-columns-4 .gallery-item {
+	max-width: 25%;
+}
+
+.gallery-columns-5 .gallery-item {
+	max-width: 20%;
+}
+
+.gallery-columns-6 .gallery-item {
+	max-width: 16.66%;
+}
+
+.gallery-columns-7 .gallery-item {
+	max-width: 14.28%;
+}
+
+.gallery-columns-8 .gallery-item {
+	max-width: 12.5%;
+}
+
+.gallery-columns-9 .gallery-item {
+	max-width: 11.11%;
+}
+
+.gallery-caption {
+	display: block;
+}

BIN
icona_testo.png


+ 17 - 0
index.html

@@ -0,0 +1,17 @@
+<html>
+  <head>
+    <script src="p5.min.js"></script>
+    <script src="libs/jquery-3.6.0.min.js"></script>
+    <script src="libs/scenemanager.js"></script>
+    <script src="libs/p5.touchgui.js"></script>
+
+    <script src="screensaver.js"></script>
+    <script src="river.js"></script>
+
+    <script src="sketch.js"></script>
+  </head>
+  <body>
+    <main>
+    </main>
+  </body>
+</html>

+ 65 - 0
index_site.html

@@ -0,0 +1,65 @@
+<!doctype html>
+<html lang="it-IT">
+<head>
+	<meta charset="UTF-8">
+	<meta name="viewport" content="width=device-width, initial-scale=1">
+
+
+		<style type="text/css">
+img.wp-smiley,
+img.emoji {
+	display: inline !important;
+	border: none !important;
+	box-shadow: none !important;
+	height: 1em !important;
+	width: 1em !important;
+	margin: 0 .07em !important;
+	vertical-align: -0.1em !important;
+	background: none !important;
+	padding: 0 !important;
+}
+</style>
+<link rel='stylesheet' id='udatinos-style-css'  href='https://udatinos.eu/wp-content/themes/udatinos/style.css?ver=5.5.3' type='text/css' media='all' />
+		<style type="text/css">
+					.site-title,
+			.site-description {
+				position: absolute;
+				clip: rect(1px, 1px, 1px, 1px);
+			}
+				</style>
+</head>
+
+<body class="home page-template-default page page-id-58 wp-custom-logo no-sidebar">
+
+<div id="mainsub"></div>
+<div id="mainoreto"></div>
+
+
+<div id="page" class="site">
+	<a class="skip-link screen-reader-text" href="#content">Skip to content</a>
+
+	<header id="masthead" class="site-header">
+		<div class="site-branding">
+<img width="156" height="180" src="asset/UdatinosLogo-1.png" class="custom-logo" alt="udatinos logo" />
+					</div><!-- .site-branding -->
+
+
+	</header><!-- #masthead -->
+
+	<div id="content" class="site-content">
+
+	<div id="primary" class="content-area">
+	</div><!-- #primary -->
+
+
+	</div><!-- #content -->
+
+	<footer id="colophon" class="site-footer">
+		<div class="site-info">
+			
+		</div><!-- .site-info -->
+	</footer><!-- #colophon -->
+</div><!-- #page -->
+
+</body>
+</html>

File diff suppressed because it is too large
+ 1 - 0
libs/jquery-3.6.0.min.js


File diff suppressed because it is too large
+ 2 - 0
libs/p5.dom.min.js


+ 581 - 0
libs/p5.imgui.js

@@ -0,0 +1,581 @@
+/**
+ * Prototype functions to make library 
+ * method calls more like p5.js.
+ */
+
+// Create GUI context
+let imgui;
+
+p5.prototype.createGui = function() {
+  imgui = new ImGui();
+}
+
+// Start GUI
+p5.prototype.startGui = function() {
+  imgui.start();
+}
+
+// End GUI
+p5.prototype.endGui = function() {
+  imgui.end();
+}
+
+// Prototype functions for GUI elements
+p5.prototype.button = function(label, x, y, w=128, h=32) {
+  return imgui.button(label, x, y, w, h);
+}
+
+p5.prototype.checkbox = function(label, value, x, y, w=32, h=32) {
+  return imgui.checkbox(label, value, x, y, w, h);
+}
+
+p5.prototype.slider = function(label, value, x, y, w=256, h=32, min=0, max=1) {
+  return imgui.slider(label, value, x, y, w, h, min, max);
+}
+
+p5.prototype.sliderV = function(label, value, x, y, w=32, h=256, min=0, max=1) {
+  return imgui.sliderV(label, value, x, y, w, h, min, max);
+}
+
+
+/**
+ * Generates hash code from a string.
+ * @see http://stackoverflow.com/q/7616461/940217
+ * @return {number}
+ */
+String.prototype.hashCode = function(){
+    if (Array.prototype.reduce){
+        return this.split("").reduce(function(a,b){a=((a<<5)-a)+b.charCodeAt(0);return a&a},0);              
+    } 
+    var hash = 0;
+    if (this.length === 0) return hash;
+    for (var i = 0; i < this.length; i++) {
+        var character  = this.charCodeAt(i);
+        hash  = ((hash<<5)-hash)+character;
+        hash = hash & hash; // Convert to 32bit integer
+    }
+    return hash;
+}
+
+
+/*******************
+ * IMGUI
+ * 
+ * 
+ */
+class ImGui {
+  constructor() {
+    this.hotItem = 0;
+    this.activeItem = 0;
+    
+    this.style = new ImGuiStyle();
+//    this.style.StyleColorsClassic();
+  }
+  
+  // Check whether current mouse position
+  // is within a rectangle
+  regionHit(x, y, w, h) {
+    if (mouseX < x || 
+        mouseY < y || 
+        mouseX >= x + w || 
+        mouseY >= y + h) {
+      return false;
+    }
+    return true;
+  }
+  
+  setHit(id) {
+    this.hotItem = id;
+    if (this.activeItem == 0 && mouseIsPressed) {
+      this.activeItem = id;
+    }
+  }
+  
+  /// Simple checkbox IMGUI widget
+  checkbox(label, value, x, y, w=32, h=32) {
+    // Create hashed id from label
+    let id = label.hashCode();
+//    let id = new Error().stack;
+    
+    // Check whether the button should be 'hot' or 'active'
+    if (this.regionHit(x, y, w, h)) {
+      this.hotItem = id;
+      if (this.activeItem == 0 && mouseIsPressed) {
+        this.activeItem = id;
+        value.val = !value.val;
+      }
+    }
+    
+    // Render button
+    let x8  = x+w/6;
+    let y8  = y+h/6;
+    let w16 = w-w/3;
+    let h16 = h-h/3;
+    let xw  = x8+w16;
+    let yh  = y8+h16;
+    let strokeMult = map(((w > h) ? w : h), 32, 1000, 2, 20);
+    
+    push();
+    rectMode(CORNER);
+    stroke(this.style.col_checkOuterStroke);
+    strokeWeight(this.style.checkStrokeWt);
+    fill(this.style.col_checkOuterFill);
+    rect(x, y, w, h, this.style.rounding);
+    
+    
+    if (this.hotItem == id && !value.val) {
+      // Button is 'hot' and 'false'
+      fill(this.style.col_checkOuterFillHover);
+      rect(x, y, w, h, this.style.rounding);
+    }
+    else if (this.hotItem == id && value.val) {
+      // Button is 'hot' and 'true'
+      push();
+      stroke(this.style.col_checkInnerStrokeHover);
+      strokeWeight(this.style.checkStrokeWt*strokeMult);
+      line(x8, y8, xw, yh);
+      line(xw, y8, x8, yh);
+      pop();
+      
+      if (this.activeItem == id) {
+        // Button is also 'active'
+        fill(this.style.col_checkOuterFillActive);
+        rect(x, y, w, h, this.style.rounding);
+        
+        push();
+        stroke(this.style.col_checkInnerStrokeActive);
+        strokeWeight(this.style.checkStrokeWt*strokeMult);
+        line(x8, y8, xw, yh);
+        line(xw, y8, x8, yh);
+        pop();
+      }   
+    }
+    else if (value.val) {
+      // Button is 'true' but not 'hot'
+      push();
+      stroke(this.style.col_checkInnerStroke);
+      strokeWeight(this.style.checkStrokeWt*strokeMult);
+      line(x8, y8, xw, yh);
+      line(xw, y8, x8, yh);
+      pop();
+    }
+    
+    pop();
+    
+    // If button is 'hot' and 'active', but mouse button
+    // is not down, the user must have clicked the button.
+    if (mouseIsPressed && 
+        this.hotItem == id && 
+        this.activeItem == id) {
+      return true;
+    }
+    
+    // Otherwise, no clicky.
+    return false;
+  }
+  
+  /// Simple button IMGUI widget
+  button(label, x, y, w=128, h=32) {
+    // Create hashed id from stack
+    let id = label.hashCode();
+    
+    // Check for 'hot' or 'active'
+    if (this.regionHit(x, y, w, h)) {
+      this.setHit(id);
+    }
+    
+    // Render button
+    push();
+    stroke(this.style.col_buttonStroke);
+    strokeWeight(this.style.buttonStrokeWt);
+    rectMode(CORNER);
+    
+    if (this.hotItem == id) {
+      if (this.activeItem == id) {
+        // Button is both 'hot' and 'active'
+        fill(this.style.col_buttonFillActive);
+        rect(x, y, w, h, this.style.rounding);
+      }
+      else {
+        // Button is merely 'hot'
+        fill(this.style.col_buttonFillHover);
+        rect(x, y, w, h, this.style.rounding);
+      }
+    }
+    else {
+      // Button is not hot, but it may be active
+      fill(this.style.col_buttonFill);
+      rect(x, y, w, h, this.style.rounding);      
+    }
+    
+    // Label rendering.
+    push();
+      fill(this.style.col_buttonLabel);
+      noStroke();
+      textAlign(CENTER, CENTER);
+      textFont(this.style.labelFont);
+      let size = w/10;
+      if (size > this.style.labelFontMaxSize) {
+        size = this.style.labelFontMaxSize;
+      }
+      textSize(size);
+      text(label, x + w/2, y + h/2);
+    pop();
+    
+    pop();
+    
+    // If button is 'hot' and 'active', but mouse button
+    // is not down, the user must have clicked the button.
+    if (mouseIsPressed && 
+        this.hotItem == id && 
+        this.activeItem == id) {
+      return true;
+    }
+    
+    // Otherwise, no clicky.
+    return false;
+  }
+  
+  /// Simple slider IMGUI widget
+  slider(label, value, x, y, w=256, h=32, min=0, max=1) {
+    // Create hashed id from label
+    let id = label.hashCode();
+    
+    // Calculate mouse cursor's relative x offset
+    let xpos = map(value.val, min, max, 0, w-32);
+    
+    // Check for 'hot' or 'active'
+    if (this.regionHit(x, y, w, h)) {
+      this.setHit(id);
+    }
+    
+    // Render the slider
+    if (this.activeItem == id) { 
+      this.drawSlider(xpos, x, y, w, h, 
+                      this.style.col_sliderBgFillActive,
+                      this.style.col_sliderIndctrFillActive,
+                      this.style.col_sliderGrabFillActive,
+                      this.style.col_sliderGrabStroke);
+    }
+    else if (this.hotItem == id) { 
+      this.drawSlider(xpos, x, y, w, h, 
+                      this.style.col_sliderBgFillHover,
+                      this.style.col_sliderIndctrFillHover,
+                      this.style.col_sliderGrabFillHover,
+                      this.style.col_sliderGrabStroke);
+    }
+    else {
+      this.drawSlider(xpos, x, y, w, h, 
+                      this.style.col_sliderBgFill,
+                      this.style.col_sliderIndctrFill,
+                      this.style.col_sliderGrabFill,
+                      this.style.col_sliderGrabStroke);
+    }
+    
+    // Update widget value
+    if (this.activeItem == id) {
+      
+      let mousePos = mouseX - x;
+      let v = map(mousePos, 0, w, min, max, true);
+      
+      if (v != value.val) {
+        value.val = v;
+        return true;
+      }
+    }
+    return false;
+  }
+  
+  /// Simple vertical slider IMGUI widget
+  sliderV(label, value, x, y, w=32, h=256, min=0, max=1) {
+    // Create hashed id from label
+    let id = label.hashCode();
+    
+    // Calculate mouse cursor's relative y offset
+    let ypos = map(value.val, min, max, 0, h-32);
+    
+    // Check for 'hot' or 'active'
+    if (this.regionHit(x, y, w, h)) {
+      this.setHit(id);
+    }
+    
+    // Render the slider
+    if (this.activeItem == id) { 
+      this.drawSliderV(ypos, x, y, w, h, 
+                       this.style.col_sliderBgFillActive,
+                       this.style.col_sliderIndctrFillActive,
+                       this.style.col_sliderGrabFillActive,
+                       this.style.col_sliderGrabStroke);
+    }
+    else if (this.hotItem == id) { 
+      this.drawSliderV(ypos, x, y, w, h, 
+                       this.style.col_sliderBgFillHover,
+                       this.style.col_sliderIndctrFillHover,
+                       this.style.col_sliderGrabFillHover,
+                       this.style.col_sliderGrabStroke);
+    }
+    else {
+      this.drawSliderV(ypos, x, y, w, h, 
+                       this.style.col_sliderBgFill,
+                       this.style.col_sliderIndctrFill,
+                       this.style.col_sliderGrabFill,
+                       this.style.col_sliderGrabStroke);
+    }
+    
+    // Update widget value
+    if (this.activeItem == id) {
+      
+      let mousePos = mouseY - y;
+      let v = map(mousePos, 0, h, min, max, true);
+      
+      if (v != value.val) {
+        value.val = v;
+        return true;
+      }
+    }
+    return false;
+  }
+  
+  /// Draw function for slider
+  drawSlider(xpos, x, y, w, h, bgFill, indctrFill, grabFill, grabStroke) {
+    push();
+      stroke(this.style.col_sliderStroke);
+      strokeWeight(this.style.sliderStrokeWt);
+      rectMode(CORNER);
+
+      // Render bg
+      fill(bgFill);
+      rect(x, y, w, h, this.style.rounding);
+
+      // Render indicator
+      push();
+        noStroke();
+        fill(indctrFill);
+  //      rect(x+0.2*h, y+0.2*h, xpos+0.*h, h-0.4*h, 
+  //           this.style.rounding, 0, 0, this.style.rounding);
+        rect(x+10, y+10, xpos+12, h-20, 
+             this.style.rounding, 0, 0, this.style.rounding);
+      pop();
+
+      // Render grab
+      push();
+        stroke(grabStroke);
+        fill(grabFill);
+        rect(x+8+xpos, y+8, 16, h-16, this.style.rounding);
+      pop();
+    pop();
+  }
+  
+  /// Draw function for vertical slider
+  drawSliderV(ypos, x, y, w, h, bgFill, indctrFill, grabFill, grabStroke) {
+    push();
+      stroke(this.style.col_sliderStroke);
+      strokeWeight(this.style.sliderStrokeWt);
+      rectMode(CORNER);
+
+      // Render bg
+      fill(bgFill);
+      rect(x, y, w, h, this.style.rounding);
+
+      // Render indicator
+      push();
+        noStroke();
+        fill(indctrFill);
+  //      rect(x+0.2*w, y+ypos+0.1*w, w-0.4*w, h-ypos-0.3*w, 
+  //           0, 0, this.style.rounding, this.style.rounding);
+        rect(x+10, y+ypos+12, w-20, h-ypos-20, 
+             0, 0, this.style.rounding, this.style.rounding);
+      pop();
+
+      // Render grab
+      push();
+        stroke(grabStroke);
+        fill(grabFill);
+        rect(x+8, y+8+ypos, w-16, 16, this.style.rounding);
+      pop();
+    pop();
+  }  
+  
+  /// Prepare for start IMGUI code
+  start() {
+    this.hotItem = 0;
+  }
+  
+  /// Finish at end IMGUI code
+  end() {
+    if (!mouseIsPressed) {
+      this.activeItem = 0;
+    }
+    else {
+      if (this.activeItem == 0) {
+        this.activeItem = -1;
+      }
+    }
+  }
+}
+
+
+/*******************
+ * IMGUI STYLE
+ * 
+ * 
+ */
+
+class ImGuiStyle {
+  constructor() {
+    // Global pars
+    this.rounding                       = 10;
+    this.labelFont                      = 'Arial';
+    this.labelFontMaxSize               = 30;
+    this.strokeWt                       = 2;
+
+    // Button pars
+    this.buttonStrokeWt                 = this.strokeWt;
+    this.col_buttonStroke               = color(0);
+    this.col_buttonFill                 = color(160);
+    this.col_buttonFillHover            = color(196);
+    this.col_buttonFillActive           = color(220);
+    this.col_buttonLabel                = color(0);
+    
+    // Checkbox pars
+    this.checkStrokeWt                  = this.strokeWt;
+    this.col_checkOuterStroke           = color(0);
+    this.col_checkOuterStrokeHover      = color(0);
+    this.col_checkOuterStrokeActive     = color(0);
+    this.col_checkOuterFill             = color(128);
+    this.col_checkOuterFillHover        = color(144);
+    this.col_checkOuterFillActive       = color(160);
+    this.col_checkInnerFill             = color(200);
+    this.col_checkInnerStroke           = color(200);
+    this.col_checkInnerFillHover        = color(220);
+    this.col_checkInnerStrokeHover      = color(220);
+    this.col_checkInnerFillActive       = color(240);
+    this.col_checkInnerStrokeActive     = color(240);
+    
+    // Slider pars
+    this.sliderStrokeWt                 = this.strokeWt;
+    this.col_sliderStroke               = color(0);
+    this.col_sliderBgFill               = color(160);
+    this.col_sliderBgFillHover          = color(175);
+    this.col_sliderBgFillActive         = color(175);
+    this.col_sliderBgStroke             = color(0);
+    this.col_sliderBgStrokeHover        = color(0);
+    this.col_sliderBgStrokeActive       = color(0);
+    this.col_sliderIndctrFill           = color(128);
+    this.col_sliderIndctrFillHover      = color(144);
+    this.col_sliderIndctrFillActive     = color(144);
+    this.col_sliderIndctrStroke         = color(128);
+    this.col_sliderIndctrStrokeHover    = color(144);
+    this.col_sliderIndctrStrokeActive   = color(144);
+    this.col_sliderGrabFill             = color(64);
+    this.col_sliderGrabFillHover        = color(96);
+    this.col_sliderGrabFillActive       = color(240);
+    this.col_sliderGrabStroke           = color(64);
+    this.col_sliderGrabStrokeHover      = color(0);
+    this.col_sliderGrabStrokeActive     = color(0);   
+  }
+  
+  StyleColorsGrayscale() {
+    this.rounding                       = 10;
+    this.labelFont                      = 'Arial';
+    this.labelFontMaxSize               = 30;
+    this.strokeWt                       = 2;
+
+    // Button pars
+    this.buttonStrokeWt                 = this.strokeWt;
+    this.col_buttonStroke               = color(0);
+    this.col_buttonFill                 = color(160);
+    this.col_buttonFillHover            = color(196);
+    this.col_buttonFillActive           = color(220);
+    this.col_buttonLabel                = color(0);
+    
+    // Checkbox pars
+    this.checkStrokeWt                  = this.strokeWt;
+    this.col_checkOuterStroke           = color(0);
+    this.col_checkOuterStrokeHover      = color(0);
+    this.col_checkOuterStrokeActive     = color(0);
+    this.col_checkOuterFill             = color(128);
+    this.col_checkOuterFillHover        = color(144);
+    this.col_checkOuterFillActive       = color(160);
+    this.col_checkInnerFill             = color(200);
+    this.col_checkInnerStroke           = color(200);
+    this.col_checkInnerFillHover        = color(220);
+    this.col_checkInnerStrokeHover      = color(220);
+    this.col_checkInnerFillActive       = color(240);
+    this.col_checkInnerStrokeActive     = color(240);
+    
+    // Slider pars
+    this.sliderStrokeWt                 = this.strokeWt;
+    this.col_sliderStroke               = color(0);
+    this.col_sliderBgFill               = color(160);
+    this.col_sliderBgFillHover          = color(175);
+    this.col_sliderBgFillActive         = color(175);
+    this.col_sliderBgStroke             = color(0);
+    this.col_sliderBgStrokeHover        = color(0);
+    this.col_sliderBgStrokeActive       = color(0);
+    this.col_sliderIndctrFill           = color(128);
+    this.col_sliderIndctrFillHover      = color(144);
+    this.col_sliderIndctrFillActive     = color(144);
+    this.col_sliderIndctrStroke         = color(128);
+    this.col_sliderIndctrStrokeHover    = color(144);
+    this.col_sliderIndctrStrokeActive   = color(144);
+    this.col_sliderGrabFill             = color(64);
+    this.col_sliderGrabFillHover        = color(96);
+    this.col_sliderGrabFillActive       = color(240);
+    this.col_sliderGrabStroke           = color(64);
+    this.col_sliderGrabStrokeHover      = color(96);
+    this.col_sliderGrabStrokeActive     = color(0); 
+  }
+  
+  StyleColorsClassic() {
+    this.rounding                       = 10;
+    this.labelFont                      = 'Arial';
+    this.labelFontMaxSize               = 30;
+    this.strokeWt                       = 5;
+
+    // Button pars
+    this.buttonStrokeWt                 = this.strokeWt;
+    this.col_buttonStroke               = color('#D5CAD6');
+    this.col_buttonFill                 = color('#EFEFF0');
+    this.col_buttonFillHover            = color('#F7F7F7');
+    this.col_buttonFillActive           = color('#C9F0FF');
+    this.col_buttonLabel                = color('#6B5E62');
+    
+    // Checkbox pars
+    this.checkStrokeWt                  = this.strokeWt;
+    this.col_checkOuterStroke           = color('#D5CAD6');
+    this.col_checkOuterStrokeHover      = color('#D5CAD6');
+    this.col_checkOuterStrokeActive     = color('#D5CAD6');
+    this.col_checkOuterFill             = color('#EFEFF0');
+    this.col_checkOuterFillHover        = color('#F7F7F7');
+    this.col_checkOuterFillActive       = color('#C9F0FF');
+    this.col_checkInnerFill             = color('#6B5E62');
+    this.col_checkInnerStroke           = color('#6B5E62');
+    this.col_checkInnerFillHover        = color('#7A6B70');
+    this.col_checkInnerStrokeHover      = color('#7A6B70');
+    this.col_checkInnerFillActive       = color('#7A6B70');
+    this.col_checkInnerStrokeActive     = color('#7A6B70');
+    
+    // Slider pars
+    this.sliderStrokeWt                 = this.strokeWt;
+    this.col_sliderStroke               = color('#D5CAD6');
+    this.col_sliderBgFill               = color('#EFEFF0');
+    this.col_sliderBgFillHover          = color('#F7F7F7');
+    this.col_sliderBgFillActive         = color('#F7F7F7');
+    this.col_sliderBgStroke             = color(0);
+    this.col_sliderBgStrokeHover        = color(0);
+    this.col_sliderBgStrokeActive       = color(0);
+    this.col_sliderIndctrFill           = color('#D5CAD6');
+    this.col_sliderIndctrFillHover      = color('#D5CAD6');
+    this.col_sliderIndctrFillActive     = color('#D5CAD6');
+    this.col_sliderIndctrStroke         = color(128);
+    this.col_sliderIndctrStrokeHover    = color(144);
+    this.col_sliderIndctrStrokeActive   = color(144);
+    this.col_sliderGrabFill             = color('#6B5E62');
+    this.col_sliderGrabFillHover        = color('#7A6B70');
+    this.col_sliderGrabFillActive       = color('#C9F0FF');
+    this.col_sliderGrabStroke           = color('#6B5E62');
+    this.col_sliderGrabStrokeHover      = color('#7A6B70');
+    this.col_sliderGrabStrokeActive     = color('#7A6B70'); 
+  }
+}

File diff suppressed because it is too large
+ 23 - 0
libs/p5.sound.min.js


+ 2583 - 0
libs/p5.svg.js

@@ -0,0 +1,2583 @@
+/*!!
+ *  p5.svg v0.5.2
+ *  SVG Runtime for p5.js.
+ *
+ *  Copyright (C) 2015-2016 Zeno Zeng
+ *  Licensed under the LGPL license.
+ */
+(function (root, factory) {
+    if (typeof define === 'function' && define.amd) {
+        define('p5.svg', ['p5'], function (p5) {
+            factory(p5);
+        });
+    }
+    else if (typeof exports === 'object') {
+        module.exports = factory;
+    }
+    else {
+        factory(root['p5']);
+    }
+})(this, function (p5) {
+
+(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(require,module,exports){
+/*!!
+ *  Canvas 2 Svg v1.0.9
+ *  A low level canvas to SVG converter. Uses a mock canvas context to build an SVG document.
+ *
+ *  Licensed under the MIT license:
+ *  http://www.opensource.org/licenses/mit-license.php
+ *
+ *  Author:
+ *  Kerry Liu
+ *
+ *  Copyright (c) 2014 Gliffy Inc.
+ */
+
+;(function() {
+    "use strict";
+
+    var STYLES, ctx, CanvasGradient, CanvasPattern, namedEntities;
+
+    //helper function to format a string
+    function format(str, args) {
+        var keys = Object.keys(args), i;
+        for (i=0; i<keys.length; i++) {
+            str = str.replace(new RegExp("\\{" + keys[i] + "\\}", "gi"), args[keys[i]]);
+        }
+        return str;
+    }
+
+    //helper function that generates a random string
+    function randomString(holder) {
+        var chars, randomstring, i;
+        if (!holder) {
+            throw new Error("cannot create a random attribute name for an undefined object");
+        }
+        chars = "ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
+        randomstring = "";
+        do {
+            randomstring = "";
+            for (i = 0; i < 12; i++) {
+                randomstring += chars[Math.floor(Math.random() * chars.length)];
+            }
+        } while (holder[randomstring]);
+        return randomstring;
+    }
+
+    //helper function to map named to numbered entities
+    function createNamedToNumberedLookup(items, radix) {
+        var i, entity, lookup = {}, base10, base16;
+        items = items.split(',');
+        radix = radix || 10;
+        // Map from named to numbered entities.
+        for (i = 0; i < items.length; i += 2) {
+            entity = '&' + items[i + 1] + ';';
+            base10 = parseInt(items[i], radix);
+            lookup[entity] = '&#'+base10+';';
+        }
+        //FF and IE need to create a regex from hex values ie &nbsp; == \xa0
+        lookup["\\xa0"] = '&#160;';
+        return lookup;
+    }
+
+    //helper function to map canvas-textAlign to svg-textAnchor
+    function getTextAnchor(textAlign) {
+        //TODO: support rtl languages
+        var mapping = {"left":"start", "right":"end", "center":"middle", "start":"start", "end":"end"};
+        return mapping[textAlign] || mapping.start;
+    }
+
+    //helper function to map canvas-textBaseline to svg-dominantBaseline
+    function getDominantBaseline(textBaseline) {
+        //INFO: not supported in all browsers
+        var mapping = {"alphabetic": "alphabetic", "hanging": "hanging", "top":"text-before-edge", "bottom":"text-after-edge", "middle":"central"};
+        return mapping[textBaseline] || mapping.alphabetic;
+    }
+
+    // Unpack entities lookup where the numbers are in radix 32 to reduce the size
+    // entity mapping courtesy of tinymce
+    namedEntities = createNamedToNumberedLookup(
+        '50,nbsp,51,iexcl,52,cent,53,pound,54,curren,55,yen,56,brvbar,57,sect,58,uml,59,copy,' +
+            '5a,ordf,5b,laquo,5c,not,5d,shy,5e,reg,5f,macr,5g,deg,5h,plusmn,5i,sup2,5j,sup3,5k,acute,' +
+            '5l,micro,5m,para,5n,middot,5o,cedil,5p,sup1,5q,ordm,5r,raquo,5s,frac14,5t,frac12,5u,frac34,' +
+            '5v,iquest,60,Agrave,61,Aacute,62,Acirc,63,Atilde,64,Auml,65,Aring,66,AElig,67,Ccedil,' +
+            '68,Egrave,69,Eacute,6a,Ecirc,6b,Euml,6c,Igrave,6d,Iacute,6e,Icirc,6f,Iuml,6g,ETH,6h,Ntilde,' +
+            '6i,Ograve,6j,Oacute,6k,Ocirc,6l,Otilde,6m,Ouml,6n,times,6o,Oslash,6p,Ugrave,6q,Uacute,' +
+            '6r,Ucirc,6s,Uuml,6t,Yacute,6u,THORN,6v,szlig,70,agrave,71,aacute,72,acirc,73,atilde,74,auml,' +
+            '75,aring,76,aelig,77,ccedil,78,egrave,79,eacute,7a,ecirc,7b,euml,7c,igrave,7d,iacute,7e,icirc,' +
+            '7f,iuml,7g,eth,7h,ntilde,7i,ograve,7j,oacute,7k,ocirc,7l,otilde,7m,ouml,7n,divide,7o,oslash,' +
+            '7p,ugrave,7q,uacute,7r,ucirc,7s,uuml,7t,yacute,7u,thorn,7v,yuml,ci,fnof,sh,Alpha,si,Beta,' +
+            'sj,Gamma,sk,Delta,sl,Epsilon,sm,Zeta,sn,Eta,so,Theta,sp,Iota,sq,Kappa,sr,Lambda,ss,Mu,' +
+            'st,Nu,su,Xi,sv,Omicron,t0,Pi,t1,Rho,t3,Sigma,t4,Tau,t5,Upsilon,t6,Phi,t7,Chi,t8,Psi,' +
+            't9,Omega,th,alpha,ti,beta,tj,gamma,tk,delta,tl,epsilon,tm,zeta,tn,eta,to,theta,tp,iota,' +
+            'tq,kappa,tr,lambda,ts,mu,tt,nu,tu,xi,tv,omicron,u0,pi,u1,rho,u2,sigmaf,u3,sigma,u4,tau,' +
+            'u5,upsilon,u6,phi,u7,chi,u8,psi,u9,omega,uh,thetasym,ui,upsih,um,piv,812,bull,816,hellip,' +
+            '81i,prime,81j,Prime,81u,oline,824,frasl,88o,weierp,88h,image,88s,real,892,trade,89l,alefsym,' +
+            '8cg,larr,8ch,uarr,8ci,rarr,8cj,darr,8ck,harr,8dl,crarr,8eg,lArr,8eh,uArr,8ei,rArr,8ej,dArr,' +
+            '8ek,hArr,8g0,forall,8g2,part,8g3,exist,8g5,empty,8g7,nabla,8g8,isin,8g9,notin,8gb,ni,8gf,prod,' +
+            '8gh,sum,8gi,minus,8gn,lowast,8gq,radic,8gt,prop,8gu,infin,8h0,ang,8h7,and,8h8,or,8h9,cap,8ha,cup,' +
+            '8hb,int,8hk,there4,8hs,sim,8i5,cong,8i8,asymp,8j0,ne,8j1,equiv,8j4,le,8j5,ge,8k2,sub,8k3,sup,8k4,' +
+            'nsub,8k6,sube,8k7,supe,8kl,oplus,8kn,otimes,8l5,perp,8m5,sdot,8o8,lceil,8o9,rceil,8oa,lfloor,8ob,' +
+            'rfloor,8p9,lang,8pa,rang,9ea,loz,9j0,spades,9j3,clubs,9j5,hearts,9j6,diams,ai,OElig,aj,oelig,b0,' +
+            'Scaron,b1,scaron,bo,Yuml,m6,circ,ms,tilde,802,ensp,803,emsp,809,thinsp,80c,zwnj,80d,zwj,80e,lrm,' +
+            '80f,rlm,80j,ndash,80k,mdash,80o,lsquo,80p,rsquo,80q,sbquo,80s,ldquo,80t,rdquo,80u,bdquo,810,dagger,' +
+            '811,Dagger,81g,permil,81p,lsaquo,81q,rsaquo,85c,euro', 32);
+
+
+    //Some basic mappings for attributes and default values.
+    STYLES = {
+        "strokeStyle":{
+            svgAttr : "stroke", //corresponding svg attribute
+            canvas : "#000000", //canvas default
+            svg : "none",       //svg default
+            apply : "stroke"    //apply on stroke() or fill()
+        },
+        "fillStyle":{
+            svgAttr : "fill",
+            canvas : "#000000",
+            svg : null, //svg default is black, but we need to special case this to handle canvas stroke without fill
+            apply : "fill"
+        },
+        "lineCap":{
+            svgAttr : "stroke-linecap",
+            canvas : "butt",
+            svg : "butt",
+            apply : "stroke"
+        },
+        "lineJoin":{
+            svgAttr : "stroke-linejoin",
+            canvas : "miter",
+            svg : "miter",
+            apply : "stroke"
+        },
+        "miterLimit":{
+            svgAttr : "stroke-miterlimit",
+            canvas : 10,
+            svg : 4,
+            apply : "stroke"
+        },
+        "lineWidth":{
+            svgAttr : "stroke-width",
+            canvas : 1,
+            svg : 1,
+            apply : "stroke"
+        },
+        "globalAlpha": {
+            svgAttr : "opacity",
+            canvas : 1,
+            svg : 1,
+            apply : "fill stroke"
+        },
+        "font":{
+            //font converts to multiple svg attributes, there is custom logic for this
+            canvas : "10px sans-serif"
+        },
+        "shadowColor":{
+            canvas : "#000000"
+        },
+        "shadowOffsetX":{
+            canvas : 0
+        },
+        "shadowOffsetY":{
+            canvas : 0
+        },
+        "shadowBlur":{
+            canvas : 0
+        },
+        "textAlign":{
+            canvas : "start"
+        },
+        "textBaseline":{
+            canvas : "alphabetic"
+        }
+    };
+
+    /**
+     *
+     * @param gradientNode - reference to the gradient
+     * @constructor
+     */
+    CanvasGradient = function(gradientNode) {
+        this.__root = gradientNode;
+    };
+
+    /**
+     * Adds a color stop to the gradient root
+     */
+    CanvasGradient.prototype.addColorStop = function(offset, color) {
+        var stop = this.__createElement("stop"), regex, matches;
+        stop.setAttribute("offset", offset);
+        if(color.indexOf("rgba") !== -1) {
+            //separate alpha value, since webkit can't handle it
+            regex = /rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d?\.?\d*)\s*\)/gi;
+            matches = regex.exec(color);
+            stop.setAttribute("stop-color", format("rgb({r},{g},{b})", {r:matches[1], g:matches[2], b:matches[3]}));
+            stop.setAttribute("stop-opacity", matches[4]);
+        } else {
+            stop.setAttribute("stop-color", color);
+        }
+        this.__root.appendChild(stop);
+    };
+
+    CanvasPattern = function(pattern, ctx) {
+        this.__root = pattern;
+        this.__ctx = ctx;
+    };
+
+    /**
+     * The mock canvas context
+     * @param o - options include:
+     * width - width of your canvas (defaults to 500)
+     * height - height of your canvas (defaults to 500)
+     * enableMirroring - enables canvas mirroring (get image data) (defaults to false)
+     */
+    ctx = function(o) {
+
+        var defaultOptions = { width:500, height:500, enableMirroring : false }, options;
+
+        //keep support for this way of calling C2S: new C2S(width,height)
+        if(arguments.length > 1) {
+            options = defaultOptions;
+            options.width = arguments[0];
+            options.height = arguments[1];
+        } else if( !o ) {
+            options = defaultOptions;
+        } else {
+            options = o;
+        }
+
+        if(!(this instanceof ctx)) {
+            //did someone call this without new?
+            return new ctx(options);
+        }
+
+        //setup options
+        this.width = options.width || defaultOptions.width;
+        this.height = options.height || defaultOptions.height;
+        this.enableMirroring = options.enableMirroring !== undefined ? options.enableMirroring : defaultOptions.enableMirroring;
+
+        this.canvas = this;   ///point back to this instance!
+        this.__canvas = document.createElement("canvas");
+        this.__ctx = this.__canvas.getContext("2d");
+
+        this.__setDefaultStyles();
+        this.__stack = [this.__getStyleState()];
+        this.__groupStack = [];
+
+        //the root svg element
+        this.__root = document.createElementNS("http://www.w3.org/2000/svg", "svg");
+        this.__root.setAttribute("version", 1.1);
+        this.__root.setAttribute("xmlns", "http://www.w3.org/2000/svg");
+        this.__root.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xlink", "http://www.w3.org/1999/xlink");
+        this.__root.setAttribute("width", this.width);
+        this.__root.setAttribute("height", this.height);
+
+        //make sure we don't generate the same ids in defs
+        this.__ids = {};
+
+        //defs tag
+        this.__defs = document.createElementNS("http://www.w3.org/2000/svg", "defs");
+        this.__root.appendChild(this.__defs);
+
+        //also add a group child. the svg element can't use the transform attribute
+        this.__currentElement = document.createElementNS("http://www.w3.org/2000/svg", "g");
+        this.__root.appendChild(this.__currentElement);
+    };
+
+    /**
+     * Creates the specified svg element
+     * @private
+     */
+    ctx.prototype.__createElement = function(elementName, properties, resetFill) {
+        if (typeof properties === "undefined") {
+            properties = {};
+        }
+
+        var element = document.createElementNS("http://www.w3.org/2000/svg", elementName),
+            keys = Object.keys(properties), i, key;
+        if(resetFill) {
+            //if fill or stroke is not specified, the svg element should not display. By default SVG's fill is black.
+            element.setAttribute("fill", "none");
+            element.setAttribute("stroke", "none");
+        }
+        for(i=0; i<keys.length; i++) {
+            key = keys[i];
+            element.setAttribute(key, properties[key]);
+        }
+        return element;
+    };
+
+    /**
+     * Applies default canvas styles to the context
+     * @private
+     */
+    ctx.prototype.__setDefaultStyles = function() {
+        //default 2d canvas context properties see:http://www.w3.org/TR/2dcontext/
+        var keys = Object.keys(STYLES), i, key;
+        for(i=0; i<keys.length; i++) {
+            key = keys[i];
+            this[key] = STYLES[key].canvas;
+        }
+    };
+
+    /**
+     * Applies styles on restore
+     * @param styleState
+     * @private
+     */
+    ctx.prototype.__applyStyleState = function(styleState) {
+        var keys = Object.keys(styleState), i, key;
+        for(i=0; i<keys.length; i++) {
+            key = keys[i];
+            this[key] = styleState[key];
+        }
+    };
+
+    /**
+     * Gets the current style state
+     * @return {Object}
+     * @private
+     */
+    ctx.prototype.__getStyleState = function() {
+        var i, styleState = {}, keys = Object.keys(STYLES), key;
+        for(i=0; i<keys.length; i++) {
+            key = keys[i];
+            styleState[key] = this[key];
+        }
+        return styleState;
+    };
+
+    /**
+     * Apples the current styles to the current SVG element. On "ctx.fill" or "ctx.stroke"
+     * @param type
+     * @private
+     */
+    ctx.prototype.__applyStyleToCurrentElement = function(type) {
+        var keys = Object.keys(STYLES), i, style, value, id, regex, matches;
+        for(i=0; i<keys.length; i++) {
+            style = STYLES[keys[i]];
+            value = this[keys[i]];
+            if(style.apply) {
+                //is this a gradient or pattern?
+                if(style.apply.indexOf("fill")!==-1 && value instanceof CanvasPattern) {
+                    //pattern
+                    if(value.__ctx) {
+                        //copy over defs
+                        while(value.__ctx.__defs.childNodes.length) {
+                            id = value.__ctx.__defs.childNodes[0].getAttribute("id");
+                            this.__ids[id] = id;
+                            this.__defs.appendChild(value.__ctx.__defs.childNodes[0]);
+                        }
+                    }
+                    this.__currentElement.setAttribute("fill", format("url(#{id})", {id:value.__root.getAttribute("id")}));
+                }
+                else if(style.apply.indexOf("fill")!==-1 && value instanceof CanvasGradient) {
+                    //gradient
+                    this.__currentElement.setAttribute("fill", format("url(#{id})", {id:value.__root.getAttribute("id")}));
+                } else if(style.apply.indexOf(type)!==-1 && style.svg !== value) {
+                    if((style.svgAttr === "stroke" || style.svgAttr === "fill") && value.indexOf("rgba") !== -1) {
+                        //separate alpha value, since illustrator can't handle it
+                        regex = /rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d?\.?\d*)\s*\)/gi;
+                        matches = regex.exec(value);
+                        this.__currentElement.setAttribute(style.svgAttr, format("rgb({r},{g},{b})", {r:matches[1], g:matches[2], b:matches[3]}));
+                        this.__currentElement.setAttribute(style.svgAttr+"-opacity", matches[4]);
+                    } else {
+                        //otherwise only update attribute if right type, and not svg default
+                        this.__currentElement.setAttribute(style.svgAttr, value);
+                    }
+                }
+            }
+        }
+
+    };
+
+    /**
+     * Will return the closest group or svg node. May return the current element.
+     * @private
+     */
+    ctx.prototype.__closestGroupOrSvg = function(node) {
+        node = node || this.__currentElement;
+        if(node.nodeName === "g" || node.nodeName === "svg") {
+            return node;
+        } else {
+            return this.__closestGroupOrSvg(node.parentNode);
+        }
+    };
+
+    /**
+     * Returns the serialized value of the svg so far
+     * @param fixNamedEntities - Standalone SVG doesn't support named entities, which document.createTextNode encodes.
+     *                           If true, we attempt to find all named entities and encode it as a numeric entity.
+     * @return serialized svg
+     */
+    ctx.prototype.getSerializedSvg = function(fixNamedEntities) {
+        var serialized = new XMLSerializer().serializeToString(this.__root),
+            keys, i, key, value, regexp, xmlns;
+
+        //IE search for a duplicate xmnls because they didn't implement setAttributeNS correctly
+        xmlns = /xmlns="http:\/\/www\.w3\.org\/2000\/svg".+xmlns="http:\/\/www\.w3\.org\/2000\/svg/gi;
+        if(xmlns.test(serialized)) {
+            serialized = serialized.replace('xmlns="http://www.w3.org/2000/svg','xmlns:xlink="http://www.w3.org/1999/xlink');
+        }
+
+        if(fixNamedEntities) {
+            keys = Object.keys(namedEntities);
+            //loop over each named entity and replace with the proper equivalent.
+            for(i=0; i<keys.length; i++) {
+                key = keys[i];
+                value = namedEntities[key];
+                regexp = new RegExp(key, "gi");
+                if(regexp.test(serialized)) {
+                    serialized = serialized.replace(regexp, value);
+                }
+            }
+        }
+
+        return serialized;
+    };
+
+
+    /**
+     * Returns the root svg
+     * @return
+     */
+    ctx.prototype.getSvg = function() {
+        return this.__root;
+    };
+    /**
+     * Will generate a group tag.
+     */
+    ctx.prototype.save = function() {
+        var group = this.__createElement("g"), parent = this.__closestGroupOrSvg();
+        this.__groupStack.push(parent);
+        parent.appendChild(group);
+        this.__currentElement = group;
+        this.__stack.push(this.__getStyleState());
+    };
+    /**
+     * Sets current element to parent, or just root if already root
+     */
+    ctx.prototype.restore = function(){
+        this.__currentElement = this.__groupStack.pop();
+        var state = this.__stack.pop();
+        this.__applyStyleState(state);
+
+    };
+
+    /**
+     * Helper method to add transform
+     * @private
+     */
+    ctx.prototype.__addTransform = function(t) {
+
+        //if the current element has siblings, add another group
+        var parent = this.__closestGroupOrSvg();
+        if(parent.childNodes.length > 0) {
+            var group = this.__createElement("g");
+            parent.appendChild(group);
+            this.__currentElement = group;
+        }
+
+        var transform = this.__currentElement.getAttribute("transform");
+        if(transform) {
+            transform += " ";
+        } else {
+            transform = "";
+        }
+        transform += t;
+        this.__currentElement.setAttribute("transform", transform);
+    };
+
+    /**
+     *  scales the current element
+     */
+    ctx.prototype.scale = function(x, y) {
+        if(y === undefined) {
+            y = x;
+        }
+        this.__addTransform(format("scale({x},{y})", {x:x, y:y}));
+    };
+
+    /**
+     * rotates the current element
+     */
+    ctx.prototype.rotate = function(angle){
+        var degrees = (angle * 180 / Math.PI);
+        this.__addTransform(format("rotate({angle},{cx},{cy})", {angle:degrees, cx:0, cy:0}));
+    };
+
+    /**
+     * translates the current element
+     */
+    ctx.prototype.translate = function(x, y){
+        this.__addTransform(format("translate({x},{y})", {x:x,y:y}));
+    };
+
+    /**
+     * applies a transform to the current element
+     */
+    ctx.prototype.transform = function(a, b, c, d, e, f){
+        this.__addTransform(format("matrix({a},{b},{c},{d},{e},{f})", {a:a, b:b, c:c, d:d, e:e, f:f}));
+    };
+
+    /**
+     * Create a new Path Element
+     */
+    ctx.prototype.beginPath = function(){
+        var path, parent;
+
+        // Note that there is only one current default path, it is not part of the drawing state.
+        // See also: https://html.spec.whatwg.org/multipage/scripting.html#current-default-path
+        this.__currentDefaultPath = "";
+        this.__currentPosition = {};
+
+        path = this.__createElement("path", {}, true);
+        parent = this.__closestGroupOrSvg();
+        parent.appendChild(path);
+        this.__currentElement = path;
+    };
+
+    /**
+     * Helper function to apply currentDefaultPath to current path element
+     * @private
+     */
+    ctx.prototype.__applyCurrentDefaultPath = function() {
+        if(this.__currentElement.nodeName === "path") {
+            var d = this.__currentDefaultPath;
+            this.__currentElement.setAttribute("d", d);
+        } else {
+            throw new Error("Attempted to apply path command to node " + this.__currentElement.nodeName);
+        }
+    };
+
+    /**
+     * Helper function to add path command
+     * @private
+     */
+    ctx.prototype.__addPathCommand = function(command){
+        this.__currentDefaultPath += " ";
+        this.__currentDefaultPath += command;
+    };
+
+    /**
+     * Adds the move command to the current path element,
+     * if the currentPathElement is not empty create a new path element
+     */
+    ctx.prototype.moveTo = function(x,y){
+        if(this.__currentElement.nodeName !== "path") {
+            this.beginPath();
+        }
+
+        // creates a new subpath with the given point
+        this.__currentPosition = {x: x, y: y};
+        this.__addPathCommand(format("M {x} {y}", {x:x, y:y}));
+    };
+
+    /**
+     * Closes the current path
+     */
+    ctx.prototype.closePath = function(){
+        this.__addPathCommand("Z");
+    };
+
+    /**
+     * Adds a line to command
+     */
+    ctx.prototype.lineTo = function(x, y){
+        this.__currentPosition = {x: x, y: y};
+        if (this.__currentDefaultPath.indexOf('M') > -1) {
+            this.__addPathCommand(format("L {x} {y}", {x:x, y:y}));
+        } else {
+            this.__addPathCommand(format("M {x} {y}", {x:x, y:y}));
+        }
+    };
+
+    /**
+     * Add a bezier command
+     */
+    ctx.prototype.bezierCurveTo = function(cp1x, cp1y, cp2x, cp2y, x, y) {
+        this.__currentPosition = {x: x, y: y};
+        this.__addPathCommand(format("C {cp1x} {cp1y} {cp2x} {cp2y} {x} {y}",
+            {cp1x:cp1x, cp1y:cp1y, cp2x:cp2x, cp2y:cp2y, x:x, y:y}));
+    };
+
+    /**
+     * Adds a quadratic curve to command
+     */
+    ctx.prototype.quadraticCurveTo = function(cpx, cpy, x, y){
+        this.__currentPosition = {x: x, y: y};
+        this.__addPathCommand(format("Q {cpx} {cpy} {x} {y}", {cpx:cpx, cpy:cpy, x:x, y:y}));
+    };
+
+
+    /**
+     * Return a new normalized vector of given vector
+     */
+    var normalize = function(vector) {
+        var len = Math.sqrt(vector[0] * vector[0] + vector[1] * vector[1]);
+        return [vector[0] / len, vector[1] / len];
+    };
+
+    /**
+     * Adds the arcTo to the current path
+     *
+     * @see http://www.w3.org/TR/2015/WD-2dcontext-20150514/#dom-context-2d-arcto
+     */
+    ctx.prototype.arcTo = function(x1, y1, x2, y2, radius) {
+        // Let the point (x0, y0) be the last point in the subpath.
+        var x0 = this.__currentPosition && this.__currentPosition.x;
+        var y0 = this.__currentPosition && this.__currentPosition.y;
+
+        // First ensure there is a subpath for (x1, y1).
+        if (typeof x0 == "undefined" || typeof y0 == "undefined") {
+            return;
+        }
+
+        // Negative values for radius must cause the implementation to throw an IndexSizeError exception.
+        if (radius < 0) {
+            throw new Error("IndexSizeError: The radius provided (" + radius + ") is negative.");
+        }
+
+        // If the point (x0, y0) is equal to the point (x1, y1),
+        // or if the point (x1, y1) is equal to the point (x2, y2),
+        // or if the radius radius is zero,
+        // then the method must add the point (x1, y1) to the subpath,
+        // and connect that point to the previous point (x0, y0) by a straight line.
+        if (((x0 === x1) && (y0 === y1))
+            || ((x1 === x2) && (y1 === y2))
+            || (radius === 0)) {
+            this.lineTo(x1, y1);
+            return;
+        }
+
+        // Otherwise, if the points (x0, y0), (x1, y1), and (x2, y2) all lie on a single straight line,
+        // then the method must add the point (x1, y1) to the subpath,
+        // and connect that point to the previous point (x0, y0) by a straight line.
+        var unit_vec_p1_p0 = normalize([x0 - x1, y0 - y1]);
+        var unit_vec_p1_p2 = normalize([x2 - x1, y2 - y1]);
+        if (unit_vec_p1_p0[0] * unit_vec_p1_p2[1] === unit_vec_p1_p0[1] * unit_vec_p1_p2[0]) {
+            this.lineTo(x1, y1);
+            return;
+        }
+
+        // Otherwise, let The Arc be the shortest arc given by circumference of the circle that has radius radius,
+        // and that has one point tangent to the half-infinite line that crosses the point (x0, y0) and ends at the point (x1, y1),
+        // and that has a different point tangent to the half-infinite line that ends at the point (x1, y1), and crosses the point (x2, y2).
+        // The points at which this circle touches these two lines are called the start and end tangent points respectively.
+
+        // note that both vectors are unit vectors, so the length is 1
+        var cos = (unit_vec_p1_p0[0] * unit_vec_p1_p2[0] + unit_vec_p1_p0[1] * unit_vec_p1_p2[1]);
+        var theta = Math.acos(Math.abs(cos));
+
+        // Calculate origin
+        var unit_vec_p1_origin = normalize([
+            unit_vec_p1_p0[0] + unit_vec_p1_p2[0],
+            unit_vec_p1_p0[1] + unit_vec_p1_p2[1]
+        ]);
+        var len_p1_origin = radius / Math.sin(theta / 2);
+        var x = x1 + len_p1_origin * unit_vec_p1_origin[0];
+        var y = y1 + len_p1_origin * unit_vec_p1_origin[1];
+
+        // Calculate start angle and end angle
+        // rotate 90deg clockwise (note that y axis points to its down)
+        var unit_vec_origin_start_tangent = [
+            -unit_vec_p1_p0[1],
+            unit_vec_p1_p0[0]
+        ];
+        // rotate 90deg counter clockwise (note that y axis points to its down)
+        var unit_vec_origin_end_tangent = [
+            unit_vec_p1_p2[1],
+            -unit_vec_p1_p2[0]
+        ];
+        var getAngle = function(vector) {
+            // get angle (clockwise) between vector and (1, 0)
+            var x = vector[0];
+            var y = vector[1];
+            if (y >= 0) { // note that y axis points to its down
+                return Math.acos(x);
+            } else {
+                return -Math.acos(x);
+            }
+        };
+        var startAngle = getAngle(unit_vec_origin_start_tangent);
+        var endAngle = getAngle(unit_vec_origin_end_tangent);
+
+        // Connect the point (x0, y0) to the start tangent point by a straight line
+        this.lineTo(x + unit_vec_origin_start_tangent[0] * radius,
+                    y + unit_vec_origin_start_tangent[1] * radius);
+
+        // Connect the start tangent point to the end tangent point by arc
+        // and adding the end tangent point to the subpath.
+        this.arc(x, y, radius, startAngle, endAngle);
+    };
+
+    /**
+     * Sets the stroke property on the current element
+     */
+    ctx.prototype.stroke = function(){
+        if(this.__currentElement.nodeName === "path") {
+            this.__currentElement.setAttribute("paint-order", "fill stroke markers");
+        }
+        this.__applyCurrentDefaultPath();
+        this.__applyStyleToCurrentElement("stroke");
+    };
+
+    /**
+     * Sets fill properties on the current element
+     */
+    ctx.prototype.fill = function(){
+        if(this.__currentElement.nodeName === "path") {
+            this.__currentElement.setAttribute("paint-order", "stroke fill markers");
+        }
+        this.__applyCurrentDefaultPath();
+        this.__applyStyleToCurrentElement("fill");
+    };
+
+    /**
+     *  Adds a rectangle to the path.
+     */
+    ctx.prototype.rect = function(x, y, width, height){
+        if(this.__currentElement.nodeName !== "path") {
+            this.beginPath();
+        }
+        this.moveTo(x, y);
+        this.lineTo(x+width, y);
+        this.lineTo(x+width, y+height);
+        this.lineTo(x, y+height);
+        this.lineTo(x, y);
+        this.closePath();
+    };
+
+
+    /**
+     * adds a rectangle element
+     */
+    ctx.prototype.fillRect = function(x, y, width, height){
+        var rect, parent;
+        rect = this.__createElement("rect", {
+            x : x,
+            y : y,
+            width : width,
+            height : height
+        }, true);
+        parent = this.__closestGroupOrSvg();
+        parent.appendChild(rect);
+        this.__currentElement = rect;
+        this.__applyStyleToCurrentElement("fill");
+    };
+
+    /**
+     * Draws a rectangle with no fill
+     * @param x
+     * @param y
+     * @param width
+     * @param height
+     */
+    ctx.prototype.strokeRect = function(x, y, width, height){
+        var rect, parent;
+        rect = this.__createElement("rect", {
+            x : x,
+            y : y,
+            width : width,
+            height : height
+        }, true);
+        parent = this.__closestGroupOrSvg();
+        parent.appendChild(rect);
+        this.__currentElement = rect;
+        this.__applyStyleToCurrentElement("stroke");
+    };
+
+
+    /**
+     * "Clears" a canvas by just drawing a white rectangle in the current group.
+     */
+    ctx.prototype.clearRect = function(x, y, width, height) {
+        var rect, parent = this.__closestGroupOrSvg();
+        rect = this.__createElement("rect", {
+            x : x,
+            y : y,
+            width : width,
+            height : height,
+            fill : "#FFFFFF"
+        }, true);
+        parent.appendChild(rect);
+    };
+
+    /**
+     * Adds a linear gradient to a defs tag.
+     * Returns a canvas gradient object that has a reference to it's parent def
+     */
+    ctx.prototype.createLinearGradient = function(x1, y1, x2, y2){
+        var grad = this.__createElement("linearGradient", {
+            id : randomString(this.__ids),
+            x1 : x1+"px",
+            x2 : x2+"px",
+            y1 : y1+"px",
+            y2 : y2+"px",
+            "gradientUnits" : "userSpaceOnUse"
+        }, false);
+        this.__defs.appendChild(grad);
+        return new CanvasGradient(grad);
+    };
+
+    /**
+     * Adds a radial gradient to a defs tag.
+     * Returns a canvas gradient object that has a reference to it's parent def
+     */
+    ctx.prototype.createRadialGradient = function(x0, y0, r0, x1, y1, r1){
+        var grad = this.__createElement("radialGradient", {
+            id : randomString(this.__ids),
+            cx : x1+"px",
+            cy : y1+"px",
+            r  : r1+"px",
+            fx : x0+"px",
+            fy : y0+"px",
+            "gradientUnits" : "userSpaceOnUse"
+        }, false);
+        this.__defs.appendChild(grad);
+        return new CanvasGradient(grad);
+
+    };
+
+    /**
+     * Parses the font string and returns svg mapping
+     * @private
+     */
+    ctx.prototype.__parseFont = function() {
+        var regex = /^\s*(?=(?:(?:[-a-z]+\s*){0,2}(italic|oblique))?)(?=(?:(?:[-a-z]+\s*){0,2}(small-caps))?)(?=(?:(?:[-a-z]+\s*){0,2}(bold(?:er)?|lighter|[1-9]00))?)(?:(?:normal|\1|\2|\3)\s*){0,3}((?:xx?-)?(?:small|large)|medium|smaller|larger|[.\d]+(?:\%|in|[cem]m|ex|p[ctx]))(?:\s*\/\s*(normal|[.\d]+(?:\%|in|[cem]m|ex|p[ctx])))?\s*([-,\"\sa-z]+?)\s*$/i;
+        var fontPart = regex.exec( this.font );
+        var data = {
+            style : fontPart[1] || 'normal',
+            size : fontPart[4] || '10px',
+            family : fontPart[6] || 'sans-serif',
+            weight: fontPart[3] || 'normal',
+            decoration : fontPart[2] || 'normal',
+            href : null
+        };
+
+        //canvas doesn't support underline natively, but we can pass this attribute
+        if(this.__fontUnderline === "underline") {
+            data.decoration = "underline";
+        }
+
+        //canvas also doesn't support linking, but we can pass this as well
+        if(this.__fontHref) {
+            data.href = this.__fontHref;
+        }
+
+        return data;
+    };
+
+    /**
+     * Helper to link text fragments
+     * @param font
+     * @param element
+     * @return {*}
+     * @private
+     */
+    ctx.prototype.__wrapTextLink = function(font, element) {
+        if(font.href) {
+            var a = this.__createElement("a");
+            a.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", font.href);
+            a.appendChild(element);
+            return a;
+        }
+        return element;
+    };
+
+    /**
+     * Fills or strokes text
+     * @param text
+     * @param x
+     * @param y
+     * @param action - stroke or fill
+     * @private
+     */
+    ctx.prototype.__applyText = function(text, x, y, action) {
+        var font = this.__parseFont(),
+            parent = this.__closestGroupOrSvg(),
+            textElement = this.__createElement("text", {
+                "font-family" : font.family,
+                "font-size" : font.size,
+                "font-style" : font.style,
+                "font-weight" : font.weight,
+                "text-decoration" : font.decoration,
+                "x" : x,
+                "y" : y,
+                "text-anchor": getTextAnchor(this.textAlign),
+                "dominant-baseline": getDominantBaseline(this.textBaseline)
+            }, true);
+
+        textElement.appendChild(document.createTextNode(text));
+        this.__currentElement = textElement;
+        this.__applyStyleToCurrentElement(action);
+        parent.appendChild(this.__wrapTextLink(font,textElement));
+    };
+
+    /**
+     * Creates a text element
+     * @param text
+     * @param x
+     * @param y
+     */
+    ctx.prototype.fillText = function(text, x, y){
+        this.__applyText(text, x, y, "fill");
+    };
+
+    /**
+     * Strokes text
+     * @param text
+     * @param x
+     * @param y
+     */
+    ctx.prototype.strokeText = function(text, x, y){
+        this.__applyText(text, x, y, "stroke");
+    };
+
+    /**
+     * No need to implement this for svg.
+     * @param text
+     * @return {TextMetrics}
+     */
+    ctx.prototype.measureText = function(text){
+        this.__ctx.font = this.font;
+        return this.__ctx.measureText(text);
+    };
+
+    /**
+     *  Arc command!
+     */
+    ctx.prototype.arc = function(x, y, radius, startAngle, endAngle, counterClockwise) {
+        startAngle = startAngle % (2*Math.PI);
+        endAngle = endAngle % (2*Math.PI);
+        if(startAngle === endAngle) {
+            //circle time! subtract some of the angle so svg is happy (svg elliptical arc can't draw a full circle)
+            endAngle = ((endAngle + (2*Math.PI)) - 0.001 * (counterClockwise ? -1 : 1)) % (2*Math.PI);
+        }
+        var endX = x+radius*Math.cos(endAngle),
+            endY = y+radius*Math.sin(endAngle),
+            startX = x+radius*Math.cos(startAngle),
+            startY = y+radius*Math.sin(startAngle),
+            sweepFlag = counterClockwise ? 0 : 1,
+            largeArcFlag = 0,
+            diff = endAngle - startAngle;
+
+        // https://github.com/gliffy/canvas2svg/issues/4
+        if(diff < 0) {
+            diff += 2*Math.PI;
+        }
+
+        if(counterClockwise) {
+            largeArcFlag = diff > Math.PI ? 0 : 1;
+        } else {
+            largeArcFlag = diff > Math.PI ? 1 : 0;
+        }
+
+        this.lineTo(startX, startY);
+        this.__addPathCommand(format("A {rx} {ry} {xAxisRotation} {largeArcFlag} {sweepFlag} {endX} {endY}",
+            {rx:radius, ry:radius, xAxisRotation:0, largeArcFlag:largeArcFlag, sweepFlag:sweepFlag, endX:endX, endY:endY}));
+
+        this.__currentPosition = {x: endX, y: endY};
+    };
+
+    /**
+     * Generates a ClipPath from the clip command.
+     */
+    ctx.prototype.clip = function(){
+        var group = this.__closestGroupOrSvg(),
+            clipPath = this.__createElement("clipPath"),
+            id =  randomString(this.__ids),
+            newGroup = this.__createElement("g");
+
+        group.removeChild(this.__currentElement);
+        clipPath.setAttribute("id", id);
+        clipPath.appendChild(this.__currentElement);
+
+        this.__defs.appendChild(clipPath);
+
+        //set the clip path to this group
+        group.setAttribute("clip-path", format("url(#{id})", {id:id}));
+
+        //clip paths can be scaled and transformed, we need to add another wrapper group to avoid later transformations
+        // to this path
+        group.appendChild(newGroup);
+
+        this.__currentElement = newGroup;
+
+    };
+
+    /**
+     * Draws a canvas, image or mock context to this canvas.
+     * Note that all svg dom manipulation uses node.childNodes rather than node.children for IE support.
+     * http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-drawimage
+     */
+    ctx.prototype.drawImage = function(){
+        //convert arguments to a real array
+        var args = Array.prototype.slice.call(arguments),
+            image=args[0],
+            dx, dy, dw, dh, sx=0, sy=0, sw, sh, parent, svg, defs, group,
+            currentElement, svgImage, canvas, context, id;
+
+        if(args.length === 3) {
+            dx = args[1];
+            dy = args[2];
+            sw = image.width;
+            sh = image.height;
+            dw = sw;
+            dh = sh;
+        } else if(args.length === 5) {
+            dx = args[1];
+            dy = args[2];
+            dw = args[3];
+            dh = args[4];
+            sw = image.width;
+            sh = image.height;
+        } else if(args.length === 9) {
+            sx = args[1];
+            sy = args[2];
+            sw = args[3];
+            sh = args[4];
+            dx = args[5];
+            dy = args[6];
+            dw = args[7];
+            dh = args[8];
+        } else {
+            throw new Error("Inavlid number of arguments passed to drawImage: " + arguments.length);
+        }
+
+        parent = this.__closestGroupOrSvg();
+        currentElement = this.__currentElement;
+
+        if(image instanceof ctx) {
+            //canvas2svg mock canvas context. In the future we may want to clone nodes instead.
+            //also I'm currently ignoring dw, dh, sw, sh, sx, sy for a mock context.
+            svg = image.getSvg();
+            defs = svg.childNodes[0];
+            while(defs.childNodes.length) {
+                id = defs.childNodes[0].getAttribute("id");
+                this.__ids[id] = id;
+                this.__defs.appendChild(defs.childNodes[0]);
+            }
+            group = svg.childNodes[1];
+            parent.appendChild(group);
+            this.__currentElement = group;
+            this.translate(dx, dy);
+            this.__currentElement = currentElement;
+        } else if(image.nodeName === "CANVAS" || image.nodeName === "IMG") {
+            //canvas or image
+            svgImage = this.__createElement("image");
+            svgImage.setAttribute("width", dw);
+            svgImage.setAttribute("height", dh);
+            svgImage.setAttribute("preserveAspectRatio", "none");
+
+            if(sx || sy || sw !== image.width || sh !== image.height) {
+                //crop the image using a temporary canvas
+                canvas = document.createElement("canvas");
+                canvas.width = dw;
+                canvas.height = dh;
+                context = canvas.getContext("2d");
+                context.drawImage(image, sx, sy, sw, sh, 0, 0, dw, dh);
+                image = canvas;
+            }
+
+            svgImage.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href",
+                image.nodeName === "CANVAS" ? image.toDataURL() : image.getAttribute("src"));
+            parent.appendChild(svgImage);
+            this.__currentElement = svgImage;
+            this.translate(dx, dy);
+            this.__currentElement = currentElement;
+        }
+    };
+
+    /**
+     * Generates a pattern tag
+     */
+    ctx.prototype.createPattern = function(image, repetition){
+        var pattern = document.createElementNS("http://www.w3.org/2000/svg", "pattern"), id = randomString(this.__ids),
+            img;
+        pattern.setAttribute("id", id);
+        pattern.setAttribute("width", image.width);
+        pattern.setAttribute("height", image.height);
+        if(image.nodeName === "CANVAS" || image.nodeName === "IMG") {
+            img = document.createElementNS("http://www.w3.org/2000/svg", "image");
+            img.setAttribute("width", image.width);
+            img.setAttribute("height", image.height);
+            img.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href",
+                image.nodeName === "CANVAS" ? image.toDataURL() : image.getAttribute("src"));
+            pattern.appendChild(img);
+            this.__defs.appendChild(pattern);
+        } else if(image instanceof ctx) {
+            pattern.appendChild(image.__root.childNodes[1]);
+            this.__defs.appendChild(pattern);
+        }
+        return new CanvasPattern(pattern, this);
+    };
+
+    /**
+     * Not yet implemented
+     */
+    ctx.prototype.drawFocusRing = function(){};
+    ctx.prototype.createImageData = function(){};
+    ctx.prototype.getImageData = function(){};
+    ctx.prototype.putImageData = function(){};
+    ctx.prototype.globalCompositeOperation = function(){};
+    ctx.prototype.setTransform = function(){};
+
+    //add options for alternative namespace
+    module.exports = ctx;
+
+}());
+
+},{}],2:[function(require,module,exports){
+var C2S = require('./canvas2svg');
+
+var Context = function(width, height, options) {
+    C2S.call(this);
+    this.__width = width;
+    this.__height = height;
+    this.generations = [[]]; // used to collect element references for different generations
+
+    var _this = this;
+    this.__imageSmoothingEnabled = true;
+
+    ["mozImageSmoothingEnabled",
+     "webkitImageSmoothingEnabled",
+     "msImageSmoothingEnabled",
+     "imageSmoothingEnabled"].forEach(function(k) {
+         Object.defineProperty(_this, k, {
+             get: function() {
+                 return _this.__imageSmoothingEnabled;
+             },
+             set: function(val) {
+                 _this.__imageSmoothingEnabled = val;
+             }
+         });
+     });
+
+    options = options || {};
+
+    ["fillStyle", "strokeStyle"].forEach(function(prop) {
+        var key = "__" + prop;
+        Object.defineProperty(_this, prop, {
+            get: function() {
+                return _this[key];
+            },
+            set: function(val) {
+                if (val.indexOf('NaN') > -1) {
+                    console.warn("svgcanvas: invalid value for " + prop + ", fail to set it to " + val);
+                    return;
+                }
+                _this[key] = val;
+            }
+        });
+    });
+
+
+    if (options.debug) {
+        this.__history = []; // method history
+
+        var methods = [];
+        for(var key in this) {
+            if (typeof this[key] === "function") {
+                if (key.indexOf('__') !== 0) {
+                    if (key !== 'getSerializedSvg') {
+                        methods.push(key);
+                    }
+                }
+            }
+        }
+        ["__fillStyle", "__strokeStyle"].forEach(function(prop) {
+            var key = "__debug__" + prop;
+            Object.defineProperty(_this, prop, {
+                get: function() {
+                    return _this[key];
+                },
+                set: function(val) {
+                    var call = prop.replace(/__/g, '') + " = " + val;
+                    _this.__history.push(call);
+                    _this[key] = val;
+                }
+            });
+        });
+        methods.forEach(function(method) {
+            var fn = _this[method];
+            _this[method] = function() {
+                var call = method + '(' + Array.prototype.slice.call(arguments).join(', ') + ');';
+
+                // keep call history
+                _this.__history.push(call);
+                if (_this.__history.length > 100) {
+                    _this.__history.shift();
+                }
+
+                return fn.apply(_this, arguments);
+            };
+        });
+    }
+};
+
+Context.prototype = Object.create(C2S.prototype);
+
+Context.prototype.scale = function(x, y) {
+    if (x === undefined || y === undefined) {
+        return;
+    } else {
+        C2S.prototype.scale.apply(this, arguments);
+    }
+};
+
+Context.prototype.__createElement = function(elementName, properties, resetFill) {
+    if (!this.__imageSmoothingEnabled) {
+        // only shape elements can use the shape-rendering attribute
+        if (["circle", "ellipse", "line", "path", "polygon", "polyline", "rect"].indexOf(elementName) > -1) {
+            properties = properties || {};
+            properties["shape-rendering"] = "crispEdges"; // disable anti-aliasing
+        }
+    }
+
+    var element = C2S.prototype.__createElement.call(this, elementName, properties, resetFill);
+    var currentGeneration = this.generations[this.generations.length - 1];
+    currentGeneration.push(element);
+    return element;
+};
+
+Context.prototype.__gc = function() {
+    this.generations.push([]);
+    var ctx = this;
+    // make sure it happens after current job done
+    // for example: in p5.js's redraw use setTimeout will make gc called after both save() and restore() called
+    setTimeout(function() {
+        if (ctx.__groupStack.length > 0) {
+            // we are between ctx.save() and ctx.restore(), skip gc
+            return;
+        }
+        if (ctx.__currentElement.nodeName === 'path') {
+            // we are still in path, skip gc
+            return;
+        }
+        // keep only latest generation
+        while (ctx.generations.length > 1) {
+            var elements = ctx.generations.shift();
+            var lastCount = 0;
+            var count = elements.length;
+            while (count > 0) {
+                lastCount = count;
+                elements = elements.filter(function(elem) {
+                    // in case children may from live generation, gc from bottom to top
+                    var children = elem.children || elem.childNodes; // childNodes for IE
+                    if (children.length === 0) {
+                        elem.parentNode.removeChild(elem);
+                        return false;
+                    } else {
+                        return true;
+                    }
+                });
+                count = elements.length;
+                if (count === lastCount) {
+                    // could not gc more, exit now
+                    // save this elements to live generation
+                    var liveGeneration = ctx.generations[ctx.generations.length - 1];
+                    elements.forEach(function(elem) {
+                        liveGeneration.push(elem);
+                    });
+                    // exit
+                    break;
+                }
+            }
+        }
+    }, 0);
+};
+
+Context.prototype.clearRect = function(x, y, w, h) {
+    if (x === 0 && y === 0 && w === this.__width && h === this.__height) {
+        // remove all
+        this.generations.forEach(function(elems) {
+            elems.forEach(function(elem) {
+                if (elem) {
+                    elem.parentNode.removeChild(elem);
+                }
+            });
+        });
+        this.generations = [[]];
+        var g = this.__createElement('g');
+        this.__root.appendChild(g);
+        this.__currentElement = g;
+    } else {
+        C2S.prototype.clearRect.call(this, x, y, w, h);
+    }
+};
+
+Context.prototype.fillRect = function(x, y, w, h) {
+    if (x === 0 && y === 0 && w === this.__width && h === this.__height) {
+        this.__gc();
+    }
+    C2S.prototype.fillRect.call(this, x, y, w, h);
+};
+
+// Simple version of drawImage
+// Note that this version does not handle drawing mock context
+Context.prototype.drawImage = function() {
+    var canvas = document.createElement('canvas');
+    canvas.width = this.__width;
+    canvas.height = this.__height;
+    var args = arguments;
+    var ctx = canvas.getContext('2d');
+    ctx.drawImage.apply(ctx, args);
+    // Note: don't use foreign object,
+    // otherwise the saved SVG may be unusable for other application
+    var url = canvas.toDataURL('image/png');
+    var image = this.__createElement('image', {
+        x: 0,
+        y: 0,
+        width: canvas.width,
+        height: canvas.height,
+        preserveAspectRatio: 'none'
+    });
+    var parent = this.__closestGroupOrSvg();
+    image.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", url);
+    parent.appendChild(image);
+};
+
+Context.prototype.getSerializedSvg = null;
+
+module.exports = Context;
+
+},{"./canvas2svg":1}],3:[function(require,module,exports){
+var Context = require('./context');
+
+function SVGCanvas(options) {
+
+    var debug = options && options.debug;
+
+    this.ctx = new Context(100, 100, {debug: debug});
+    this.svg = this.ctx.__root;
+
+    // sync attributes to svg
+    var svg = this.svg;
+    var _this = this;
+
+    var wrapper = document.createElement('div');
+    wrapper.style.display = 'inline-block';
+    wrapper.appendChild(svg);
+    this.wrapper = wrapper;
+
+    Object.defineProperty(this, 'className', {
+        get: function() {
+            return wrapper.getAttribute('class') || '';
+        },
+        set: function(val) {
+            return wrapper.setAttribute('class', val);
+        }
+    });
+
+    ["width", "height"].forEach(function(prop) {
+        Object.defineProperty(_this, prop, {
+            get: function() {
+                return svg.getAttribute(prop) | 0;
+            },
+            set: function(val) {
+                if (isNaN(val) || (typeof val === "undefined")) {
+                    return;
+                }
+                _this.ctx['__'+prop] = val;
+                svg.setAttribute(prop, val);
+                return wrapper[prop] = val;
+            }
+        });
+    });
+
+    ["style", "id"].forEach(function(prop) {
+        Object.defineProperty(_this, prop, {
+            get: function() {
+                return wrapper[prop];
+            },
+            set: function(val) {
+                if (typeof val !== "undefined") {
+                    return wrapper[prop] = val;
+                }
+            }
+        });
+    });
+
+    ["getBoundingClientRect"].forEach(function(fn) {
+        _this[fn] = function() {
+            return svg[fn]();
+        };
+    });
+}
+
+SVGCanvas.prototype.getContext = function(type) {
+    if (type !== '2d') {
+        throw new Error('Unsupported type of context for SVGCanvas');
+    }
+
+    return this.ctx;
+};
+
+// you should always use URL.revokeObjectURL after your work done
+SVGCanvas.prototype.toObjectURL = function() {
+    var data = new XMLSerializer().serializeToString(this.svg);
+    var svg = new Blob([data], {type: 'image/svg+xml;charset=utf-8'});
+    return URL.createObjectURL(svg);
+};
+
+SVGCanvas.prototype.toDataURL = function(type, options) {
+    var xml = new XMLSerializer().serializeToString(this.svg);
+
+    // documentMode is an IE-only property
+    // http://msdn.microsoft.com/en-us/library/ie/cc196988(v=vs.85).aspx
+    // http://stackoverflow.com/questions/10964966/detect-ie-version-prior-to-v9-in-javascript
+    var isIE = document.documentMode;
+
+    if (isIE) {
+        // This is patch from canvas2svg
+        // IE search for a duplicate xmnls because they didn't implement setAttributeNS correctly
+        var xmlns = /xmlns="http:\/\/www\.w3\.org\/2000\/svg".+xmlns="http:\/\/www\.w3\.org\/2000\/svg/gi;
+        if(xmlns.test(xml)) {
+            xml = xml.replace('xmlns="http://www.w3.org/2000/svg','xmlns:xlink="http://www.w3.org/1999/xlink');
+        }
+    }
+
+    var SVGDataURL = "data:image/svg+xml;charset=utf-8," + encodeURIComponent(xml);
+    if (type === "image/svg+xml" || !type) {
+        return SVGDataURL;
+    }
+    if (type === "image/jpeg" || type === "image/png") {
+        var canvas = document.createElement('canvas');
+        canvas.width = this.width;
+        canvas.height = this.height;
+        var ctx = canvas.getContext('2d');
+        var img = new Image();
+        img.src = SVGDataURL;
+        if (img.complete && img.width > 0 && img.height > 0) {
+            // for chrome, it's ready immediately
+            ctx.drawImage(img, 0, 0);
+            return canvas.toDataURL(type, options);
+        } else {
+            // for firefox, it's not possible to provide sync api in current thread
+            // and web worker doesn't provide canvas API, so
+            throw new Error('svgcanvas.toDataURL() for jpeg/png is only available in Chrome.');
+        }
+    }
+    throw new Error('Unknown type for SVGCanvas.prototype.toDataURL, please use image/jpeg | image/png | image/svg+xml.');
+};
+
+// will return wrapper element: <div><svg></svg></div>
+SVGCanvas.prototype.getElement = function() {
+    return this.wrapper;
+};
+
+module.exports = SVGCanvas;
+
+},{"./context":2}],4:[function(require,module,exports){
+var constants = {
+    SVG: 'svg'
+};
+
+module.exports = constants;
+
+},{}],5:[function(require,module,exports){
+module.exports = function(p5) {
+    /**
+     * Returns an Array of SVGElements of current SVG Graphics matching given selector
+     *
+     * @function querySVG
+     * @memberof p5.prototype
+     * @param {String} selector CSS selector for query
+     * @returns {SVGElement[]}
+     */
+    p5.prototype.querySVG = function(selector) {
+        var svg = this._renderer && this._renderer.svg;
+        if (!svg) {
+            return null;
+        }
+        return p5.SVGElement.prototype.query.call({elt: svg}, selector);
+    };
+
+    /**
+     * @namespace SVGElement
+     * @constructor
+     * @param {Element} element
+     */
+    function SVGElement(element) {
+        if (!element) {
+            return null;
+        }
+        return p5.Element.apply(this, arguments);
+    }
+
+    SVGElement.prototype = Object.create(p5.Element.prototype);
+
+    /**
+     * Returns an Array of children of current SVG Element matching given selector
+     *
+     * @function query
+     * @memberof SVGElement.prototype
+     * @param {String} selector CSS selector for query
+     * @returns {SVGElement[]}
+     */
+    SVGElement.prototype.query = function(selector) {
+        var elements = this.elt.querySelectorAll(selector);
+        var objects = [];
+        for (var i = 0; i < elements.length; i++) {
+            objects[i] = new SVGElement(elements[i]);
+        }
+        return objects;
+    };
+
+    /**
+     * Append a new child to current element.
+     *
+     * @function append
+     * @memberof SVGElement.prototype
+     * @param {SVGElement|Element} element
+     */
+    SVGElement.prototype.append = function(element) {
+        var elt = element.elt || element;
+        this.elt.appendChild(elt);
+        return this;
+    };
+
+    /**
+     * Apply different attribute operation based on arguments.length
+     * <ul>
+     *     <li>setAttribute(name, value)</li>
+     *     <li>setAttributeNS(namespace, name, value)</li>
+     *     <li>getAttribute(name)</li>
+     * </ul>
+     *
+     * @function attribute
+     * @memberof SVGElement.prototype
+     */
+    SVGElement.prototype.attribute = function() {
+        var args = arguments;
+        if (args.length === 3) {
+            this.elt.setAttributeNS.apply(this.elt, args);
+        }
+        if (args.length === 2) {
+            this.elt.setAttribute.apply(this.elt, args);
+        }
+        if (args.length === 1) {
+            return this.elt.getAttribute.apply(this.elt, args);
+        }
+        return this;
+    };
+
+    /**
+     * Apply filter on current element.
+     * If called multiple times,
+     * these filters will be chained together and combine to a bigger SVG filter.
+     *
+     * @function filter
+     * @memberof SVGElement.prototype
+     * @param {String} filter BLUR, GRAY, INVERT, THRESHOLD, OPAQUE, ERODE, DILATE (defined in p5's constants)
+     * @param {Any} argument Argument for that filter
+     */
+    SVGElement.prototype.filter = function(filter, arg) {
+        p5.SVGFilters.apply(this, filter, arg);
+        return this;
+    };
+
+    /**
+     * Remove applied filter on current element
+     * After called, rest filters will be chained together
+     * and combine to a new SVG filter.
+     *
+     * @function unfilter
+     * @memberof SVGElement.prototype
+     * @param {String} filter BLUR, GRAY, INVERT, THRESHOLD, OPAQUE, ERODE, DILATE (defined in p5's constants)
+     * @param {Any} argument Argument for that filter
+     */
+    SVGElement.prototype.unfilter = function(filterName, arg) {
+        var filters = this.attribute('data-p5-svg-filters') || '[]';
+        filters = JSON.parse(filters);
+        if (arg === undefined) {
+            arg = null;
+        }
+        var found = false;
+        filters = filters.reverse().filter(function(filter) {
+            if ((filter[0] === filterName) && (filter[1] === arg) && !found) {
+                found = true;
+                return false;
+            }
+            return true;
+        }).reverse();
+        this.attribute('data-p5-svg-filters', JSON.stringify(filters));
+        p5.SVGFilters.apply(this, null);
+        return this;
+    };
+
+    /**
+     * Create SVGElement
+     *
+     * @function create
+     * @memberof SVGElement
+     * @param {String} nodeName
+     * @param {Object} [attributes] Attributes for the element
+     * @return {SVGElement}
+     */
+    SVGElement.create = function(nodeName, attributes) {
+        attributes = attributes || {};
+        var elt = document.createElementNS('http://www.w3.org/2000/svg', nodeName);
+        Object.keys(attributes).forEach(function(k) {
+            elt.setAttribute(k, attributes[k]);
+        });
+        return new SVGElement(elt);
+    };
+
+    /**
+     * Tell if current element matching given selector.
+     * This is polyfill from MDN.
+     *
+     * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/matches
+     *
+     * @function matches
+     * @memberof SVGElement.prototype
+     * @param {String} selector CSS Selector
+     * @return {Bool}
+     */
+    SVGElement.prototype.matches = function(selector) {
+        var element = this.elt;
+        var matches = (element.document || element.ownerDocument).querySelectorAll(selector);
+        var i = 0;
+        while (matches[i] && matches[i] !== element) {
+            i++;
+        }
+        return matches[i] ? true : false;
+    };
+
+    /**
+     * Get defs element, or create one if not exists
+     *
+     * @private
+     */
+    SVGElement.prototype._getDefs = function() {
+        var svg = this.parentNode('svg');
+        var defs = svg.query('defs');
+        if (defs[0]) {
+            defs = defs[0];
+        } else {
+            defs = SVGElement.create('defs');
+            svg.append(defs);
+        }
+        return defs;
+    };
+
+    /**
+     * Get parentNode.
+     * If selector not given, returns parentNode.
+     * Otherwise, will look up all ancestors,
+     * and return closest element matching given selector,
+     * or return null if not found.
+     *
+     * @function parentNode
+     * @memberof SVGElement.prototype
+     * @param {String} [selector] CSS Selector
+     * @return {SVGElement}
+     */
+    SVGElement.prototype.parentNode = function(selector) {
+        if (!selector) {
+            return new SVGElement(this.elt.parentNode);
+        }
+        var elt = this;
+        while (elt) {
+            elt = this.parentNode();
+            if (elt && elt.matches(selector)) {
+                return elt;
+            }
+        }
+        return null;
+    };
+
+    p5.SVGElement = SVGElement;
+};
+
+},{}],6:[function(require,module,exports){
+// SVG Filter
+
+module.exports = function(p5) {
+    var _filter = p5.prototype.filter;
+
+    var SVGFilters = require('./p5.SVGFilters')(p5);
+
+    /**
+     * Register a custom SVG Filter
+     *
+     * @function registerSVGFilter
+     * @memberof p5.prototype
+     * @param {String} name Name for Custom SVG filter
+     * @param {Function} filterFunction filterFunction(inGraphicsName, resultGraphicsName, value)
+     *                                  should return SVGElement or Array of SVGElement.
+     * @example
+     * registerSVGFilter('myblur', function(inGraphicsName, resultGraphicsName, value) {
+     *     return SVGElement.create('feGaussianBlur', {
+     *         stdDeviation: val,
+     *         in: inGraphics,
+     *         result: resultGraphics,
+     *         'color-interpolation-filters': 'sRGB'
+     *     });
+     * });
+     * filter('myblur', 5);
+     */
+    p5.prototype.registerSVGFilter = function(name, fn) {
+        SVGFilters[name] = fn;
+    };
+
+    p5.prototype.filter = function(operation, value) {
+        var svg = this._renderer.svg;
+        if (svg) {
+            // move nodes to a new <g>
+            var nodes = svg.children || svg.childNodes; // childNodes is for IE
+            var g = p5.SVGElement.create('g');
+            this._renderer._setGCFlag(g.elt);
+            svg.appendChild(g.elt);
+            // convert nodeList to array and use forEach
+            // instead of using for loop,
+            // which is buggy due to the length changed during append
+            nodes = Array.prototype.slice.call(nodes);
+            nodes.forEach(function(node) {
+                if (node !== g.elt && (node.nodeName.toLowerCase() !== 'defs')) {
+                    g.elt.appendChild(node);
+                }
+            });
+
+            // apply filter
+            g.filter(operation, value);
+
+            // create new <g> so that new element won't be influenced by the filter
+            g = p5.SVGElement.create('g');
+            this._renderer._setGCFlag(g.elt);
+            this._renderer.svg.appendChild(g.elt);
+            this._renderer.drawingContext.__currentElement = g.elt;
+        } else {
+            _filter.apply(this, arguments);
+        }
+    };
+};
+
+},{"./p5.SVGFilters":10}],7:[function(require,module,exports){
+module.exports = function(p5) {
+    /**
+     * @namespace p5
+     */
+    require('./p5.RendererSVG')(p5);
+    require('./rendering')(p5);
+    require('./io')(p5);
+    require('./element')(p5);
+    require('./filters')(p5);
+
+    // attach constants to p5 instance
+    var constants = require('./constants');
+    Object.keys(constants).forEach(function(k) {
+        p5.prototype[k] = constants[k];
+    });
+};
+
+},{"./constants":4,"./element":5,"./filters":6,"./io":8,"./p5.RendererSVG":9,"./rendering":11}],8:[function(require,module,exports){
+module.exports = function(p5) {
+    /**
+     * Convert SVG Element to jpeg / png data url
+     *
+     * @private
+     * @param {SVGElement} svg SVG Element
+     * @param {String} mine Mine
+     * @param {Function} callback
+     */
+    var svg2img = function(svg, mine, callback) {
+        svg = (new XMLSerializer()).serializeToString(svg);
+        svg = 'data:image/svg+xml;charset=utf-8,' + encodeURI(svg);
+        if (mine == 'image/svg+xml') {
+            callback(null, svg);
+            return;
+        }
+        var img = new Image();
+        var canvas = document.createElement('canvas');
+        var ctx = canvas.getContext('2d');
+        img.onload = function() {
+            canvas.width = img.width;
+            canvas.height = img.height;
+            ctx.drawImage(img, 0, 0);
+            var dataURL = canvas.toDataURL(mine);
+            callback(null, dataURL);
+        };
+        img.src = svg;
+    };
+
+    /**
+     * Get SVG frame, and convert to target type
+     *
+     * @private
+     * @param {Object} options
+     * @param {SVGElement} options.svg SVG Element, defaults to current svg element
+     * @param {String} options.filename
+     * @param {String} options.ext Extension: 'svg' or 'jpg' or 'jpeg' or 'png'
+     * @param {Function} options.callback
+     */
+    p5.prototype._makeSVGFrame = function(options) {
+        var filename = options.filename || 'untitled';
+        var ext = options.extension;
+        ext = ext || this._checkFileExtension(filename, ext)[1];
+        var regexp = new RegExp('\\.' + ext + '$');
+        filename = filename.replace(regexp, '');
+        if (ext === '') {
+            ext = 'svg';
+        }
+        var mine = {
+            png: 'image/png',
+            jpeg: 'image/jpeg',
+            jpg: 'image/jpeg',
+            svg: 'image/svg+xml'
+        }[ext];
+        if (!mine) {
+            throw new Error('Fail to getFrame, invalid extension: ' + ext + ', please use png | jpeg | jpg | svg.');
+        }
+
+        var svg = options.svg || this._renderer.svg;
+        svg2img(svg, mine, function(err, dataURL) {
+            var downloadMime = 'image/octet-stream';
+            dataURL = dataURL.replace(mine, downloadMime);
+            options.callback(err, {
+                imageData: dataURL,
+                filename: filename,
+                ext: ext
+            });
+        });
+    };
+
+    /**
+     * Save the current SVG as an image. In Safari, will open the
+     * image in the window and the user must provide their own
+     * filename on save-as. Other browsers will either save the
+     * file immediately, or prompt the user with a dialogue window.
+     *
+     * @function saveSVG
+     * @memberof p5.prototype
+     * @param {Graphics|Element|SVGElement} [svg] Source to save
+     * @param {String} [filename]
+     * @param {String} [extension] Extension: 'svg' or 'jpg' or 'jpeg' or 'png'
+     */
+    p5.prototype.saveSVG = function() {
+        // don't use slice on arguments because it prevents optimizations
+        var args = arguments;
+        args = [args[0], args[1], args[2]];
+
+        var svg;
+
+        if (args[0] instanceof p5.Graphics) {
+            svg = args[0]._renderer.svg;
+            args.shift();
+        }
+
+        if (args[0] && args[0].elt) {
+            svg = args[0].elt;
+            args.shift();
+        }
+
+        if (typeof args[0] == 'object') {
+            svg = args[0];
+            args.shift();
+        }
+
+        var filename = args[0];
+        var ext = args[1];
+
+        var p = this;
+        this._makeSVGFrame({
+            svg: svg,
+            filename: filename,
+            extension: ext,
+            callback: function(err, frame) {
+                p.downloadFile(frame.imageData, frame.filename, frame.ext);
+            }
+        });
+    };
+
+    /**
+     * Extends p5's saveFrames with SVG support
+     *
+     * @function saveFrames
+     * @memberof p5.prototype
+     * @param {String} filename filename
+     * @param {String} extension Extension: 'svg' or 'jpg' or 'jpeg' or 'png'
+     * @param {Number} duration duration
+     * @param {Number} fps fps
+     * @param {Function} callback callback
+     */
+    var _saveFrames = p5.prototype.saveFrames;
+    p5.prototype.saveFrames = function(filename, extension, duration, fps, callback) {
+        var args = arguments;
+
+        if (!this._renderer.svg) {
+            _saveFrames.apply(this, args);
+            return;
+        }
+
+        duration = duration || 3;
+        duration = p5.prototype.constrain(duration, 0, 15);
+        duration = duration * 1000;
+        fps = fps || 15;
+        fps = p5.prototype.constrain(fps, 0, 22);
+        var count = 0;
+
+        var frames = [];
+        var pending = 0;
+
+        var p = this;
+        var frameFactory = setInterval(function () {
+            (function(count) {
+                pending++;
+                p._makeSVGFrame({
+                    filename: filename + count,
+                    extension: extension,
+                    callback: function(err, frame) {
+                        frames[count] = frame;
+                        pending--;
+                    }
+                });
+            })(count);
+            count++;
+        }, 1000 / fps);
+
+        var done = function() {
+            if (pending > 0) {
+                setTimeout(function() {
+                    done();
+                }, 10);
+                return;
+            }
+            if (callback) {
+                callback(frames);
+            } else {
+                frames.forEach(function(f) {
+                    p.downloadFile(f.imageData, f.filename, f.ext);
+                });
+            }
+        };
+
+        setTimeout(function () {
+            clearInterval(frameFactory);
+            done();
+        }, duration + 0.01);
+    };
+
+    /**
+     * Extends p5's save method with SVG support
+     *
+     * @function save
+     * @memberof p5.prototype
+     * @param {Graphics|Element|SVGElement} [source] Source to save
+     * @param {String} [filename] filename
+     */
+    var _save = p5.prototype.save;
+    p5.prototype.save = function() {
+        var args = arguments;
+        args = [args[0], args[1]];
+
+        var svg;
+
+        if (args[0] instanceof p5.Graphics) {
+            var svgcanvas = args[0].elt;
+            svg = svgcanvas.svg;
+            args.shift();
+        }
+
+        if (args[0] && args[0].elt) {
+            svg = args[0].elt;
+            args.shift();
+        }
+
+        if (typeof args[0] == 'object') {
+            svg = args[0];
+            args.shift();
+        }
+
+        svg = svg || (this._renderer && this._renderer.svg);
+
+        var filename = args[0];
+        var supportedExtensions = ['jpeg', 'png', 'jpg', 'svg', ''];
+        var ext = this._checkFileExtension(filename, '')[1];
+
+        var useSVG = svg && svg.nodeName && svg.nodeName.toLowerCase() === 'svg' && supportedExtensions.indexOf(ext) > -1;
+
+        if (useSVG) {
+            this.saveSVG(svg, filename);
+        } else {
+            return _save.apply(this, arguments);
+        }
+    };
+
+    /**
+     * Custom get in p5.svg (handles http and dataurl)
+     * @private
+     */
+    p5.prototype._svg_get = function(path, successCallback, failureCallback) {
+        if (path.indexOf('data:') === 0) {
+            if (path.indexOf(',') === -1) {
+                failureCallback(new Error('Fail to parse dataurl: ' + path));
+                return;
+            }
+            var svg = path.split(',').pop();
+            // force request to dataurl to be async
+            // so that it won't make preload mess
+            setTimeout(function() {
+                if (path.indexOf(';base64,') > -1) {
+                    svg = atob(svg);
+                } else {
+                    svg = decodeURIComponent(svg);
+                }
+                successCallback(svg);
+            }, 1);
+            return svg;
+        } else {
+            this.httpGet(path, successCallback);
+            return null;
+        }
+    };
+
+    /**
+     * loadSVG (like loadImage, but will return SVGElement)
+     *
+     * @function loadSVG
+     * @memberof p5.prototype
+     * @returns {p5.SVGElement}
+     */
+    p5.prototype.loadSVG = function(path, successCallback, failureCallback) {
+        var div = document.createElement('div');
+        var element = new p5.SVGElement(div);
+        this._svg_get(path, function(svg) {
+            div.innerHTML = svg;
+            svg = div.querySelector('svg');
+            if (!svg) {
+                if (failureCallback) {
+                    failureCallback(new Error('Fail to create <svg>.'));
+                }
+                return;
+            }
+            element.elt = svg;
+            if (successCallback) {
+                successCallback(element);
+            }
+        }, failureCallback);
+        return element;
+    };
+    // cause preload to wait
+    p5.prototype._preloadMethods.loadSVG = p5.prototype;
+
+    p5.prototype.getDataURL = function() {
+        return this._renderer.elt.toDataURL('image/svg+xml');
+    };
+};
+
+},{}],9:[function(require,module,exports){
+var SVGCanvas = require('svgcanvas');
+
+module.exports = function(p5) {
+    /**
+     * @namespace RendererSVG
+     * @constructor
+     * @param {Element} elt canvas element to be replaced
+     * @param {p5} pInst p5 Instance
+     * @param {Bool} isMainCanvas
+     */
+    function RendererSVG(elt, pInst, isMainCanvas) {
+        var svgCanvas = new SVGCanvas();
+        var svg = svgCanvas.svg;
+
+        // replace <canvas> with <svg> and copy id, className
+        var parent = elt.parentNode;
+        var id = elt.id;
+        var className = elt.className;
+        parent.replaceChild(svgCanvas.getElement(), elt);
+        svgCanvas.id = id;
+        svgCanvas.className = className;
+        elt = svgCanvas; // our fake <canvas>
+
+        elt.parentNode = {
+            // fake parentNode.removeChild so that noCanvas will work
+            removeChild: function(element) {
+                if (element === elt) {
+                    var wrapper = svgCanvas.getElement();
+                    wrapper.parentNode.removeChild(wrapper);
+                }
+            }
+        };
+
+        p5.Renderer2D.call(this, elt, pInst, isMainCanvas);
+
+        this.isSVG = true;
+        this.svg = svg;
+
+        return this;
+    }
+
+    RendererSVG.prototype = Object.create(p5.Renderer2D.prototype);
+
+    RendererSVG.prototype._applyDefaults = function() {
+        p5.Renderer2D.prototype._applyDefaults.call(this);
+        this.drawingContext.lineWidth = 1;
+    };
+
+    RendererSVG.prototype.line = function(x1, y1, x2, y2) {
+        var styleEmpty = 'rgba(0,0,0,0)';
+        var ctx = this.drawingContext;
+        if (!this._doStroke) {
+            return this;
+        } else if(ctx.strokeStyle === styleEmpty){
+            return this;
+        }
+        ctx.beginPath();
+        ctx.moveTo(x1, y1);
+        ctx.lineTo(x2, y2);
+        ctx.stroke();
+        return this;
+    };
+
+    RendererSVG.prototype.resize = function(w, h) {
+        if (!w || !h) {
+            // ignore invalid values for width and height
+            return;
+        }
+        if (this.width !== w || this.height !== h) {
+            // canvas will be cleared if its size changed
+            // so, we do same thing for SVG
+            // note that at first this.width and this.height is undefined
+            // so, also check that
+            if (this.width && this.height) {
+                this.drawingContext.clearRect(0, 0, this.width, this.height);
+            }
+        }
+        this._withPixelDensity(function() {
+            p5.Renderer2D.prototype.resize.call(this, w, h);
+        });
+        // For scale, crop
+        // see also: http://sarasoueidan.com/blog/svg-coordinate-systems/
+        this.svg.setAttribute('viewBox', [0, 0, w, h].join(' '));
+    };
+
+    /**
+     * @private
+     */
+    RendererSVG.prototype._withPixelDensity = function(fn) {
+        var pixelDensity = this._pInst.pixelDensity;
+        this._pInst.pixelDensity = 1; // 1 is OK for SVG
+        fn.apply(this);
+        this._pInst.pixelDensity = pixelDensity;
+    };
+
+    RendererSVG.prototype.background = function() {
+        var args = arguments;
+        this._withPixelDensity(function() {
+            p5.Renderer2D.prototype.background.apply(this, args);
+        });
+    };
+
+    RendererSVG.prototype.resetMatrix = function() {
+        this._withPixelDensity(function() {
+            p5.Renderer2D.prototype.resetMatrix.apply(this);
+        });
+    };
+
+    /**
+     * set gc flag for svgcanvas
+     *
+     * @private
+     */
+    RendererSVG.prototype._setGCFlag = function(element) {
+        var that = this.drawingContext;
+        var currentGeneration = that.generations[that.generations.length - 1];
+        currentGeneration.push(element);
+    };
+
+    /**
+     * Append a element to current SVG Graphics
+     *
+     * @function appendChild
+     * @memberof RendererSVG.prototype
+     * @param {SVGElement|Element} element
+     */
+    RendererSVG.prototype.appendChild = function(element) {
+        if (element && element.elt) {
+            element = element.elt;
+        }
+        this._setGCFlag(element);
+        var g = this.drawingContext.__closestGroupOrSvg();
+        g.appendChild(element);
+    };
+
+    /**
+     * Draw an image or SVG to current SVG Graphics
+     *
+     * @function image
+     * @memberof RendererSVG.prototype
+     * @param {p5.Graphics|SVGGraphics|SVGElement|Element} image
+     * @param {Number} x
+     * @param {Number} y
+     * @param {Number} width
+     * @param {Number} height
+     */
+    RendererSVG.prototype.image = function(img, x, y, w, h) {
+        if (!img) {
+            throw new Error('Invalid image: ' + img);
+        }
+        var elt = img._renderer && img._renderer.svg; // handle SVG Graphics
+        elt = elt || (img.elt && img.elt.nodeName && (img.elt.nodeName.toLowerCase() === 'svg') && img.elt); // SVGElement
+        elt = elt || (img.nodeName && (img.nodeName.toLowerCase() == 'svg') && img); // <svg>
+        if (elt) {
+            // it's <svg> element, let's handle it
+            elt = elt.cloneNode(true);
+            elt.setAttribute('width', w);
+            elt.setAttribute('height', h);
+            elt.setAttribute('x', x);
+            elt.setAttribute('y', y);
+            this.appendChild(elt);
+        } else {
+            p5.Renderer2D.prototype.image.apply(this, arguments);
+        }
+    };
+
+    p5.RendererSVG = RendererSVG;
+};
+
+},{"svgcanvas":3}],10:[function(require,module,exports){
+module.exports = function(p5) {
+    var SVGFilters = function() {};
+
+    var SVGElement = p5.SVGElement;
+
+    var generateID = function() {
+        return Date.now().toString() + Math.random().toString().replace(/0\./, '');
+    };
+
+    // @private
+    // We have to build a filter for each element
+    // the `filter: f1 f2` and svg param is not supported by many browsers
+    // so we can just modify the filter def to do so
+    SVGFilters.apply = function(svgElement, func, arg) {
+        // get filters
+        var filters = svgElement.attribute('data-p5-svg-filters') || '[]';
+        filters = JSON.parse(filters);
+        if (func) {
+            filters.push([func, arg]);
+        }
+        svgElement.attribute('data-p5-svg-filters', JSON.stringify(filters));
+
+        if (filters.length === 0) {
+            svgElement.attribute('filter', null);
+            return;
+        }
+
+        // generate filters chain
+        filters = filters.map(function(filter, index) {
+            var inGraphics = index === 0 ? 'SourceGraphic' : ('result-' + (index - 1));
+            var resultGraphics = 'result-' + index;
+            return SVGFilters[filter[0]].call(null, inGraphics, resultGraphics, filter[1]);
+        });
+
+        // get filter id for this element or create one
+        var filterid = svgElement.attribute('data-p5-svg-filter-id');
+        if (!filterid) {
+            filterid = 'p5-svg-' + generateID();
+            svgElement.attribute('data-p5-svg-filter-id', filterid);
+        }
+        // Note that when filters is [], we will remove filter attr
+        // So, here, we write this attr every time
+        svgElement.attribute('filter', 'url(#' + filterid + ')');
+
+        // create <filter>
+        var filter = SVGElement.create('filter', {id: filterid});
+        filters.forEach(function(elt) {
+            if (!Array.isArray(elt)) {
+                elt = [elt];
+            }
+            elt.forEach(function(elt) {
+                filter.append(elt);
+            });
+        });
+
+        // get defs
+        var defs = svgElement._getDefs();
+        var oldfilter = defs.query('#' + filterid)[0];
+        if (!oldfilter) {
+            defs.append(filter);
+        } else {
+            oldfilter.elt.parentNode.replaceChild(filter.elt, oldfilter.elt);
+        }
+    };
+
+    SVGFilters.blur = function(inGraphics, resultGraphics, val) {
+        return SVGElement.create('feGaussianBlur', {
+            stdDeviation: val,
+            in: inGraphics,
+            result: resultGraphics,
+            'color-interpolation-filters': 'sRGB'
+        });
+    };
+
+    // See also: http://www.w3.org/TR/SVG11/filters.html#feColorMatrixElement
+    // See also: http://stackoverflow.com/questions/21977929/match-colors-in-fecolormatrix-filter
+    SVGFilters.colorMatrix = function(inGraphics, resultGraphics, matrix) {
+        return SVGElement.create('feColorMatrix', {
+            type: 'matrix',
+            values: matrix.join(' '),
+            'color-interpolation-filters': 'sRGB',
+            in: inGraphics,
+            result: resultGraphics
+        });
+    };
+
+    // Here we use CIE luminance for RGB
+    SVGFilters.gray = function(inGraphics, resultGraphics) {
+        var matrix = [
+            0.2126, 0.7152, 0.0722, 0, 0, // R'
+            0.2126, 0.7152, 0.0722, 0, 0, // G'
+            0.2126, 0.7152, 0.0722, 0, 0, // B'
+            0, 0, 0, 1, 0 // A'
+        ];
+        return SVGFilters.colorMatrix(inGraphics, resultGraphics, matrix);
+    };
+
+    SVGFilters.threshold = function(inGraphics, resultGraphics, val) {
+        var elements = [];
+        elements.push(SVGFilters.gray(inGraphics, resultGraphics + '-tmp'));
+        var componentTransfer = SVGElement.create('feComponentTransfer', {
+            'in': resultGraphics + '-tmp',
+            result: resultGraphics
+        });
+        var thresh = Math.floor(val * 255);
+        ['R', 'G', 'B'].forEach(function(channel) {
+            // Note that original value is from 0 to 1
+            var func = SVGElement.create('feFunc' + channel, {
+                type: 'linear',
+                slope: 255, // all non-zero * 255
+                intercept: (thresh - 1) * -1
+            });
+            componentTransfer.append(func);
+        });
+        elements.push(componentTransfer);
+        return elements;
+    };
+
+    SVGFilters.invert = function(inGraphics, resultGraphics) {
+        var matrix = [
+            -1, 0, 0, 0, 1,
+            0, -1, 0, 0, 1,
+            0, 0, -1, 0, 1,
+            0, 0, 0, 1, 0
+        ];
+        return SVGFilters.colorMatrix(inGraphics, resultGraphics, matrix);
+    };
+
+    SVGFilters.opaque = function(inGraphics, resultGraphics) {
+        var matrix = [
+            1, 0, 0, 0, 0, // original R
+            0, 1, 0, 0, 0, // original G
+            0, 0, 1, 0, 0, // original B
+            0, 0, 0, 0, 1 // set A to 1
+        ];
+        return SVGFilters.colorMatrix(inGraphics, resultGraphics, matrix);
+    };
+
+    /**
+     * Generate discrete table values based on the given color map function
+     *
+     * @private
+     * @param {Function} fn - Function to map channel values (val ∈ [0, 255])
+     * @see http://www.w3.org/TR/SVG/filters.html#feComponentTransferElement
+     */
+    SVGFilters._discreteTableValues = function(fn) {
+        var table = [];
+        for (var val = 0; val < 256; val++) {
+            var newval = fn(val);
+            table.push(newval / 255); // map to ∈ [0, 1]
+        }
+        return table;
+    };
+
+    /**
+     * Limits each channel of the image to the number of colors specified as
+     * the parameter. The parameter can be set to values between 2 and 255, but
+     * results are most noticeable in the lower ranges.
+     *
+     * Adapted from p5's Filters.posterize
+     */
+    SVGFilters.posterize = function(inGraphics, resultGraphics, level) {
+        level = parseInt(level, 10);
+        if ((level < 2) || (level > 255)) {
+            throw new Error(
+                'Level must be greater than 2 and less than 255 for posterize'
+            );
+        }
+
+        var tableValues = SVGFilters._discreteTableValues(function(val) {
+            return (((val * level) >> 8) * 255) / (level - 1);
+        });
+
+        var componentTransfer = SVGElement.create('feComponentTransfer', {
+            'in': inGraphics,
+            result: resultGraphics,
+            'color-interpolation-filters': 'sRGB'
+        });
+        ['R', 'G', 'B'].forEach(function(channel) {
+            var func = SVGElement.create('feFunc' + channel, {
+                type: 'discrete',
+                tableValues: tableValues.join(' ')
+            });
+            componentTransfer.append(func);
+        });
+
+        return componentTransfer;
+    };
+
+    SVGFilters._blendOffset = function(inGraphics, resultGraphics, mode) {
+        var elements = [];
+        [
+            ['left', -1, 0],
+            ['right', 1, 0],
+            ['up', 0, -1],
+            ['down', 0, 1]
+        ].forEach(function(neighbor) {
+            elements.push(SVGElement.create('feOffset', {
+                'in': inGraphics,
+                result: resultGraphics + '-' + neighbor[0],
+                dx: neighbor[1],
+                dy: neighbor[2]
+            }));
+        });
+        [
+            [null, inGraphics],
+            [resultGraphics + '-left', resultGraphics + '-tmp-0'],
+            [resultGraphics + '-right', resultGraphics + '-tmp-1'],
+            [resultGraphics + '-up', resultGraphics + '-tmp-2'],
+            [resultGraphics + '-down', resultGraphics + '-tmp-3']
+        ].forEach(function(layer, i, layers) {
+            if (i === 0) {
+                return;
+            }
+            elements.push(SVGElement.create('feBlend', {
+                'in': layers[i - 1][1],
+                in2: layer[0],
+                result: layer[1],
+                mode: mode
+            }));
+        });
+        return elements;
+    };
+
+    /**
+     * Increases the bright areas in an image
+     *
+     * Will create 4 offset layer and blend them using darken mode
+     */
+    SVGFilters.erode = function(inGraphics, resultGraphics) {
+        return SVGFilters._blendOffset(inGraphics, resultGraphics, 'darken');
+    };
+
+    SVGFilters.dilate = function(inGraphics, resultGraphics) {
+        return SVGFilters._blendOffset(inGraphics, resultGraphics, 'lighten');
+    };
+
+    p5.SVGFilters = SVGFilters;
+
+    return SVGFilters;
+};
+
+},{}],11:[function(require,module,exports){
+var constants = require('./constants');
+var SVGCanvas = require('svgcanvas');
+
+module.exports = function(p5) {
+    // patch p5.Graphics for SVG
+    var _graphics = p5.Graphics;
+    p5.Graphics = function(w, h, renderer, pInst) {
+        var args = arguments;
+        _graphics.apply(this, args);
+        if (renderer === constants.SVG) {
+            // replace <canvas> with <svg>
+            var c = this._renderer.elt;
+            this._renderer = new p5.RendererSVG(c, pInst, false); // replace renderer
+            c = this._renderer.elt;
+            this.elt = c; // replace this.elt
+            // do default again
+            this._renderer.resize(w, h);
+            this._renderer._applyDefaults();
+        }
+        return this;
+    };
+    p5.Graphics.prototype = _graphics.prototype;
+
+    /**
+     * Due to a known issue (image is not surely ready before onload fires),
+     * we have no way to draw SVG element synchronously.
+     * So, this method will load a SVG Graphics
+     * and then convert it to Canvas Graphics asynchronously
+     *
+     * @see https://github.com/zenozeng/p5.js-svg/issues/78
+     *
+     * @function loadGraphics
+     * @memberof p5.prototype
+     * @param {p5.Graphics} graphics the p5.Grphaics object
+     * @param {Function(p5.Graphics)} [successCallback] Function to be called once
+     *                                 the SVG Graphics is loaded. Will be passed the
+     *                                 p5.Graphics.
+     * @param {Function(Event)}    [failureCallback] called with event error.
+     *
+     * @example
+     * pg = createGraphics(100, 100, SVG);
+     * background(200);
+     * pg.background(100);
+     * pg.ellipse(pg.width/2, pg.height/2, 50, 50);
+     * loadGraphics(pg, function(pgCanvas) {
+     *      image(pgCanvas, 50, 50);
+     *      image(pgCanvas, 0, 0, 50, 50);
+     * });
+     *
+     */
+    p5.prototype.loadGraphics = function(graphics, successCallback, failureCallback) {
+        if (graphics._renderer.svg) {
+            var svg = graphics._renderer.svg;
+            var url = SVGCanvas.prototype.toDataURL.call(graphics._renderer.elt, 'image/svg+xml');
+            var pg = this.createGraphics(graphics.width, graphics.height);
+            // also copy SVG, so we can keep vector SVG when image(pg) in SVG runtime
+            pg._renderer.svg = svg.cloneNode(true);
+            pg.loadImage(url, function(img) {
+                pg.image(img);
+                successCallback(pg);
+            }, failureCallback);
+        } else {
+            successCallback(graphics);
+        }
+    };
+
+    /**
+     * Patched version of createCanvas
+     *
+     * use createCanvas(100, 100, SVG) to create SVG canvas.
+     *
+     * Creates a SVG element in the document, and sets its width and
+     * height in pixels. This method should be called only once at
+     * the start of setup.
+     * @function createCanvas
+     * @memberof p5.prototype
+     * @param {Number} width - Width (in px) for SVG Element
+     * @param {Number} height - Height (in px) for SVG Element
+     * @return {Graphics}
+     */
+    var _createCanvas = p5.prototype.createCanvas;
+    p5.prototype.createCanvas = function(w, h, renderer) {
+        var graphics = _createCanvas.apply(this, arguments);
+        if (renderer === constants.SVG) {
+            var c = graphics.elt;
+            this._setProperty('_renderer', new p5.RendererSVG(c, this, true));
+            this._isdefaultGraphics = true;
+            this._renderer.resize(w, h);
+            this._renderer._applyDefaults();
+        }
+        return this._renderer;
+    };
+};
+
+},{"./constants":4,"svgcanvas":3}],12:[function(require,module,exports){
+require('../src/index.js')(p5);
+
+},{"../src/index.js":7}]},{},[12]);
+});

+ 2814 - 0
libs/p5.touchgui.js

@@ -0,0 +1,2814 @@
+// Create GUI context
+let _gui;
+
+/**
+ * Prototype functions to make library 
+ * method calls more like p5.js.
+ */
+p5.prototype.createGui = function() {
+  _gui = new Gui();
+  return _gui;
+};
+
+p5.prototype.drawGui = function() {
+  _gui.draw();
+};
+
+// Prototype functions for GUI elements
+p5.prototype.createButton = function(label, x, y, w=128, h=32) {
+  let obj = new GuiButton(label, x, y, w, h);
+  _gui._add(obj);
+  return obj;
+};
+
+p5.prototype.createToggle = function(label, x, y, w=128, h=32, defaultVal = false) {
+  let obj = new GuiToggle(label, x, y, w, h, defaultVal);
+  _gui._add(obj);
+  return obj;
+};
+
+p5.prototype.createCheckbox = function(label, x, y, w=32, h=32, defaultVal = false) {
+  let obj = new GuiCheckbox(label, x, y, w, h, defaultVal);
+  _gui._add(obj);
+  return obj;
+};
+
+p5.prototype.createSlider = function(label, x, y, w=256, h=32, min=0, max=1) {
+  let obj = new GuiSlider(label, x, y, w, h, min, max);
+  _gui._add(obj);
+  return obj;
+};
+
+p5.prototype.createSliderV = function(label, x, y, w=32, h=256, min=0, max=1) {
+  let obj = new GuiSliderV(label, x, y, w, h, min, max);
+  _gui._add(obj);
+  return obj;
+};
+
+p5.prototype.createCrossfader = function(label, x, y, w=256, h=32, min=(-1), max=1) {
+  let obj = new GuiCrossfader(label, x, y, w, h, min, max);
+  _gui._add(obj);
+  return obj;
+};
+
+p5.prototype.createCrossfaderV = function(label, x, y, w=256, h=32, min=(-1), max=1) {
+  let obj = new GuiCrossfaderV(label, x, y, w, h, min, max);
+  _gui._add(obj);
+  return obj;
+};
+
+p5.prototype.createSlider2d = function(label, x, y, w=256, h=256, minX=(-1), maxX=1, minY=(-1), maxY=1) {
+  let obj = new GuiSlider2d(label, x, y, w, h, minX, maxX, minY, maxY);
+  _gui._add(obj);
+  return obj;
+};
+
+p5.prototype.createJoystick = function(label, x, y, w=256, h=256, minX=(-1), maxX=1, minY=(-1), maxY=1) {
+  let obj = new GuiJoystick(label, x, y, w, h, minX, maxX, minY, maxY);
+  _gui._add(obj);
+  return obj;
+};
+
+p5.prototype._guiPostDraw = function() {
+  if (_gui != null) {
+    _gui._postDraw();
+  }
+};
+
+p5.prototype.registerMethod('post', p5.prototype._guiPostDraw);
+
+/**
+ * Generates hash code from a string.
+ * @see http://stackoverflow.com/q/7616461/940217
+ * @return {number}
+ * Note: this is not being used in this version of the library. Will remove once I'm
+ *  sure it's going to stay that way.
+ */
+String.prototype.hashCode = function(){
+    if (Array.prototype.reduce){
+        return this.split("").reduce(function(a,b){a=((a<<5)-a)+b.charCodeAt(0);return a&a},0);              
+    } 
+    var hash = 0;
+    if (this.length === 0) return hash;
+    for (var i = 0; i < this.length; i++) {
+        var character  = this.charCodeAt(i);
+        hash  = ((hash<<5)-hash)+character;
+        hash = hash & hash; // Convert to 32bit integer
+    }
+    return hash;
+}
+
+function _findByKey(obj, value) {
+    return Object.keys(obj)[Object.values(obj).indexOf(value)];
+}
+
+/*******************
+ * Gui
+ * - Creates a GUI context to track all GUI objects.
+ *
+ *  TODO: add 'page' property so that objects can be grouped and toggled by page
+ */
+class Gui {
+  constructor() {
+    this.objects        = [];
+    
+    this.touchInput     = false; // true if the last input was a touch event
+    this._activeIds      = {};
+    this._ptouches      = {};
+    this._hoverObj      = null;
+    
+    this._style          = new GuiStyle();
+    this.updateStyle();
+    
+    // Define touchGui eventHandlers for mouse and touch so as not to interfere
+    // with p5.js eventHandlers
+    
+    this._onMouseDown    = this._onMouseDown.bind(this);
+    this._onMouseMove    = this._onMouseMove.bind(this);
+    this._onMouseLeave   = this._onMouseLeave.bind(this);
+    this._onMouseUp      = this._onMouseUp.bind(this);
+    this._onTouchStart   = this._onTouchStart.bind(this);
+    this._onTouchMove    = this._onTouchMove.bind(this);
+    this._onTouchEnd     = this._onTouchEnd.bind(this);
+    this._onTouchCancel  = this._onTouchCancel.bind(this);
+    
+    document.addEventListener("mousedown", this._onMouseDown, false);
+    document.addEventListener("mousemove", this._onMouseMove, false);
+    document.addEventListener("mouseleave", this._onMouseLeave, false);
+    document.addEventListener("mouseup", this._onMouseUp, false);
+    document.addEventListener("touchstart", this._onTouchStart, false);
+    document.addEventListener("touchmove", this._onTouchMove, false);
+    document.addEventListener("touchend", this._onTouchEnd, false);
+    document.addEventListener("touchcancel", this._onTouchCancel, false);
+  }
+  
+  // Add a new object to the GUI context
+  _add(newObj) {    
+    newObj._index = this.objects.length;
+    this.objects.push(newObj);
+    
+    return true;
+  }
+  
+  // Gets array of objects from the GUI context that match the label
+  get(label) {
+    let fetched = [];
+    this.objects.forEach((obj) => {
+      if (obj.label == label) {
+        fetched.push(obj);
+      }
+    });
+    
+    if (fetched.length == 0) {
+      console.error("p5.touchgui: No GUI object with label \'" + label + "\' has been found.");
+    }
+    
+    return fetched;
+  }
+  
+  // Get position relative to canvas
+  _getCanvasPos(x, y) {
+    let rect = canvas.getBoundingClientRect();
+    let sx = canvas.scrollWidth / this.width || 1;
+    let sy = canvas.scrollHeight / this.height || 1;
+    let p = {x: 0, y: 0};
+    
+    p.x = (x - rect.left) / sx;
+    p.y = (y - rect.top) / sy;
+    
+    return p;
+  }
+  
+  // Update and draw the GUI (should be run each frame after background())
+  draw() {
+    this.objects.forEach((obj) => {
+      if (obj.visible) { 
+        obj.draw(); 
+      }
+    });
+  }
+  
+  // Automatically gets run after the draw loop, storing each object's previous state
+  // for reference in the next frame
+  _postDraw() {
+    this.objects.forEach((obj) => {
+      obj._postDraw();
+    });
+  }
+  
+  //// STYLE
+  
+  // Loads a built-in preset style by string name
+  loadStyle(presetName) {
+    switch (presetName) {
+      case "Default":
+        this._style.Gray();
+        break;
+      case "Gray":
+        this._style.Gray();
+        break;
+      case "Rose":
+        this._style.Rose();
+        break;
+      case "Seafoam":
+        this._style.Seafoam();
+        break;
+      case "Blue":
+        this._style.Blue();
+        break;
+      case "TerminalGreen":
+        this._style.TerminalGreen();
+        break;
+      case "TerminalRed":
+        this._style.TerminalRed();
+        break;
+      case "TerminalBlue":
+        this._style.TerminalBlue();
+        break;
+      case "TerminalYellow":
+        this._style.TerminalYellow();
+        break;
+      case "TerminalMagenta":
+        this._style.TerminalMagenta();
+        break;
+      default:
+        console.warn("\'" + presetName + "\' preset does not exist. Defaulting to \'Gray\'.")
+        this._style.Gray();
+    }
+    
+    this.updateStyle();
+    
+    console.log("\'" + presetName + "\' preset loaded.")
+  }
+  
+  // Update all objects' style parameters with global style
+  updateStyle() {
+    this.objects.forEach((obj) => {
+      switch (obj._type) {
+        case "button":
+          obj._style = Object.create(this._style.button);
+          break;
+        case "toggle":
+          obj._style = Object.create(this._style.toggle);
+          break;
+        case "checkbox":
+          obj._style = Object.create(this._style.checkbox);
+          break;
+        case "slider":
+          obj._style = Object.create(this._style.slider);
+          break;
+        case "crossfader":
+          obj._style = Object.create(this._style.slider);
+          obj._style.strokeCenter = Object.create(this._style.crossfader.strokeCenter);
+          obj._style.strokeCenterHover = Object.create(this._style.crossfader.strokeCenterHover);
+          obj._style.strokeCenterActive = Object.create(this._style.crossfader.strokeCenterActive);
+          break;
+        case "slider2d":
+          obj._style = Object.create(this._style.slider);
+          obj._style.handleRadius = this._style.slider2d.handleRadius;
+          break;
+        case "joystick":
+          obj._style = Object.create(this._style.slider);
+          obj._style.handleRadius = this._style.slider2d.handleRadius;
+          break;
+        default:
+          console.error(obj.label + " has an invalid type. Please submit a bug report.");
+      }
+    });
+  }
+  
+  // TODO: These load and save style as JSON functions need a lot more 
+  //  consideration before implementation. There are questions such as:
+  //    - Does this save and load layout as well as style?
+  //    - What is the best way to deep copy elements?
+  
+  // Load style from a JSON file.
+  /*loadStyleJSON(filename) {
+     console.warn("loadStyleJSON(): This function is not yet implemented.");
+    
+    if (typeof filename === "string") {
+      loadJSON(filename, (style)=> {
+        let target = {};
+        
+        // Cycle through all top level style properties
+        Object.keys(style).forEach((i) => {
+          if (typeof style[i] !== "object") {
+            // If the property is not an object, copy it to target
+            target[i] = style[i];
+          }
+          else {
+            // If the property is an object, create an empty object on the target...
+            target[i] = {};
+
+            // Loop through all child items...
+            Object.keys(style[i]).forEach((j) => {
+              if (typeof style[i][j] === "string" && style[i] != "font") {
+                // Copy any non-font string objects as p5.Color objects
+                target[i][j] = color(style[i][j]);
+              }
+              else {
+                // Copy any other properties directly
+                target[i][j] = style[i][j];
+              }
+            });
+          }
+        });
+        
+        this._style = Object.create(target);
+        this.updateStyle();
+      });
+    }
+    else {
+      console.error("loadStyleJSON(): Please input a string as a filename.");
+    }
+  }
+  
+  // Saves current style as a JSON file.
+  saveStyleJSON(filename) {
+    console.warn("saveStyleJSON(): This function is not yet implemented.");
+    
+    if (typeof filename === "string") {
+      // If the filename is a string, create target object to which we'll transfer the style properties
+      let target = {};
+      
+      // Cycle through all top level style properties
+      Object.keys(this._style).forEach((i) => {
+        if (typeof this._style[i] !== "object") {
+          // If the property is not an object, copy it to target
+          target[i] = this._style[i];
+        }
+        else {
+          // If the property is an object, create an empty object on the target...
+          target[i] = {};
+          
+          // Loop through all child items...
+          Object.keys(this._style[i]).forEach((j) => {
+            if (typeof this._style[i][j] === "object") {
+              // Copy any objects as strings (bc they are p5.Color objects)
+              target[i][j] = this._style[i][j].toString();
+            }
+            else {
+              // Copy any other properties directly
+              target[i][j] = this._style[i][j];
+            }
+          });
+        }
+      });
+      
+      // Save the resultant target object as a JSON file
+      saveJSON(target, filename, false);
+    }
+    else {
+      console.error("saveStyleJSON(): Please input a string as a filename.");
+    }
+  }*/
+  
+  //// GLOBAL STYLE SETTINGS
+  // These functions set specific style properties for all objects
+  setStrokeWeight(strokeWeight) {
+    if (typeof strokeWeight === "number") {
+      this._style.strokeWeight          = strokeWeight;
+      this._style.button.strokeWeight   = strokeWeight;
+      this._style.toggle.strokeWeight   = strokeWeight;
+      this._style.checkbox.strokeWeight = strokeWeight;
+      this._style.slider.strokeWeight   = strokeWeight;
+
+      this.objects.forEach((obj) => {
+        obj.setStyle("strokeWeight", strokeWeight);
+      });
+    }
+    else {
+      console.error("setStrokeWeight(): please enter a number.");
+    }
+  }
+  
+  setRounding(rounding) {
+    if (typeof rounding === "number") {
+      this._style.rounding          = rounding;
+      this._style.button.rounding   = rounding;
+      this._style.toggle.rounding   = rounding;
+      this._style.checkbox.rounding = rounding;
+      this._style.slider.rounding   = rounding;
+
+      this.objects.forEach((obj) => {
+        obj.setStyle("rounding", rounding);
+      });
+    }
+    else {
+      console.error("setRounding(): please enter a number.");
+    }
+  }
+  
+  setFont(font) {
+    if (typeof font === "string") {
+      this._style.font          = font;
+      this._style.button.font   = font;
+      this._style.toggle.font   = font;
+      
+      this.objects.forEach((obj) => {
+        obj.setStyle("font", font);
+      });
+    }
+    else if (typeof font === "object") {
+      this.objects.forEach((obj) => {
+        obj.setStyle("font", font);
+      });
+    }
+    else {
+      console.error("setFont(): please enter a string or p5.Font object.");
+    }
+  }
+  
+  setTextSize(textSize) {
+    if (typeof textSize === "number") {
+      this._style.textSize          = textSize;
+      this._style.button.textSize   = textSize;
+      this._style.toggle.textSize   = textSize;
+
+      this.objects.forEach((obj) => {
+        obj.setStyle("textSize", textSize);
+      });
+    }
+    else {
+      console.error("setTextSize(): please enter a number.");
+    }
+  }
+  
+  setTrackWidth(trackWidth) {
+    if (typeof trackWidth === "number") {
+      this._style.slider.trackWidth   = trackWidth;
+
+      this.objects.forEach((obj) => {
+        if (obj._family === "slider") {
+          obj.setStyle("trackWidth", constrain(trackWidth, 0, 1));
+        }
+      });
+    }
+  }
+  
+  //// EVENT HANDLING
+  
+  // MOUSE
+  _onMouseDown(e) {
+    // Get a hit result for the click and the current mouse position
+    let result  = this._checkHit(mouseX, mouseY);
+    let m       = this._getCanvasPos(e.clientX, e.clientY);
+    
+    // If there's a successful hit and the object is visible and enabled,
+    // process the mouse press
+    if (result.hit) {
+      if (result.obj.visible && result.obj.enabled) {
+        let obj = result.obj;
+        this._onPress(obj, m);
+        this._activeIds[-1] = obj._index;
+      }
+    }
+  }
+  
+  _onMouseMove(e) {
+    let m = this._getCanvasPos(e.clientX, e.clientY);
+    
+    // If any mouse buttons are pressed
+    if (e.buttons >= 1) {
+      // And if the mouse isn't currently locked on an object,
+      // process the mouse input
+      if (this._activeIds[-1] != null) {
+        let obj = this.objects[this._activeIds[-1]];
+        this._onMove(obj, m);
+      }
+    }
+    else {
+      // If not, check for mouse hovering over an object
+      let result  = this._checkHit(mouseX, mouseY);
+      
+      if (this._hoverObj != null) {
+        this._hoverObj._hover  = false;
+        this._hoverObj         = null;
+      }
+      
+      if (result.hit) {
+        if (result.obj.visible && result.obj.enabled) {
+          result.obj._hover = true;
+          this._hoverObj    = result.obj;
+        }
+      }
+    }
+  }
+  
+  // In case the mouse leaves the screen, make sure to
+  // deactivate any hovers
+  _onMouseLeave(e) {
+    if (this._hoverObj != null) {
+      this._hoverObj._hover  = false;
+      this._hoverObj         = null;
+    }
+  }
+  
+  _onMouseUp(e) {
+    // If the mouse was locked to an object, process the release
+    if (this._activeIds[-1] != null) {
+      let obj = this.objects[this._activeIds[-1]];
+      this._onRelease(obj);
+    }
+    
+    // Set the mouse active ID to null (no objects locked)
+    this._activeIds[-1] = null;
+  }
+  
+  // MULTI-TOUCH
+  
+  _onTouchStart(e) {
+    // If any touch events are registered, shut off any hovered objects
+    if (this._hoverObj != null) {
+      this._hoverObj._hover  = false;
+      this._hoverObj         = null;
+    }
+    
+    // Loop through all active touchpoints
+    for (let i = 0; i < e.touches.length; i++) {
+      let t       = this._getCanvasPos(e.touches[i].clientX, e.touches[i].clientY);
+      let id      = e.touches[i].identifier;
+      let result  = this._checkHit(t.x, t.y);
+      
+      // If there's a hit
+      if (result.hit) {
+        // And the object is visible and enabled and the touch is not
+        // already locked on an object, process the input
+        if (result.obj.visible && result.obj.enabled && this._activeIds[id] == null) {
+          let obj = result.obj;
+          this._onPress(obj, t);
+          this._activeIds[id] = obj._index;
+        }
+      }
+    }
+
+    // Store current touches for future reference
+    this._ptouches = e.touches;
+  }
+
+  _onTouchMove(e) {
+    // If any touch events are registered, shut off any hovered objects
+    if (this._hoverObj != null) {
+      this._hoverObj._hover  = false;
+      this._hoverObj         = null;
+    }
+    
+    // Loop through all active touch
+    for (let i = 0; i < e.touches.length; i++) {
+      let t   = this._getCanvasPos(e.touches[i].clientX, e.touches[i].clientY);
+      let id  = e.touches[i].identifier;
+      
+      // If the touch is already locked on an object, process the input
+      if (this._activeIds[id] != null) {
+        let obj = this.objects[this._activeIds[id]];
+        this._onMove(obj, t);
+      }
+    }
+
+    // Store current touches for future reference
+    this._ptouches = e.touches;
+  }
+  
+  _onTouchEnd(e) {
+    // Prevent browser handling of touch event as mouse event
+    if (e.cancelable) { e.preventDefault(); }
+    
+    // Get removed touch id
+    let id = null; 
+    for (let i = 0; i < this._ptouches.length; i++) {
+      let found = false;
+      
+      for (let j = 0; j < e.touches.length; j++) {
+        if (e.touches[j].identifier == this._ptouches[i].identifier) {
+          found = true;
+        }
+      }
+      
+      if (!found) { id = this._ptouches[i].identifier; }
+    }
+    
+    // If the touch was locked on an object, release the object
+    if (this._activeIds[id] != null) {
+      let obj = this.objects[this._activeIds[id]];     
+      this._onRelease(obj);
+    }
+    
+    // Set the touch active ID to null (no objects locked)
+    this._activeIds[id] = null;
+    
+    // Store current touches for future reference
+    this._ptouches = e.touches;
+  }
+  
+  // In case there are 'touchcancel' events, issue a warning
+  _onTouchCancel(e) {
+    // Prevent browser handling of touch event as mouse event
+    if (e.cancelable) { e.preventDefault(); }
+    
+    // Process as touch end for now
+    this._onTouchEnd(e);
+  }
+  
+  ////
+  
+  // Process input press 'p' on a specified object
+  _onPress(obj, p) {
+    obj._setStates(true, false, false);
+    obj._setSelect(p.x, p.y);
+    obj._setTrigger();
+    obj._setActive(true);
+
+    if (obj.onPress != null) {
+      if (typeof obj.onPress === "function") {
+        obj.onPress();
+      }
+      else {
+        console.error("guiObject.onPress(): Please assign a valid function for " + obj.label + " \'onPress\' callback.");
+      }
+    }
+  }
+  
+  // Process input move 'p' on a specified object
+  _onMove(obj, p) {
+    obj._setStates(false, true, false);
+    obj._setSelect(p.x, p.y);
+    obj._setTrigger();
+    obj._setActive(true);
+  }
+  
+  // Process input release on a specified object
+  _onRelease(obj) {
+    obj._setStates(false, false, true);
+    obj._setTrigger();
+    obj._setActive(false);
+
+    if (obj.onRelease != null) {
+      if (typeof obj.onRelease === "function") {
+        obj.onRelease();
+      }
+      else {
+        console.error("guiObject.onRelease(): Please assign a valid function for " + obj.label + " \'onRelease\' callback.");
+      }
+    }
+  }
+  
+  _checkHit(x, y) {
+    let result = {
+      hit: false,
+      index: null,
+      obj: null
+    };
+    
+    this.objects.forEach((obj) => {
+      if (obj._checkHit(x, y)) {
+        result.hit    = true;
+        result.index  = obj._index;
+        result.obj    = obj;
+      }
+    });
+    
+    return result;
+  }
+}
+
+/*******************
+ * GuiObject
+ * - This is the base class for all GuiObjects. It contains common variables
+ *   and its update() method handles mouse and touch inputs on a per object
+ *   basis depending on its defined interaction mode.
+ *
+ *  TODO: add an individual input lock toggle. May require further checking at the
+ *        gui context scope.
+ *  TODO: add 'page' property so that objects can be grouped and toggled by page
+ */
+class GuiObject {
+  constructor(label, x, y, w, h) {
+    // Internal variables not meant to be exposed to users
+    this._active    = false;
+    this._pactive   = false;
+    this._hover     = false;
+    this._selU      = null;     // selection U and V within object
+    this._selV      = null;
+    this._triggered = false;    // An internal variable, but affected by behavior mode
+    this._index     = null;     // Index representing object location when added to context stack
+    
+    this._pisPressed  = false;
+    this._pisHeld     = false;
+    this._pisReleased = false;
+    this._pisChanged  = false;
+    this._pselU     = null;
+    this._pselV     = null;
+    
+    this._family    = "button"; // Default settings, defined in child class constructor
+    this._type      = "button";
+    
+    // Public variables meant for user access
+    this.label      = label;
+    this.x          = x;
+    this.y          = y;
+    this.w          = w;
+    this.h          = h;
+    this.isInteger  = false;      // Used to have sliders lock to ints
+    this.mode       = "onPress";  // User can define behavior mode: 
+                                  // "onPress", "onHold", "onRelease"
+    
+    this.isPressed    = false;
+    this.isHeld       = false;
+    this.isReleased   = false;
+    this.isChanged    = false;
+    this.onPress    = null;
+    this.onHold     = null;
+    this.onRelease  = null;
+    this.onChange   = null;
+    
+    this.val        = 0;
+    // this.lock       = true;
+    this.enabled    = true;     // enabled for input, false if for display only
+    this.visible    = true;     // visibility flag for object; 
+                                //  when not visible, input is overridden to false    
+    this._style      = null;     // Stores object style settings
+    
+    // TODO: Implement object-level locking. Right now everything is locked
+    //   by default.
+    // this.lock       = true;
+    
+    // Check if the _gui has been created.
+    if (_gui == null) {
+      console.error("p5.touchgui: No Gui has been created. Please call CreateGui() before creating any GuiObjects.");
+    }
+  }
+  
+  // Basic function for checking hits on a rectangle
+  _checkHit(x, y) {
+    if (x < this.x || 
+        y < this.y || 
+        x >= this.x + this.w || 
+        y >= this.y + this.h) {
+      return false;
+    }
+    return true;
+  }
+  
+  // Sets the object's 'isPressed', 'isHeld', 'isReleased', and 'isChanged' states
+  _setStates(newPressed, newHeld, newReleased) {
+    this.isPressed  = newPressed;
+    this.isHeld     = newHeld;
+    this.isReleased = newReleased;
+    
+    if (!(this._pisPressed && !this._pisHeld) && 
+        (this._pisPressed != this.isPressed || 
+         this._pisHeld != this.isHeld || 
+         this._pisReleased != this.isReleased)) {
+      this.isChanged = true;
+    }
+  }
+  
+  // Sets the input selection U and V, normalized and relative to UI object location and size
+  // Note: this might break if objects are drawn with CENTER mode in the future
+  //    (instead of CORNERS mode)
+  _setSelect(x, y) {
+    this._selU = constrain(x - this.x, 0, this.w)/this.w;
+    this._selV = constrain(y - this.y, 0, this.h)/this.h;
+    
+    // If the object is a 'slider' type, set 'isChanged' state if any input location change
+    if (this._family == "slider" && (this._selU != this._pselU || this._selV != this._pselV)) {
+      this.isChanged = true;
+    }
+  }
+  
+  
+  // Set the object trigger, used internally for interaction behavior mode
+  _setTrigger() {
+    // Handle improper trigger mode input from user
+    if (this.mode !== "onPress" &&
+        this.mode !== "onHold" &&
+        this.mode !== "onRelease") {
+      console.warn("Interaction mode for " + this.label + " must be set to \"onPress\", \"onHold\", or \"onRelease\". Defaulting to \"onPress\".");
+        this.mode = "onPress";
+    }
+    
+    // Set triggered based on mode
+    if (this.mode === "onPress" && this.isPressed) {
+      this._triggered = true;
+    }
+    else if (this.mode === "onHold" && this.isHeld) {
+      this._triggered = true;
+    }
+    else if (this.mode === "onRelease" && this.isReleased) {
+      this._triggered = true;
+    }
+    else {
+      this._triggered = false;
+    }
+  }
+  
+  // Set the object's 'active' state as well as 'isChanged' state if different than
+  // previous frame. This gets further defined in children classes by calling
+  // super._setActive().
+  _setActive(active) {
+    this._active = active;
+    
+    if (this._active != this._pactive) {
+      this.isChanged = true;
+    }
+  }
+  
+  // Stores the object's state for reference in a future frame and
+  // calls onHold or onChange if defined.
+  _postDraw() {
+    // Determine whether or not a press on the object is being isHeld
+    if (this.isPressed) {
+      this.isHeld = true;
+    } 
+    else if (this.isReleased) {
+      this.isHeld = false;
+    }
+    
+    // These callbacks need to be implemented here because they need 
+    // to be triggered each frame, if triggered at all
+    if (this.isHeld) {
+      if (this.onHold != null) {
+        if (typeof this.onHold === "function") {
+          this.onHold();
+        }
+        else {
+          console.error("guiObject.onHold(): Please assign a valid function for " + this.label + " \'onHold\' callback.");
+        }
+      }
+    }
+    
+    if (this.isChanged) {
+      if (this.onChange != null) {
+        if (typeof this.onChange === "function") {
+          this.onChange();
+        }
+        else {
+          console.error("guiObject.onChange(): Please assign a valid function for " + this.label + " \'onChange\' callback.");
+        }
+      }
+    }
+
+    // Store all necessary values from this frame for future reference
+    this._pisPressed   = this.isPressed;
+    this._pisHeld      = this.isHeld;
+    this._pisReleased  = this.isReleased;
+    this._pisChanged   = this.isChanged;
+    this._pactive    = this._active;
+    this._pselU      = this._selU;
+    this._pselV      = this._selV;
+
+    // Reset these variables
+    this.isPressed   = false;
+    this.isReleased  = false;
+    this.isChanged   = false;
+  }
+  
+  //// STYLE
+  
+  /* 
+   * Method for setting style of individual GUI object. Use cases look like :
+   *      b1.setStyle("fillBg", color(128));
+   *      b1.setStyle({
+   *        fillBg: color(128),
+   *        strokeBg: color(0)
+   *      });
+   *
+   * TODO: review for any additional error handling that may be needed
+   */
+  
+  setStyle(...args) {
+    if (args.length === 2 && typeof args[0] === "string") {
+      // If there are two input arguments and the first is a string (aka property name)
+      if (this._style[args[0]] !== null) {
+        // Set the style property if it exists
+        this._style[args[0]] = args[1];
+      }
+      else {
+        console.error("GuiObject.setStyle(): Object property \'" + args[0] + "\' does not exist.");
+      }
+    }
+    else if (args.length === 1 && typeof args[0] === "object") {
+      // If there is one input argument and it is an object
+      let settings = args[0];
+      let settingNames = Object.keys(settings);
+      
+      for (let i = 0; i < settingNames.length; i++) {
+        // Loop through the inputted style properties
+        let key = settingNames[i];
+        
+        if (this._style[key] != null) {
+          // If it matches one of this object's properties in name and type, set it
+          if (typeof this._style[key] === typeof settings[key]) {
+            this._style[key] = settings[key];
+          }
+          else {
+            console.error("GuiObject.setStyle(): wrong data type for \'" + settingNames[i] + "\' in object type \'" + this._type + "\'.");
+          }
+        }
+        else {
+          console.error("GuiObject.setStyle(): Object property \'" + settingNames[i] + "\' does not exist in type \'" + this._type + "\'.");
+        }
+      }
+    }
+    else {
+      console.error("GuiObject.setStyle(): please provide a valid input.");
+    }
+  }
+}
+
+
+/**
+ * GuiButton
+ * - Momentary button with a label.
+ */
+class GuiButton extends GuiObject {
+  constructor(label, x, y, w=128, h=32) {
+    super(label, x, y, w, h);
+    
+    this.labelOn  = label;
+    this.labelOff = label;
+    
+    this._family  = "button";
+    this._type    = "button";
+    this._plabel  = label;    // Internal handling for updating labelOn/labelOff
+    
+    this._style    = {..._gui._style.button};
+  }
+  
+  _setActive(active) {
+    super._setActive(active);
+    
+    // Set val to active
+    // Note: doesn't account for ability to override when input=false
+    this.val = this._active;
+  }
+  
+  draw() {
+    // Render button
+    push();
+    
+      strokeWeight(this._style.strokeWeight);
+      rectMode(CORNER);
+
+      if (this._active) {
+        stroke(this._style.strokeBgActive);
+        fill(this._style.fillBgActive);
+      }
+      else if (this._hover) {
+        stroke(this._style.strokeBgHover);
+        fill(this._style.fillBgHover);
+      }
+      else {
+        stroke(this._style.strokeBg);
+        fill(this._style.fillBg);
+      }
+    
+      rect(this.x, this.y, this.w, this.h, this._style.rounding);
+
+      // Label rendering.
+      push();
+        if (this._active) { fill(this._style.fillLabelActive); }
+        else if (this._hover) { fill(this._style.fillLabelHover); }
+        else { fill(this._style.fillLabel); }
+        
+        noStroke();
+        textAlign(CENTER, CENTER);
+        textFont(this._style.font);
+        let size = this.w*0.9;
+        if (size > this._style.textSize) {
+          size = this._style.textSize;
+        }
+        textSize(size);
+        
+        if (this.val) {
+          text(this.labelOn, this.x + this.w/2, this.y + this.h/2);
+        }
+        else {
+          text(this.labelOff, this.x + this.w/2, this.y + this.h/2);
+        }
+      pop();
+
+    pop();
+  }
+  
+  _postDraw() {
+    super._postDraw();
+    
+    // Internal handling for updating labelOn/labelOff
+    if (this._plabel != this.label) {
+      this.labelOn  = this.label;
+      this.labelOff = this.label;
+      this._plabel  = this.label;
+    }
+  }
+}
+
+/**
+ * GuiToggle
+ * - Toggle button with a label.
+ */
+class GuiToggle extends GuiObject { 
+  constructor(label, x, y, w=128, h=32, defaultVal = false) {
+    super(label, x, y, w, h);
+    
+    this.val      = defaultVal;
+    
+    this.labelOn  = label;
+    this.labelOff = label;
+    
+    this._family  = "toggle";
+    this._type    = "toggle";
+    this._plabel  = label;    // Internal handling for updating labelOn/labelOff
+    
+    this._style    = {..._gui._style.toggle};
+  }
+
+  _setActive(active) {
+    super._setActive(active);
+    
+    if (this._triggered) {
+      this.val = !this.val;
+    }
+  }
+  
+  draw() {
+    // Render button based on state
+    if (this._active && this._hover && this.val) {
+      // Active Off
+      this._drawState(this._style.strokeBgOffActive,
+                     this._style.fillBgOffActive,
+                     this._style.fillLabelOffActive);
+    }
+    else if (this._active && this._hover && !this.val) {
+      // Active On
+      this._drawState(this._style.strokeBgOnActive,
+                     this._style.fillBgOnActive,
+                     this._style.fillLabelOnActive);
+    }
+    else if (this._hover && this.val) {
+      // Hover On
+      this._drawState(this._style.strokeBgOnHover,
+                     this._style.fillBgOnHover,
+                     this._style.fillLabelOnHover);
+    }
+    else if (this._hover && !this.val) {
+      // Hover Off
+      this._drawState(this._style.strokeBgOffHover,
+                     this._style.fillBgOffHover,
+                     this._style.fillLabelOffHover);
+    }
+    else if (this.val) {
+      // Inactive On
+      this._drawState(this._style.strokeBgOn,
+                     this._style.fillBgOn,
+                     this._style.fillLabelOn);
+    }
+    else {
+      // Inactive Off
+      this._drawState(this._style.strokeBgOff,
+                     this._style.fillBgOff,
+                     this._style.fillLabelOff); 
+    }
+  }
+  
+  _drawState(strokeBg, fillBg, fillLabel) {
+    push();
+    
+      strokeWeight(this._style.strokeWeight);
+      rectMode(CORNER);
+
+      stroke(strokeBg);
+      fill(fillBg);
+      rect(this.x, this.y, this.w, this.h, this._style.rounding);
+
+      // Label fill
+      fill(fillLabel);
+
+      // Label rendering.
+      push();
+        noStroke();
+        textAlign(CENTER, CENTER);
+        textFont(this._style.font);
+        let size = this.w*0.9;
+        if (size > this._style.textSize) {
+          size = this._style.textSize;
+        }
+        textSize(size);
+        
+        if (this.val) {
+          text(this.labelOn, this.x + this.w/2, this.y + this.h/2);
+        }
+        else {
+          text(this.labelOff, this.x + this.w/2, this.y + this.h/2);
+        }
+        
+      pop();
+    
+    pop();
+  }
+  
+  _postDraw() {
+    super._postDraw();
+    
+    // Internal handling for updating labelOn/labelOff
+    if (this._plabel != this.label) {
+      this.labelOn  = this.label;
+      this.labelOff = this.label;
+      this._plabel  = this.label;
+    }
+  }
+}
+
+/**
+ * GuiCheckbox
+ * - Checkbox. Similar to a toggle but with a big X instead of a label.
+ */
+class GuiCheckbox extends GuiObject {
+  constructor(label, x, y, w=32, h=32, defaultVal = false) {
+    super(label, x, y, w, h);
+    
+    this.val    = defaultVal;
+    
+    this._family  = "checkbox";
+    this._type    = "checkbox";
+    
+    this._style    = {..._gui._style.checkbox};
+  }
+  
+  _setActive(active) {
+    super._setActive(active);
+    
+    if (this._triggered) {
+      this.val = !this.val;
+    }
+  }
+  
+  draw() {
+    // Render checkbox
+    if (this._active && this._hover && this.val) {
+      // Active On
+      this._drawState(this._style.fillBgActive);
+      this._drawCheck(this._style.fillCheckActive);
+    }
+    else if (this._active && this._hover && !this.val) {
+      // Active Off
+      this._drawState(this._style.fillBgActive);
+    }
+    else if (this._hover && this.val) {
+      // Hover On
+      this._drawState(this._style.fillBgHover);
+      this._drawCheck(this._style.fillCheckHover);
+    }
+    else if (this._hover && !this.val) {
+      // Hover Off
+      this._drawState(this._style.fillBgHover);
+    }
+    else if (this.val) {
+      // Inactive On
+      this._drawState(this._style.fillBg);
+      this._drawCheck(this._style.fillCheck);
+    }
+    else {
+      // Inactive Off
+      this._drawState(this._style.fillBg);
+    }
+    textSize(this.h);
+    text(this.label,this.x+this.w+5,this.y+this.h/2);
+  }
+  
+  _drawState(fillBg) {
+    push();
+      // Draw background shape
+      rectMode(CORNER);
+      stroke(this._style.strokeBg);
+      strokeWeight(this._style.strokeWeight);
+      fill(fillBg);
+      rect(this.x, this.y, this.w, this.h, this._style.rounding);
+    pop();
+  }
+  
+  _drawCheck(fillCheck) {
+    // Note: I don't really like how this is done lol; it's sloppy and can be better
+    let x8  = this.x+this.w/6;
+    let y8  = this.y+this.h/6;
+    let w16 = this.w-this.w/3;
+    let h16 = this.h-this.h/3;
+    let xw  = x8+w16;
+    let yh  = y8+h16;
+    let strokeMult = map(((this.w > this.h) ? this.w : this.h), 32, 1000, 2, 20);
+    
+    push();
+      stroke(fillCheck);
+      strokeWeight(this._style.strokeWeight*strokeMult);
+      line(x8, y8, xw, yh);
+      line(xw, y8, x8, yh);
+    pop();
+  }
+}
+
+/**
+ * GuiSlider
+ * - Horizontal slider.
+ *
+ *  TODO: fix hard coding of buffers (e.g. this.w-24)
+ *  TODO: fix so that touch corresponds with handle
+ */
+class GuiSlider extends GuiObject {
+  constructor(label, x, y, w=256, h=32, min=0, max=1) {
+    super(label, x, y, w, h);
+    
+    this.min    = min;
+    this.max    = max;
+    this.val    = min + (max - min)/2;
+    
+    this._family  = "slider";
+    this._type    = "slider";
+    
+    this._style    = {..._gui._style.slider};
+  } 
+
+  _setActive(active) {
+    super._setActive(active);
+    
+    if (this._active && this._selU != null) {
+      this.val  = map(this._selU, 0, 1, this.min, this.max);
+      this.val  = this.isInteger ? int(this.val) : this.val;
+    }
+  }
+  
+  draw() {
+    if (this._active) {
+      this._drawState(this._style.fillBgActive,
+                     this._style.fillTrackActive,
+                     this._style.fillHandleActive,
+                     this._style.strokeBgActive,
+                     this._style.strokeTrackActive,
+                     this._style.strokeHandleActive);
+    }
+    else if (this._hover) {
+      this._drawState(this._style.fillBgHover,
+                     this._style.fillTrackHover,
+                     this._style.fillHandleHover,
+                     this._style.strokeBgHover,
+                     this._style.strokeTrackHover,
+                     this._style.strokeHandleHover);
+    }
+    else {
+      this._drawState(this._style.fillBg,
+                     this._style.fillTrack,
+                     this._style.fillHandle,
+                     this._style.strokeBg,
+                     this._style.strokeTrack,
+                     this._style.strokeHandle);
+    }
+  }
+  
+  _drawState(fillBg, fillTrack, fillHandle, strokeBg, strokeTrack, strokeHandle) {
+    let xpos = map(this.val, this.min, this.max, 8, this.w-24);
+
+    push();
+      strokeWeight(this._style.strokeWeight);
+      rectMode(CORNER);
+
+      // Render bg
+      stroke(strokeBg);
+      fill(fillBg);
+      rect(this.x, this.y, this.w, this.h, this._style.rounding);
+
+      // Render track
+      this._style.trackWidth = constrain(this._style.trackWidth, 0, 1);
+      let h = this.h-20;
+    
+      push();
+        stroke(strokeTrack);
+        fill(fillTrack);
+    
+        if (this._style.trackWidth > 0) {
+          rect(this.x+10, 
+               this.y+10 + h*(1-this._style.trackWidth)*0.5, 
+               xpos, 
+               h*this._style.trackWidth, 
+               this._style.rounding, 0, 0, this._style.rounding);
+        }
+        else {
+          line(this.x+10, 
+               this.y+10 + h*(1-this._style.trackWidth)*0.5, 
+               this.x+10+xpos, 
+               this.y+10 + h*(1-this._style.trackWidth)*0.5);
+        }
+      pop();
+
+      // Render handle
+      push();
+        stroke(strokeHandle);
+        fill(fillHandle);
+        rect(this.x+xpos, this.y+8, 16, this.h-16, this._style.rounding);
+      pop();
+    pop();
+  }
+}
+
+/**
+ * GuiSliderV
+ * - Vertical slider.
+ *   Note: this may be modifiable to extend GuiSlider, but for simplicity it is
+ *         presently extending GuiObject.
+ *
+ *  TODO: fix hard coding of buffers (e.g. this.h-24)
+ *  TODO: fix so that touch corresponds with handle
+ */
+class GuiSliderV extends GuiObject {
+  constructor(label, x, y, w=32, h=256, min=0, max=1) {
+    super(label, x, y, w, h);
+    
+    this.min    = min;
+    this.max    = max;
+    this.val    = min + (max - min)/2;
+    
+    this._family  = "slider";
+    this._type    = "slider";
+    
+    this._style    = {..._gui._style.slider};
+  }
+  
+  _setActive(active) {
+    super._setActive(active);
+    
+    if (this._active && this._selV != null) {
+      this.val  = map(this._selV, 1, 0, this.min, this.max);
+      this.val  = this.isInteger ? int(this.val) : this.val;
+    }
+  }
+  
+  draw() {
+    if (this._active) {
+      this._drawState(this._style.fillBgActive,
+                     this._style.fillTrackActive,
+                     this._style.fillHandleActive,
+                     this._style.strokeBgActive,
+                     this._style.strokeTrackActive,
+                     this._style.strokeHandleActive);
+    }
+    else if (this._hover) {
+      this._drawState(this._style.fillBgHover,
+                     this._style.fillTrackHover,
+                     this._style.fillHandleHover,
+                     this._style.strokeBgHover,
+                     this._style.strokeTrackHover,
+                     this._style.strokeHandleHover);
+    }
+    else {
+      this._drawState(this._style.fillBg,
+                     this._style.fillTrack,
+                     this._style.fillHandle,
+                     this._style.strokeBg,
+                     this._style.strokeTrack,
+                     this._style.strokeHandle);
+    }
+  }
+  
+  _drawState(fillBg, fillTrack, fillHandle, strokeBg, strokeTrack, strokeHandle) {
+    let ypos = map(this.val, this.min, this.max, this.h-24, 8);
+    
+    push();
+      strokeWeight(this._style.strokeWeight);
+      rectMode(CORNER);
+
+      // Render bg
+      stroke(strokeBg);
+      fill(fillBg);
+      rect(this.x, this.y, this.w, this.h, this._style.rounding);
+
+      // Render track
+      this._style.trackWidth = constrain(this._style.trackWidth, 0, 1);
+      let w = this.w-20;
+    
+      push();
+        stroke(strokeTrack);
+        fill(fillTrack);
+    
+        if (this._style.trackWidth > 0) {
+            rect(this.x+10 + w*(1-this._style.trackWidth)*0.5, 
+                 this.y+ypos+10, 
+                 w*this._style.trackWidth, 
+                 this.h-ypos-20, 
+                 0, 0, this._style.rounding, this._style.rounding);
+        }
+        else {
+            line(this.x+10 + w*0.5, this.y+ypos+10, 
+                 this.x+10 + w*0.5, this.y+this.h-10);
+        }
+      pop();
+
+      // Render handle
+      push();
+        stroke(strokeHandle);
+        fill(fillHandle);
+        rect(this.x+8, this.y+ypos, this.w-16, 16, this._style.rounding);
+      pop();
+    pop();
+  }
+}
+
+/**
+ * GuiCrossfader
+ * - Horizontal cross fader. Indicator drawn from center.
+ *
+ *  TODO: fix so that touch corresponds with handle
+ *  TODO: fix hard coding of buffers (e.g. this.w-24)
+ */
+class GuiCrossfader extends GuiSlider {
+  constructor(label, x, y, w=256, h=32, min=(-1), max=1) {
+    super(label, x, y, w, h, min, max);
+    
+    this.snap   = false; // If true, snaps value back to 0 when not active
+    
+    this._family  = "slider";
+    this._type    = "crossfader";
+    
+    this._style = Object.create(_gui._style.slider);
+    this._style.strokeCenter = Object.create(_gui._style.crossfader.strokeCenter);
+    this._style.strokeCenterHover = Object.create(_gui._style.crossfader.strokeCenterHover);
+    this._style.strokeCenterActive = Object.create(_gui._style.crossfader.strokeCenterActive);
+  }
+  
+  _setActive(active) {
+    super._setActive(active);
+    
+    if (!this._active && this.snap) {
+      this.val = (this.min + this.max)/2;
+    }
+  }
+  
+  _drawState(fillBg, fillTrack, fillHandle, strokeBg, strokeTrack, strokeHandle) {
+    let xpos = map(this.val, this.min, this.max, 8, this.w-24);
+    let halfXpos = (this.w-16)/2;
+
+    push();
+      strokeWeight(this._style.strokeWeight);
+      rectMode(CORNER);
+
+      // Render bg
+      stroke(strokeBg);
+      fill(fillBg);
+      rect(this.x, this.y, this.w, this.h, this._style.rounding);
+ 
+      // Render track from center
+      this._style.trackWidth = constrain(this._style.trackWidth, 0, 1);
+      let h = this.h-20;
+    
+      push();
+        stroke(strokeTrack);
+        fill(fillTrack);
+    
+        if (xpos >= halfXpos) {
+          if (this._style.trackWidth > 0) {
+            rect(this.x+halfXpos+8, 
+                 this.y+10 + h*(1-this._style.trackWidth)*0.5, 
+                 xpos-halfXpos, 
+                 h*this._style.trackWidth);
+          }
+          else {
+            line(this.x+halfXpos+8, 
+                 this.y+10 + h*(1-this._style.trackWidth)*0.5, 
+                 this.x+8+xpos, 
+                 this.y+10 + h*(1-this._style.trackWidth)*0.5);
+          }
+          
+        }
+        else {
+          if (this._style.trackWidth > 0) {
+            rect(this.x+xpos, 
+                 this.y+10 + h*(1-this._style.trackWidth)*0.5, 
+                 halfXpos-xpos+8, 
+                 h*this._style.trackWidth);
+          }
+          else {
+            line(this.x+xpos, 
+                 this.y+10 + h*(1-this._style.trackWidth)*0.5, 
+                 this.x+halfXpos+8, 
+                 this.y+10 + h*(1-this._style.trackWidth)*0.5);
+          }
+        }
+    
+        // Draw center line
+        stroke(this._style.strokeCenter);
+        strokeWeight(this._style.strokeWeight);
+        line(this.x+this.w/2, this.y, this.x+this.w/2, this.y+this.h);
+      pop();
+
+      // Render handle
+      push();
+        stroke(strokeHandle);
+        fill(fillHandle);
+        rect(this.x+xpos, this.y+8, 16, this.h-16, this._style.rounding);
+      pop();
+    pop();
+  }
+}
+
+/**
+ * GuiCrossfaderV
+ * - Vertical cross fader. Indicator drawn from center.
+ *
+ *  TODO: fix so that touch corresponds with handle
+ *  TODO: fix hard coding of buffers (e.g. this.h-24)
+ */
+class GuiCrossfaderV extends GuiSliderV {
+  constructor(label, x, y, w=256, h=32, min=(-1), max=1) {
+    super(label, x, y, w, h, min, max);
+    
+    this.snap = false; // If true, snaps value back to 0 when not active
+    
+    this._family  = "slider";
+    this._type    = "crossfader";
+    
+    this._style = Object.create(_gui._style.slider);
+    this._style.strokeCenter = Object.create(_gui._style.crossfader.strokeCenter);
+    this._style.strokeCenterHover = Object.create(_gui._style.crossfader.strokeCenterHover);
+    this._style.strokeCenterActive = Object.create(_gui._style.crossfader.strokeCenterActive);
+  }
+  
+  _setActive(active) {
+    super._setActive(active);
+    
+    if (!this._active && this.snap) {
+      this.val = (this.min + this.max)/2;
+    }
+  }
+  
+  _drawState(fillBg, fillTrack, fillHandle, strokeBg, strokeTrack, strokeHandle) {
+    let ypos = map(this.val, this.min, this.max, this.h-24, 8);
+    let halfYpos = (this.h-16)/2;
+
+    push();
+      strokeWeight(this._style.strokeWeight);
+      rectMode(CORNER);
+
+      // Render bg
+      stroke(strokeBg);
+      fill(fillBg);
+      rect(this.x, this.y, this.w, this.h, this._style.rounding);
+
+      // Render track from center
+      this._style.trackWidth = constrain(this._style.trackWidth, 0, 1);
+      let w = this.w-20;
+    
+      push();
+        stroke(strokeTrack);
+        fill(fillTrack);
+    
+        if (ypos >= halfYpos) {
+          if (this._style.trackWidth > 0) {
+            rect(this.x+10 + w*(1-this._style.trackWidth)*0.5, 
+                 this.y+halfYpos+8, 
+                 w*this._style.trackWidth, 
+                 ypos-halfYpos);
+          }
+          else {
+            line(this.x+10 + w*(1-this._style.trackWidth)*0.5, 
+                 this.y+halfYpos+8, 
+                 this.x+10 + w*(1-this._style.trackWidth)*0.5, 
+                 this.y+8+ypos);
+          }
+        }
+        else {
+          if (this._style.trackWidth > 0) {
+            rect(this.x+10 + w*(1-this._style.trackWidth)*0.5, 
+                 this.y+ypos, 
+                 w*this._style.trackWidth, 
+                 halfYpos-ypos+8);
+          }
+          else {
+            line(this.x+10 + w*(1-this._style.trackWidth)*0.5, 
+                 this.y+ypos, 
+                 this.x+10 + w*(1-this._style.trackWidth)*0.5, 
+                 this.y+halfYpos+8);
+          }
+        }
+    
+        // Draw center line
+        stroke(this._style.strokeCenter);
+        strokeWeight(this._style.strokeWeight);
+        line(this.x, this.y+this.h/2, this.x+this.w, this.y+this.h/2);
+      pop();
+
+      // Render handle
+      push();
+        stroke(strokeHandle);
+        fill(fillHandle);
+        rect(this.x+8, this.y+ypos, this.w-16, 16, this._style.rounding);
+      pop();
+    pop();
+  }
+}
+
+/**
+ * Gui2dSlider
+ * - Two dimensional slider that returns an X/Y pair of values
+ *
+ *  TODO: fix hard coding of buffers (e.g. this.w-24)
+ *  TODO: fix so that touch corresponds with handle
+ */
+class GuiSlider2d extends GuiObject {
+  constructor(label, x, y, w=256, h=256, minX=(-1), maxX=1, minY=(-1), maxY=1) {
+    super(label, x, y, w, h);
+    
+    this.minX   = minX;
+    this.maxX   = maxX;
+    this.minY   = minY;
+    this.maxY   = maxY;
+    this.val    = {x:0, y:0};
+    this.valX   = minX + (maxX - minX)/2;
+    this.valY   = minY + (maxY - minY)/2;
+    
+    this._family  = "slider";
+    this._type    = "slider2d";
+    
+    this._style = Object.create(_gui._style.slider);
+    this._style.handleRadius = _gui._style.slider2d.handleRadius;
+  }
+  
+  _setActive(active) {
+    super._setActive(active);
+    
+    if (this._active && this._selU != null && this._selV != null) {
+      this.valX = map(this._selU, 0, 1, this.minX, this.maxX);
+      this.valY = map(this._selV, 1, 0, this.minY, this.maxY);
+      
+      if (this.isInteger && this._type == "slider2d") {
+        this.valX = int(this.valX);
+        this.valY = int(this.valY);
+      }
+      
+      this.val  = {x: this.valX, y:this.valY};
+    }
+  }
+  
+  draw() {
+    if (this._active) {
+      this._drawState(this._style.fillBgActive,
+                     this._style.fillTrackActive,
+                     this._style.fillHandleActive,
+                     this._style.strokeBgActive,
+                     this._style.strokeTrackActive,
+                     this._style.strokeHandleActive);
+    }
+    else if (this._hover) {
+      this._drawState(this._style.fillBgHover,
+                     this._style.fillTrackHover,
+                     this._style.fillHandleHover,
+                     this._style.strokeBgHover,
+                     this._style.strokeTrackHover,
+                     this._style.strokeHandleHover);
+    }
+    else {
+      this._drawState(this._style.fillBg,
+                     this._style.fillTrack,
+                     this._style.fillHandle,
+                     this._style.strokeBg,
+                     this._style.strokeTrack,
+                     this._style.strokeHandle);
+    }
+  }
+  
+  _drawState(fillBg, fillTrack, fillHandle, strokeBg, strokeTrack, strokeHandle) {
+    let xpos = map(this.valX, this.minX, this.maxX, 8, this.w-24);
+    let ypos = map(this.valY, this.minY, this.maxY, this.h-24, 8);
+
+    push();
+      strokeWeight(this._style.strokeWeight);
+      rectMode(CORNER);
+
+      // Render bg
+      stroke(strokeBg);
+      fill(fillBg);
+      rect(this.x, this.y, this.w, this.h, this._style.rounding);
+
+      // Render crosshair (track)
+      push();
+        stroke(fillTrack);
+        line(this.x, this.y+ypos+8, this.x+this.w, this.y+ypos+8);
+        line(this.x+xpos+8, this.y, this.x+xpos+8, this.y+this.h);
+      pop();
+
+      // Render handle
+      push();
+        stroke(strokeHandle);
+        fill(fillHandle);
+    
+        ellipse(this.x+xpos+8, 
+                this.y+ypos+8,
+                this._style.handleRadius,
+                this._style.handleRadius);
+      pop();
+    pop();
+  }
+}
+
+/**
+ * GuiJoystick
+ * - Two dimensional slider that returns an X/Y pair of values 
+ *   relative to a resetting zero point at its center.
+ */
+class GuiJoystick extends GuiSlider2d {
+  constructor(label, x, y, w=256, h=256, minX=(-1), maxX=1, minY=(-1), maxY=1) {
+    super(label, x, y, w, h, minX, maxX, minY, maxY);
+    
+    this.snap = true; // If true, snaps value back to 0 when not active
+    
+    this._family  = "slider";
+    this._type    = "joystick";
+    
+    this._style = Object.create(_gui._style.slider);
+    this._style.handleRadius = _gui._style.joystick.handleRadius;
+  }
+  
+  _setActive(active) {
+    super._setActive(active);
+    
+    if (!this._active && this.snap) {
+      this.valX = (this.minX + this.maxX)/2;
+      this.valY = (this.minY + this.maxY)/2;
+      this.val  = {x: this.valX, y:this.valY};
+    }
+  }
+  
+  _drawState(fillBg, fillTrack, fillHandle, strokeBg, strokeTrack, strokeHandle) {
+    let xpos = map(this.valX, this.minX, this.maxX, 8, this.w-24);
+    let ypos = map(this.valY, this.minY, this.maxY, this.h-24, 8);
+
+    push();
+      strokeWeight(this._style.strokeWeight);
+      rectMode(CORNER);
+
+      // Render bg
+      stroke(strokeBg);
+      fill(fillBg);
+      rect(this.x, this.y, this.w, this.h, this._style.rounding);
+
+      // Render circle (track)
+      push();
+        stroke(fillTrack);
+        let r = this.w*this._style.trackRatio;
+        if (this.w > this.h) {
+          r = this.h*this._style.trackRatio;
+        }
+    
+        ellipse(this.x+this.w/2, this.y+this.h/2, r)
+      pop();
+
+      // Render handle
+      push();
+        stroke(strokeHandle);
+        fill(fillHandle);
+    
+        ellipse(this.x+xpos+8, 
+                this.y+ypos+8,
+                this._style.handleRadius,
+                this._style.handleRadius);
+      pop();
+    pop();
+  }
+}
+
+/**
+ * GuiRadio
+ * - A user-defined number of toggles, of which only one can be turned on at a time.
+ */
+class GuiRadio extends GuiObject {
+  // TODO: write this. Maybe this can be done by adding a 'group' property
+}
+
+
+
+
+
+/*******************
+ * GuiStyle
+ * - A style class that contains various presets for colors, rounding, etc.
+ *
+ *  TODO: Create more color palettes.
+ *  TODO: Study material-ui implementation of colors and try 
+ *        to implement something similar (i.e. primary and accent color)
+ */
+class GuiStyle { 
+  constructor() {
+    this.name             = "DefaultGray";
+    
+    // Global pars
+    this.strokeWeight     = 2;
+    this.rounding         = 10;
+    this.font             = 'Arial';
+    this.textSize         = 20;
+
+    this.button = {
+      strokeWeight:       2,
+      rounding:           10,
+      font:               'Arial',
+      textSize:           20, 
+      fillBg:             color(130),
+      fillBgHover:        color(196),
+      fillBgActive:       color(220),
+      fillLabel:          color(0),
+      fillLabelHover:     color(0),
+      fillLabelActive:    color(0),
+      strokeBg:           color(0), 
+      strokeBgHover:      color(0), 
+      strokeBgActive:     color(0)
+    };
+    
+    this.toggle = {
+      strokeWeight:       2, 
+      rounding:           10,
+      font:               'Arial',
+      textSize:           20, 
+      fillBgOff:          color(130),
+      fillBgOffHover:     color(196),
+      fillBgOffActive:    color(220),
+      fillBgOn:           color(230),
+      fillBgOnHover:      color(245), 
+      fillBgOnActive:     color(255),
+      fillLabelOff:       color(0), 
+      fillLabelOffHover:  color(0), 
+      fillLabelOffActive: color(0), 
+      fillLabelOn:        color(0), 
+      fillLabelOnHover:   color(0), 
+      fillLabelOnActive:  color(0), 
+      strokeBgOff:        color(0), 
+      strokeBgOffHover:   color(0), 
+      strokeBgOffActive:  color(0), 
+      strokeBgOn:         color(0), 
+      strokeBgOnHover:    color(0), 
+      strokeBgOnActive:   color(0)
+    }
+    
+    this.checkbox = {
+      strokeWeight:       2, 
+      rounding:           10,
+      fillBg:             color(100),
+      fillBgHover:        color(144),
+      fillBgActive:       color(160),
+      fillCheck:          color(200), 
+      fillCheckHover:     color(220), 
+      fillCheckActive:    color(240), 
+      strokeBg:           color(0)
+    }
+    
+    this.slider = {
+      strokeWeight:       2, 
+      rounding:           10,
+      trackWidth:         1,
+      fillBg:             color(130),
+      fillBgHover:        color(175),
+      fillBgActive:       color(175),
+      fillTrack:          color(100), 
+      fillTrackHover:     color(144), 
+      fillTrackActive:    color(144), 
+      fillHandle:         color(64), 
+      fillHandleHover:    color(96), 
+      fillHandleActive:   color(240), 
+      strokeBg:           color(0), 
+      strokeBgHover:      color(0), 
+      strokeBgActive:     color(0), 
+      strokeTrack:        color(100), 
+      strokeTrackHover:   color(144), 
+      strokeTrackActive:  color(144),
+      strokeHandle:       color(64), 
+      strokeHandleHover:  color(0), 
+      strokeHandleActive: color(0) 
+    }
+    
+    this.crossfader = {
+      strokeCenter:       color(100), 
+      strokeCenterHover:  color(100), 
+      strokeCenterActive: color(100)
+    }
+    
+    this.slider2d = {
+      handleRadius:       16
+    }
+    
+    this.joystick = {
+      handleRadius:       16
+    }
+  }
+  
+  // Default
+  Gray() {
+    this.name             = "DefaultGray";
+    
+    // Global pars
+    this.strokeWeight     = 2;
+    this.rounding         = 10;
+    this.font             = 'Arial';
+    this.textSize         = 20;
+
+    this.button = {
+      strokeWeight:       2,
+      rounding:           10,
+      font:               'Arial',
+      textSize:           20, 
+      fillBg:             color(130),
+      fillBgHover:        color(196),
+      fillBgActive:       color(220),
+      fillLabel:          color(0),
+      fillLabelHover:     color(0),
+      fillLabelActive:    color(0),
+      strokeBg:           color(0), 
+      strokeBgHover:      color(0), 
+      strokeBgActive:     color(0)
+    };
+    
+    this.toggle = {
+      strokeWeight:       2, 
+      rounding:           10,
+      font:               'Arial',
+      textSize:           20, 
+      fillBgOff:          color(130),
+      fillBgOffHover:     color(196),
+      fillBgOffActive:    color(220),
+      fillBgOn:           color(230),
+      fillBgOnHover:      color(245), 
+      fillBgOnActive:     color(255),
+      fillLabelOff:       color(0), 
+      fillLabelOffHover:  color(0), 
+      fillLabelOffActive: color(0), 
+      fillLabelOn:        color(0), 
+      fillLabelOnHover:   color(0), 
+      fillLabelOnActive:  color(0), 
+      strokeBgOff:        color(0), 
+      strokeBgOffHover:   color(0), 
+      strokeBgOffActive:  color(0), 
+      strokeBgOn:         color(0), 
+      strokeBgOnHover:    color(0), 
+      strokeBgOnActive:   color(0)
+    }
+    
+    this.checkbox = {
+      strokeWeight:       2, 
+      rounding:           10,
+      fillBg:             color(100),
+      fillBgHover:        color(144),
+      fillBgActive:       color(160),
+      fillCheck:          color(200), 
+      fillCheckHover:     color(220), 
+      fillCheckActive:    color(240), 
+      strokeBg:           color(0)
+    }
+    
+    this.slider = {
+      strokeWeight:       2, 
+      rounding:           10,
+      trackWidth:         1,
+      fillBg:             color(130),
+      fillBgHover:        color(175),
+      fillBgActive:       color(175),
+      fillTrack:          color(100), 
+      fillTrackHover:     color(144), 
+      fillTrackActive:    color(144), 
+      fillHandle:         color(64), 
+      fillHandleHover:    color(96), 
+      fillHandleActive:   color(240), 
+      strokeBg:           color(0), 
+      strokeBgHover:      color(0), 
+      strokeBgActive:     color(0), 
+      strokeTrack:        color(100), 
+      strokeTrackHover:   color(144), 
+      strokeTrackActive:  color(144),
+      strokeHandle:       color(64), 
+      strokeHandleHover:  color(0), 
+      strokeHandleActive: color(0) 
+    }
+    
+    this.crossfader = {
+      strokeCenter:       color(100), 
+      strokeCenterHover:  color(100), 
+      strokeCenterActive: color(100)
+    }
+    
+    this.slider2d = {
+      handleRadius:       16
+    }
+    
+    this.joystick = {
+      handleRadius:       16
+    }
+  }
+
+  // 
+  Rose() {
+    this.name             = "Rose";
+    
+    // Global pars
+    this.strokeWeight     = 2;
+    this.rounding         = 10;
+    this.font             = 'Arial';
+    this.textSize         = 20;
+
+    this.button = {
+      strokeWeight:       2,
+      rounding:           10,
+      font:               'Arial',
+      textSize:           20, 
+      fillBg:             color('#E57FBE'),
+      fillBgHover:        color('#EFABD5'),
+      fillBgActive:       color('#FFE6F4'),
+      fillLabel:          color('#3F102F'),
+      fillLabelHover:     color('#3F102F'),
+      fillLabelActive:    color('#3F102F'),
+      strokeBg:           color('#3F102F'), 
+      strokeBgHover:      color('#3F102F'), 
+      strokeBgActive:     color('#3F102F')
+    };
+    
+    this.toggle = {
+      strokeWeight:       2, 
+      rounding:           10,
+      font:               'Arial',
+      textSize:           20, 
+      fillBgOff:          color('#CC69AB'),
+      fillBgOffHover:     color('#E288C4'),
+      fillBgOffActive:    color('#FFF3FA'),
+      fillBgOn:           color('#FFE6F4'),
+      fillBgOnHover:      color('#FFF3FA'), 
+      fillBgOnActive:     color('#FAFAFA'),
+      fillLabelOff:       color('#3F102F'), 
+      fillLabelOffHover:  color('#3F102F'), 
+      fillLabelOffActive: color('#3F102F'), 
+      fillLabelOn:        color('#3F102F'), 
+      fillLabelOnHover:   color('#3F102F'), 
+      fillLabelOnActive:  color('#3F102F'), 
+      strokeBgOff:        color('#3F102F'), 
+      strokeBgOffHover:   color('#3F102F'), 
+      strokeBgOffActive:  color('#3F102F'), 
+      strokeBgOn:         color('#3F102F'), 
+      strokeBgOnHover:    color('#3F102F'), 
+      strokeBgOnActive:   color('#3F102F')
+    }
+    
+    this.checkbox = {
+      strokeWeight:       2, 
+      rounding:           10,
+      fillBg:             color('#7F3663'),
+      fillBgHover:        color('#C45093'),
+      fillBgActive:       color('#E57FBE'),
+      fillCheck:          color('#FFE6F4'), 
+      fillCheckHover:     color('#FFF3FA'), 
+      fillCheckActive:    color('#FAFAFA'), 
+      strokeBg:           color('#3F102F')
+    }
+    
+    this.slider = {
+      strokeWeight:       2, 
+      rounding:           10,
+      trackWidth:         1,
+      fillBg:             color('#FFE6F4'),
+      fillBgHover:        color('#FFE6F4'),
+      fillBgActive:       color('#FFF3FA'),
+      fillTrack:          color('#C45093'), 
+      fillTrackHover:     color('#CC66A6'), 
+      fillTrackActive:    color('#D877B4'), 
+      fillHandle:         color('#7F3663'), 
+      fillHandleHover:    color('#E57FBE'), 
+      fillHandleActive:   color('#FAFAFA'), 
+      strokeBg:           color('#3F102F'), 
+      strokeBgHover:      color('#3F102F'), 
+      strokeBgActive:     color('#3F102F'), 
+      strokeTrack:        color('#C45093'), 
+      strokeTrackHover:   color('#CC66A6'), 
+      strokeTrackActive:  color('#D877B4'),
+      strokeHandle:       color('#3F102F'), 
+      strokeHandleHover:  color('#3F102F'), 
+      strokeHandleActive: color('#3F102F') 
+    }
+    
+    this.crossfader = {
+      strokeCenter:       color('#C45093'), 
+      strokeCenterHover:  color('#CC66A6'), 
+      strokeCenterActive: color('#D877B4')
+    }
+    
+    this.slider2d = {
+      handleRadius:       16
+    }
+    
+    this.joystick = {
+      handleRadius:       16
+    }
+  }
+
+  // 
+  Seafoam() {
+    this.name             = "Seafoam";
+    
+    // Global pars
+    this.strokeWeight     = 2;
+    this.rounding         = 10;
+    this.font             = 'Arial';
+    this.textSize         = 20;
+
+    this.button = {
+      strokeWeight:       2,
+      rounding:           10,
+      font:               'Arial',
+      textSize:           20, 
+      fillBg:             color('#7FE5BE'),
+      fillBgHover:        color('#ABEFD5'),
+      fillBgActive:       color('#E6FFF4'),
+      fillLabel:          color('#103F2F'),
+      fillLabelHover:     color('#103F2F'),
+      fillLabelActive:    color('#103F2F'),
+      strokeBg:           color('#103F2F'), 
+      strokeBgHover:      color('#103F2F'), 
+      strokeBgActive:     color('#103F2F')
+    };
+    
+    this.toggle = {
+      strokeWeight:       2, 
+      rounding:           10,
+      font:               'Arial',
+      textSize:           20, 
+      fillBgOff:          color('#69CCAB'),
+      fillBgOffHover:     color('#88E2C4'),
+      fillBgOffActive:    color('#F3FFFA'),
+      fillBgOn:           color('#E6FFF4'),
+      fillBgOnHover:      color('#F3FFFA'), 
+      fillBgOnActive:     color('#FAFAFA'),
+      fillLabelOff:       color('#103F2F'), 
+      fillLabelOffHover:  color('#103F2F'), 
+      fillLabelOffActive: color('#103F2F'), 
+      fillLabelOn:        color('#103F2F'), 
+      fillLabelOnHover:   color('#103F2F'), 
+      fillLabelOnActive:  color('#103F2F'), 
+      strokeBgOff:        color('#103F2F'), 
+      strokeBgOffHover:   color('#103F2F'), 
+      strokeBgOffActive:  color('#103F2F'), 
+      strokeBgOn:         color('#103F2F'), 
+      strokeBgOnHover:    color('#103F2F'), 
+      strokeBgOnActive:   color('#103F2F')
+    }
+    
+    this.checkbox = {
+      strokeWeight:       2, 
+      rounding:           10,
+      fillBg:             color('#367F63'),
+      fillBgHover:        color('#50C493'),
+      fillBgActive:       color('#7FE5BE'),
+      fillCheck:          color('#E6FFF4'), 
+      fillCheckHover:     color('#F3FFFA'), 
+      fillCheckActive:    color('#FAFAFA'), 
+      strokeBg:           color('#103F2F')
+    }
+    
+    this.slider = {
+      strokeWeight:       2, 
+      rounding:           10,
+      trackWidth:         1,
+      fillBg:             color('#E6FFF4'),
+      fillBgHover:        color('#E6FFF4'),
+      fillBgActive:       color('#F3FFFA'),
+      fillTrack:          color('#50C493'), 
+      fillTrackHover:     color('#66CCA6'), 
+      fillTrackActive:    color('#77D8B4'), 
+      fillHandle:         color('#367F63'), 
+      fillHandleHover:    color('#7FE5BE'), 
+      fillHandleActive:   color('#FAFAFA'), 
+      strokeBg:           color('#103F2F'), 
+      strokeBgHover:      color('#103F2F'), 
+      strokeBgActive:     color('#103F2F'), 
+      strokeTrack:        color('#50C493'), 
+      strokeTrackHover:   color('#66CCA6'), 
+      strokeTrackActive:  color('#77D8B4'),
+      strokeHandle:       color('#103F2F'), 
+      strokeHandleHover:  color('#103F2F'), 
+      strokeHandleActive: color('#103F2F') 
+    }
+    
+    this.crossfader = {
+      strokeCenter:       color('#50C493'), 
+      strokeCenterHover:  color('#66CCA6'), 
+      strokeCenterActive: color('#77D8B4')
+    }
+    
+    this.slider2d = {
+      handleRadius:       16
+    }
+    
+    this.joystick = {
+      handleRadius:       16
+    }
+  }
+  
+  // 
+  Blue() {
+    this.name             = "Blue";
+    
+    // Global pars
+    this.strokeWeight     = 2;
+    this.rounding         = 10;
+    this.font             = 'Arial';
+    this.textSize         = 20;
+
+    this.button = {
+      strokeWeight:       2,
+      rounding:           10,
+      font:               'Arial',
+      textSize:           20, 
+      fillBg:             color('#7FBEE5'),
+      fillBgHover:        color('#ABD5EF'),
+      fillBgActive:       color('#E6F4FF'),
+      fillLabel:          color('#102F3F'),
+      fillLabelHover:     color('#102F3F'),
+      fillLabelActive:    color('#102F3F'),
+      strokeBg:           color('#102F3F'), 
+      strokeBgHover:      color('#102F3F'), 
+      strokeBgActive:     color('#102F3F')
+    };
+    
+    this.toggle = {
+      strokeWeight:       2, 
+      rounding:           10,
+      font:               'Arial',
+      textSize:           20, 
+      fillBgOff:          color('#69ABCC'),
+      fillBgOffHover:     color('#88C4E2'),
+      fillBgOffActive:    color('#F3FAFF'),
+      fillBgOn:           color('#E6F4FF'),
+      fillBgOnHover:      color('#F3FAFF'), 
+      fillBgOnActive:     color('#FAFAFA'),
+      fillLabelOff:       color('#102F3F'), 
+      fillLabelOffHover:  color('#102F3F'), 
+      fillLabelOffActive: color('#102F3F'), 
+      fillLabelOn:        color('#102F3F'), 
+      fillLabelOnHover:   color('#102F3F'), 
+      fillLabelOnActive:  color('#102F3F'), 
+      strokeBgOff:        color('#102F3F'), 
+      strokeBgOffHover:   color('#102F3F'), 
+      strokeBgOffActive:  color('#102F3F'), 
+      strokeBgOn:         color('#102F3F'), 
+      strokeBgOnHover:    color('#102F3F'), 
+      strokeBgOnActive:   color('#102F3F')
+    }
+    
+    this.checkbox = {
+      strokeWeight:       2, 
+      rounding:           10,
+      fillBg:             color('#36637F'),
+      fillBgHover:        color('#5093C4'),
+      fillBgActive:       color('#7FBEE5'),
+      fillCheck:          color('#E6F4FF'), 
+      fillCheckHover:     color('#F3FAFF'), 
+      fillCheckActive:    color('#FAFAFA'), 
+      strokeBg:           color('#102F3F')
+    }
+    
+    this.slider = {
+      strokeWeight:       2, 
+      rounding:           10,
+      trackWidth:         1,
+      fillBg:             color('#E6F4FF'),
+      fillBgHover:        color('#E6F4FF'),
+      fillBgActive:       color('#F3FAFF'),
+      fillTrack:          color('#5093C4'), 
+      fillTrackHover:     color('#66A6CC'), 
+      fillTrackActive:    color('#77B4D8'), 
+      fillHandle:         color('#36637F'), 
+      fillHandleHover:    color('#7FBEE5'), 
+      fillHandleActive:   color('#FAFAFA'), 
+      strokeBg:           color('#102F3F'), 
+      strokeBgHover:      color('#102F3F'), 
+      strokeBgActive:     color('#102F3F'), 
+      strokeTrack:        color('#5093C4'), 
+      strokeTrackHover:   color('#66A6CC'), 
+      strokeTrackActive:  color('#77B4D8'),
+      strokeHandle:       color('#102F3F'), 
+      strokeHandleHover:  color('#102F3F'), 
+      strokeHandleActive: color('#102F3F') 
+    }
+    
+    this.crossfader = {
+      strokeCenter:       color('#5093C4'), 
+      strokeCenterHover:  color('#66A6CC'), 
+      strokeCenterActive: color('#77B4D8')
+    }
+    
+    this.slider2d = {
+      handleRadius:       16
+    }
+    
+    this.joystick = {
+      handleRadius:       16
+    }
+  }
+  
+  // 
+  TerminalGreen() {
+    this.name             = "TerminalGreen";
+    
+    // Global pars
+    this.strokeWeight     = 2;
+    this.rounding         = 10;
+    this.font             = 'Arial';
+    this.textSize         = 20;
+
+    this.button = {
+      strokeWeight:       2,
+      rounding:           10,
+      font:               'Arial',
+      textSize:           20, 
+      fillBg:             color('#000000'),
+      fillBgHover:        color('#003000'),
+      fillBgActive:       color('#00F200'),
+      fillLabel:          color('#00FF00'),
+      fillLabelHover:     color('#00FF00'),
+      fillLabelActive:    color('#000000'),
+      strokeBg:           color('#00FF00'), 
+      strokeBgHover:      color('#00FF00'), 
+      strokeBgActive:     color('#007F00')
+    };
+    
+    this.toggle = {
+      strokeWeight:       2, 
+      rounding:           10,
+      font:               'Arial',
+      textSize:           20, 
+      fillBgOff:          color('#000000'),
+      fillBgOffHover:     color('#003000'),
+      fillBgOffActive:    color('#00F200'),
+      fillBgOn:           color('#00D800'),
+      fillBgOnHover:      color('#00F200'), 
+      fillBgOnActive:     color('#00FF00'),
+      fillLabelOff:       color('#00FF00'), 
+      fillLabelOffHover:  color('#00FF00'), 
+      fillLabelOffActive: color('#000000'), 
+      fillLabelOn:        color('#000000'), 
+      fillLabelOnHover:   color('#000000'), 
+      fillLabelOnActive:  color('#000000'), 
+      strokeBgOff:        color('#00FF00'), 
+      strokeBgOffHover:   color('#00FF00'), 
+      strokeBgOffActive:  color('#007F00'), 
+      strokeBgOn:         color('#007F00'), 
+      strokeBgOnHover:    color('#007F00'), 
+      strokeBgOnActive:   color('#007F00')
+    }
+    
+    this.checkbox = {
+      strokeWeight:       2, 
+      rounding:           10,
+      fillBg:             color('#000000'),
+      fillBgHover:        color('#003000'),
+      fillBgActive:       color('#007F00'),
+      fillCheck:          color('#00D800'), 
+      fillCheckHover:     color('#00F200'), 
+      fillCheckActive:    color('#00FF00'), 
+      strokeBg:           color('#00FF00')
+    }
+    
+    this.slider = {
+      strokeWeight:       2, 
+      rounding:           10,
+      trackWidth:         1,
+      fillBg:             color('#000000'),
+      fillBgHover:        color('#003000'),
+      fillBgActive:       color('#005000'),
+      fillTrack:          color('#007F00'), 
+      fillTrackHover:     color('#008F00'), 
+      fillTrackActive:    color('#00AC00'), 
+      fillHandle:         color('#000000'), 
+      fillHandleHover:    color('#006000'), 
+      fillHandleActive:   color('#00FF00'), 
+      strokeBg:           color('#00FF00'), 
+      strokeBgHover:      color('#00FF00'), 
+      strokeBgActive:     color('#00FF00'), 
+      strokeTrack:        color('#007F00'), 
+      strokeTrackHover:   color('#008F00'), 
+      strokeTrackActive:  color('#00AC00'),
+      strokeHandle:       color('#00FF00'), 
+      strokeHandleHover:  color('#00FF00'), 
+      strokeHandleActive: color('#00FF00') 
+    }
+    
+    this.crossfader = {
+      strokeCenter:       color('#007F00'), 
+      strokeCenterHover:  color('#007F00'), 
+      strokeCenterActive: color('#007F00')
+    }
+    
+    this.slider2d = {
+      handleRadius:       16
+    }
+    
+    this.joystick = {
+      handleRadius:       16
+    }
+  }
+  
+  // 
+  TerminalRed() {
+    this.name             = "TerminalRed";
+    
+    // Global pars
+    this.strokeWeight     = 2;
+    this.rounding         = 10;
+    this.font             = 'Arial';
+    this.textSize         = 20;
+
+    this.button = {
+      strokeWeight:       2,
+      rounding:           10,
+      font:               'Arial',
+      textSize:           20, 
+      fillBg:             color('#000000'),
+      fillBgHover:        color('#300000'),
+      fillBgActive:       color('#F20000'),
+      fillLabel:          color('#FF0000'),
+      fillLabelHover:     color('#FF0000'),
+      fillLabelActive:    color('#000000'),
+      strokeBg:           color('#FF0000'), 
+      strokeBgHover:      color('#FF0000'), 
+      strokeBgActive:     color('#7F0000')
+    };
+    
+    this.toggle = {
+      strokeWeight:       2, 
+      rounding:           10,
+      font:               'Arial',
+      textSize:           20, 
+      fillBgOff:          color('#000000'),
+      fillBgOffHover:     color('#300000'),
+      fillBgOffActive:    color('#F20000'),
+      fillBgOn:           color('#D80000'),
+      fillBgOnHover:      color('#F20000'), 
+      fillBgOnActive:     color('#FF0000'),
+      fillLabelOff:       color('#FF0000'), 
+      fillLabelOffHover:  color('#FF0000'), 
+      fillLabelOffActive: color('#000000'), 
+      fillLabelOn:        color('#000000'), 
+      fillLabelOnHover:   color('#000000'), 
+      fillLabelOnActive:  color('#000000'), 
+      strokeBgOff:        color('#FF0000'), 
+      strokeBgOffHover:   color('#FF0000'), 
+      strokeBgOffActive:  color('#7F0000'), 
+      strokeBgOn:         color('#7F0000'), 
+      strokeBgOnHover:    color('#7F0000'), 
+      strokeBgOnActive:   color('#7F0000')
+    }
+    
+    this.checkbox = {
+      strokeWeight:       2, 
+      rounding:           10,
+      fillBg:             color('#000000'),
+      fillBgHover:        color('#300000'),
+      fillBgActive:       color('#7F0000'),
+      fillCheck:          color('#D80000'), 
+      fillCheckHover:     color('#F20000'), 
+      fillCheckActive:    color('#FF0000'), 
+      strokeBg:           color('#FF0000')
+    }
+    
+    this.slider = {
+      strokeWeight:       2, 
+      rounding:           10,
+      trackWidth:         1,
+      fillBg:             color('#000000'),
+      fillBgHover:        color('#300000'),
+      fillBgActive:       color('#500000'),
+      fillTrack:          color('#7F0000'), 
+      fillTrackHover:     color('#8F0000'), 
+      fillTrackActive:    color('#AC0000'), 
+      fillHandle:         color('#000000'), 
+      fillHandleHover:    color('#600000'), 
+      fillHandleActive:   color('#FF0000'), 
+      strokeBg:           color('#FF0000'), 
+      strokeBgHover:      color('#FF0000'), 
+      strokeBgActive:     color('#FF0000'), 
+      strokeTrack:        color('#7F0000'), 
+      strokeTrackHover:   color('#8F0000'), 
+      strokeTrackActive:  color('#AC0000'),
+      strokeHandle:       color('#FF0000'), 
+      strokeHandleHover:  color('#FF0000'), 
+      strokeHandleActive: color('#FF0000') 
+    }
+    
+    this.crossfader = {
+      strokeCenter:       color('#7F0000'), 
+      strokeCenterHover:  color('#7F0000'), 
+      strokeCenterActive: color('#7F0000')
+    }
+    
+    this.slider2d = {
+      handleRadius:       16
+    }
+    
+    this.joystick = {
+      handleRadius:       16
+    }
+  }
+  
+  // 
+  TerminalBlue() {
+    this.name             = "TerminalBlue";
+    
+    // Global pars
+    this.strokeWeight     = 2;
+    this.rounding         = 10;
+    this.font             = 'Arial';
+    this.textSize         = 20;
+
+    this.button = {
+      strokeWeight:       2,
+      rounding:           10,
+      font:               'Arial',
+      textSize:           20, 
+      fillBg:             color('#000000'),
+      fillBgHover:        color('#000030'),
+      fillBgActive:       color('#4040F2'),
+      fillLabel:          color('#4040FF'),
+      fillLabelHover:     color('#4040FF'),
+      fillLabelActive:    color('#000000'),
+      strokeBg:           color('#4040FF'), 
+      strokeBgHover:      color('#4040FF'), 
+      strokeBgActive:     color('#40407F')
+    };
+    
+    this.toggle = {
+      strokeWeight:       2, 
+      rounding:           10,
+      font:               'Arial',
+      textSize:           20, 
+      fillBgOff:          color('#000000'),
+      fillBgOffHover:     color('#000030'),
+      fillBgOffActive:    color('#4040F2'),
+      fillBgOn:           color('#4040D8'),
+      fillBgOnHover:      color('#4040F2'), 
+      fillBgOnActive:     color('#4040FF'),
+      fillLabelOff:       color('#4040FF'), 
+      fillLabelOffHover:  color('#4040FF'), 
+      fillLabelOffActive: color('#000000'), 
+      fillLabelOn:        color('#000000'), 
+      fillLabelOnHover:   color('#000000'), 
+      fillLabelOnActive:  color('#000000'), 
+      strokeBgOff:        color('#4040FF'), 
+      strokeBgOffHover:   color('#4040FF'), 
+      strokeBgOffActive:  color('#40407F'), 
+      strokeBgOn:         color('#40407F'), 
+      strokeBgOnHover:    color('#40407F'), 
+      strokeBgOnActive:   color('#40407F')
+    }
+    
+    this.checkbox = {
+      strokeWeight:       2, 
+      rounding:           10,
+      fillBg:             color('#000000'),
+      fillBgHover:        color('#000030'),
+      fillBgActive:       color('#40407F'),
+      fillCheck:          color('#4040D8'), 
+      fillCheckHover:     color('#4040F2'), 
+      fillCheckActive:    color('#4040FF'), 
+      strokeBg:           color('#4040FF')
+    }
+    
+    this.slider = {
+      strokeWeight:       2, 
+      rounding:           10,
+      trackWidth:         1,
+      fillBg:             color('#000000'),
+      fillBgHover:        color('#000030'),
+      fillBgActive:       color('#000050'),
+      fillTrack:          color('#20207F'), 
+      fillTrackHover:     color('#20208F'), 
+      fillTrackActive:    color('#2020AC'), 
+      fillHandle:         color('#000000'), 
+      fillHandleHover:    color('#000060'), 
+      fillHandleActive:   color('#4040FF'), 
+      strokeBg:           color('#4040FF'), 
+      strokeBgHover:      color('#4040FF'), 
+      strokeBgActive:     color('#4040FF'), 
+      strokeTrack:        color('#20207F'), 
+      strokeTrackHover:   color('#20208F'), 
+      strokeTrackActive:  color('#2020AC'),
+      strokeHandle:       color('#4040FF'), 
+      strokeHandleHover:  color('#4040FF'), 
+      strokeHandleActive: color('#4040FF') 
+    }
+    
+    this.crossfader = {
+      strokeCenter:       color('#40407F'), 
+      strokeCenterHover:  color('#40407F'), 
+      strokeCenterActive: color('#40407F')
+    }
+    
+    this.slider2d = {
+      handleRadius:       16
+    }
+    
+    this.joystick = {
+      handleRadius:       16
+    }
+  }
+  
+  // 
+  TerminalYellow() {
+    this.name             = "TerminalYellow";
+    
+    // Global pars
+    this.strokeWeight     = 2;
+    this.rounding         = 10;
+    this.font             = 'Arial';
+    this.textSize         = 20;
+
+    this.button = {
+      strokeWeight:       2,
+      rounding:           10,
+      font:               'Arial',
+      textSize:           20, 
+      fillBg:             color('#000000'),
+      fillBgHover:        color('#303000'),
+      fillBgActive:       color('#F2F200'),
+      fillLabel:          color('#FFFF00'),
+      fillLabelHover:     color('#FFFF00'),
+      fillLabelActive:    color('#000000'),
+      strokeBg:           color('#FFFF00'), 
+      strokeBgHover:      color('#FFFF00'), 
+      strokeBgActive:     color('#7F7F00')
+    };
+    
+    this.toggle = {
+      strokeWeight:       2, 
+      rounding:           10,
+      font:               'Arial',
+      textSize:           20, 
+      fillBgOff:          color('#000000'),
+      fillBgOffHover:     color('#303000'),
+      fillBgOffActive:    color('#F2F200'),
+      fillBgOn:           color('#D8D800'),
+      fillBgOnHover:      color('#F2F200'), 
+      fillBgOnActive:     color('#FFFF00'),
+      fillLabelOff:       color('#FFFF00'), 
+      fillLabelOffHover:  color('#FFFF00'), 
+      fillLabelOffActive: color('#000000'), 
+      fillLabelOn:        color('#000000'), 
+      fillLabelOnHover:   color('#000000'), 
+      fillLabelOnActive:  color('#000000'), 
+      strokeBgOff:        color('#FFFF00'), 
+      strokeBgOffHover:   color('#FFFF00'), 
+      strokeBgOffActive:  color('#7F7F00'), 
+      strokeBgOn:         color('#7F7F00'), 
+      strokeBgOnHover:    color('#7F7F00'), 
+      strokeBgOnActive:   color('#7F7F00')
+    }
+    
+    this.checkbox = {
+      strokeWeight:       2, 
+      rounding:           10,
+      fillBg:             color('#000000'),
+      fillBgHover:        color('#303000'),
+      fillBgActive:       color('#7F7F00'),
+      fillCheck:          color('#D8D800'), 
+      fillCheckHover:     color('#F2F200'), 
+      fillCheckActive:    color('#FFFF00'), 
+      strokeBg:           color('#FFFF00')
+    }
+    
+    this.slider = {
+      strokeWeight:       2, 
+      rounding:           10,
+      trackWidth:         1,
+      fillBg:             color('#000000'),
+      fillBgHover:        color('#303000'),
+      fillBgActive:       color('#505000'),
+      fillTrack:          color('#7F7F00'), 
+      fillTrackHover:     color('#8F8F00'), 
+      fillTrackActive:    color('#ACAC00'), 
+      fillHandle:         color('#000000'), 
+      fillHandleHover:    color('#606000'), 
+      fillHandleActive:   color('#FFFF00'), 
+      strokeBg:           color('#FFFF00'), 
+      strokeBgHover:      color('#FFFF00'), 
+      strokeBgActive:     color('#FFFF00'), 
+      strokeTrack:        color('#7F7F00'), 
+      strokeTrackHover:   color('#8F8F00'), 
+      strokeTrackActive:  color('#ACAC00'),
+      strokeHandle:       color('#FFFF00'), 
+      strokeHandleHover:  color('#FFFF00'), 
+      strokeHandleActive: color('#FFFF00') 
+    }
+    
+    this.crossfader = {
+      strokeCenter:       color('#7F7F00'), 
+      strokeCenterHover:  color('#7F7F00'), 
+      strokeCenterActive: color('#7F7F00')
+    }
+    
+    this.slider2d = {
+      handleRadius:       16
+    }
+    
+    this.joystick = {
+      handleRadius:       16
+    }
+  }
+  
+  // 
+  TerminalMagenta() {
+    this.name             = "TerminalMagenta";
+    
+    // Global pars
+    this.strokeWeight     = 2;
+    this.rounding         = 10;
+    this.font             = 'Arial';
+    this.textSize         = 20;
+
+    this.button = {
+      strokeWeight:       2,
+      rounding:           10,
+      font:               'Arial',
+      textSize:           20, 
+      fillBg:             color('#000000'),
+      fillBgHover:        color('#300030'),
+      fillBgActive:       color('#F200F2'),
+      fillLabel:          color('#FF00FF'),
+      fillLabelHover:     color('#FF00FF'),
+      fillLabelActive:    color('#000000'),
+      strokeBg:           color('#FF00FF'), 
+      strokeBgHover:      color('#FF00FF'), 
+      strokeBgActive:     color('#7F007F')
+    };
+    
+    this.toggle = {
+      strokeWeight:       2, 
+      rounding:           10,
+      font:               'Arial',
+      textSize:           20, 
+      fillBgOff:          color('#000000'),
+      fillBgOffHover:     color('#300030'),
+      fillBgOffActive:    color('#F200F2'),
+      fillBgOn:           color('#D800D8'),
+      fillBgOnHover:      color('#F200F2'), 
+      fillBgOnActive:     color('#FF00FF'),
+      fillLabelOff:       color('#FF00FF'), 
+      fillLabelOffHover:  color('#FF00FF'), 
+      fillLabelOffActive: color('#000000'), 
+      fillLabelOn:        color('#000000'), 
+      fillLabelOnHover:   color('#000000'), 
+      fillLabelOnActive:  color('#000000'), 
+      strokeBgOff:        color('#FF00FF'), 
+      strokeBgOffHover:   color('#FF00FF'), 
+      strokeBgOffActive:  color('#7F007F'), 
+      strokeBgOn:         color('#7F007F'), 
+      strokeBgOnHover:    color('#7F007F'), 
+      strokeBgOnActive:   color('#7F007F')
+    }
+    
+    this.checkbox = {
+      strokeWeight:       2, 
+      rounding:           10,
+      fillBg:             color('#000000'),
+      fillBgHover:        color('#300030'),
+      fillBgActive:       color('#7F007F'),
+      fillCheck:          color('#D800D8'), 
+      fillCheckHover:     color('#F200F2'), 
+      fillCheckActive:    color('#FF00FF'), 
+      strokeBg:           color('#FF00FF')
+    }
+    
+    this.slider = {
+      strokeWeight:       2, 
+      rounding:           10,
+      trackWidth:         1,
+      fillBg:             color('#000000'),
+      fillBgHover:        color('#300030'),
+      fillBgActive:       color('#500050'),
+      fillTrack:          color('#7F007F'), 
+      fillTrackHover:     color('#8F008F'), 
+      fillTrackActive:    color('#AC00AC'), 
+      fillHandle:         color('#000000'), 
+      fillHandleHover:    color('#600060'), 
+      fillHandleActive:   color('#FF00FF'), 
+      strokeBg:           color('#FF00FF'), 
+      strokeBgHover:      color('#FF00FF'), 
+      strokeBgActive:     color('#FF00FF'), 
+      strokeTrack:        color('#7F007F'), 
+      strokeTrackHover:   color('#8F008F'), 
+      strokeTrackActive:  color('#AC00AC'),
+      strokeHandle:       color('#FF00FF'), 
+      strokeHandleHover:  color('#FF00FF'), 
+      strokeHandleActive: color('#FF00FF') 
+    }
+    
+    this.crossfader = {
+      strokeCenter:       color('#7F007F'), 
+      strokeCenterHover:  color('#7F007F'), 
+      strokeCenterActive: color('#7F007F')
+    }
+    
+    this.slider2d = {
+      handleRadius:       16
+    }
+    
+    this.joystick = {
+      handleRadius:       16
+    }
+  }
+}

File diff suppressed because it is too large
+ 21656 - 0
libs/p5_patch.js


+ 204 - 0
libs/scenemanager.js

@@ -0,0 +1,204 @@
+//
+// p5 SceneManager helps you create p5.js sketches with multiple states / scenes
+// Each scene is a like a sketch within the main sketch. You focus on creating
+// the scene like a regular sketch and SceneManager ensure scene switching
+// routing the main setup(), draw(), mousePressed(), etc. events to the 
+// appropriate current scene.
+//
+// Author: Marian Veteanu
+// http://github.com/mveteanu
+//
+function SceneManager(p)
+{
+    this.scenes = [];
+    this.scene = null;
+    
+    // Wire relevant p5.js events, except setup()
+    // If you don't call this method, you need to manually wire events
+    this.wire = function()
+    {
+        const P5Events = [ "mouseClicked", 
+                "mousePressed", 
+                "mouseReleased", 
+                "mouseMoved", 
+                "mouseDragged", 
+                "doubleClicked", 
+                "mouseWheel", 
+                "keyPressed", 
+                "keyReleased", 
+                "keyTyped", 
+                "touchStarted", 
+                "touchMoved", 
+                "touchEnded", 
+                "deviceMoved", 
+                "deviceTurned", 
+                "deviceShaken" ];
+
+        var me = this;
+        var o = p != null ? p : window;
+
+        // Wire draw manually for speed reasons...
+        o.draw = function(){ me.draw(); };
+
+        // This loop will wire automatically all P5 events to each scene like this:
+        // o.mouseClicked = function() { me.handleEvent("mouseClicked"); }
+        for(var i = 0; i < P5Events.length; i++)
+        {
+            let sEvent = P5Events[i]; // let is necesary to set the scope at the level of for
+            o[sEvent] = function() { me.handleEvent(sEvent) };
+        }
+        
+        return me;
+    }
+
+
+    // Add a scene to the collection
+    // You need to add all the scenes if intend to call .showNextScene()
+    this.addScene = function( fnScene )
+    {
+        var oScene = new fnScene(p);
+
+        // inject p as a property of the scene
+        this.p = p;
+        
+        // inject sceneManager as a property of the scene
+        oScene.sceneManager = this;
+
+        var o = {   fnScene: fnScene, 
+                    oScene: oScene,
+                    hasSetup : "setup" in oScene,
+                    hasEnter : "enter" in oScene,
+                    hasDraw : "draw" in oScene,
+                    setupExecuted : false,
+                    enterExecuted : false };
+
+        this.scenes.push(o);
+        return o;
+    }
+
+    // Return the index of a scene in the internal collection
+    this.findSceneIndex = function( fnScene )
+    {
+        for(var i = 0; i < this.scenes.length; i++)
+        {
+            var o = this.scenes[i]; 
+            if ( o.fnScene == fnScene )
+                return i;
+        }
+
+        return -1;
+    }
+
+    // Return a scene object wrapper
+    this.findScene = function( fnScene )
+    {
+        var i = this.findSceneIndex( fnScene );
+        return i >= 0 ? this.scenes[i] : null;
+    }
+
+    // Returns true if the current displayed scene is fnScene
+    this.isCurrent = function ( fnScene )
+    {
+        if ( this.scene == null )
+            return false;
+
+        return this.scene.fnScene == fnScene;
+    }
+
+    // Show a scene based on the function name
+    // Optionally you can send arguments to the scene
+    // Arguments will be retrieved in the scene via .sceneArgs property
+    this.showScene = function( fnScene, sceneArgs )
+    {
+        var o = this.findScene( fnScene );
+
+        if ( o == null )
+            o = this.addScene( fnScene );
+        
+        // Re-arm the enter function at each show of the scene
+        o.enterExecuted = false;
+
+        this.scene = o;
+
+        // inject sceneArgs as a property of the scene
+        o.oScene.sceneArgs = sceneArgs;
+    }
+
+    // Show the next scene in the collection
+    // Useful if implementing demo applications 
+    // where you want to advance scenes automatically
+    this.showNextScene = function( sceneArgs )
+    {
+        if ( this.scenes.length == 0 )
+            return;
+
+        var nextSceneIndex = 0;
+
+        if ( this.scene != null )
+        {
+            // search current scene... 
+            // can be optimized to avoid searching current scene...
+            var i = this.findSceneIndex( this.scene.fnScene );
+            nextSceneIndex = i < this.scenes.length - 1 ? i + 1 : 0;
+        }
+
+        var nextScene = this.scenes[nextSceneIndex];
+        this.showScene( nextScene.fnScene, sceneArgs );
+    }
+    
+    // This is the SceneManager .draw() method
+    // This will dispatch the main draw() to the 
+    // current scene draw() method
+    this.draw = function()
+    {
+        // take the current scene in a variable to protect it in case
+        // it gets changed by the user code in the events such as setup()...
+        var currScene = this.scene;
+        
+        if ( currScene == null )
+            return;
+
+        if ( currScene.hasSetup && !currScene.setupExecuted  )
+        {
+            currScene.oScene.setup();
+            currScene.setupExecuted = true;
+        }
+
+        if ( currScene.hasEnter && !currScene.enterExecuted  )
+        {
+            currScene.oScene.enter();
+            currScene.enterExecuted = true;
+        }
+
+        if ( currScene.hasDraw )
+        {
+            currScene.oScene.draw();
+        }
+    }
+
+
+    // Handle a certain even for a scene... 
+    // It is used by the anonymous functions from the wire() function
+    this.handleEvent = function(sEvent)
+    {
+        if ( this.scene == null || this.scene.oScene == null )
+            return;
+
+        var fnSceneEvent = this.scene.oScene[sEvent];
+        if (fnSceneEvent)
+            fnSceneEvent.call(this.scene.oScene);
+    }
+
+    // Legacy method... preserved for maintaining compatibility
+    this.mousePressed = function()
+    {
+        this.handleEvent("mousePressed");
+    }
+
+    // Legacy method... preserved for maintaining compatibility
+    this.keyPressed = function()
+    {
+        this.handleEvent("keyPressed");
+    }
+
+}

BIN
media/elephants-dream.webm


BIN
media/file_example_MOV_640_800kB.mov


+ 457 - 0
oreto_restyle.svg

@@ -0,0 +1,457 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="Livello_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 2200 900" style="enable-background:new 0 0 2200 900;" xml:space="preserve">
+<style type="text/css">
+	.st0{fill:none;}
+	.st1{fill:#B86AF0;}
+	.st2{fill:#74EA57;}
+	.st3{fill:url(#SVGID_1_);}
+	.st4{fill:url(#SVGID_2_);}
+	.st5{fill:url(#SVGID_3_);}
+</style>
+<pattern  y="900" width="204" height="184" patternUnits="userSpaceOnUse" id="Unnamed_Pattern" viewBox="0 -184 204 184" style="overflow:visible;">
+	<g>
+		<rect y="-184" class="st0" width="204" height="184"/>
+		<g>
+			<rect y="-184" class="st0" width="204" height="184"/>
+			<rect y="-184" class="st1" width="204" height="184"/>
+		</g>
+	</g>
+</pattern>
+<rect x="4" y="958.3" class="st2" width="2200" height="898"/>
+<polygon points="1919.2,1035.9 1922.5,1038.4 1926.9,1043 1930.7,1047.3 1933.6,1051.3 1935,1054.5 1935.3,1056.7 1935.6,1058.5 
+	1935.2,1059.3 1930.6,1062.2 1926,1063.6 1920.5,1066.4 1914,1069.7 1910,1073.5 1906,1078.2 1904.5,1079.5 1899.4,1083.5 
+	1893.7,1087.4 1889,1091.1 1883.8,1094.9 1878.3,1099.5 1874.4,1102.9 1872,1105.1 1869.3,1107.8 1865.6,1112.3 1861.2,1117.5 
+	1857.6,1121.8 1855.4,1124.6 1852,1128.5 1850.3,1131.5 1848.1,1134.5 1846.4,1136.8 1843.5,1140.8 1840,1145.1 1836.8,1149.5 
+	1835.6,1150.9 1834.1,1152.6 1830.6,1155.8 1828.1,1159.1 1825.1,1163.3 1822.3,1166.4 1814.7,1174.5 1806.6,1183.1 1800.8,1188.9 
+	1792.9,1196.7 1785.8,1204.1 1777.4,1212.5 1776.2,1214.9 1775.2,1216.8 1771.3,1220.3 1764.9,1226.3 1760.9,1230.7 1757.3,1234.4 
+	1752.5,1239.5 1748.9,1243.3 1746.2,1246.4 1743.6,1249 1741.7,1249.8 1738.7,1250.2 1730,1253.4 1720.1,1257.1 1717.8,1258.3 
+	1714.9,1259.4 1712.9,1259.9 1707.8,1261 1701.3,1260.5 1688.1,1259.7 1686.4,1259.5 1682.7,1261.6 1679.7,1263.7 1677.8,1266.3 
+	1671.4,1278.1 1664.4,1290.8 1663.7,1291.5 1658,1293.5 1656,1294.2 1651.8,1294.2 1648.1,1294.1 1646.3,1293.2 1644.4,1292.5 
+	1640.7,1292.1 1637.2,1293 1635,1294.9 1632.9,1297.9 1632.4,1300.1 1631.9,1302.2 1632.3,1305.5 1632,1307.7 1630.4,1310.9 
+	1628.1,1312.7 1624.6,1313.7 1621,1314.4 1616.2,1315.3 1613.7,1314.4 1612.4,1312.9 1611.2,1309.8 1610.9,1304.6 1610.3,1297.8 
+	1609.5,1292.3 1608.7,1289.4 1607.1,1286.2 1605.3,1283.8 1603.2,1280.9 1602,1279.3 1600,1279.3 1597.9,1280.5 1597.4,1282.7 
+	1597.9,1286.1 1598.3,1289.9 1597.7,1292.3 1595.8,1293.2 1587.4,1295.5 1584,1297.7 1580.8,1300.3 1579.3,1303.9 1576.4,1310.5 
+	1573.9,1315.7 1573.4,1317.5 1573.9,1319 1576.2,1321.1 1581.1,1326.8 1585,1331.4 1588.2,1335.3 1590.6,1338.2 1591,1340.2 
+	1590.6,1342 1587.9,1344.9 1581.7,1349.4 1576.2,1352.6 1572.1,1354.6 1569.4,1355.7 1564.9,1354.2 1561.8,1352.7 1558.7,1350.1 
+	1554.5,1346.8 1552.9,1344.8 1552.8,1343 1553.7,1339.9 1556.3,1336.1 1556.4,1332.2 1556.4,1330.1 1553.8,1326.2 1552.5,1324.4 
+	1549.5,1323.5 1546.6,1324.8 1542.6,1328.3 1540.8,1332.7 1538.9,1338.3 1537.6,1340.6 1536.2,1344.5 1534.9,1349.3 1534.9,1352.7 
+	1536.4,1357.8 1541.4,1371.1 1543.2,1373.4 1548.5,1377.6 1552.5,1381.4 1553.7,1382.8 1553.1,1384.5 1551.9,1386.8 1543.7,1394.2 
+	1533.7,1402.8 1530.2,1405.5 1526.6,1407.5 1521.9,1409 1520.9,1408.2 1516.1,1402.3 1511.1,1396.3 1508.1,1391.7 1505.6,1386.3 
+	1503.5,1382.4 1501.8,1378.6 1500,1375.4 1499.2,1374.2 1496.7,1372.6 1494.3,1372.1 1491.1,1373 1486.2,1375 1480.5,1379.8 
+	1475.1,1385 1469.7,1391 1464.3,1395.1 1455.7,1402.2 1450.2,1406.7 1448.3,1407.9 1447.1,1409.6 1446.2,1411.7 1444.6,1413.3 
+	1442.1,1417.6 1439.9,1421 1438.9,1426.9 1438.4,1431.9 1438.6,1434.4 1436.5,1435.7 1432.3,1436.6 1428.8,1436.1 1424.1,1434 
+	1414.5,1430.9 1407.3,1428.9 1400.6,1428.3 1396.5,1428.5 1393.1,1429.6 1389.2,1431.6 1385.2,1434.7 1381.1,1437.9 1378.1,1440.7 
+	1376.5,1442.8 1374.5,1444.9 1371.9,1447 1369.5,1448.8 1366.8,1448.9 1364.5,1449.1 1362.2,1448.9 1359.9,1448.1 1357.7,1449.4 
+	1355.8,1450.9 1355.7,1453.5 1356.5,1457.2 1356.9,1460.6 1355.9,1462.4 1356.7,1464.5 1355.6,1468.5 1355.1,1469.3 1351,1470.9 
+	1339.7,1472.9 1337.1,1473 1331.9,1474.6 1324.4,1477.3 1317.9,1480.3 1315.3,1483.3 1308.5,1490.9 1305.2,1493.6 1300.2,1497.3 
+	1297.2,1499.6 1293.6,1504.6 1290,1508.7 1287.9,1510.7 1282.5,1515.5 1277.7,1519 1269.4,1523.8 1265.3,1527.1 1259.9,1532.3 
+	1248.3,1537.5 1239.3,1541 1231,1543.8 1224.9,1546.5 1221.2,1548.1 1219.9,1550 1219.3,1552.3 1219.8,1555.1 1220.2,1556.9 
+	1220.1,1557.9 1218.9,1559.2 1216.4,1558.4 1210.8,1556.7 1207.7,1555.9 1206.1,1556.4 1203.5,1557.2 1200.7,1559.7 1199.7,1561.2 
+	1196.4,1567.8 1192.9,1574.5 1190.1,1580.5 1187.7,1584.5 1185.9,1588.3 1184.8,1588.6 1183.4,1587.9 1177.2,1586 1171,1583.7 
+	1170.7,1583.5 1161.9,1583 1158.7,1583 1153.2,1583.6 1144.9,1584.6 1139.4,1585.1 1136.3,1585.6 1133.7,1586.2 1131.9,1587.7 
+	1130.2,1589.6 1129.2,1592.6 1128.3,1597.9 1127.2,1603 1126.3,1607.4 1126.2,1610.4 1126.5,1613.8 1126.1,1615.4 1125.3,1618.1 
+	1124.5,1620 1123.8,1622.1 1123.8,1623.6 1122.9,1625.5 1121.6,1627.5 1118.8,1630.8 1116.7,1632.4 1115.5,1633.4 1114.1,1634.6 
+	1111.5,1637.9 1109.3,1639.9 1108.8,1642.5 1108.1,1647 1108.1,1652.4 1108.6,1655.6 1109.8,1658.1 1111.7,1660.6 1113,1662.6 
+	1115.6,1665 1117.7,1666.7 1119.4,1668.4 1121.4,1670.4 1122.3,1672 1123.6,1675.1 1124,1677.5 1123.9,1680.5 1123.7,1682.5 
+	1122.1,1684.9 1120.6,1686.9 1118.4,1688.4 1115.5,1691.1 1114.3,1693.1 1113.5,1695.9 1112.6,1701 1111.7,1706 1110.7,1711.5 
+	1109.5,1715.5 1107.8,1720.2 1106.2,1723.7 1104.4,1726.8 1102.9,1729 1101.2,1731 1099.1,1731.6 1094.8,1732.3 1091.4,1732.8 
+	1086.9,1733.1 1082.3,1733.1 1080.6,1733.4 1077.1,1734.6 1073,1735.6 1068.3,1736.8 1065.2,1737.6 1062.8,1741.2 1061.5,1744.9 
+	1060,1748.9 1058.8,1751.9 1058.3,1754.4 1057.7,1758.6 1058,1762.4 1057.8,1765.7 1057.6,1769.1 1057.6,1771.9 1057.3,1774.6 
+	1057.2,1776 1055.7,1778 1053.1,1781.5 1049.8,1784.2 1045.2,1788.8 1040.9,1793.6 1037.9,1796.7 1034.7,1800.1 1033.4,1801.6 
+	1030.8,1803 1027.5,1803.1 1025.3,1801.9 1023.5,1801.1 1022.2,1800.2 1020,1800.8 1015.8,1802.3 1014,1803 1011.3,1805.5 
+	1010.1,1806.4 1009.2,1808.7 1007.6,1811.7 1006.1,1813.8 1004.9,1815.4 1003.5,1816.2 1001.8,1817.1 1000.1,1817.6 998.3,1817.6 
+	997.3,1817.3 995.8,1816.4 994.8,1815 993.6,1813.9 992.7,1811.8 992.1,1808.4 990.9,1806.8 989.6,1805.7 988.6,1803.6 
+	988.1,1802.7 987,1801.6 985.6,1800.6 984.5,1799.4 983,1798.3 981.5,1797.8 978.9,1797 977.8,1796 976.7,1795.2 973,1795.5 
+	953.6,1796.5 946.7,1797.5 940.7,1797.9 932.1,1798.7 923.9,1799.6 919.1,1800.1 917.5,1801 916.7,1802.1 915,1802.1 912.9,1801.1 
+	909.5,1797.3 907.9,1795 905.4,1792 902.8,1789.6 899.5,1788.6 893.7,1788.1 889.2,1787.4 885.9,1787.6 884.4,1787.5 878.5,1783.1 
+	857,1768.7 850.3,1763.6 847.3,1761.8 836.3,1756.1 830,1752.5 825.1,1749 818.7,1745.1 817.2,1743.7 815.4,1741 813.1,1738.2 
+	810,1736.2 806.2,1734 796.7,1729.5 792.5,1728.1 789.5,1727.3 785.1,1725.9 780.2,1724.6 776.5,1723.8 772.4,1720 769,1716.7 
+	764.9,1712.9 761.2,1710 757.2,1707.6 754.7,1706 751.6,1705.1 746.8,1704.2 744,1703.9 742.4,1703 738.4,1700.9 735.8,1699.9 
+	730.9,1699.5 715.6,1698.6 710.5,1698.4 706.1,1697.5 700.4,1696.7 699.9,1695.9 699.3,1694.3 696.3,1692.2 690.3,1688 686,1685.1 
+	682.9,1683 681.5,1681.7 678.1,1678.7 673.8,1677.6 666.1,1676.1 658.8,1675.6 654.8,1675.3 649.2,1675.5 643.1,1675.5 
+	641.5,1675.6 632.6,1673.4 630.1,1672.9 627.4,1671.6 625.2,1670.4 622.5,1670 619.7,1669.9 616.8,1670.1 615,1671 612.6,1673 
+	611.1,1674.6 609.6,1676.2 607.4,1678.1 605.9,1679.7 604.6,1682.4 602.9,1685.3 600.6,1688 596.1,1691.7 592.2,1695.3 
+	589.7,1698.3 584.9,1705.1 579.8,1711.8 574.7,1719.2 570.4,1721.2 568.9,1722.2 565.1,1723.2 558.1,1724.7 554,1721.7 547,1716.9 
+	543.4,1714.2 539.2,1712.2 536.3,1711 532.7,1710.4 529,1709.8 525.4,1710 522.9,1710 518.3,1710.1 516.4,1710.2 512.7,1710 
+	509.1,1710.4 506.4,1711.3 503.9,1713 501.5,1715.7 498.9,1718.6 495.7,1722.4 492.7,1726.3 491.5,1728.4 488.4,1729.2 
+	484.1,1730.5 480.8,1732.1 477.4,1735.3 475.2,1737.3 473.5,1740.5 470.9,1744.8 468.4,1746.8 464.2,1749.4 461,1751.4 
+	458.1,1753.8 452.2,1754.4 448.2,1755.1 444.3,1756.3 440.4,1757.4 439.3,1758.6 438.2,1760.6 433.8,1762.2 431.6,1764.2 
+	427.5,1766.1 421.2,1768 414.5,1769.9 408.5,1770.9 403,1771.7 397.9,1772.2 395,1772.7 393.2,1774.2 391.6,1775.4 387.2,1775.2 
+	384.5,1775.4 380.8,1776 366.7,1779.6 362.7,1780.8 356.5,1779.8 353.9,1779.7 345.2,1781.1 335.6,1782.3 327.8,1783.3 
+	317.1,1783.8 312.3,1784.2 304.9,1785.6 297.3,1787 273.7,1789.5 267.1,1790.9 261.5,1791.6 243.2,1794.1 235.6,1795.5 
+	226.7,1796.9 219.3,1798.2 211.6,1799.3 206.1,1799.8 201.1,1800.2 197.9,1800.4 197,1801 197.8,1801.1 205.7,1800.6 215.4,1799.6 
+	223.9,1798.1 234.1,1796.5 241.7,1795 245.9,1794.5 254.9,1793.4 260.2,1792.6 265.6,1792 270,1791.4 273.5,1790.7 278,1790.2 
+	284.4,1789.4 290,1788.8 297.4,1787.8 302.1,1787.1 307.2,1786 311,1785.5 315,1784.9 320.2,1784.8 329.2,1784 336,1783.5 
+	341.9,1782.6 348.4,1781.7 352.7,1780.9 354.6,1780.7 359.3,1781.2 363.2,1781.7 367.1,1780.9 371.4,1779.5 377,1778 382.2,1776.9 
+	386.6,1776 390.6,1776 391.8,1776 393.3,1775 395.6,1773.4 400.5,1772.9 405.3,1772.2 409.6,1771.7 416.8,1770.1 422.7,1768.7 
+	426.7,1767.4 430.7,1765.6 432.7,1764.5 434.2,1763.2 435.2,1762.5 437.7,1761.8 438.8,1761.2 440.4,1758.8 441.3,1758.1 
+	443.9,1757.1 446.5,1756.3 449.4,1755.7 452.4,1755 455.2,1754.6 457.3,1754.7 458.3,1754.4 459.8,1753.4 462.7,1751.4 
+	466.3,1749.2 469.2,1747.5 471.9,1745.3 474.3,1740.6 475.5,1738.6 477,1736.9 479.5,1734.5 481.5,1732.9 484.5,1731.3 
+	486.8,1730.7 490.3,1729.7 491.6,1729.5 492.6,1728 493.7,1726.1 495.2,1724.1 498.4,1720.2 502.6,1715.9 504.2,1713.6 
+	505.5,1712.7 508.1,1711.5 510.3,1711.2 513.9,1711 516.7,1710.9 519.7,1710.7 522.2,1710.8 525.3,1710.8 527.2,1710.7 
+	529.3,1710.7 531.1,1711 535.6,1711.6 538,1712.6 542.8,1714.7 545.7,1717 549.5,1719.7 556.3,1724.4 557.6,1725.3 558.8,1725.3 
+	562.3,1724.4 565.1,1723.8 568.1,1723.1 569.3,1722.8 571.2,1721.6 574.8,1719.8 576.1,1718.7 577.5,1716.2 583.2,1708.7 
+	587.3,1702.9 590.6,1698.6 592.1,1696.5 593.8,1694.6 596.3,1692.5 599.3,1690.1 602.5,1687.3 603.8,1685.3 605.1,1683.1 
+	606.3,1680.3 607.3,1679.3 609.5,1677.3 611.4,1675.3 614.2,1672.5 616.7,1671.2 619.6,1670.5 621.8,1670.6 624.4,1670.9 
+	626.2,1671.6 628.5,1672.8 631.2,1673.9 633.5,1674.3 638.4,1675.4 641,1676.1 644,1676.4 647.9,1676.5 652.8,1676.2 658.1,1676.6 
+	663,1676.8 667,1677 669.7,1677.4 673.1,1678.3 677.2,1679.1 678.6,1680.3 680.4,1682.1 682.7,1683.7 688.6,1687.9 694.2,1691.6 
+	696.8,1693.5 698.4,1694.8 699.1,1696.1 700.2,1697.2 701.6,1697.7 708,1698.7 710.8,1699.3 715.2,1699.7 723.5,1699.8 
+	730.2,1700.2 734.2,1700.8 735.7,1700.9 738,1702.2 741,1703.6 743.1,1704.5 745.2,1705 750.2,1705.9 753.7,1706.6 757.8,1709 
+	761.3,1711 763.1,1712.3 765.9,1714.8 768.9,1717.8 771.6,1720.6 774.5,1723.4 775.9,1724.4 778,1725 783.4,1726.3 789.1,1728.3 
+	793.6,1729.4 797.2,1730.7 800.9,1732.3 804.6,1734.2 806.8,1735.2 809.9,1737.2 812.7,1739.6 814.6,1741.1 816.1,1743.6 
+	817.6,1745.5 821.7,1747.8 825.1,1749.9 826.8,1751.2 829.2,1752.9 832.1,1754.9 838.5,1758 842.7,1760.2 846.6,1762.4 
+	849.4,1764.1 852,1766 856.7,1769.3 860,1771.8 865.4,1775.3 869.3,1777.7 872.5,1780 875.4,1782.3 879.2,1784.7 882.1,1786.8 
+	883.5,1787.9 884.2,1788.4 886.1,1788.3 888.2,1788.4 889.7,1788.4 892.9,1788.8 897,1789.3 899.2,1789.6 901,1789.8 902,1790.3 
+	903.2,1791 905,1793 907.9,1796.3 909.8,1798.9 910.9,1800.1 912.3,1801.7 914.1,1802.7 916.4,1803.1 917.8,1802.4 919.4,1801.1 
+	922.5,1800.6 930,1799.7 939.3,1798.6 945.3,1798 949,1797.7 952.9,1797.4 957.9,1797 960.9,1796.9 963,1796.5 968.5,1796.4 
+	973.9,1796 976.1,1795.9 977.1,1796.4 977.7,1797 978.9,1797.6 981.1,1798.3 982.5,1798.9 983.6,1799.8 984.8,1800.8 986.4,1802.1 
+	987.4,1803.1 988.1,1804.1 988.3,1805.2 989.2,1806.4 991,1808.1 991.5,1809.2 992,1811.6 992.4,1813.1 993.6,1814.9 995.1,1816.5 
+	996.6,1817.8 999.3,1818.3 1000.7,1818.3 1003.3,1817 1005.1,1815.9 1006.9,1813.7 1008.1,1812.2 1009.1,1810.8 1010.1,1808.3 
+	1011.1,1806.2 1013.1,1804.8 1013.8,1804 1016.8,1802.8 1019.7,1801.6 1022,1801.1 1023.5,1801.8 1025.3,1802.7 1026.6,1803.4 
+	1028.5,1803.8 1030.7,1803.7 1033.2,1802.5 1034.1,1801.7 1035.3,1800.3 1041.2,1794.5 1044,1791.4 1048.6,1786.4 1052.5,1782.9 
+	1054.2,1781.2 1056.9,1777.8 1058,1776 1058.4,1771.9 1058.5,1767.2 1058.6,1762.7 1058.5,1757.6 1058.9,1754.3 1059.8,1751.5 
+	1062.4,1745.2 1063.8,1741.2 1064.6,1739.8 1066,1738.6 1068,1737.6 1070.7,1737.1 1074.3,1736.1 1077.1,1735.4 1079.6,1734.5 
+	1081.1,1734 1082.8,1733.8 1085,1733.8 1088.4,1733.6 1091.5,1733.4 1094.8,1732.9 1098.3,1732.4 1100.9,1731.8 1101.7,1731.4 
+	1102.9,1729.9 1105.4,1726.7 1106.6,1725.1 1108.8,1720.3 1110.3,1715.2 1111.8,1710 1113,1702.1 1113.9,1698.2 1114.5,1694.8 
+	1115.8,1692.6 1117.3,1690.4 1120.1,1688.1 1122.3,1686.1 1123.1,1684.3 1124.3,1682.4 1124.5,1680.8 1124.5,1677.3 1124.1,1674.8 
+	1123.4,1673 1122.1,1670.6 1119.7,1667.5 1118.4,1666.4 1116,1664.5 1113.6,1661.8 1111.2,1658.7 1109.1,1654.8 1108.6,1651.5 
+	1108.8,1648 1109,1645 1109.6,1641.7 1110.3,1640.2 1112.1,1638.3 1114.2,1635.7 1115.3,1634.6 1116.9,1633.2 1119.1,1631.7 
+	1121.6,1629.1 1123.6,1625.8 1124.4,1623.6 1124.7,1622 1125.6,1619.6 1126.9,1616.7 1127.3,1614.5 1126.9,1611.1 1126.8,1608.8 
+	1127.3,1606.3 1127.8,1603.6 1128.3,1601 1129,1597.8 1129.4,1595.3 1130.3,1592.3 1130.8,1590.2 1132.3,1588.3 1133.8,1586.9 
+	1136.5,1586.5 1141.3,1585.9 1147.7,1585.1 1151.9,1584.5 1157.6,1583.8 1160.3,1583.4 1164.4,1583.7 1169.1,1584 1170.6,1584.2 
+	1172.1,1584.8 1175,1586 1177.5,1587.1 1180.7,1588.2 1183.6,1588.9 1185,1589.2 1184.1,1590.2 1185.5,1591.1 1187.2,1588.2 
+	1190.4,1583 1193.1,1579 1194.7,1576.3 1195.8,1572.7 1197.4,1568.3 1199.2,1565 1201.2,1561.6 1203.4,1559.3 1205.6,1558 
+	1207.7,1557.7 1209.7,1557.9 1211.7,1558.6 1213.2,1559.5 1214.1,1560.3 1216.2,1561.1 1217.6,1561.1 1219.5,1560.3 1221.3,1558.6 
+	1221.8,1557.4 1221.9,1555.4 1221.1,1553.2 1221.5,1551.3 1223,1550 1226,1548.5 1230.1,1546.6 1235.7,1544.2 1239.1,1542.5 
+	1242.4,1541.7 1248.1,1539.7 1254.4,1536.6 1258.8,1534.5 1261.4,1533.2 1264.5,1530.3 1268.8,1526.9 1270.9,1524.8 1272.6,1523.7 
+	1277.7,1520.9 1281.2,1518.2 1284.7,1515.4 1288.5,1511.7 1291.6,1508.3 1294.7,1505.1 1297.5,1502 1300.4,1499.1 1303.1,1496.5 
+	1306,1494.3 1309.7,1491.1 1312,1489 1314.2,1486.6 1317.6,1482.6 1319.8,1481 1326.3,1478.2 1328.5,1477.3 1331.3,1476 
+	1332.6,1475.4 1336.8,1474.8 1340.6,1474 1344.2,1473.6 1347.3,1473 1352.5,1471.9 1355,1471.3 1357,1470.2 1358.1,1468.4 
+	1358.3,1466.3 1358.7,1459.2 1358.7,1454.1 1358.7,1451.2 1359,1450.4 1360.3,1449.9 1362.2,1450.7 1364.8,1451 1369.1,1450.6 
+	1371.3,1449.7 1375,1446.7 1379.3,1442.1 1383.4,1438.5 1386.3,1435.6 1391.5,1433 1395.4,1430.8 1399.1,1430.4 1402.7,1430.2 
+	1407.3,1431 1410.5,1431.5 1413.9,1432.6 1417.8,1434.4 1423.5,1437.1 1427.1,1438.6 1429.1,1438.8 1433.3,1438.5 1437,1438.8 
+	1439.8,1437.3 1441.3,1435.1 1441.1,1432.2 1440.8,1429.3 1441.9,1424.8 1443.3,1420.5 1445.1,1416.2 1446.9,1414.2 1450.7,1409.3 
+	1452.8,1406.5 1457.2,1403.7 1464.1,1398.4 1466.5,1396.7 1473.8,1391.4 1476.1,1389 1479.2,1385 1483.5,1380.7 1487.8,1377.5 
+	1490.7,1376.1 1493.4,1374.8 1495.3,1374.7 1496.3,1375.5 1496.8,1376.3 1496.8,1377.6 1498,1379.5 1501.6,1384 1501.9,1385.3 
+	1502.5,1387.7 1504.5,1392 1505.5,1394.1 1508,1398.2 1511.2,1402.6 1513.1,1404.9 1517.3,1408.1 1518.3,1409.4 1520.8,1410.8 
+	1522.4,1410.9 1527,1409.6 1531,1407.6 1533.3,1406.4 1537.2,1402.2 1540.9,1398.6 1546.4,1394 1551.4,1389.5 1554,1386.8 
+	1554.7,1385.7 1554.7,1382.9 1554.4,1380.9 1550.3,1376.7 1547.9,1374 1545.8,1370.5 1542.7,1366.2 1540.8,1364 1540.1,1358.8 
+	1539.1,1354 1539.2,1349.4 1539.1,1343 1539.8,1339.8 1540.7,1337.4 1542.4,1332.7 1543.8,1329.4 1545.5,1327.4 1547.5,1326 
+	1549.5,1325.7 1551.8,1326.5 1553.2,1328.3 1554.7,1330.9 1554.8,1333.3 1553.7,1336.7 1551.6,1340 1550.5,1343.5 1550.9,1346.2 
+	1553.7,1349.6 1556.9,1352.4 1561.1,1355.4 1564.5,1356.6 1568.6,1357.4 1570.2,1357.5 1573.9,1355.8 1578.6,1353.3 1583.9,1350.6 
+	1587.4,1348.3 1590.9,1345 1592.8,1341.7 1592.3,1336.9 1590.7,1333.2 1587.3,1329.6 1584.9,1326.2 1582.3,1323.6 1580.3,1322.1 
+	1578.2,1319.9 1576.1,1317.8 1575.6,1315.9 1577.1,1312.6 1580.9,1305.9 1582.1,1302.2 1583.1,1300.4 1587.5,1297.4 1589.1,1296.5 
+	1591.9,1295.5 1594.9,1295 1598.2,1293.9 1599.6,1293 1600.1,1290.1 1599.4,1286.9 1598.9,1283.7 1599.6,1281.7 1600.7,1281.2 
+	1602.2,1282 1605.2,1285.8 1607.5,1291.8 1608.4,1296.8 1608.5,1299.8 1607.9,1301.6 1608.1,1304.1 1608.5,1308.3 1609.6,1309.7 
+	1609.8,1311.6 1610.3,1314.8 1612.5,1317.2 1614.5,1317.7 1619.3,1317.8 1624.8,1316.6 1630.9,1313.2 1633.3,1310.6 1634,1308.8 
+	1634.5,1304.9 1634.1,1301.1 1636.4,1296.9 1637.3,1295.4 1638.7,1294 1640.4,1293.7 1643.6,1295.2 1647.6,1296.3 1652,1296.7 
+	1656.1,1296.8 1659.6,1295.9 1664.6,1293.4 1666,1292.3 1671.3,1283.2 1674.5,1277.8 1680.6,1266.9 1682.2,1264.7 1684.2,1263.4 
+	1687.7,1262.2 1689,1262 1691.7,1262.1 1696.1,1262.6 1698.2,1262.8 1702,1262.2 1705.2,1262 1710.4,1261.7 1715.7,1261.3 
+	1718.2,1261.1 1722.3,1259.7 1728.6,1257.1 1734.7,1254.4 1739.2,1252.4 1744.2,1250.3 1746.7,1247.8 1750.9,1243.7 1757.4,1237.1 
+	1760.5,1234.4 1762.5,1231.6 1766.1,1226.9 1769.3,1223.6 1771.8,1221.2 1775.1,1218 1777.1,1215.5 1778.7,1212.8 1781.8,1209.3 
+	1788.6,1202.8 1793.5,1198.3 1796.5,1195.5 1798.2,1196.7 1802.3,1192.5 1810.3,1184.5 1814.8,1179.5 1820.1,1173.7 1827.8,1163.7 
+	1831.6,1159 1834.3,1155.5 1837,1152.8 1839.3,1151.6 1843.7,1146.8 1847,1141.7 1849.7,1138.4 1853.6,1131.5 1854.9,1128.3 
+	1857.8,1124.9 1861.3,1121.4 1865.8,1116.7 1867.9,1114 1869.5,1113.3 1872.3,1110 1873.5,1107.3 1874.5,1105.5 1877.4,1102.9 
+	1880.7,1099 1885.7,1096.3 1889.9,1093.9 1892.8,1090.9 1894.4,1089.1 1896.8,1088 1899.5,1085.4 1906.3,1080.3 1909.6,1077.1 
+	1913.6,1073.8 1917.9,1069.7 1922.8,1067.2 1927.1,1065.4 1929.9,1064.1 1932.6,1063.5 1934.6,1060.8 1936.2,1059.8 1936.7,1060.5 
+	1942.2,1063.5 1947,1066.6 1951.3,1068.7 1955.7,1071.7 1961.3,1076.5 1963,1079.1 1965.8,1083.5 1967.3,1086.1 1969.5,1088.4 
+	1977.4,1094.3 1981.9,1096.5 2003,1092.8 2011,1045.6 2004.2,1017.3 1979.1,999.7 1948,998 1918.1,997.7 1902.8,1007.2 
+	1901.8,1016.5 1911.9,1027.8 "/>
+<polyline points="1901.8,1016.5 1831.6,958 2204,958 2204,1228 2098.5,1177.1 1981.9,1096.5 "/>
+<pattern  id="SVGID_1_" xlink:href="#Unnamed_Pattern" patternTransform="matrix(1 0 0 -1 -62 -17332.1738)">
+</pattern>
+<rect y="0.3" class="st3" width="2200" height="898"/>
+<polygon points="1915.2,77.9 1918.5,80.4 1922.9,85 1926.7,89.3 1929.6,93.3 1931,96.5 1931.3,98.7 1931.6,100.5 1931.2,101.3 
+	1926.6,104.2 1922,105.6 1916.5,108.4 1910,111.7 1906,115.5 1902,120.2 1900.5,121.5 1895.4,125.5 1889.7,129.4 1885,133.1 
+	1879.8,136.9 1874.3,141.5 1870.4,144.9 1868,147.1 1865.3,149.8 1861.6,154.3 1857.2,159.5 1853.6,163.8 1851.4,166.6 1848,170.5 
+	1846.3,173.5 1844.1,176.5 1842.4,178.8 1839.5,182.8 1836,187.1 1832.8,191.5 1831.6,192.9 1830.1,194.6 1826.6,197.8 
+	1824.1,201.1 1821.1,205.3 1818.3,208.4 1810.7,216.5 1802.6,225.1 1796.8,230.9 1788.9,238.7 1781.8,246.1 1773.4,254.5 
+	1772.2,256.9 1771.2,258.8 1767.3,262.3 1760.9,268.3 1756.9,272.7 1753.3,276.4 1748.5,281.5 1744.9,285.3 1742.2,288.4 
+	1739.6,291 1737.7,291.8 1734.7,292.2 1726,295.4 1716.1,299.1 1713.8,300.3 1710.9,301.4 1708.9,301.9 1703.8,303 1697.3,302.5 
+	1684.1,301.7 1682.4,301.5 1678.7,303.6 1675.7,305.7 1673.8,308.3 1667.4,320.1 1660.4,332.8 1659.7,333.5 1654,335.5 1652,336.2 
+	1647.8,336.2 1644.1,336.1 1642.3,335.2 1640.4,334.5 1636.7,334.1 1633.2,335 1631,336.9 1628.9,339.9 1628.4,342.1 1627.9,344.2 
+	1628.3,347.5 1628,349.7 1626.4,352.9 1624.1,354.7 1620.6,355.7 1617,356.4 1612.2,357.3 1609.7,356.4 1608.4,354.9 1607.2,351.8 
+	1606.9,346.6 1606.3,339.8 1605.5,334.3 1604.7,331.4 1603.1,328.2 1601.3,325.8 1599.2,322.9 1598,321.3 1596,321.3 1593.9,322.5 
+	1593.4,324.7 1593.9,328.1 1594.3,331.9 1593.7,334.3 1591.8,335.2 1583.4,337.5 1580,339.7 1576.8,342.3 1575.3,345.9 
+	1572.4,352.5 1569.9,357.7 1569.4,359.5 1569.9,361 1572.2,363.1 1577.1,368.8 1581,373.4 1584.2,377.3 1586.6,380.2 1587,382.2 
+	1586.6,384 1583.9,386.9 1577.7,391.4 1572.2,394.6 1568.1,396.6 1565.4,397.7 1560.9,396.2 1557.8,394.7 1554.7,392.1 
+	1550.5,388.8 1548.9,386.8 1548.8,385 1549.7,381.9 1552.3,378.1 1552.4,374.2 1552.4,372.1 1549.8,368.2 1548.5,366.4 
+	1545.5,365.5 1542.6,366.8 1538.6,370.3 1536.8,374.7 1534.9,380.3 1533.6,382.6 1532.2,386.5 1530.9,391.3 1530.9,394.7 
+	1532.4,399.8 1537.4,413.1 1539.2,415.4 1544.5,419.6 1548.5,423.4 1549.7,424.8 1549.1,426.5 1547.9,428.8 1539.7,436.2 
+	1529.7,444.8 1526.2,447.5 1522.6,449.5 1517.9,451 1516.9,450.2 1512.1,444.3 1507.1,438.3 1504.1,433.7 1501.6,428.3 
+	1499.5,424.4 1497.8,420.6 1496,417.4 1495.2,416.2 1492.7,414.6 1490.3,414.1 1487.1,415 1482.2,417 1476.5,421.8 1471.1,427 
+	1465.7,433 1460.3,437.1 1451.7,444.2 1446.2,448.7 1444.3,449.9 1443.1,451.6 1442.2,453.7 1440.6,455.3 1438.1,459.6 1435.9,463 
+	1434.9,468.9 1434.4,473.9 1434.6,476.4 1432.5,477.7 1428.3,478.6 1424.8,478.1 1420.1,476 1410.5,472.9 1403.3,470.9 
+	1396.6,470.3 1392.5,470.5 1389.1,471.6 1385.2,473.6 1381.2,476.7 1377.1,479.9 1374.1,482.7 1372.5,484.8 1370.5,486.9 
+	1367.9,489 1365.5,490.8 1362.8,490.9 1360.5,491.1 1358.2,490.9 1355.9,490.1 1353.7,491.4 1351.8,492.9 1351.7,495.5 
+	1352.5,499.2 1352.9,502.6 1351.9,504.4 1352.7,506.5 1351.6,510.5 1351.1,511.3 1347,512.9 1335.7,514.9 1333.1,515 1327.9,516.6 
+	1320.4,519.3 1313.9,522.3 1311.3,525.3 1304.5,532.9 1301.2,535.6 1296.2,539.3 1293.2,541.6 1289.6,546.6 1286,550.7 
+	1283.9,552.7 1278.5,557.5 1273.7,561 1265.4,565.8 1261.3,569.1 1255.9,574.3 1244.3,579.5 1235.3,583 1227,585.8 1220.9,588.5 
+	1217.2,590.1 1215.9,592 1215.3,594.3 1215.8,597.1 1216.2,598.9 1216.1,599.9 1214.9,601.2 1212.4,600.4 1206.8,598.7 
+	1203.7,597.9 1202.1,598.4 1199.5,599.2 1196.7,601.7 1195.7,603.2 1192.4,609.8 1188.9,616.5 1186.1,622.5 1183.7,626.5 
+	1181.9,630.3 1180.8,630.6 1179.4,629.9 1173.2,628 1167,625.7 1166.7,625.5 1157.9,625 1154.7,625 1149.2,625.6 1140.9,626.6 
+	1135.4,627.1 1132.3,627.6 1129.7,628.2 1127.9,629.7 1126.2,631.6 1125.2,634.6 1124.3,639.9 1123.2,645 1122.3,649.4 
+	1122.2,652.4 1122.5,655.8 1122.1,657.4 1121.3,660.1 1120.5,662 1119.8,664.1 1119.8,665.6 1118.9,667.5 1117.6,669.5 
+	1114.8,672.8 1112.7,674.4 1111.5,675.4 1110.1,676.6 1107.5,679.9 1105.3,681.9 1104.8,684.5 1104.1,689 1104.1,694.4 
+	1104.6,697.6 1105.8,700.1 1107.7,702.6 1109,704.6 1111.6,707 1113.7,708.7 1115.4,710.4 1117.4,712.4 1118.3,714 1119.6,717.1 
+	1120,719.5 1119.9,722.5 1119.7,724.5 1118.1,726.9 1116.6,728.9 1114.4,730.4 1111.5,733.1 1110.3,735.1 1109.5,737.9 1108.6,743 
+	1107.7,748 1106.7,753.5 1105.5,757.5 1103.8,762.2 1102.2,765.7 1100.4,768.8 1098.9,771 1097.2,773 1095.1,773.6 1090.8,774.3 
+	1087.4,774.8 1082.9,775.1 1078.3,775.1 1076.6,775.4 1073.1,776.6 1069,777.6 1064.3,778.8 1061.2,779.6 1058.8,783.2 
+	1057.5,786.9 1056,790.9 1054.8,793.9 1054.3,796.4 1053.7,800.6 1054,804.4 1053.8,807.7 1053.6,811.1 1053.6,813.9 1053.3,816.6 
+	1053.2,818 1051.7,820 1049.1,823.5 1045.8,826.2 1041.2,830.8 1036.9,835.6 1033.9,838.7 1030.7,842.1 1029.4,843.6 1026.8,845 
+	1023.5,845.1 1021.3,843.9 1019.5,843.1 1018.2,842.2 1016,842.8 1011.8,844.3 1010,845 1007.3,847.5 1006.1,848.4 1005.2,850.7 
+	1003.6,853.7 1002.1,855.8 1000.9,857.4 999.5,858.2 997.8,859.1 996.1,859.6 994.3,859.6 993.3,859.3 991.8,858.4 990.8,857 
+	989.6,855.9 988.7,853.8 988.1,850.4 986.9,848.8 985.6,847.7 984.6,845.6 984.1,844.7 983,843.6 981.6,842.6 980.5,841.4 
+	979,840.3 977.5,839.8 974.9,839 973.8,838 972.7,837.2 969,837.5 949.6,838.5 942.7,839.5 936.7,839.9 928.1,840.7 919.9,841.6 
+	915.1,842.1 913.5,843 912.7,844.1 911,844.1 908.9,843.1 905.5,839.3 903.9,837 901.4,834 898.8,831.6 895.5,830.6 889.7,830.1 
+	885.2,829.4 881.9,829.6 880.4,829.5 874.5,825.1 853,810.7 846.3,805.6 843.3,803.8 832.3,798.1 826,794.5 821.1,791 814.7,787.1 
+	813.2,785.7 811.4,783 809.1,780.2 806,778.2 802.2,776 792.7,771.5 788.5,770.1 785.5,769.3 781.1,767.9 776.2,766.6 772.5,765.8 
+	768.4,762 765,758.7 760.9,754.9 757.2,752 753.2,749.6 750.7,748 747.6,747.1 742.8,746.2 740,745.9 738.4,745 734.4,742.9 
+	731.8,741.9 726.9,741.5 711.6,740.6 706.5,740.4 702.1,739.5 696.4,738.7 695.9,737.9 695.3,736.3 692.3,734.2 686.3,730 
+	682,727.1 678.9,725 677.5,723.7 674.1,720.7 669.8,719.6 662.1,718.1 654.8,717.6 650.8,717.3 645.2,717.5 639.1,717.5 
+	637.5,717.6 628.6,715.4 626.1,714.9 623.4,713.6 621.2,712.4 618.5,712 615.7,711.9 612.8,712.1 611,713 608.6,715 607.1,716.6 
+	605.6,718.2 603.4,720.1 601.9,721.7 600.6,724.4 598.9,727.3 596.6,730 592.1,733.7 588.2,737.3 585.7,740.3 580.9,747.1 
+	575.8,753.8 570.7,761.2 566.4,763.2 564.9,764.2 561.1,765.2 554.1,766.7 550,763.7 543,758.9 539.4,756.2 535.2,754.2 532.3,753 
+	528.7,752.4 525,751.8 521.4,752 518.9,752 514.3,752.1 512.4,752.2 508.7,752 505.1,752.4 502.4,753.3 499.9,755 497.5,757.7 
+	494.9,760.6 491.7,764.4 488.7,768.3 487.5,770.4 484.4,771.2 480.1,772.5 476.8,774.1 473.4,777.3 471.2,779.3 469.5,782.5 
+	466.9,786.8 464.4,788.8 460.2,791.4 457,793.4 454.1,795.8 448.2,796.4 444.2,797.1 440.3,798.3 436.4,799.4 435.3,800.6 
+	434.2,802.6 429.8,804.2 427.6,806.2 423.5,808.1 417.2,810 410.5,811.9 404.5,812.9 399,813.7 393.9,814.2 391,814.7 389.2,816.2 
+	387.6,817.4 383.2,817.2 380.5,817.4 376.8,818 362.7,821.6 358.7,822.8 352.5,821.8 349.9,821.7 341.2,823.1 331.6,824.3 
+	323.8,825.3 313.1,825.8 308.3,826.2 300.9,827.6 293.3,829 269.7,831.5 263.1,832.9 257.5,833.6 239.2,836.1 231.6,837.5 
+	222.7,838.9 215.3,840.2 207.6,841.3 202.1,841.8 197.1,842.2 193.9,842.4 193,843 193.8,843.1 201.7,842.6 211.4,841.6 
+	219.9,840.1 230.1,838.5 237.7,837 241.9,836.5 250.9,835.4 256.2,834.6 261.6,834 266,833.4 269.5,832.7 274,832.2 280.4,831.4 
+	286,830.8 293.4,829.8 298.1,829.1 303.2,828 307,827.5 311,826.9 316.2,826.8 325.2,826 332,825.5 337.9,824.6 344.4,823.7 
+	348.7,822.9 350.6,822.7 355.3,823.2 359.2,823.7 363.1,822.9 367.4,821.5 373,820 378.2,818.9 382.6,818 386.6,818 387.8,818 
+	389.3,817 391.6,815.4 396.5,814.9 401.3,814.2 405.6,813.7 412.8,812.1 418.7,810.7 422.7,809.4 426.7,807.6 428.7,806.5 
+	430.2,805.2 431.2,804.5 433.7,803.8 434.8,803.2 436.4,800.8 437.3,800.1 439.9,799.1 442.5,798.3 445.4,797.7 448.4,797 
+	451.2,796.6 453.3,796.7 454.3,796.4 455.8,795.4 458.7,793.4 462.3,791.2 465.2,789.5 467.9,787.3 470.3,782.6 471.5,780.6 
+	473,778.9 475.5,776.5 477.5,774.9 480.5,773.3 482.8,772.7 486.3,771.7 487.6,771.5 488.6,770 489.7,768.1 491.2,766.1 
+	494.4,762.2 498.6,757.9 500.2,755.6 501.5,754.7 504.1,753.5 506.3,753.2 509.9,753 512.7,752.9 515.7,752.7 518.2,752.8 
+	521.3,752.8 523.2,752.7 525.3,752.7 527.1,753 531.6,753.6 534,754.6 538.8,756.7 541.7,759 545.5,761.7 552.3,766.4 553.6,767.3 
+	554.8,767.3 558.3,766.4 561.1,765.8 564.1,765.1 565.3,764.8 567.2,763.6 570.8,761.8 572.1,760.7 573.5,758.2 579.2,750.7 
+	583.3,744.9 586.6,740.6 588.1,738.5 589.8,736.6 592.3,734.5 595.3,732.1 598.5,729.3 599.8,727.3 601.1,725.1 602.3,722.3 
+	603.3,721.3 605.5,719.3 607.4,717.3 610.2,714.5 612.7,713.2 615.6,712.5 617.8,712.6 620.4,712.9 622.2,713.6 624.5,714.8 
+	627.2,715.9 629.5,716.3 634.4,717.4 637,718.1 640,718.4 643.9,718.5 648.8,718.2 654.1,718.6 659,718.8 663,719 665.7,719.4 
+	669.1,720.3 673.2,721.1 674.6,722.3 676.4,724.1 678.7,725.7 684.6,729.9 690.2,733.6 692.8,735.5 694.4,736.8 695.1,738.1 
+	696.2,739.2 697.6,739.7 704,740.7 706.8,741.3 711.2,741.7 719.5,741.8 726.2,742.2 730.2,742.8 731.7,742.9 734,744.2 737,745.6 
+	739.1,746.5 741.2,747 746.2,747.9 749.7,748.6 753.8,751 757.3,753 759.1,754.3 761.9,756.8 764.9,759.8 767.6,762.6 770.5,765.4 
+	771.9,766.4 774,767 779.4,768.3 785.1,770.3 789.6,771.4 793.2,772.7 796.9,774.3 800.6,776.2 802.8,777.2 805.9,779.2 
+	808.7,781.6 810.6,783.1 812.1,785.6 813.6,787.5 817.7,789.8 821.1,791.9 822.8,793.2 825.2,794.9 828.1,796.9 834.5,800 
+	838.7,802.2 842.6,804.4 845.4,806.1 848,808 852.7,811.3 856,813.8 861.4,817.3 865.3,819.7 868.5,822 871.4,824.3 875.2,826.7 
+	878.1,828.8 879.5,829.9 880.2,830.4 882.1,830.3 884.2,830.4 885.7,830.4 888.9,830.8 893,831.3 895.2,831.6 897,831.8 898,832.3 
+	899.2,833 901,835 903.9,838.3 905.8,840.9 906.9,842.1 908.3,843.7 910.1,844.7 912.4,845.1 913.8,844.4 915.4,843.1 918.5,842.6 
+	926,841.7 935.3,840.6 941.3,840 945,839.7 948.9,839.4 953.9,839 956.9,838.9 959,838.5 964.5,838.4 969.9,838 972.1,837.9 
+	973.1,838.4 973.7,839 974.9,839.6 977.1,840.3 978.5,840.9 979.6,841.8 980.8,842.8 982.4,844.1 983.4,845.1 984.1,846.1 
+	984.3,847.2 985.2,848.4 987,850.1 987.5,851.2 988,853.6 988.4,855.1 989.6,856.9 991.1,858.5 992.6,859.8 995.3,860.3 
+	996.7,860.3 999.3,859 1001.1,857.9 1002.9,855.7 1004.1,854.2 1005.1,852.8 1006.1,850.3 1007.1,848.2 1009.1,846.8 1009.8,846 
+	1012.8,844.8 1015.7,843.6 1018,843.1 1019.5,843.8 1021.3,844.7 1022.6,845.4 1024.5,845.8 1026.7,845.7 1029.2,844.5 
+	1030.1,843.7 1031.3,842.3 1037.2,836.5 1040,833.4 1044.6,828.4 1048.5,824.9 1050.2,823.2 1052.9,819.8 1054,818 1054.4,813.9 
+	1054.5,809.2 1054.6,804.7 1054.5,799.6 1054.9,796.3 1055.8,793.5 1058.4,787.2 1059.8,783.2 1060.6,781.8 1062,780.6 1064,779.6 
+	1066.7,779.1 1070.3,778.1 1073.1,777.4 1075.6,776.5 1077.1,776 1078.8,775.8 1081,775.8 1084.4,775.6 1087.5,775.4 1090.8,774.9 
+	1094.3,774.4 1096.9,773.8 1097.7,773.4 1098.9,771.9 1101.4,768.7 1102.6,767.1 1104.8,762.3 1106.3,757.2 1107.8,752 1109,744.1 
+	1109.9,740.2 1110.5,736.8 1111.8,734.6 1113.3,732.4 1116.1,730.1 1118.3,728.1 1119.1,726.3 1120.3,724.4 1120.5,722.8 
+	1120.5,719.3 1120.1,716.8 1119.4,715 1118.1,712.6 1115.7,709.5 1114.4,708.4 1112,706.5 1109.6,703.8 1107.2,700.7 1105.1,696.8 
+	1104.6,693.5 1104.8,690 1105,687 1105.6,683.7 1106.3,682.2 1108.1,680.3 1110.2,677.7 1111.3,676.6 1112.9,675.2 1115.1,673.7 
+	1117.6,671.1 1119.6,667.8 1120.4,665.6 1120.7,664 1121.6,661.6 1122.9,658.7 1123.3,656.5 1122.9,653.1 1122.8,650.8 
+	1123.3,648.3 1123.8,645.6 1124.3,643 1125,639.8 1125.4,637.3 1126.3,634.3 1126.8,632.2 1128.3,630.3 1129.8,628.9 1132.5,628.5 
+	1137.3,627.9 1143.7,627.1 1147.9,626.5 1153.6,625.8 1156.3,625.4 1160.4,625.7 1165.1,626 1166.6,626.2 1168.1,626.8 1171,628 
+	1173.5,629.1 1176.7,630.2 1179.6,630.9 1181,631.2 1180.1,632.2 1181.5,633.1 1183.2,630.2 1186.4,625 1189.1,621 1190.7,618.3 
+	1191.8,614.7 1193.4,610.3 1195.2,607 1197.2,603.6 1199.4,601.3 1201.6,600 1203.7,599.7 1205.7,599.9 1207.7,600.6 1209.2,601.5 
+	1210.1,602.3 1212.2,603.1 1213.6,603.1 1215.5,602.3 1217.3,600.6 1217.8,599.4 1217.9,597.4 1217.1,595.2 1217.5,593.3 1219,592 
+	1222,590.5 1226.1,588.6 1231.7,586.2 1235.1,584.5 1238.4,583.7 1244.1,581.7 1250.4,578.6 1254.8,576.5 1257.4,575.2 
+	1260.5,572.3 1264.8,568.9 1266.9,566.8 1268.6,565.7 1273.7,562.9 1277.2,560.2 1280.7,557.4 1284.5,553.7 1287.6,550.3 
+	1290.7,547.1 1293.5,544 1296.4,541.1 1299.1,538.5 1302,536.3 1305.7,533.1 1308,531 1310.2,528.6 1313.6,524.6 1315.8,523 
+	1322.3,520.2 1324.5,519.3 1327.3,518 1328.6,517.4 1332.8,516.8 1336.6,516 1340.2,515.6 1343.3,515 1348.5,513.9 1351,513.3 
+	1353,512.2 1354.1,510.4 1354.3,508.3 1354.7,501.2 1354.7,496.1 1354.7,493.2 1355,492.4 1356.3,491.9 1358.2,492.7 1360.8,493 
+	1365.1,492.6 1367.3,491.7 1371,488.7 1375.3,484.1 1379.4,480.5 1382.3,477.6 1387.5,475 1391.4,472.8 1395.1,472.4 1398.7,472.2 
+	1403.3,473 1406.5,473.5 1409.9,474.6 1413.8,476.4 1419.5,479.1 1423.1,480.6 1425.1,480.8 1429.3,480.5 1433,480.8 1435.8,479.3 
+	1437.3,477.1 1437.1,474.2 1436.8,471.3 1437.9,466.8 1439.3,462.5 1441.1,458.2 1442.9,456.2 1446.7,451.3 1448.8,448.5 
+	1453.2,445.7 1460.1,440.4 1462.5,438.7 1469.8,433.4 1472.1,431 1475.2,427 1479.5,422.7 1483.8,419.5 1486.7,418.1 1489.4,416.8 
+	1491.3,416.7 1492.3,417.5 1492.8,418.3 1492.8,419.6 1494,421.5 1497.6,426 1497.9,427.3 1498.5,429.7 1500.5,434 1501.5,436.1 
+	1504,440.2 1507.2,444.6 1509.1,446.9 1513.3,450.1 1514.3,451.4 1516.8,452.8 1518.4,452.9 1523,451.6 1527,449.6 1529.3,448.4 
+	1533.2,444.2 1536.9,440.6 1542.4,436 1547.4,431.5 1550,428.8 1550.7,427.7 1550.7,424.9 1550.4,422.9 1546.3,418.7 1543.9,416 
+	1541.8,412.5 1538.7,408.2 1536.8,406 1536.1,400.8 1535.1,396 1535.2,391.4 1535.1,385 1535.8,381.8 1536.7,379.4 1538.4,374.7 
+	1539.8,371.4 1541.5,369.4 1543.5,368 1545.5,367.7 1547.8,368.5 1549.2,370.3 1550.7,372.9 1550.8,375.3 1549.7,378.7 1547.6,382 
+	1546.5,385.5 1546.9,388.2 1549.7,391.6 1552.9,394.4 1557.1,397.4 1560.5,398.6 1564.6,399.4 1566.2,399.5 1569.9,397.8 
+	1574.6,395.3 1579.9,392.6 1583.4,390.3 1586.9,387 1588.8,383.7 1588.3,378.9 1586.7,375.2 1583.3,371.6 1580.9,368.2 
+	1578.3,365.6 1576.3,364.1 1574.2,361.9 1572.1,359.8 1571.6,357.9 1573.1,354.6 1576.9,347.9 1578.1,344.2 1579.1,342.4 
+	1583.5,339.4 1585.1,338.5 1587.9,337.5 1590.9,337 1594.2,335.9 1595.6,335 1596.1,332.1 1595.4,328.9 1594.9,325.7 1595.6,323.7 
+	1596.7,323.2 1598.2,324 1601.2,327.8 1603.5,333.8 1604.4,338.8 1604.5,341.8 1603.9,343.6 1604.1,346.1 1604.5,350.3 
+	1605.6,351.7 1605.8,353.6 1606.3,356.8 1608.5,359.2 1610.5,359.7 1615.3,359.8 1620.8,358.6 1626.9,355.2 1629.3,352.6 
+	1630,350.8 1630.5,346.9 1630.1,343.1 1632.4,338.9 1633.3,337.4 1634.7,336 1636.4,335.7 1639.6,337.2 1643.6,338.3 1648,338.7 
+	1652.1,338.8 1655.6,337.9 1660.6,335.4 1662,334.3 1667.3,325.2 1670.5,319.8 1676.6,308.9 1678.2,306.7 1680.2,305.4 
+	1683.7,304.2 1685,304 1687.7,304.1 1692.1,304.6 1694.2,304.8 1698,304.2 1701.2,304 1706.4,303.7 1711.7,303.3 1714.2,303.1 
+	1718.3,301.7 1724.6,299.1 1730.7,296.4 1735.2,294.4 1740.2,292.3 1742.7,289.8 1746.9,285.7 1753.4,279.1 1756.5,276.4 
+	1758.5,273.6 1762.1,268.9 1765.3,265.6 1767.8,263.2 1771.1,260 1773.1,257.5 1774.7,254.8 1777.8,251.3 1784.6,244.8 
+	1789.5,240.3 1792.5,237.5 1794.2,238.7 1798.3,234.5 1806.3,226.5 1810.8,221.5 1816.1,215.7 1823.8,205.7 1827.6,201 
+	1830.3,197.5 1833,194.8 1835.3,193.6 1839.7,188.8 1843,183.7 1845.7,180.4 1849.6,173.5 1850.9,170.3 1853.8,166.9 1857.3,163.4 
+	1861.8,158.7 1863.9,156 1865.5,155.3 1868.3,152 1869.5,149.3 1870.5,147.5 1873.4,144.9 1876.7,141 1881.7,138.3 1885.9,135.9 
+	1888.8,132.9 1890.4,131.1 1892.8,130 1895.5,127.4 1902.3,122.3 1905.6,119.1 1909.6,115.8 1913.9,111.7 1918.8,109.2 
+	1923.1,107.4 1925.9,106.1 1928.6,105.5 1930.6,102.8 1932.2,101.8 1932.7,102.5 1938.2,105.5 1943,108.6 1947.3,110.7 
+	1951.7,113.7 1957.3,118.5 1959,121.1 1961.8,125.5 1963.3,128.1 1965.5,130.4 1973.4,136.3 1977.9,138.5 1999,134.8 2007,87.6 
+	2000.2,59.3 1975.1,41.7 1944,40 1914.1,39.7 1898.8,49.2 1897.8,58.5 1907.9,69.8 "/>
+<polyline points="1897.8,58.5 1827.6,0 2200,0 2200,270 2094.5,219.1 1977.9,138.5 "/>
+<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="-90.3764" y1="996.0674" x2="1881.6235" y2="1684.0674" gradientTransform="matrix(1 0 0 -1 0 899.2756)">
+	<stop  offset="0" style="stop-color:#FFFFFF"/>
+	<stop  offset="1.740528e-02" style="stop-color:#F3F1FE"/>
+	<stop  offset="7.662444e-02" style="stop-color:#CFC5FB"/>
+	<stop  offset="0.1366" style="stop-color:#B0A1F8"/>
+	<stop  offset="0.1966" style="stop-color:#9985F7"/>
+	<stop  offset="0.2566" style="stop-color:#8871F5"/>
+	<stop  offset="0.3166" style="stop-color:#7E65F4"/>
+	<stop  offset="0.3769" style="stop-color:#7B61F4"/>
+	<stop  offset="0.6067" style="stop-color:#7A5FF4"/>
+	<stop  offset="0.6895" style="stop-color:#7558F4"/>
+	<stop  offset="0.7485" style="stop-color:#6D4DF4"/>
+	<stop  offset="0.7958" style="stop-color:#623CF4"/>
+	<stop  offset="0.8333" style="stop-color:#5428F4"/>
+</linearGradient>
+<rect x="-4" y="-959.7" class="st4" width="2200" height="898"/>
+<polygon points="1911.2,-882.1 1914.5,-879.6 1918.9,-875 1922.7,-870.7 1925.6,-866.7 1927,-863.5 1927.3,-861.3 1927.6,-859.5 
+	1927.2,-858.7 1922.6,-855.8 1918,-854.4 1912.5,-851.6 1906,-848.3 1902,-844.5 1898,-839.8 1896.5,-838.5 1891.4,-834.5 
+	1885.7,-830.6 1881,-826.9 1875.8,-823.1 1870.3,-818.5 1866.4,-815.1 1864,-812.9 1861.3,-810.2 1857.6,-805.7 1853.2,-800.5 
+	1849.6,-796.2 1847.4,-793.4 1844,-789.5 1842.3,-786.5 1840.1,-783.5 1838.4,-781.2 1835.5,-777.2 1832,-772.9 1828.8,-768.5 
+	1827.6,-767.1 1826.1,-765.4 1822.6,-762.2 1820.1,-758.9 1817.1,-754.7 1814.3,-751.6 1806.7,-743.5 1798.6,-734.9 1792.8,-729.1 
+	1784.9,-721.3 1777.8,-713.9 1769.4,-705.5 1768.2,-703.1 1767.2,-701.2 1763.3,-697.7 1756.9,-691.7 1752.9,-687.3 1749.3,-683.6 
+	1744.5,-678.5 1740.9,-674.7 1738.2,-671.6 1735.6,-669 1733.7,-668.2 1730.7,-667.8 1722,-664.6 1712.1,-660.9 1709.8,-659.7 
+	1706.9,-658.6 1704.9,-658.1 1699.8,-657 1693.3,-657.5 1680.1,-658.3 1678.4,-658.5 1674.7,-656.4 1671.7,-654.3 1669.8,-651.7 
+	1663.4,-639.9 1656.4,-627.2 1655.7,-626.5 1650,-624.5 1648,-623.8 1643.8,-623.8 1640.1,-623.9 1638.3,-624.8 1636.4,-625.5 
+	1632.7,-625.9 1629.2,-625 1627,-623.1 1624.9,-620.1 1624.4,-617.9 1623.9,-615.8 1624.3,-612.5 1624,-610.3 1622.4,-607.1 
+	1620.1,-605.3 1616.6,-604.3 1613,-603.6 1608.2,-602.7 1605.7,-603.6 1604.4,-605.1 1603.2,-608.2 1602.9,-613.4 1602.3,-620.2 
+	1601.5,-625.7 1600.7,-628.6 1599.1,-631.8 1597.3,-634.2 1595.2,-637.1 1594,-638.7 1592,-638.7 1589.9,-637.5 1589.4,-635.3 
+	1589.9,-631.9 1590.3,-628.1 1589.7,-625.7 1587.8,-624.8 1579.4,-622.5 1576,-620.3 1572.8,-617.7 1571.3,-614.1 1568.4,-607.5 
+	1565.9,-602.3 1565.4,-600.5 1565.9,-599 1568.2,-596.9 1573.1,-591.2 1577,-586.6 1580.2,-582.7 1582.6,-579.8 1583,-577.8 
+	1582.6,-576 1579.9,-573.1 1573.7,-568.6 1568.2,-565.4 1564.1,-563.4 1561.4,-562.3 1556.9,-563.8 1553.8,-565.3 1550.7,-567.9 
+	1546.5,-571.2 1544.9,-573.2 1544.8,-575 1545.7,-578.1 1548.3,-581.9 1548.4,-585.8 1548.4,-587.9 1545.8,-591.8 1544.5,-593.6 
+	1541.5,-594.5 1538.6,-593.2 1534.6,-589.7 1532.8,-585.3 1530.9,-579.7 1529.6,-577.4 1528.2,-573.5 1526.9,-568.7 1526.9,-565.3 
+	1528.4,-560.2 1533.4,-546.9 1535.2,-544.6 1540.5,-540.4 1544.5,-536.6 1545.7,-535.2 1545.1,-533.5 1543.9,-531.2 1535.7,-523.8 
+	1525.7,-515.2 1522.2,-512.5 1518.6,-510.5 1513.9,-509 1512.9,-509.8 1508.1,-515.7 1503.1,-521.7 1500.1,-526.3 1497.6,-531.7 
+	1495.5,-535.6 1493.8,-539.4 1492,-542.6 1491.2,-543.8 1488.7,-545.4 1486.3,-545.9 1483.1,-545 1478.2,-543 1472.5,-538.2 
+	1467.1,-533 1461.7,-527 1456.3,-522.9 1447.7,-515.8 1442.2,-511.3 1440.3,-510.1 1439.1,-508.4 1438.2,-506.3 1436.6,-504.7 
+	1434.1,-500.4 1431.9,-497 1430.9,-491.1 1430.4,-486.1 1430.6,-483.6 1428.5,-482.3 1424.3,-481.4 1420.8,-481.9 1416.1,-484 
+	1406.5,-487.1 1399.3,-489.1 1392.6,-489.7 1388.5,-489.5 1385.1,-488.4 1381.2,-486.4 1377.2,-483.3 1373.1,-480.1 1370.1,-477.3 
+	1368.5,-475.2 1366.5,-473.1 1363.9,-471 1361.5,-469.2 1358.8,-469.1 1356.5,-468.9 1354.2,-469.1 1351.9,-469.9 1349.7,-468.6 
+	1347.8,-467.1 1347.7,-464.5 1348.5,-460.8 1348.9,-457.4 1347.9,-455.6 1348.7,-453.5 1347.6,-449.5 1347.1,-448.7 1343,-447.1 
+	1331.7,-445.1 1329.1,-445 1323.9,-443.4 1316.4,-440.7 1309.9,-437.7 1307.3,-434.7 1300.5,-427.1 1297.2,-424.4 1292.2,-420.7 
+	1289.2,-418.4 1285.6,-413.4 1282,-409.3 1279.9,-407.3 1274.5,-402.5 1269.7,-399 1261.4,-394.2 1257.3,-390.9 1251.9,-385.7 
+	1240.3,-380.5 1231.3,-377 1223,-374.2 1216.9,-371.5 1213.2,-369.9 1211.9,-368 1211.3,-365.7 1211.8,-362.9 1212.2,-361.1 
+	1212.1,-360.1 1210.9,-358.8 1208.4,-359.6 1202.8,-361.3 1199.7,-362.1 1198.1,-361.6 1195.5,-360.8 1192.7,-358.3 1191.7,-356.8 
+	1188.4,-350.2 1184.9,-343.5 1182.1,-337.5 1179.7,-333.5 1177.9,-329.7 1176.8,-329.4 1175.4,-330.1 1169.2,-332 1163,-334.3 
+	1162.7,-334.5 1153.9,-335 1150.7,-335 1145.2,-334.4 1136.9,-333.4 1131.4,-332.9 1128.3,-332.4 1125.7,-331.8 1123.9,-330.3 
+	1122.2,-328.4 1121.2,-325.4 1120.3,-320.1 1119.2,-315 1118.3,-310.6 1118.2,-307.6 1118.5,-304.2 1118.1,-302.6 1117.3,-299.9 
+	1116.5,-298 1115.8,-295.9 1115.8,-294.4 1114.9,-292.5 1113.6,-290.5 1110.8,-287.2 1108.7,-285.6 1107.5,-284.6 1106.1,-283.4 
+	1103.5,-280.1 1101.3,-278.1 1100.8,-275.5 1100.1,-271 1100.1,-265.6 1100.6,-262.4 1101.8,-259.9 1103.7,-257.4 1105,-255.4 
+	1107.6,-253 1109.7,-251.3 1111.4,-249.6 1113.4,-247.6 1114.3,-246 1115.6,-242.9 1116,-240.5 1115.9,-237.5 1115.7,-235.5 
+	1114.1,-233.1 1112.6,-231.1 1110.4,-229.6 1107.5,-226.9 1106.3,-224.9 1105.5,-222.1 1104.6,-217 1103.7,-212 1102.7,-206.5 
+	1101.5,-202.5 1099.8,-197.8 1098.2,-194.3 1096.4,-191.2 1094.9,-189 1093.2,-187 1091.1,-186.4 1086.8,-185.7 1083.4,-185.2 
+	1078.9,-184.9 1074.3,-184.9 1072.6,-184.6 1069.1,-183.4 1065,-182.4 1060.3,-181.2 1057.2,-180.4 1054.8,-176.8 1053.5,-173.1 
+	1052,-169.1 1050.8,-166.1 1050.3,-163.6 1049.7,-159.4 1050,-155.6 1049.8,-152.3 1049.6,-148.9 1049.6,-146.1 1049.3,-143.4 
+	1049.2,-142 1047.7,-140 1045.1,-136.5 1041.8,-133.8 1037.2,-129.2 1032.9,-124.4 1029.9,-121.3 1026.7,-117.9 1025.4,-116.4 
+	1022.8,-115 1019.5,-114.9 1017.3,-116.1 1015.5,-116.9 1014.2,-117.8 1012,-117.2 1007.8,-115.7 1006,-115 1003.3,-112.5 
+	1002.1,-111.6 1001.2,-109.3 999.6,-106.3 998.1,-104.2 996.9,-102.6 995.5,-101.8 993.8,-100.9 992.1,-100.4 990.3,-100.4 
+	989.3,-100.7 987.8,-101.6 986.8,-103 985.6,-104.1 984.7,-106.2 984.1,-109.6 982.9,-111.2 981.6,-112.3 980.6,-114.4 
+	980.1,-115.3 979,-116.4 977.6,-117.4 976.5,-118.6 975,-119.7 973.5,-120.2 970.9,-121 969.8,-122 968.7,-122.8 965,-122.5 
+	945.6,-121.5 938.7,-120.5 932.7,-120.1 924.1,-119.3 915.9,-118.4 911.1,-117.9 909.5,-117 908.7,-115.9 907,-115.9 904.9,-116.9 
+	901.5,-120.7 899.9,-123 897.4,-126 894.8,-128.4 891.5,-129.4 885.7,-129.9 881.2,-130.6 877.9,-130.4 876.4,-130.5 870.5,-134.9 
+	849,-149.3 842.3,-154.4 839.3,-156.2 828.3,-161.9 822,-165.5 817.1,-169 810.7,-172.9 809.2,-174.3 807.4,-177 805.1,-179.8 
+	802,-181.8 798.2,-184 788.7,-188.5 784.5,-189.9 781.5,-190.7 777.1,-192.1 772.2,-193.4 768.5,-194.2 764.4,-198 761,-201.3 
+	756.9,-205.1 753.2,-208 749.2,-210.4 746.7,-212 743.6,-212.9 738.8,-213.8 736,-214.1 734.4,-215 730.4,-217.1 727.8,-218.1 
+	722.9,-218.5 707.6,-219.4 702.5,-219.6 698.1,-220.5 692.4,-221.3 691.9,-222.1 691.3,-223.7 688.3,-225.8 682.3,-230 678,-232.9 
+	674.9,-235 673.5,-236.3 670.1,-239.3 665.8,-240.4 658.1,-241.9 650.8,-242.4 646.8,-242.7 641.2,-242.5 635.1,-242.5 
+	633.5,-242.4 624.6,-244.6 622.1,-245.1 619.4,-246.4 617.2,-247.6 614.5,-248 611.7,-248.1 608.8,-247.9 607,-247 604.6,-245 
+	603.1,-243.4 601.6,-241.8 599.4,-239.9 597.9,-238.3 596.6,-235.6 594.9,-232.7 592.6,-230 588.1,-226.3 584.2,-222.7 
+	581.7,-219.7 576.9,-212.9 571.8,-206.2 566.7,-198.8 562.4,-196.8 560.9,-195.8 557.1,-194.8 550.1,-193.3 546,-196.3 539,-201.1 
+	535.4,-203.8 531.2,-205.8 528.3,-207 524.7,-207.6 521,-208.2 517.4,-208 514.9,-208 510.3,-207.9 508.4,-207.8 504.7,-208 
+	501.1,-207.6 498.4,-206.7 495.9,-205 493.5,-202.3 490.9,-199.4 487.7,-195.6 484.7,-191.7 483.5,-189.6 480.4,-188.8 
+	476.1,-187.5 472.8,-185.9 469.4,-182.7 467.2,-180.7 465.5,-177.5 462.9,-173.2 460.4,-171.2 456.2,-168.6 453,-166.6 
+	450.1,-164.2 444.2,-163.6 440.2,-162.9 436.3,-161.7 432.4,-160.6 431.3,-159.4 430.2,-157.4 425.8,-155.8 423.6,-153.8 
+	419.5,-151.9 413.2,-150 406.5,-148.1 400.5,-147.1 395,-146.3 389.9,-145.8 387,-145.3 385.2,-143.8 383.6,-142.6 379.2,-142.8 
+	376.5,-142.6 372.8,-142 358.7,-138.4 354.7,-137.2 348.5,-138.2 345.9,-138.3 337.2,-136.9 327.6,-135.7 319.8,-134.7 
+	309.1,-134.2 304.3,-133.8 296.9,-132.4 289.3,-131 265.7,-128.5 259.1,-127.1 253.5,-126.4 235.2,-123.9 227.6,-122.5 
+	218.7,-121.1 211.3,-119.8 203.6,-118.7 198.1,-118.2 193.1,-117.8 189.9,-117.6 189,-117 189.8,-116.9 197.7,-117.4 207.4,-118.4 
+	215.9,-119.9 226.1,-121.5 233.7,-123 237.9,-123.5 246.9,-124.6 252.2,-125.4 257.6,-126 262,-126.6 265.5,-127.3 270,-127.8 
+	276.4,-128.6 282,-129.2 289.4,-130.2 294.1,-130.9 299.2,-132 303,-132.5 307,-133.1 312.2,-133.2 321.2,-134 328,-134.5 
+	333.9,-135.4 340.4,-136.3 344.7,-137.1 346.6,-137.3 351.3,-136.8 355.2,-136.3 359.1,-137.1 363.4,-138.5 369,-140 374.2,-141.1 
+	378.6,-142 382.6,-142 383.8,-142 385.3,-143 387.6,-144.6 392.5,-145.1 397.3,-145.8 401.6,-146.3 408.8,-147.9 414.7,-149.3 
+	418.7,-150.6 422.7,-152.4 424.7,-153.5 426.2,-154.8 427.2,-155.5 429.7,-156.2 430.8,-156.8 432.4,-159.2 433.3,-159.9 
+	435.9,-160.9 438.5,-161.7 441.4,-162.3 444.4,-163 447.2,-163.4 449.3,-163.3 450.3,-163.6 451.8,-164.6 454.7,-166.6 
+	458.3,-168.8 461.2,-170.5 463.9,-172.7 466.3,-177.4 467.5,-179.4 469,-181.1 471.5,-183.5 473.5,-185.1 476.5,-186.7 
+	478.8,-187.3 482.3,-188.3 483.6,-188.5 484.6,-190 485.7,-191.9 487.2,-193.9 490.4,-197.8 494.6,-202.1 496.2,-204.4 
+	497.5,-205.3 500.1,-206.5 502.3,-206.8 505.9,-207 508.7,-207.1 511.7,-207.3 514.2,-207.2 517.3,-207.2 519.2,-207.3 
+	521.3,-207.3 523.1,-207 527.6,-206.4 530,-205.4 534.8,-203.3 537.7,-201 541.5,-198.3 548.3,-193.6 549.6,-192.7 550.8,-192.7 
+	554.3,-193.6 557.1,-194.2 560.1,-194.9 561.3,-195.2 563.2,-196.4 566.8,-198.2 568.1,-199.3 569.5,-201.8 575.2,-209.3 
+	579.3,-215.1 582.6,-219.4 584.1,-221.5 585.8,-223.4 588.3,-225.5 591.3,-227.9 594.5,-230.7 595.8,-232.7 597.1,-234.9 
+	598.3,-237.7 599.3,-238.7 601.5,-240.7 603.4,-242.7 606.2,-245.5 608.7,-246.8 611.6,-247.5 613.8,-247.4 616.4,-247.1 
+	618.2,-246.4 620.5,-245.2 623.2,-244.1 625.5,-243.7 630.4,-242.6 633,-241.9 636,-241.6 639.9,-241.5 644.8,-241.8 650.1,-241.4 
+	655,-241.2 659,-241 661.7,-240.6 665.1,-239.7 669.2,-238.9 670.6,-237.7 672.4,-235.9 674.7,-234.3 680.6,-230.1 686.2,-226.4 
+	688.8,-224.5 690.4,-223.2 691.1,-221.9 692.2,-220.8 693.6,-220.3 700,-219.3 702.8,-218.7 707.2,-218.3 715.5,-218.2 
+	722.2,-217.8 726.2,-217.2 727.7,-217.1 730,-215.8 733,-214.4 735.1,-213.5 737.2,-213 742.2,-212.1 745.7,-211.4 749.8,-209 
+	753.3,-207 755.1,-205.7 757.9,-203.2 760.9,-200.2 763.6,-197.4 766.5,-194.6 767.9,-193.6 770,-193 775.4,-191.7 781.1,-189.7 
+	785.6,-188.6 789.2,-187.3 792.9,-185.7 796.6,-183.8 798.8,-182.8 801.9,-180.8 804.7,-178.4 806.6,-176.9 808.1,-174.4 
+	809.6,-172.5 813.7,-170.2 817.1,-168.1 818.8,-166.8 821.2,-165.1 824.1,-163.1 830.5,-160 834.7,-157.8 838.6,-155.6 
+	841.4,-153.9 844,-152 848.7,-148.7 852,-146.2 857.4,-142.7 861.3,-140.3 864.5,-138 867.4,-135.7 871.2,-133.3 874.1,-131.2 
+	875.5,-130.1 876.2,-129.6 878.1,-129.7 880.2,-129.6 881.7,-129.6 884.9,-129.2 889,-128.7 891.2,-128.4 893,-128.2 894,-127.7 
+	895.2,-127 897,-125 899.9,-121.7 901.8,-119.1 902.9,-117.9 904.3,-116.3 906.1,-115.3 908.4,-114.9 909.8,-115.6 911.4,-116.9 
+	914.5,-117.4 922,-118.3 931.3,-119.4 937.3,-120 941,-120.3 944.9,-120.6 949.9,-121 952.9,-121.1 955,-121.5 960.5,-121.6 
+	965.9,-122 968.1,-122.1 969.1,-121.6 969.7,-121 970.9,-120.4 973.1,-119.7 974.5,-119.1 975.6,-118.2 976.8,-117.2 978.4,-115.9 
+	979.4,-114.9 980.1,-113.9 980.3,-112.8 981.2,-111.6 983,-109.9 983.5,-108.8 984,-106.4 984.4,-104.9 985.6,-103.1 987.1,-101.5 
+	988.6,-100.2 991.3,-99.7 992.7,-99.7 995.3,-101 997.1,-102.1 998.9,-104.3 1000.1,-105.8 1001.1,-107.2 1002.1,-109.7 
+	1003.1,-111.8 1005.1,-113.2 1005.8,-114 1008.8,-115.2 1011.7,-116.4 1014,-116.9 1015.5,-116.2 1017.3,-115.3 1018.6,-114.6 
+	1020.5,-114.2 1022.7,-114.3 1025.2,-115.5 1026.1,-116.3 1027.3,-117.7 1033.2,-123.5 1036,-126.6 1040.6,-131.6 1044.5,-135.1 
+	1046.2,-136.8 1048.9,-140.2 1050,-142 1050.4,-146.1 1050.5,-150.8 1050.6,-155.3 1050.5,-160.4 1050.9,-163.7 1051.8,-166.5 
+	1054.4,-172.8 1055.8,-176.8 1056.6,-178.2 1058,-179.4 1060,-180.4 1062.7,-180.9 1066.3,-181.9 1069.1,-182.6 1071.6,-183.5 
+	1073.1,-184 1074.8,-184.2 1077,-184.2 1080.4,-184.4 1083.5,-184.6 1086.8,-185.1 1090.3,-185.6 1092.9,-186.2 1093.7,-186.6 
+	1094.9,-188.1 1097.4,-191.3 1098.6,-192.9 1100.8,-197.7 1102.3,-202.8 1103.8,-208 1105,-215.9 1105.9,-219.8 1106.5,-223.2 
+	1107.8,-225.4 1109.3,-227.6 1112.1,-229.9 1114.3,-231.9 1115.1,-233.7 1116.3,-235.6 1116.5,-237.2 1116.5,-240.7 1116.1,-243.2 
+	1115.4,-245 1114.1,-247.4 1111.7,-250.5 1110.4,-251.6 1108,-253.5 1105.6,-256.2 1103.2,-259.3 1101.1,-263.2 1100.6,-266.5 
+	1100.8,-270 1101,-273 1101.6,-276.3 1102.3,-277.8 1104.1,-279.7 1106.2,-282.3 1107.3,-283.4 1108.9,-284.8 1111.1,-286.3 
+	1113.6,-288.9 1115.6,-292.2 1116.4,-294.4 1116.7,-296 1117.6,-298.4 1118.9,-301.3 1119.3,-303.5 1118.9,-306.9 1118.8,-309.2 
+	1119.3,-311.7 1119.8,-314.4 1120.3,-317 1121,-320.2 1121.4,-322.7 1122.3,-325.7 1122.8,-327.8 1124.3,-329.7 1125.8,-331.1 
+	1128.5,-331.5 1133.3,-332.1 1139.7,-332.9 1143.9,-333.5 1149.6,-334.2 1152.3,-334.6 1156.4,-334.3 1161.1,-334 1162.6,-333.8 
+	1164.1,-333.2 1167,-332 1169.5,-330.9 1172.7,-329.8 1175.6,-329.1 1177,-328.8 1176.1,-327.8 1177.5,-326.9 1179.2,-329.8 
+	1182.4,-335 1185.1,-339 1186.7,-341.7 1187.8,-345.3 1189.4,-349.7 1191.2,-353 1193.2,-356.4 1195.4,-358.7 1197.6,-360 
+	1199.7,-360.3 1201.7,-360.1 1203.7,-359.4 1205.2,-358.5 1206.1,-357.7 1208.2,-356.9 1209.6,-356.9 1211.5,-357.7 1213.3,-359.4 
+	1213.8,-360.6 1213.9,-362.6 1213.1,-364.8 1213.5,-366.7 1215,-368 1218,-369.5 1222.1,-371.4 1227.7,-373.8 1231.1,-375.5 
+	1234.4,-376.3 1240.1,-378.3 1246.4,-381.4 1250.8,-383.5 1253.4,-384.8 1256.5,-387.7 1260.8,-391.1 1262.9,-393.2 1264.6,-394.3 
+	1269.7,-397.1 1273.2,-399.8 1276.7,-402.6 1280.5,-406.3 1283.6,-409.7 1286.7,-412.9 1289.5,-416 1292.4,-418.9 1295.1,-421.5 
+	1298,-423.7 1301.7,-426.9 1304,-429 1306.2,-431.4 1309.6,-435.4 1311.8,-437 1318.3,-439.8 1320.5,-440.7 1323.3,-442 
+	1324.6,-442.6 1328.8,-443.2 1332.6,-444 1336.2,-444.4 1339.3,-445 1344.5,-446.1 1347,-446.7 1349,-447.8 1350.1,-449.6 
+	1350.3,-451.7 1350.7,-458.8 1350.7,-463.9 1350.7,-466.8 1351,-467.6 1352.3,-468.1 1354.2,-467.3 1356.8,-467 1361.1,-467.4 
+	1363.3,-468.3 1367,-471.3 1371.3,-475.9 1375.4,-479.5 1378.3,-482.4 1383.5,-485 1387.4,-487.2 1391.1,-487.6 1394.7,-487.8 
+	1399.3,-487 1402.5,-486.5 1405.9,-485.4 1409.8,-483.6 1415.5,-480.9 1419.1,-479.4 1421.1,-479.2 1425.3,-479.5 1429,-479.2 
+	1431.8,-480.7 1433.3,-482.9 1433.1,-485.8 1432.8,-488.7 1433.9,-493.2 1435.3,-497.5 1437.1,-501.8 1438.9,-503.8 1442.7,-508.7 
+	1444.8,-511.5 1449.2,-514.3 1456.1,-519.6 1458.5,-521.3 1465.8,-526.6 1468.1,-529 1471.2,-533 1475.5,-537.3 1479.8,-540.5 
+	1482.7,-541.9 1485.4,-543.2 1487.3,-543.3 1488.3,-542.5 1488.8,-541.7 1488.8,-540.4 1490,-538.5 1493.6,-534 1493.9,-532.7 
+	1494.5,-530.3 1496.5,-526 1497.5,-523.9 1500,-519.8 1503.2,-515.4 1505.1,-513.1 1509.3,-509.9 1510.3,-508.6 1512.8,-507.2 
+	1514.4,-507.1 1519,-508.4 1523,-510.4 1525.3,-511.6 1529.2,-515.8 1532.9,-519.4 1538.4,-524 1543.4,-528.5 1546,-531.2 
+	1546.7,-532.3 1546.7,-535.1 1546.4,-537.1 1542.3,-541.3 1539.9,-544 1537.8,-547.5 1534.7,-551.8 1532.8,-554 1532.1,-559.2 
+	1531.1,-564 1531.2,-568.6 1531.1,-575 1531.8,-578.2 1532.7,-580.6 1534.4,-585.3 1535.8,-588.6 1537.5,-590.6 1539.5,-592 
+	1541.5,-592.3 1543.8,-591.5 1545.2,-589.7 1546.7,-587.1 1546.8,-584.7 1545.7,-581.3 1543.6,-578 1542.5,-574.5 1542.9,-571.8 
+	1545.7,-568.4 1548.9,-565.6 1553.1,-562.6 1556.5,-561.4 1560.6,-560.6 1562.2,-560.5 1565.9,-562.2 1570.6,-564.7 1575.9,-567.4 
+	1579.4,-569.7 1582.9,-573 1584.8,-576.3 1584.3,-581.1 1582.7,-584.8 1579.3,-588.4 1576.9,-591.8 1574.3,-594.4 1572.3,-595.9 
+	1570.2,-598.1 1568.1,-600.2 1567.6,-602.1 1569.1,-605.4 1572.9,-612.1 1574.1,-615.8 1575.1,-617.6 1579.5,-620.6 1581.1,-621.5 
+	1583.9,-622.5 1586.9,-623 1590.2,-624.1 1591.6,-625 1592.1,-627.9 1591.4,-631.1 1590.9,-634.3 1591.6,-636.3 1592.7,-636.8 
+	1594.2,-636 1597.2,-632.2 1599.5,-626.2 1600.4,-621.2 1600.5,-618.2 1599.9,-616.4 1600.1,-613.9 1600.5,-609.7 1601.6,-608.3 
+	1601.8,-606.4 1602.3,-603.2 1604.5,-600.8 1606.5,-600.3 1611.3,-600.2 1616.8,-601.4 1622.9,-604.8 1625.3,-607.4 1626,-609.2 
+	1626.5,-613.1 1626.1,-616.9 1628.4,-621.1 1629.3,-622.6 1630.7,-624 1632.4,-624.3 1635.6,-622.8 1639.6,-621.7 1644,-621.3 
+	1648.1,-621.2 1651.6,-622.1 1656.6,-624.6 1658,-625.7 1663.3,-634.8 1666.5,-640.2 1672.6,-651.1 1674.2,-653.3 1676.2,-654.6 
+	1679.7,-655.8 1681,-656 1683.7,-655.9 1688.1,-655.4 1690.2,-655.2 1694,-655.8 1697.2,-656 1702.4,-656.3 1707.7,-656.7 
+	1710.2,-656.9 1714.3,-658.3 1720.6,-660.9 1726.7,-663.6 1731.2,-665.6 1736.2,-667.7 1738.7,-670.2 1742.9,-674.3 1749.4,-680.9 
+	1752.5,-683.6 1754.5,-686.4 1758.1,-691.1 1761.3,-694.4 1763.8,-696.8 1767.1,-700 1769.1,-702.5 1770.7,-705.2 1773.8,-708.7 
+	1780.6,-715.2 1785.5,-719.7 1788.5,-722.5 1790.2,-721.3 1794.3,-725.5 1802.3,-733.5 1806.8,-738.5 1812.1,-744.3 1819.8,-754.3 
+	1823.6,-759 1826.3,-762.5 1829,-765.2 1831.3,-766.4 1835.7,-771.2 1839,-776.3 1841.7,-779.6 1845.6,-786.5 1846.9,-789.7 
+	1849.8,-793.1 1853.3,-796.6 1857.8,-801.3 1859.9,-804 1861.5,-804.7 1864.3,-808 1865.5,-810.7 1866.5,-812.5 1869.4,-815.1 
+	1872.7,-819 1877.7,-821.7 1881.9,-824.1 1884.8,-827.1 1886.4,-828.9 1888.8,-830 1891.5,-832.6 1898.3,-837.7 1901.6,-840.9 
+	1905.6,-844.2 1909.9,-848.3 1914.8,-850.8 1919.1,-852.6 1921.9,-853.9 1924.6,-854.5 1926.6,-857.2 1928.2,-858.2 1928.7,-857.5 
+	1934.2,-854.5 1939,-851.4 1943.3,-849.3 1947.7,-846.3 1953.3,-841.5 1955,-838.9 1957.8,-834.5 1959.3,-831.9 1961.5,-829.6 
+	1969.4,-823.7 1973.9,-821.5 1995,-825.2 2003,-872.4 1996.2,-900.7 1971.1,-918.3 1940,-920 1910.1,-920.3 1894.8,-910.8 
+	1893.8,-901.5 1903.9,-890.2 "/>
+<polyline points="1893.8,-901.5 1823.6,-960 2196,-960 2196,-690 2090.5,-740.9 1973.9,-821.5 "/>
+<path class="st2" d="M-362.5,1184.3h-11c-22.4,0-40.5-18.1-40.5-40.5l0,0c0-22.4,18.1-40.5,40.5-40.5h11c22.4,0,40.5,18.1,40.5,40.5
+	l0,0C-322,1166.1-340.1,1184.3-362.5,1184.3z"/>
+<pattern  id="SVGID_3_" xlink:href="#Unnamed_Pattern" patternTransform="matrix(1 0 0 -1 -62 -17332.1738)">
+</pattern>
+<rect x="-874" y="324.3" class="st5" width="204" height="184"/>
+</svg>

BIN
oreto_restyle_1720x520.png


File diff suppressed because it is too large
+ 2 - 0
p5.min.js


+ 69 - 0
river.js

@@ -0,0 +1,69 @@
+function River(){
+  this._timer;
+  this._bg;
+  this._gui;
+  this._checks;
+  this._poi;
+  this.enter = function()
+  {
+
+
+    this._timer=millis();
+    this._bg = loadImage('oreto_restyle_1720x520.png');
+
+    //background("#b86af0");
+    console.log("ENTER RIVER")
+  }
+
+  this.setup = function() {
+    createCanvas(_w, _h);
+    this._gui = createGui();
+    this._checks=[]
+
+    for (let step = 0; step < pois.length; step++) {
+      this._checks.push(createCheckbox("Checkbox"+step, 50, 50 + (step*20),10,10,true));
+    }
+    
+  }
+
+  this.draw = function() {
+
+     if(millis()-this._timer > 20000){
+      _mgr.showScene( Screensaver );
+    }
+  
+   background(this._bg);
+   drawGui();
+
+   for (let step = 0; step < pois.length; step++) {
+    cb = this._checks[step];
+    if(cb.val){
+      fill(255)
+      //getPin(trx1,try1);
+      pois[step].adapt();
+      pois[step].pin();
+    }
+
+   }
+   if (mouseIsPressed) {
+      fill(0);
+      resetTimer();
+    } 
+  }
+  this.mouseClicked = function(){
+
+   for (let step = 0; step < pois.length; step++) {
+    if(pois[step].overMe()){
+      console.log("Clicked on: " + poi.id);
+    }  
+   }
+  }
+  function  resetTimer(){
+
+      console.log("Timer: " + this._timer)
+      this._timer=millis() 
+        
+      console.log("Timer: " + this._timer + " millis: " + millis())
+  }
+
+}

+ 29 - 0
screensaver.js

@@ -0,0 +1,29 @@
+function Screensaver(){
+ this.enter = function()
+    {
+      console.log("ENTER SCREESAVER")
+        textX = 10;
+        textY = 0;
+
+      }
+  this.setup= function() {
+    cnv=createCanvas(_w, _h);
+    cnv.mouseClicked(toRiver);
+    console.log("ScSv STARTED ")
+  }
+
+  this.draw = function() {
+        let ourText='Click Over Me';
+        background("teal");
+        fill("black");
+        textSize(50 + cos(frameCount * 0.025) * 25);
+        textLeading(sin(frameCount * 0.01)*50);
+        text(ourText, 40, height/2, 300, 350);
+  }
+  
+  function toRiver(){
+
+      console.log("Mouse pressed in ScSv")
+      _mgr.showScene( River );
+  }
+}

+ 108 - 0
sketch.js

@@ -0,0 +1,108 @@
+var _mgr;
+var _w,_h; 
+var poi01 = {
+  x: 252,
+  y: 144,
+  id: "Poi01",
+  img: null,
+  _img: null,
+  area: function(){
+      let square = {
+      x1: this.x+random(-1, 1),
+      y1: this.y+random(-1, 1),
+      x2: this.x-7+random(-1, 1),
+      y2: this.y+7+random(-1, 1),
+      x3: this.x+7+random(-1, 1),
+      y3: this.y+7+random(-1, 1)
+    }
+    let delta=0;
+    if(mouseX >= square.x2 && mouseX <= square.x3 && mouseY >= square.y1 && mouseY <= square.y3){
+      delta = delta + 5;
+    }
+    square.y1-=delta;
+    square.x2-=delta;
+
+    square.y2+=delta;
+    square.x3+=delta;
+    square.y3+=delta;
+    return square; 
+  },
+  pin: function(){
+    let square = this.area();
+
+    if(this.overMe()){
+      return  image(this._img, square.x1,square.y1 ); 
+    }
+    return image(this.img, square.x1,square.y1 ); 
+  },
+  adapt: function(){
+   // this.img.resize(20, 20);
+    //this._img= Object.assign({},this.img));
+
+    //this._img.resize(50, 50);
+  },
+  setIcon: function(filename){
+    //small
+    this.img=loadImage(filename,
+      function(img){
+        img.resize(20,20);
+      });  
+    //big
+    this._img=loadImage(filename,
+      function(img){
+        img.resize(50,50);
+      });
+  },
+  overMe: function(){
+    let square = this.area();  
+    return (mouseX >= square.x1 && mouseX <= (square.x1+this.img.width) && mouseY >= square.y1 && mouseY <= (square.y1+this.img.height));
+  }
+};
+
+var pois=[];
+   
+function setup()
+{
+  createCanvas(600, 500);
+  console.log("STARTED");
+  var poi=Object.create(poi01);
+
+  poi.x= 346;
+  poi.y= 332;
+  poi.id="First One";
+  poi.setIcon('icona_testo.png');
+  pois.push(poi);
+
+  poi=Object.create(poi01);
+  poi.x= 746;
+  poi.y= 432;
+  poi.id="Two";
+  poi.setIcon('icona_testo.png');
+  pois.push(poi);
+   _mgr = new SceneManager();
+  _w = 1270
+  _h = 520
+
+  // Preload scenes. Preloading is normally optional
+  // ... but needed if showNextScene() is used.
+  _mgr.addScene ( Screensaver );
+  _mgr.addScene ( River );
+
+  console.log("Try to display screensaver");
+  _mgr.showScene(Screensaver);
+}
+
+function draw()
+{
+    _mgr.draw();
+}
+
+function mousePressed()
+{
+    _mgr.handleEvent("mousePressed");
+}
+
+function mouseClicked()
+{
+    _mgr.handleEvent("mouseClicked");
+}

Some files were not shown because too many files changed in this diff