| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203 | /***    P R O C E S S I N G . J S - 1.4.1    a port of the Processing visualization language    Processing.js is licensed under the MIT License, see LICENSE.    For a list of copyright holders, please refer to AUTHORS.    http://processingjs.org***/(function(window, document, Math, undef) {  var nop = function() {};  var debug = function() {    if ("console" in window) return function(msg) {      window.console.log("Processing.js: " + msg)    };    return nop  }();  var ajax = function(url) {    var xhr = new XMLHttpRequest;    xhr.open("GET", url, false);    if (xhr.overrideMimeType) xhr.overrideMimeType("text/plain");    xhr.setRequestHeader("If-Modified-Since", "Fri, 01 Jan 1960 00:00:00 GMT");    xhr.send(null);    if (xhr.status !== 200 && xhr.status !== 0) throw "XMLHttpRequest failed, status code " + xhr.status;    return xhr.responseText  };  var isDOMPresent = "document" in this && !("fake" in this.document);  document.head = document.head || document.getElementsByTagName("head")[0];  function setupTypedArray(name, fallback) {    if (name in window) return window[name];    if (typeof window[fallback] === "function") return window[fallback];    return function(obj) {      if (obj instanceof Array) return obj;      if (typeof obj === "number") {        var arr = [];        arr.length = obj;        return arr      }    }  }  if (document.documentMode >= 9 && !document.doctype) throw "The doctype directive is missing. The recommended doctype in Internet Explorer is the HTML5 doctype: <!DOCTYPE html>";  var Float32Array = setupTypedArray("Float32Array", "WebGLFloatArray"),    Int32Array = setupTypedArray("Int32Array", "WebGLIntArray"),    Uint16Array = setupTypedArray("Uint16Array", "WebGLUnsignedShortArray"),    Uint8Array = setupTypedArray("Uint8Array", "WebGLUnsignedByteArray");  var PConstants = {    X: 0,    Y: 1,    Z: 2,    R: 3,    G: 4,    B: 5,    A: 6,    U: 7,    V: 8,    NX: 9,    NY: 10,    NZ: 11,    EDGE: 12,    SR: 13,    SG: 14,    SB: 15,    SA: 16,    SW: 17,    TX: 18,    TY: 19,    TZ: 20,    VX: 21,    VY: 22,    VZ: 23,    VW: 24,    AR: 25,    AG: 26,    AB: 27,    DR: 3,    DG: 4,    DB: 5,    DA: 6,    SPR: 28,    SPG: 29,    SPB: 30,    SHINE: 31,    ER: 32,    EG: 33,    EB: 34,    BEEN_LIT: 35,    VERTEX_FIELD_COUNT: 36,    P2D: 1,    JAVA2D: 1,    WEBGL: 2,    P3D: 2,    OPENGL: 2,    PDF: 0,    DXF: 0,    OTHER: 0,    WINDOWS: 1,    MAXOSX: 2,    LINUX: 3,    EPSILON: 1.0E-4,    MAX_FLOAT: 3.4028235E38,    MIN_FLOAT: -3.4028235E38,    MAX_INT: 2147483647,    MIN_INT: -2147483648,    PI: Math.PI,    TWO_PI: 2 * Math.PI,    HALF_PI: Math.PI / 2,    THIRD_PI: Math.PI / 3,    QUARTER_PI: Math.PI / 4,    DEG_TO_RAD: Math.PI / 180,    RAD_TO_DEG: 180 / Math.PI,    WHITESPACE: " \t\n\r\u000c\u00a0",    RGB: 1,    ARGB: 2,    HSB: 3,    ALPHA: 4,    CMYK: 5,    TIFF: 0,    TARGA: 1,    JPEG: 2,    GIF: 3,    BLUR: 11,    GRAY: 12,    INVERT: 13,    OPAQUE: 14,    POSTERIZE: 15,    THRESHOLD: 16,    ERODE: 17,    DILATE: 18,    REPLACE: 0,    BLEND: 1 << 0,    ADD: 1 << 1,    SUBTRACT: 1 << 2,    LIGHTEST: 1 << 3,    DARKEST: 1 << 4,    DIFFERENCE: 1 << 5,    EXCLUSION: 1 << 6,    MULTIPLY: 1 << 7,    SCREEN: 1 << 8,    OVERLAY: 1 << 9,    HARD_LIGHT: 1 << 10,    SOFT_LIGHT: 1 << 11,    DODGE: 1 << 12,    BURN: 1 << 13,    ALPHA_MASK: 4278190080,    RED_MASK: 16711680,    GREEN_MASK: 65280,    BLUE_MASK: 255,    CUSTOM: 0,    ORTHOGRAPHIC: 2,    PERSPECTIVE: 3,    POINT: 2,    POINTS: 2,    LINE: 4,    LINES: 4,    TRIANGLE: 8,    TRIANGLES: 9,    TRIANGLE_STRIP: 10,    TRIANGLE_FAN: 11,    QUAD: 16,    QUADS: 16,    QUAD_STRIP: 17,    POLYGON: 20,    PATH: 21,    RECT: 30,    ELLIPSE: 31,    ARC: 32,    SPHERE: 40,    BOX: 41,    GROUP: 0,    PRIMITIVE: 1,    GEOMETRY: 3,    VERTEX: 0,    BEZIER_VERTEX: 1,    CURVE_VERTEX: 2,    BREAK: 3,    CLOSESHAPE: 4,    OPEN: 1,    CLOSE: 2,    CORNER: 0,    CORNERS: 1,    RADIUS: 2,    CENTER_RADIUS: 2,    CENTER: 3,    DIAMETER: 3,    CENTER_DIAMETER: 3,    BASELINE: 0,    TOP: 101,    BOTTOM: 102,    NORMAL: 1,    NORMALIZED: 1,    IMAGE: 2,    MODEL: 4,    SHAPE: 5,    SQUARE: "butt",    ROUND: "round",    PROJECT: "square",    MITER: "miter",    BEVEL: "bevel",    AMBIENT: 0,    DIRECTIONAL: 1,    SPOT: 3,    BACKSPACE: 8,    TAB: 9,    ENTER: 10,    RETURN: 13,    ESC: 27,    DELETE: 127,    CODED: 65535,    SHIFT: 16,    CONTROL: 17,    ALT: 18,    CAPSLK: 20,    PGUP: 33,    PGDN: 34,    END: 35,    HOME: 36,    LEFT: 37,    UP: 38,    RIGHT: 39,    DOWN: 40,    F1: 112,    F2: 113,    F3: 114,    F4: 115,    F5: 116,    F6: 117,    F7: 118,    F8: 119,    F9: 120,    F10: 121,    F11: 122,    F12: 123,    NUMLK: 144,    META: 157,    INSERT: 155,    ARROW: "default",    CROSS: "crosshair",    HAND: "pointer",    MOVE: "move",    TEXT: "text",    WAIT: "wait",    NOCURSOR: "url('data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=='), auto",    DISABLE_OPENGL_2X_SMOOTH: 1,    ENABLE_OPENGL_2X_SMOOTH: -1,    ENABLE_OPENGL_4X_SMOOTH: 2,    ENABLE_NATIVE_FONTS: 3,    DISABLE_DEPTH_TEST: 4,    ENABLE_DEPTH_TEST: -4,    ENABLE_DEPTH_SORT: 5,    DISABLE_DEPTH_SORT: -5,    DISABLE_OPENGL_ERROR_REPORT: 6,    ENABLE_OPENGL_ERROR_REPORT: -6,    ENABLE_ACCURATE_TEXTURES: 7,    DISABLE_ACCURATE_TEXTURES: -7,    HINT_COUNT: 10,    SINCOS_LENGTH: 720,    PRECISIONB: 15,    PRECISIONF: 1 << 15,    PREC_MAXVAL: (1 << 15) - 1,    PREC_ALPHA_SHIFT: 24 - 15,    PREC_RED_SHIFT: 16 - 15,    NORMAL_MODE_AUTO: 0,    NORMAL_MODE_SHAPE: 1,    NORMAL_MODE_VERTEX: 2,    MAX_LIGHTS: 8  };  function virtHashCode(obj) {    if (typeof obj === "string") {      var hash = 0;      for (var i = 0; i < obj.length; ++i) hash = hash * 31 + obj.charCodeAt(i) & 4294967295;      return hash    }    if (typeof obj !== "object") return obj & 4294967295;    if (obj.hashCode instanceof Function) return obj.hashCode();    if (obj.$id === undef) obj.$id = Math.floor(Math.random() * 65536) - 32768 << 16 | Math.floor(Math.random() * 65536);    return obj.$id  }  function virtEquals(obj, other) {    if (obj === null || other === null) return obj === null && other === null;    if (typeof obj === "string") return obj === other;    if (typeof obj !== "object") return obj === other;    if (obj.equals instanceof Function) return obj.equals(other);    return obj === other  }  var ObjectIterator = function(obj) {    if (obj.iterator instanceof    Function) return obj.iterator();    if (obj instanceof Array) {      var index = -1;      this.hasNext = function() {        return ++index < obj.length      };      this.next = function() {        return obj[index]      }    } else throw "Unable to iterate: " + obj;  };  var ArrayList = function() {    function Iterator(array) {      var index = 0;      this.hasNext = function() {        return index < array.length      };      this.next = function() {        return array[index++]      };      this.remove = function() {        array.splice(index, 1)      }    }    function ArrayList(a) {      var array;      if (a instanceof ArrayList) array = a.toArray();      else {        array = [];        if (typeof a === "number") array.length = a > 0 ? a : 0      }      this.get = function(i) {        return array[i]      };      this.contains = function(item) {        return this.indexOf(item) > -1      };      this.indexOf = function(item) {        for (var i = 0, len = array.length; i < len; ++i) if (virtEquals(item, array[i])) return i;        return -1      };      this.lastIndexOf = function(item) {        for (var i = array.length - 1; i >= 0; --i) if (virtEquals(item, array[i])) return i;        return -1      };      this.add = function() {        if (arguments.length === 1) array.push(arguments[0]);        else if (arguments.length === 2) {          var arg0 = arguments[0];          if (typeof arg0 === "number") if (arg0 >= 0 && arg0 <= array.length) array.splice(arg0, 0, arguments[1]);          else throw arg0 + " is not a valid index";          else throw typeof arg0 + " is not a number";        } else throw "Please use the proper number of parameters.";      };      this.addAll = function(arg1, arg2) {        var it;        if (typeof arg1 === "number") {          if (arg1 < 0 || arg1 > array.length) throw "Index out of bounds for addAll: " + arg1 + " greater or equal than " + array.length;          it = new ObjectIterator(arg2);          while (it.hasNext()) array.splice(arg1++, 0, it.next())        } else {          it = new ObjectIterator(arg1);          while (it.hasNext()) array.push(it.next())        }      };      this.set = function() {        if (arguments.length === 2) {          var arg0 = arguments[0];          if (typeof arg0 === "number") if (arg0 >= 0 && arg0 < array.length) array.splice(arg0, 1, arguments[1]);          else throw arg0 + " is not a valid index.";          else throw typeof arg0 + " is not a number";        } else throw "Please use the proper number of parameters.";      };      this.size = function() {        return array.length      };      this.clear = function() {        array.length = 0      };      this.remove = function(item) {        if (typeof item === "number") return array.splice(item, 1)[0];        item = this.indexOf(item);        if (item > -1) {          array.splice(item, 1);          return true        }        return false      };      this.removeAll = function(c) {        var i, x, item, newList = new ArrayList;        newList.addAll(this);        this.clear();        for (i = 0, x = 0; i < newList.size(); i++) {          item = newList.get(i);          if (!c.contains(item)) this.add(x++, item)        }        if (this.size() < newList.size()) return true;        return false      };      this.isEmpty = function() {        return !array.length      };      this.clone = function() {        return new ArrayList(this)      };      this.toArray = function() {        return array.slice(0)      };      this.iterator = function() {        return new Iterator(array)      }    }    return ArrayList  }();  var HashMap = function() {    function HashMap() {      if (arguments.length === 1 && arguments[0] instanceof HashMap) return arguments[0].clone();      var initialCapacity = arguments.length > 0 ? arguments[0] : 16;      var loadFactor = arguments.length > 1 ? arguments[1] : 0.75;      var buckets = [];      buckets.length = initialCapacity;      var count = 0;      var hashMap = this;      function getBucketIndex(key) {        var index = virtHashCode(key) % buckets.length;        return index < 0 ? buckets.length + index : index      }      function ensureLoad() {        if (count <= loadFactor * buckets.length) return;        var allEntries = [];        for (var i = 0; i < buckets.length; ++i) if (buckets[i] !== undef) allEntries = allEntries.concat(buckets[i]);        var newBucketsLength = buckets.length * 2;        buckets = [];        buckets.length = newBucketsLength;        for (var j = 0; j < allEntries.length; ++j) {          var index = getBucketIndex(allEntries[j].key);          var bucket = buckets[index];          if (bucket === undef) buckets[index] = bucket = [];          bucket.push(allEntries[j])        }      }      function Iterator(conversion, removeItem) {        var bucketIndex = 0;        var itemIndex = -1;        var endOfBuckets = false;        var currentItem;        function findNext() {          while (!endOfBuckets) {            ++itemIndex;            if (bucketIndex >= buckets.length) endOfBuckets = true;            else if (buckets[bucketIndex] === undef || itemIndex >= buckets[bucketIndex].length) {              itemIndex = -1;              ++bucketIndex            } else return          }        }        this.hasNext = function() {          return !endOfBuckets        };        this.next = function() {          currentItem = conversion(buckets[bucketIndex][itemIndex]);          findNext();          return currentItem        };        this.remove = function() {          if (currentItem !== undef) {            removeItem(currentItem);            --itemIndex;            findNext()          }        };        findNext()      }      function Set(conversion, isIn, removeItem) {        this.clear = function() {          hashMap.clear()        };        this.contains = function(o) {          return isIn(o)        };        this.containsAll = function(o) {          var it = o.iterator();          while (it.hasNext()) if (!this.contains(it.next())) return false;          return true        };        this.isEmpty = function() {          return hashMap.isEmpty()        };        this.iterator = function() {          return new Iterator(conversion, removeItem)        };        this.remove = function(o) {          if (this.contains(o)) {            removeItem(o);            return true          }          return false        };        this.removeAll = function(c) {          var it = c.iterator();          var changed = false;          while (it.hasNext()) {            var item = it.next();            if (this.contains(item)) {              removeItem(item);              changed = true            }          }          return true        };        this.retainAll = function(c) {          var it = this.iterator();          var toRemove = [];          while (it.hasNext()) {            var entry = it.next();            if (!c.contains(entry)) toRemove.push(entry)          }          for (var i = 0; i < toRemove.length; ++i) removeItem(toRemove[i]);          return toRemove.length > 0        };        this.size = function() {          return hashMap.size()        };        this.toArray = function() {          var result = [];          var it = this.iterator();          while (it.hasNext()) result.push(it.next());          return result        }      }      function Entry(pair) {        this._isIn = function(map) {          return map === hashMap && pair.removed === undef        };        this.equals = function(o) {          return virtEquals(pair.key, o.getKey())        };        this.getKey = function() {          return pair.key        };        this.getValue = function() {          return pair.value        };        this.hashCode = function(o) {          return virtHashCode(pair.key)        };        this.setValue = function(value) {          var old = pair.value;          pair.value = value;          return old        }      }      this.clear = function() {        count = 0;        buckets = [];        buckets.length = initialCapacity      };      this.clone = function() {        var map = new HashMap;        map.putAll(this);        return map      };      this.containsKey = function(key) {        var index = getBucketIndex(key);        var bucket = buckets[index];        if (bucket === undef) return false;        for (var i = 0; i < bucket.length; ++i) if (virtEquals(bucket[i].key, key)) return true;        return false      };      this.containsValue = function(value) {        for (var i = 0; i < buckets.length; ++i) {          var bucket = buckets[i];          if (bucket === undef) continue;          for (var j = 0; j < bucket.length; ++j) if (virtEquals(bucket[j].value, value)) return true        }        return false      };      this.entrySet = function() {        return new Set(function(pair) {          return new Entry(pair)        },        function(pair) {          return pair instanceof Entry && pair._isIn(hashMap)        },        function(pair) {          return hashMap.remove(pair.getKey())        })      };      this.get = function(key) {        var index = getBucketIndex(key);        var bucket = buckets[index];        if (bucket === undef) return null;        for (var i = 0; i < bucket.length; ++i) if (virtEquals(bucket[i].key, key)) return bucket[i].value;        return null      };      this.isEmpty = function() {        return count === 0      };      this.keySet = function() {        return new Set(function(pair) {          return pair.key        },        function(key) {          return hashMap.containsKey(key)        },        function(key) {          return hashMap.remove(key)        })      };      this.values = function() {        return new Set(function(pair) {          return pair.value        },        function(value) {          return hashMap.containsValue(value)        },        function(value) {          return hashMap.removeByValue(value)        })      };      this.put = function(key, value) {        var index = getBucketIndex(key);        var bucket = buckets[index];        if (bucket === undef) {          ++count;          buckets[index] = [{            key: key,            value: value          }];          ensureLoad();          return null        }        for (var i = 0; i < bucket.length; ++i) if (virtEquals(bucket[i].key, key)) {          var previous = bucket[i].value;          bucket[i].value = value;          return previous        }++count;        bucket.push({          key: key,          value: value        });        ensureLoad();        return null      };      this.putAll = function(m) {        var it = m.entrySet().iterator();        while (it.hasNext()) {          var entry = it.next();          this.put(entry.getKey(), entry.getValue())        }      };      this.remove = function(key) {        var index = getBucketIndex(key);        var bucket = buckets[index];        if (bucket === undef) return null;        for (var i = 0; i < bucket.length; ++i) if (virtEquals(bucket[i].key, key)) {          --count;          var previous = bucket[i].value;          bucket[i].removed = true;          if (bucket.length > 1) bucket.splice(i, 1);          else buckets[index] = undef;          return previous        }        return null      };      this.removeByValue = function(value) {        var bucket, i, ilen, pair;        for (bucket in buckets) if (buckets.hasOwnProperty(bucket)) for (i = 0, ilen = buckets[bucket].length; i < ilen; i++) {          pair = buckets[bucket][i];          if (pair.value === value) {            buckets[bucket].splice(i, 1);            return true          }        }        return false      };      this.size = function() {        return count      }    }    return HashMap  }();  var PVector = function() {    function PVector(x, y, z) {      this.x = x || 0;      this.y = y || 0;      this.z = z || 0    }    PVector.dist = function(v1, v2) {      return v1.dist(v2)    };    PVector.dot = function(v1, v2) {      return v1.dot(v2)    };    PVector.cross = function(v1, v2) {      return v1.cross(v2)    };    PVector.angleBetween = function(v1, v2) {      return Math.acos(v1.dot(v2) / (v1.mag() * v2.mag()))    };    PVector.prototype = {      set: function(v, y, z) {        if (arguments.length === 1) this.set(v.x || v[0] || 0, v.y || v[1] || 0, v.z || v[2] || 0);        else {          this.x = v;          this.y = y;          this.z = z        }      },      get: function() {        return new PVector(this.x, this.y, this.z)      },      mag: function() {        var x = this.x,          y = this.y,          z = this.z;        return Math.sqrt(x * x + y * y + z * z)      },      add: function(v, y, z) {        if (arguments.length === 1) {          this.x += v.x;          this.y += v.y;          this.z += v.z        } else {          this.x += v;          this.y += y;          this.z += z        }      },      sub: function(v, y, z) {        if (arguments.length === 1) {          this.x -= v.x;          this.y -= v.y;          this.z -= v.z        } else {          this.x -= v;          this.y -= y;          this.z -= z        }      },      mult: function(v) {        if (typeof v === "number") {          this.x *= v;          this.y *= v;          this.z *= v        } else {          this.x *= v.x;          this.y *= v.y;          this.z *= v.z        }      },      div: function(v) {        if (typeof v === "number") {          this.x /= v;          this.y /= v;          this.z /= v        } else {          this.x /= v.x;          this.y /= v.y;          this.z /= v.z        }      },      dist: function(v) {        var dx = this.x - v.x,          dy = this.y - v.y,          dz = this.z - v.z;        return Math.sqrt(dx * dx + dy * dy + dz * dz)      },      dot: function(v, y, z) {        if (arguments.length === 1) return this.x * v.x + this.y * v.y + this.z * v.z;        return this.x * v + this.y * y + this.z * z      },      cross: function(v) {        var x = this.x,          y = this.y,          z = this.z;        return new PVector(y * v.z - v.y * z, z * v.x - v.z * x, x * v.y - v.x * y)      },      normalize: function() {        var m = this.mag();        if (m > 0) this.div(m)      },      limit: function(high) {        if (this.mag() > high) {          this.normalize();          this.mult(high)        }      },      heading2D: function() {        return -Math.atan2(-this.y, this.x)      },      toString: function() {        return "[" + this.x + ", " + this.y + ", " + this.z + "]"      },      array: function() {        return [this.x, this.y, this.z]      }    };    function createPVectorMethod(method) {      return function(v1, v2) {        var v = v1.get();        v[method](v2);        return v      }    }    for (var method in PVector.prototype) if (PVector.prototype.hasOwnProperty(method) && !PVector.hasOwnProperty(method)) PVector[method] = createPVectorMethod(method);    return PVector  }();  function DefaultScope() {}  DefaultScope.prototype = PConstants;  var defaultScope = new DefaultScope;  defaultScope.ArrayList = ArrayList;  defaultScope.HashMap = HashMap;  defaultScope.PVector = PVector;  defaultScope.ObjectIterator = ObjectIterator;  defaultScope.PConstants = PConstants;  defaultScope.defineProperty = function(obj, name, desc) {    if ("defineProperty" in Object) Object.defineProperty(obj, name, desc);    else {      if (desc.hasOwnProperty("get")) obj.__defineGetter__(name, desc.get);      if (desc.hasOwnProperty("set")) obj.__defineSetter__(name, desc.set)    }  };  function overloadBaseClassFunction(object, name, basefn) {    if (!object.hasOwnProperty(name) || typeof object[name] !== "function") {      object[name] = basefn;      return    }    var fn = object[name];    if ("$overloads" in fn) {      fn.$defaultOverload = basefn;      return    }    if (! ("$overloads" in basefn) && fn.length === basefn.length) return;    var overloads, defaultOverload;    if ("$overloads" in basefn) {      overloads = basefn.$overloads.slice(0);      overloads[fn.length] = fn;      defaultOverload = basefn.$defaultOverload    } else {      overloads = [];      overloads[basefn.length] = basefn;      overloads[fn.length] = fn;      defaultOverload = fn    }    var hubfn = function() {      var fn = hubfn.$overloads[arguments.length] || ("$methodArgsIndex" in hubfn && arguments.length > hubfn.$methodArgsIndex ? hubfn.$overloads[hubfn.$methodArgsIndex] : null) || hubfn.$defaultOverload;      return fn.apply(this, arguments)    };    hubfn.$overloads = overloads;    if ("$methodArgsIndex" in basefn) hubfn.$methodArgsIndex = basefn.$methodArgsIndex;    hubfn.$defaultOverload = defaultOverload;    hubfn.name = name;    object[name] = hubfn  }  function extendClass(subClass, baseClass) {    function extendGetterSetter(propertyName) {      defaultScope.defineProperty(subClass, propertyName, {        get: function() {          return baseClass[propertyName]        },        set: function(v) {          baseClass[propertyName] = v        },        enumerable: true      })    }    var properties = [];    for (var propertyName in baseClass) if (typeof baseClass[propertyName] === "function") overloadBaseClassFunction(subClass, propertyName, baseClass[propertyName]);    else if (propertyName.charAt(0) !== "$" && !(propertyName in subClass)) properties.push(propertyName);    while (properties.length > 0) extendGetterSetter(properties.shift());    subClass.$super = baseClass  }  defaultScope.extendClassChain = function(base) {    var path = [base];    for (var self = base.$upcast; self; self = self.$upcast) {      extendClass(self, base);      path.push(self);      base = self    }    while (path.length > 0) path.pop().$self = base  };  defaultScope.extendStaticMembers = function(derived, base) {    extendClass(derived, base)  };  defaultScope.extendInterfaceMembers = function(derived, base) {    extendClass(derived, base)  };  defaultScope.addMethod = function(object, name, fn, hasMethodArgs) {    var existingfn = object[name];    if (existingfn || hasMethodArgs) {      var args = fn.length;      if ("$overloads" in existingfn) existingfn.$overloads[args] = fn;      else {        var hubfn = function() {          var fn = hubfn.$overloads[arguments.length] || ("$methodArgsIndex" in hubfn && arguments.length > hubfn.$methodArgsIndex ? hubfn.$overloads[hubfn.$methodArgsIndex] : null) || hubfn.$defaultOverload;          return fn.apply(this, arguments)        };        var overloads = [];        if (existingfn) overloads[existingfn.length] = existingfn;        overloads[args] = fn;        hubfn.$overloads = overloads;        hubfn.$defaultOverload = existingfn || fn;        if (hasMethodArgs) hubfn.$methodArgsIndex = args;        hubfn.name = name;        object[name] = hubfn      }    } else object[name] = fn  };  function isNumericalJavaType(type) {    if (typeof type !== "string") return false;    return ["byte", "int", "char", "color", "float", "long", "double"].indexOf(type) !== -1  }  defaultScope.createJavaArray = function(type, bounds) {    var result = null,      defaultValue = null;    if (typeof type === "string") if (type === "boolean") defaultValue = false;    else if (isNumericalJavaType(type)) defaultValue = 0;    if (typeof bounds[0] === "number") {      var itemsCount = 0 | bounds[0];      if (bounds.length <= 1) {        result = [];        result.length = itemsCount;        for (var i = 0; i < itemsCount; ++i) result[i] = defaultValue      } else {        result = [];        var newBounds = bounds.slice(1);        for (var j = 0; j < itemsCount; ++j) result.push(defaultScope.createJavaArray(type, newBounds))      }    }    return result  };  var colors = {    aliceblue: "#f0f8ff",    antiquewhite: "#faebd7",    aqua: "#00ffff",    aquamarine: "#7fffd4",    azure: "#f0ffff",    beige: "#f5f5dc",    bisque: "#ffe4c4",    black: "#000000",    blanchedalmond: "#ffebcd",    blue: "#0000ff",    blueviolet: "#8a2be2",    brown: "#a52a2a",    burlywood: "#deb887",    cadetblue: "#5f9ea0",    chartreuse: "#7fff00",    chocolate: "#d2691e",    coral: "#ff7f50",    cornflowerblue: "#6495ed",    cornsilk: "#fff8dc",    crimson: "#dc143c",    cyan: "#00ffff",    darkblue: "#00008b",    darkcyan: "#008b8b",    darkgoldenrod: "#b8860b",    darkgray: "#a9a9a9",    darkgreen: "#006400",    darkkhaki: "#bdb76b",    darkmagenta: "#8b008b",    darkolivegreen: "#556b2f",    darkorange: "#ff8c00",    darkorchid: "#9932cc",    darkred: "#8b0000",    darksalmon: "#e9967a",    darkseagreen: "#8fbc8f",    darkslateblue: "#483d8b",    darkslategray: "#2f4f4f",    darkturquoise: "#00ced1",    darkviolet: "#9400d3",    deeppink: "#ff1493",    deepskyblue: "#00bfff",    dimgray: "#696969",    dodgerblue: "#1e90ff",    firebrick: "#b22222",    floralwhite: "#fffaf0",    forestgreen: "#228b22",    fuchsia: "#ff00ff",    gainsboro: "#dcdcdc",    ghostwhite: "#f8f8ff",    gold: "#ffd700",    goldenrod: "#daa520",    gray: "#808080",    green: "#008000",    greenyellow: "#adff2f",    honeydew: "#f0fff0",    hotpink: "#ff69b4",    indianred: "#cd5c5c",    indigo: "#4b0082",    ivory: "#fffff0",    khaki: "#f0e68c",    lavender: "#e6e6fa",    lavenderblush: "#fff0f5",    lawngreen: "#7cfc00",    lemonchiffon: "#fffacd",    lightblue: "#add8e6",    lightcoral: "#f08080",    lightcyan: "#e0ffff",    lightgoldenrodyellow: "#fafad2",    lightgrey: "#d3d3d3",    lightgreen: "#90ee90",    lightpink: "#ffb6c1",    lightsalmon: "#ffa07a",    lightseagreen: "#20b2aa",    lightskyblue: "#87cefa",    lightslategray: "#778899",    lightsteelblue: "#b0c4de",    lightyellow: "#ffffe0",    lime: "#00ff00",    limegreen: "#32cd32",    linen: "#faf0e6",    magenta: "#ff00ff",    maroon: "#800000",    mediumaquamarine: "#66cdaa",    mediumblue: "#0000cd",    mediumorchid: "#ba55d3",    mediumpurple: "#9370d8",    mediumseagreen: "#3cb371",    mediumslateblue: "#7b68ee",    mediumspringgreen: "#00fa9a",    mediumturquoise: "#48d1cc",    mediumvioletred: "#c71585",    midnightblue: "#191970",    mintcream: "#f5fffa",    mistyrose: "#ffe4e1",    moccasin: "#ffe4b5",    navajowhite: "#ffdead",    navy: "#000080",    oldlace: "#fdf5e6",    olive: "#808000",    olivedrab: "#6b8e23",    orange: "#ffa500",    orangered: "#ff4500",    orchid: "#da70d6",    palegoldenrod: "#eee8aa",    palegreen: "#98fb98",    paleturquoise: "#afeeee",    palevioletred: "#d87093",    papayawhip: "#ffefd5",    peachpuff: "#ffdab9",    peru: "#cd853f",    pink: "#ffc0cb",    plum: "#dda0dd",    powderblue: "#b0e0e6",    purple: "#800080",    red: "#ff0000",    rosybrown: "#bc8f8f",    royalblue: "#4169e1",    saddlebrown: "#8b4513",    salmon: "#fa8072",    sandybrown: "#f4a460",    seagreen: "#2e8b57",    seashell: "#fff5ee",    sienna: "#a0522d",    silver: "#c0c0c0",    skyblue: "#87ceeb",    slateblue: "#6a5acd",    slategray: "#708090",    snow: "#fffafa",    springgreen: "#00ff7f",    steelblue: "#4682b4",    tan: "#d2b48c",    teal: "#008080",    thistle: "#d8bfd8",    tomato: "#ff6347",    turquoise: "#40e0d0",    violet: "#ee82ee",    wheat: "#f5deb3",    white: "#ffffff",    whitesmoke: "#f5f5f5",    yellow: "#ffff00",    yellowgreen: "#9acd32"  };  (function(Processing) {    var unsupportedP5 = ("open() createOutput() createInput() BufferedReader selectFolder() " + "dataPath() createWriter() selectOutput() beginRecord() " + "saveStream() endRecord() selectInput() saveBytes() createReader() " + "beginRaw() endRaw() PrintWriter delay()").split(" "),      count = unsupportedP5.length,      prettyName, p5Name;    function createUnsupportedFunc(n) {      return function() {        throw "Processing.js does not support " + n + ".";      }    }    while (count--) {      prettyName = unsupportedP5[count];      p5Name = prettyName.replace("()", "");      Processing[p5Name] = createUnsupportedFunc(prettyName)    }  })(defaultScope);  defaultScope.defineProperty(defaultScope, "screenWidth", {    get: function() {      return window.innerWidth    }  });  defaultScope.defineProperty(defaultScope, "screenHeight", {    get: function() {      return window.innerHeight    }  });  defaultScope.defineProperty(defaultScope, "online", {    get: function() {      return true    }  });  var processingInstances = [];  var processingInstanceIds = {};  var removeInstance = function(id) {    processingInstances.splice(processingInstanceIds[id], 1);    delete processingInstanceIds[id]  };  var addInstance = function(processing) {    if (processing.externals.canvas.id === undef || !processing.externals.canvas.id.length) processing.externals.canvas.id = "__processing" + processingInstances.length;    processingInstanceIds[processing.externals.canvas.id] = processingInstances.length;    processingInstances.push(processing)  };  function computeFontMetrics(pfont) {    var emQuad = 250,      correctionFactor = pfont.size / emQuad,      canvas = document.createElement("canvas");    canvas.width = 2 * emQuad;    canvas.height = 2 * emQuad;    canvas.style.opacity = 0;    var cfmFont = pfont.getCSSDefinition(emQuad + "px", "normal"),      ctx = canvas.getContext("2d");    ctx.font = cfmFont;    var protrusions = "dbflkhyjqpg";    canvas.width = ctx.measureText(protrusions).width;    ctx.font = cfmFont;    var leadDiv = document.createElement("div");    leadDiv.style.position = "absolute";    leadDiv.style.opacity = 0;    leadDiv.style.fontFamily = '"' + pfont.name + '"';    leadDiv.style.fontSize = emQuad + "px";    leadDiv.innerHTML = protrusions + "<br/>" + protrusions;    document.body.appendChild(leadDiv);    var w = canvas.width,      h = canvas.height,      baseline = h / 2;    ctx.fillStyle = "white";    ctx.fillRect(0, 0, w, h);    ctx.fillStyle = "black";    ctx.fillText(protrusions, 0, baseline);    var pixelData = ctx.getImageData(0, 0, w, h).data;    var i = 0,      w4 = w * 4,      len = pixelData.length;    while (++i < len && pixelData[i] === 255) nop();    var ascent = Math.round(i / w4);    i = len - 1;    while (--i > 0 && pixelData[i] === 255) nop();    var descent = Math.round(i / w4);    pfont.ascent = correctionFactor * (baseline - ascent);    pfont.descent = correctionFactor * (descent - baseline);    if (document.defaultView.getComputedStyle) {      var leadDivHeight = document.defaultView.getComputedStyle(leadDiv, null).getPropertyValue("height");      leadDivHeight = correctionFactor * leadDivHeight.replace("px", "");      if (leadDivHeight >= pfont.size * 2) pfont.leading = Math.round(leadDivHeight / 2)    }    document.body.removeChild(leadDiv);    if (pfont.caching) return ctx  }  function PFont(name, size) {    if (name === undef) name = "";    this.name = name;    if (size === undef) size = 0;    this.size = size;    this.glyph = false;    this.ascent = 0;    this.descent = 0;    this.leading = 1.2 * size;    var illegalIndicator = name.indexOf(" Italic Bold");    if (illegalIndicator !== -1) name = name.substring(0, illegalIndicator);    this.style = "normal";    var italicsIndicator = name.indexOf(" Italic");    if (italicsIndicator !== -1) {      name = name.substring(0, italicsIndicator);      this.style = "italic"    }    this.weight = "normal";    var boldIndicator = name.indexOf(" Bold");    if (boldIndicator !== -1) {      name = name.substring(0, boldIndicator);      this.weight = "bold"    }    this.family = "sans-serif";    if (name !== undef) switch (name) {    case "sans-serif":    case "serif":    case "monospace":    case "fantasy":    case "cursive":      this.family = name;      break;    default:      this.family = '"' + name + '", sans-serif';      break    }    this.context2d = computeFontMetrics(this);    this.css = this.getCSSDefinition();    if (this.context2d) this.context2d.font = this.css  }  PFont.prototype.caching = true;  PFont.prototype.getCSSDefinition = function(fontSize, lineHeight) {    if (fontSize === undef) fontSize = this.size + "px";    if (lineHeight === undef) lineHeight = this.leading + "px";    var components = [this.style, "normal", this.weight, fontSize + "/" + lineHeight, this.family];    return components.join(" ")  };  PFont.prototype.measureTextWidth = function(string) {    return this.context2d.measureText(string).width  };  PFont.prototype.measureTextWidthFallback = function(string) {    var canvas = document.createElement("canvas"),      ctx = canvas.getContext("2d");    ctx.font = this.css;    return ctx.measureText(string).width  };  PFont.PFontCache = {    length: 0  };  PFont.get = function(fontName, fontSize) {    fontSize = (fontSize * 10 + 0.5 | 0) / 10;    var cache = PFont.PFontCache,      idx = fontName + "/" + fontSize;    if (!cache[idx]) {      cache[idx] = new PFont(fontName, fontSize);      cache.length++;      if (cache.length === 50) {        PFont.prototype.measureTextWidth = PFont.prototype.measureTextWidthFallback;        PFont.prototype.caching = false;        var entry;        for (entry in cache) if (entry !== "length") cache[entry].context2d = null;        return new PFont(fontName, fontSize)      }      if (cache.length === 400) {        PFont.PFontCache = {};        PFont.get = PFont.getFallback;        return new PFont(fontName, fontSize)      }    }    return cache[idx]  };  PFont.getFallback = function(fontName, fontSize) {    return new PFont(fontName, fontSize)  };  PFont.list = function() {    return ["sans-serif", "serif", "monospace", "fantasy", "cursive"]  };  PFont.preloading = {    template: {},    initialized: false,    initialize: function() {      var generateTinyFont = function() {        var encoded = "#E3KAI2wAgT1MvMg7Eo3VmNtYX7ABi3CxnbHlm" + "7Abw3kaGVhZ7ACs3OGhoZWE7A53CRobXR47AY3" + "AGbG9jYQ7G03Bm1heH7ABC3CBuYW1l7Ae3AgcG" + "9zd7AI3AE#B3AQ2kgTY18PPPUACwAg3ALSRoo3" + "#yld0xg32QAB77#E777773B#E3C#I#Q77773E#" + "Q7777777772CMAIw7AB77732B#M#Q3wAB#g3B#" + "E#E2BB//82BB////w#B7#gAEg3E77x2B32B#E#" + "Q#MTcBAQ32gAe#M#QQJ#E32M#QQJ#I#g32Q77#";        var expand = function(input) {          return "AAAAAAAA".substr(~~input ? 7 - input : 6)        };        return encoded.replace(/[#237]/g, expand)      };      var fontface = document.createElement("style");      fontface.setAttribute("type", "text/css");      fontface.innerHTML = "@font-face {\n" + '  font-family: "PjsEmptyFont";' + "\n" + "  src: url('data:application/x-font-ttf;base64," + generateTinyFont() + "')\n" + "       format('truetype');\n" + "}";      document.head.appendChild(fontface);      var element = document.createElement("span");      element.style.cssText = 'position: absolute; top: 0; left: 0; opacity: 0; font-family: "PjsEmptyFont", fantasy;';      element.innerHTML = "AAAAAAAA";      document.body.appendChild(element);      this.template = element;      this.initialized = true    },    getElementWidth: function(element) {      return document.defaultView.getComputedStyle(element, "").getPropertyValue("width")    },    timeAttempted: 0,    pending: function(intervallength) {      if (!this.initialized) this.initialize();      var element, computedWidthFont, computedWidthRef = this.getElementWidth(this.template);      for (var i = 0; i < this.fontList.length; i++) {        element = this.fontList[i];        computedWidthFont = this.getElementWidth(element);        if (this.timeAttempted < 4E3 && computedWidthFont === computedWidthRef) {          this.timeAttempted += intervallength;          return true        } else {          document.body.removeChild(element);          this.fontList.splice(i--, 1);          this.timeAttempted = 0        }      }      if (this.fontList.length === 0) return false;      return true    },    fontList: [],    addedList: {},    add: function(fontSrc) {      if (!this.initialized) this.initialize();      var fontName = typeof fontSrc === "object" ? fontSrc.fontFace : fontSrc,      fontUrl = typeof fontSrc === "object" ? fontSrc.url : fontSrc;      if (this.addedList[fontName]) return;      var style = document.createElement("style");      style.setAttribute("type", "text/css");      style.innerHTML = "@font-face{\n  font-family: '" + fontName + "';\n  src:  url('" + fontUrl + "');\n}\n";      document.head.appendChild(style);      this.addedList[fontName] = true;      var element = document.createElement("span");      element.style.cssText = "position: absolute; top: 0; left: 0; opacity: 0;";      element.style.fontFamily = '"' + fontName + '", "PjsEmptyFont", fantasy';      element.innerHTML = "AAAAAAAA";      document.body.appendChild(element);      this.fontList.push(element)    }  };  defaultScope.PFont = PFont;  var Processing = this.Processing = function(aCanvas, aCode) {    if (! (this instanceof    Processing)) throw "called Processing constructor as if it were a function: missing 'new'.";    var curElement, pgraphicsMode = aCanvas === undef && aCode === undef;    if (pgraphicsMode) curElement = document.createElement("canvas");    else curElement = typeof aCanvas === "string" ? document.getElementById(aCanvas) : aCanvas;    if (! (curElement instanceof HTMLCanvasElement)) throw "called Processing constructor without passing canvas element reference or id.";    function unimplemented(s) {      Processing.debug("Unimplemented - " + s)    }    var p = this;    p.externals = {      canvas: curElement,      context: undef,      sketch: undef    };    p.name = "Processing.js Instance";    p.use3DContext = false;    p.focused = false;    p.breakShape = false;    p.glyphTable = {};    p.pmouseX = 0;    p.pmouseY = 0;    p.mouseX = 0;    p.mouseY = 0;    p.mouseButton = 0;    p.mouseScroll = 0;    p.mouseClicked = undef;    p.mouseDragged = undef;    p.mouseMoved = undef;    p.mousePressed = undef;    p.mouseReleased = undef;    p.mouseScrolled = undef;    p.mouseOver = undef;    p.mouseOut = undef;    p.touchStart = undef;    p.touchEnd = undef;    p.touchMove = undef;    p.touchCancel = undef;    p.key = undef;    p.keyCode = undef;    p.keyPressed = nop;    p.keyReleased = nop;    p.keyTyped = nop;    p.draw = undef;    p.setup = undef;    p.__mousePressed = false;    p.__keyPressed = false;    p.__frameRate = 60;    p.frameCount = 0;    p.width = 100;    p.height = 100;    var curContext, curSketch, drawing, online = true,      doFill = true,      fillStyle = [1, 1, 1, 1],      currentFillColor = 4294967295,      isFillDirty = true,      doStroke = true,      strokeStyle = [0, 0, 0, 1],      currentStrokeColor = 4278190080,      isStrokeDirty = true,      lineWidth = 1,      loopStarted = false,      renderSmooth = false,      doLoop = true,      looping = 0,      curRectMode = 0,      curEllipseMode = 3,      normalX = 0,      normalY = 0,      normalZ = 0,      normalMode = 0,      curFrameRate = 60,      curMsPerFrame = 1E3 / curFrameRate,      curCursor = 'default',      oldCursor = curElement.style.cursor,      curShape = 20,      curShapeCount = 0,      curvePoints = [],      curTightness = 0,      curveDet = 20,      curveInited = false,      backgroundObj = -3355444,      bezDetail = 20,      colorModeA = 255,      colorModeX = 255,      colorModeY = 255,      colorModeZ = 255,      pathOpen = false,      mouseDragging = false,      pmouseXLastFrame = 0,      pmouseYLastFrame = 0,      curColorMode = 1,      curTint = null,      curTint3d = null,      getLoaded = false,      start = Date.now(),      timeSinceLastFPS = start,      framesSinceLastFPS = 0,      textcanvas, curveBasisMatrix, curveToBezierMatrix, curveDrawMatrix, bezierDrawMatrix, bezierBasisInverse, bezierBasisMatrix, curContextCache = {      attributes: {},      locations: {}    },      programObject3D, programObject2D, programObjectUnlitShape, boxBuffer, boxNormBuffer, boxOutlineBuffer, rectBuffer, rectNormBuffer, sphereBuffer, lineBuffer, fillBuffer, fillColorBuffer, strokeColorBuffer, pointBuffer, shapeTexVBO, canTex, textTex, curTexture = {      width: 0,      height: 0    },      curTextureMode = 2,      usingTexture = false,      textBuffer, textureBuffer, indexBuffer, horizontalTextAlignment = 37,      verticalTextAlignment = 0,      textMode = 4,      curFontName = "Arial",      curTextSize = 12,      curTextAscent = 9,      curTextDescent = 2,      curTextLeading = 14,      curTextFont = PFont.get(curFontName, curTextSize),      originalContext, proxyContext = null,      isContextReplaced = false,      setPixelsCached, maxPixelsCached = 1E3,      pressedKeysMap = [],      lastPressedKeyCode = null,      codedKeys = [16,      17, 18, 20, 33, 34, 35, 36, 37, 38, 39, 40, 144, 155, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 157];    var stylePaddingLeft, stylePaddingTop, styleBorderLeft, styleBorderTop;    if (document.defaultView && document.defaultView.getComputedStyle) {      stylePaddingLeft = parseInt(document.defaultView.getComputedStyle(curElement, null)["paddingLeft"], 10) || 0;      stylePaddingTop = parseInt(document.defaultView.getComputedStyle(curElement, null)["paddingTop"], 10) || 0;      styleBorderLeft = parseInt(document.defaultView.getComputedStyle(curElement, null)["borderLeftWidth"], 10) || 0;      styleBorderTop = parseInt(document.defaultView.getComputedStyle(curElement, null)["borderTopWidth"], 10) || 0    }    var lightCount = 0;    var sphereDetailV = 0,      sphereDetailU = 0,      sphereX = [],      sphereY = [],      sphereZ = [],      sinLUT = new Float32Array(720),      cosLUT = new Float32Array(720),      sphereVerts, sphereNorms;    var cam, cameraInv, modelView, modelViewInv, userMatrixStack, userReverseMatrixStack, inverseCopy, projection, manipulatingCamera = false,      frustumMode = false,      cameraFOV = 60 * (Math.PI / 180),      cameraX = p.width / 2,      cameraY = p.height / 2,      cameraZ = cameraY / Math.tan(cameraFOV / 2),      cameraNear = cameraZ / 10,      cameraFar = cameraZ * 10,      cameraAspect = p.width / p.height;    var vertArray = [],      curveVertArray = [],      curveVertCount = 0,      isCurve = false,      isBezier = false,      firstVert = true;    var curShapeMode = 0;    var styleArray = [];    var boxVerts = new Float32Array([0.5, 0.5, -0.5, 0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, -0.5, -0.5, 0.5, -0.5, 0.5, -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, -0.5, -0.5, -0.5, 0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5, 0.5, 0.5, -0.5, 0.5, -0.5, -0.5, -0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5, -0.5, -0.5,      0.5, -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5]);    var boxOutlineVerts = new Float32Array([0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5, -0.5, 0.5, -0.5, -0.5, -0.5, 0.5, -0.5, -0.5, -0.5, -0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5]);    var boxNorms = new Float32Array([0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 1, 0, 0, 1, 0,      0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0]);    var rectVerts = new Float32Array([0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0]);    var rectNorms = new Float32Array([0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1]);    var vertexShaderSrcUnlitShape = "varying vec4 vFrontColor;" + "attribute vec3 aVertex;" + "attribute vec4 aColor;" + "uniform mat4 uView;" + "uniform mat4 uProjection;" + "uniform float uPointSize;" + "void main(void) {" + "  vFrontColor = aColor;" + "  gl_PointSize = uPointSize;" + "  gl_Position = uProjection * uView * vec4(aVertex, 1.0);" + "}";    var fragmentShaderSrcUnlitShape = "#ifdef GL_ES\n" + "precision highp float;\n" + "#endif\n" + "varying vec4 vFrontColor;" + "uniform bool uSmooth;" + "void main(void){" + "  if(uSmooth == true){" + "    float dist = distance(gl_PointCoord, vec2(0.5));" + "    if(dist > 0.5){" + "      discard;" + "    }" + "  }" + "  gl_FragColor = vFrontColor;" + "}";    var vertexShaderSrc2D = "varying vec4 vFrontColor;" + "attribute vec3 aVertex;" + "attribute vec2 aTextureCoord;" + "uniform vec4 uColor;" + "uniform mat4 uModel;" + "uniform mat4 uView;" + "uniform mat4 uProjection;" + "uniform float uPointSize;" + "varying vec2 vTextureCoord;" + "void main(void) {" + "  gl_PointSize = uPointSize;" + "  vFrontColor = uColor;" + "  gl_Position = uProjection * uView * uModel * vec4(aVertex, 1.0);" + "  vTextureCoord = aTextureCoord;" + "}";    var fragmentShaderSrc2D = "#ifdef GL_ES\n" + "precision highp float;\n" + "#endif\n" + "varying vec4 vFrontColor;" + "varying vec2 vTextureCoord;" + "uniform sampler2D uSampler;" + "uniform int uIsDrawingText;" + "uniform bool uSmooth;" + "void main(void){" + "  if(uSmooth == true){" + "    float dist = distance(gl_PointCoord, vec2(0.5));" + "    if(dist > 0.5){" + "      discard;" + "    }" + "  }" + "  if(uIsDrawingText == 1){" + "    float alpha = texture2D(uSampler, vTextureCoord).a;" + "    gl_FragColor = vec4(vFrontColor.rgb * alpha, alpha);" + "  }" + "  else{" + "    gl_FragColor = vFrontColor;" + "  }" + "}";    var webglMaxTempsWorkaround = /Windows/.test(navigator.userAgent);    var vertexShaderSrc3D = "varying vec4 vFrontColor;" + "attribute vec3 aVertex;" + "attribute vec3 aNormal;" + "attribute vec4 aColor;" + "attribute vec2 aTexture;" + "varying   vec2 vTexture;" + "uniform vec4 uColor;" + "uniform bool uUsingMat;" + "uniform vec3 uSpecular;" + "uniform vec3 uMaterialEmissive;" + "uniform vec3 uMaterialAmbient;" + "uniform vec3 uMaterialSpecular;" + "uniform float uShininess;" + "uniform mat4 uModel;" + "uniform mat4 uView;" + "uniform mat4 uProjection;" + "uniform mat4 uNormalTransform;" + "uniform int uLightCount;" + "uniform vec3 uFalloff;" + "struct Light {" + "  int type;" + "  vec3 color;" + "  vec3 position;" + "  vec3 direction;" + "  float angle;" + "  vec3 halfVector;" + "  float concentration;" + "};" + "uniform Light uLights0;" + "uniform Light uLights1;" + "uniform Light uLights2;" + "uniform Light uLights3;" + "uniform Light uLights4;" + "uniform Light uLights5;" + "uniform Light uLights6;" + "uniform Light uLights7;" + "Light getLight(int index){" + "  if(index == 0) return uLights0;" + "  if(index == 1) return uLights1;" + "  if(index == 2) return uLights2;" + "  if(index == 3) return uLights3;" + "  if(index == 4) return uLights4;" + "  if(index == 5) return uLights5;" + "  if(index == 6) return uLights6;" + "  return uLights7;" + "}" + "void AmbientLight( inout vec3 totalAmbient, in vec3 ecPos, in Light light ) {" + "  float d = length( light.position - ecPos );" + "  float attenuation = 1.0 / ( uFalloff[0] + ( uFalloff[1] * d ) + ( uFalloff[2] * d * d ));" + "  totalAmbient += light.color * attenuation;" + "}" + "void DirectionalLight( inout vec3 col, inout vec3 spec, in vec3 vertNormal, in vec3 ecPos, in Light light ) {" + "  float powerFactor = 0.0;" + "  float nDotVP = max(0.0, dot( vertNormal, normalize(-light.position) ));" + "  float nDotVH = max(0.0, dot( vertNormal, normalize(-light.position-normalize(ecPos) )));" + "  if( nDotVP != 0.0 ){" + "    powerFactor = pow( nDotVH, uShininess );" + "  }" + "  col += light.color * nDotVP;" + "  spec += uSpecular * powerFactor;" + "}" + "void PointLight( inout vec3 col, inout vec3 spec, in vec3 vertNormal, in vec3 ecPos, in Light light ) {" + "  float powerFactor;" + "   vec3 VP = light.position - ecPos;" + "  float d = length( VP ); " + "  VP = normalize( VP );" + "  float attenuation = 1.0 / ( uFalloff[0] + ( uFalloff[1] * d ) + ( uFalloff[2] * d * d ));" + "  float nDotVP = max( 0.0, dot( vertNormal, VP ));" + "  vec3 halfVector = normalize( VP - normalize(ecPos) );" + "  float nDotHV = max( 0.0, dot( vertNormal, halfVector ));" + "  if( nDotVP == 0.0 ) {" + "    powerFactor = 0.0;" + "  }" + "  else {" + "    powerFactor = pow( nDotHV, uShininess );" + "  }" + "  spec += uSpecular * powerFactor * attenuation;" + "  col += light.color * nDotVP * attenuation;" + "}" + "void SpotLight( inout vec3 col, inout vec3 spec, in vec3 vertNormal, in vec3 ecPos, in Light light ) {" + "  float spotAttenuation;" + "  float powerFactor = 0.0;" + "  vec3 VP = light.position - ecPos;" + "  vec3 ldir = normalize( -light.direction );" + "  float d = length( VP );" + "  VP = normalize( VP );" + "  float attenuation = 1.0 / ( uFalloff[0] + ( uFalloff[1] * d ) + ( uFalloff[2] * d * d ) );" + "  float spotDot = dot( VP, ldir );" + (webglMaxTempsWorkaround ? "  spotAttenuation = 1.0; " : "  if( spotDot > cos( light.angle ) ) {" + "    spotAttenuation = pow( spotDot, light.concentration );" + "  }" + "  else{" + "    spotAttenuation = 0.0;" + "  }" + "  attenuation *= spotAttenuation;" + "") + "  float nDotVP = max( 0.0, dot( vertNormal, VP ) );" + "  vec3 halfVector = normalize( VP - normalize(ecPos) );" + "  float nDotHV = max( 0.0, dot( vertNormal, halfVector ) );" + "  if( nDotVP != 0.0 ) {" + "    powerFactor = pow( nDotHV, uShininess );" + "  }" + "  spec += uSpecular * powerFactor * attenuation;" + "  col += light.color * nDotVP * attenuation;" + "}" + "void main(void) {" + "  vec3 finalAmbient = vec3( 0.0 );" + "  vec3 finalDiffuse = vec3( 0.0 );" + "  vec3 finalSpecular = vec3( 0.0 );" + "  vec4 col = uColor;" + "  if ( uColor[0] == -1.0 ){" + "    col = aColor;" + "  }" + "  vec3 norm = normalize(vec3( uNormalTransform * vec4( aNormal, 0.0 ) ));" + "  vec4 ecPos4 = uView * uModel * vec4(aVertex, 1.0);" + "  vec3 ecPos = (vec3(ecPos4))/ecPos4.w;" + "  if( uLightCount == 0 ) {" + "    vFrontColor = col + vec4(uMaterialSpecular, 1.0);" + "  }" + "  else {" + "    for( int i = 0; i < 8; i++ ) {" + "      Light l = getLight(i);" + "      if( i >= uLightCount ){" + "        break;" + "      }" + "      if( l.type == 0 ) {" + "        AmbientLight( finalAmbient, ecPos, l );" + "      }" + "      else if( l.type == 1 ) {" + "        DirectionalLight( finalDiffuse, finalSpecular, norm, ecPos, l );" + "      }" + "      else if( l.type == 2 ) {" + "        PointLight( finalDiffuse, finalSpecular, norm, ecPos, l );" + "      }" + "      else {" + "        SpotLight( finalDiffuse, finalSpecular, norm, ecPos, l );" + "      }" + "    }" + "   if( uUsingMat == false ) {" + "     vFrontColor = vec4(" + "       vec3( col ) * finalAmbient +" + "       vec3( col ) * finalDiffuse +" + "       vec3( col ) * finalSpecular," + "       col[3] );" + "   }" + "   else{" + "     vFrontColor = vec4( " + "       uMaterialEmissive + " + "       (vec3(col) * uMaterialAmbient * finalAmbient ) + " + "       (vec3(col) * finalDiffuse) + " + "       (uMaterialSpecular * finalSpecular), " + "       col[3] );" + "    }" + "  }" + "  vTexture.xy = aTexture.xy;" + "  gl_Position = uProjection * uView * uModel * vec4( aVertex, 1.0 );" + "}";    var fragmentShaderSrc3D = "#ifdef GL_ES\n" + "precision highp float;\n" + "#endif\n" + "varying vec4 vFrontColor;" + "uniform sampler2D uSampler;" + "uniform bool uUsingTexture;" + "varying vec2 vTexture;" + "void main(void){" + "  if( uUsingTexture ){" + "    gl_FragColor = vec4(texture2D(uSampler, vTexture.xy)) * vFrontColor;" + "  }" + "  else{" + "    gl_FragColor = vFrontColor;" + "  }" + "}";    function uniformf(cacheId, programObj, varName, varValue) {      var varLocation = curContextCache.locations[cacheId];      if (varLocation === undef) {        varLocation = curContext.getUniformLocation(programObj, varName);        curContextCache.locations[cacheId] = varLocation      }      if (varLocation !== null) if (varValue.length === 4) curContext.uniform4fv(varLocation, varValue);      else if (varValue.length === 3) curContext.uniform3fv(varLocation, varValue);      else if (varValue.length === 2) curContext.uniform2fv(varLocation, varValue);      else curContext.uniform1f(varLocation, varValue)    }    function uniformi(cacheId, programObj, varName, varValue) {      var varLocation = curContextCache.locations[cacheId];      if (varLocation === undef) {        varLocation = curContext.getUniformLocation(programObj, varName);        curContextCache.locations[cacheId] = varLocation      }      if (varLocation !== null) if (varValue.length === 4) curContext.uniform4iv(varLocation, varValue);      else if (varValue.length === 3) curContext.uniform3iv(varLocation, varValue);      else if (varValue.length === 2) curContext.uniform2iv(varLocation, varValue);      else curContext.uniform1i(varLocation, varValue)    }    function uniformMatrix(cacheId, programObj, varName, transpose, matrix) {      var varLocation = curContextCache.locations[cacheId];      if (varLocation === undef) {        varLocation = curContext.getUniformLocation(programObj, varName);        curContextCache.locations[cacheId] = varLocation      }      if (varLocation !== -1) if (matrix.length === 16) curContext.uniformMatrix4fv(varLocation, transpose, matrix);      else if (matrix.length === 9) curContext.uniformMatrix3fv(varLocation, transpose, matrix);      else curContext.uniformMatrix2fv(varLocation, transpose, matrix)    }    function vertexAttribPointer(cacheId, programObj, varName, size, VBO) {      var varLocation = curContextCache.attributes[cacheId];      if (varLocation === undef) {        varLocation = curContext.getAttribLocation(programObj, varName);        curContextCache.attributes[cacheId] = varLocation      }      if (varLocation !== -1) {        curContext.bindBuffer(curContext.ARRAY_BUFFER, VBO);        curContext.vertexAttribPointer(varLocation, size, curContext.FLOAT, false, 0, 0);        curContext.enableVertexAttribArray(varLocation)      }    }    function disableVertexAttribPointer(cacheId, programObj, varName) {      var varLocation = curContextCache.attributes[cacheId];      if (varLocation === undef) {        varLocation = curContext.getAttribLocation(programObj, varName);        curContextCache.attributes[cacheId] = varLocation      }      if (varLocation !== -1) curContext.disableVertexAttribArray(varLocation)    }    var createProgramObject = function(curContext, vetexShaderSource, fragmentShaderSource) {      var vertexShaderObject = curContext.createShader(curContext.VERTEX_SHADER);      curContext.shaderSource(vertexShaderObject, vetexShaderSource);      curContext.compileShader(vertexShaderObject);      if (!curContext.getShaderParameter(vertexShaderObject, curContext.COMPILE_STATUS)) throw curContext.getShaderInfoLog(vertexShaderObject);      var fragmentShaderObject = curContext.createShader(curContext.FRAGMENT_SHADER);      curContext.shaderSource(fragmentShaderObject, fragmentShaderSource);      curContext.compileShader(fragmentShaderObject);      if (!curContext.getShaderParameter(fragmentShaderObject, curContext.COMPILE_STATUS)) throw curContext.getShaderInfoLog(fragmentShaderObject);      var programObject = curContext.createProgram();      curContext.attachShader(programObject, vertexShaderObject);      curContext.attachShader(programObject, fragmentShaderObject);      curContext.linkProgram(programObject);      if (!curContext.getProgramParameter(programObject, curContext.LINK_STATUS)) throw "Error linking shaders.";      return programObject    };    var imageModeCorner = function(x, y, w, h, whAreSizes) {      return {        x: x,        y: y,        w: w,        h: h      }    };    var imageModeConvert = imageModeCorner;    var imageModeCorners = function(x, y, w, h, whAreSizes) {      return {        x: x,        y: y,        w: whAreSizes ? w : w - x,        h: whAreSizes ? h : h - y      }    };    var imageModeCenter = function(x, y, w, h, whAreSizes) {      return {        x: x - w / 2,        y: y - h / 2,        w: w,        h: h      }    };    var DrawingShared = function() {};    var Drawing2D = function() {};    var Drawing3D = function() {};    var DrawingPre = function() {};    Drawing2D.prototype = new DrawingShared;    Drawing2D.prototype.constructor = Drawing2D;    Drawing3D.prototype = new DrawingShared;    Drawing3D.prototype.constructor = Drawing3D;    DrawingPre.prototype = new DrawingShared;    DrawingPre.prototype.constructor = DrawingPre;    DrawingShared.prototype.a3DOnlyFunction = nop;    var charMap = {};    var Char = p.Character = function(chr) {      if (typeof chr === "string" && chr.length === 1) this.code = chr.charCodeAt(0);      else if (typeof chr === "number") this.code = chr;      else if (chr instanceof Char) this.code = chr;      else this.code = NaN;      return charMap[this.code] === undef ? charMap[this.code] = this : charMap[this.code]    };    Char.prototype.toString = function() {      return String.fromCharCode(this.code)    };    Char.prototype.valueOf = function() {      return this.code    };    var PShape = p.PShape = function(family) {      this.family = family || 0;      this.visible = true;      this.style = true;      this.children = [];      this.nameTable = [];      this.params = [];      this.name = "";      this.image = null;      this.matrix = null;      this.kind = null;      this.close = null;      this.width = null;      this.height = null;      this.parent = null    };    PShape.prototype = {      isVisible: function() {        return this.visible      },      setVisible: function(visible) {        this.visible = visible      },      disableStyle: function() {        this.style = false;        for (var i = 0, j = this.children.length; i < j; i++) this.children[i].disableStyle()      },      enableStyle: function() {        this.style = true;        for (var i = 0, j = this.children.length; i < j; i++) this.children[i].enableStyle()      },      getFamily: function() {        return this.family      },      getWidth: function() {        return this.width      },      getHeight: function() {        return this.height      },      setName: function(name) {        this.name = name      },      getName: function() {        return this.name      },      draw: function(renderContext) {        renderContext = renderContext || p;        if (this.visible) {          this.pre(renderContext);          this.drawImpl(renderContext);          this.post(renderContext)        }      },      drawImpl: function(renderContext) {        if (this.family === 0) this.drawGroup(renderContext);        else if (this.family === 1) this.drawPrimitive(renderContext);        else if (this.family === 3) this.drawGeometry(renderContext);        else if (this.family === 21) this.drawPath(renderContext)      },      drawPath: function(renderContext) {        var i, j;        if (this.vertices.length === 0) return;        renderContext.beginShape();        if (this.vertexCodes.length === 0) if (this.vertices[0].length === 2) for (i = 0, j = this.vertices.length; i < j; i++) renderContext.vertex(this.vertices[i][0], this.vertices[i][1]);        else for (i = 0, j = this.vertices.length; i < j; i++) renderContext.vertex(this.vertices[i][0], this.vertices[i][1], this.vertices[i][2]);        else {          var index = 0;          if (this.vertices[0].length === 2) for (i = 0, j = this.vertexCodes.length; i < j; i++) if (this.vertexCodes[i] === 0) {            renderContext.vertex(this.vertices[index][0], this.vertices[index][1], this.vertices[index]["moveTo"]);            renderContext.breakShape = false;            index++          } else if (this.vertexCodes[i] === 1) {            renderContext.bezierVertex(this.vertices[index + 0][0], this.vertices[index + 0][1], this.vertices[index + 1][0], this.vertices[index + 1][1], this.vertices[index + 2][0], this.vertices[index + 2][1]);            index += 3          } else if (this.vertexCodes[i] === 2) {            renderContext.curveVertex(this.vertices[index][0], this.vertices[index][1]);            index++          } else {            if (this.vertexCodes[i] === 3) renderContext.breakShape = true          } else for (i = 0, j = this.vertexCodes.length; i < j; i++) if (this.vertexCodes[i] === 0) {            renderContext.vertex(this.vertices[index][0], this.vertices[index][1], this.vertices[index][2]);            if (this.vertices[index]["moveTo"] === true) vertArray[vertArray.length - 1]["moveTo"] = true;            else if (this.vertices[index]["moveTo"] === false) vertArray[vertArray.length - 1]["moveTo"] = false;            renderContext.breakShape = false          } else if (this.vertexCodes[i] === 1) {            renderContext.bezierVertex(this.vertices[index + 0][0], this.vertices[index + 0][1], this.vertices[index + 0][2], this.vertices[index + 1][0], this.vertices[index + 1][1], this.vertices[index + 1][2], this.vertices[index + 2][0], this.vertices[index + 2][1], this.vertices[index + 2][2]);            index += 3          } else if (this.vertexCodes[i] === 2) {            renderContext.curveVertex(this.vertices[index][0], this.vertices[index][1], this.vertices[index][2]);            index++          } else if (this.vertexCodes[i] === 3) renderContext.breakShape = true        }        renderContext.endShape(this.close ? 2 : 1)      },      drawGeometry: function(renderContext) {        var i, j;        renderContext.beginShape(this.kind);        if (this.style) for (i = 0, j = this.vertices.length; i < j; i++) renderContext.vertex(this.vertices[i]);        else for (i = 0, j = this.vertices.length; i < j; i++) {          var vert = this.vertices[i];          if (vert[2] === 0) renderContext.vertex(vert[0], vert[1]);          else renderContext.vertex(vert[0], vert[1], vert[2])        }        renderContext.endShape()      },      drawGroup: function(renderContext) {        for (var i = 0, j = this.children.length; i < j; i++) this.children[i].draw(renderContext)      },      drawPrimitive: function(renderContext) {        if (this.kind === 2) renderContext.point(this.params[0], this.params[1]);        else if (this.kind === 4) if (this.params.length === 4) renderContext.line(this.params[0], this.params[1], this.params[2], this.params[3]);        else renderContext.line(this.params[0], this.params[1], this.params[2], this.params[3], this.params[4], this.params[5]);        else if (this.kind === 8) renderContext.triangle(this.params[0], this.params[1], this.params[2], this.params[3], this.params[4], this.params[5]);        else if (this.kind === 16) renderContext.quad(this.params[0], this.params[1], this.params[2], this.params[3], this.params[4], this.params[5], this.params[6], this.params[7]);        else if (this.kind === 30) if (this.image !== null) {          var imMode = imageModeConvert;          renderContext.imageMode(0);          renderContext.image(this.image, this.params[0], this.params[1], this.params[2], this.params[3]);          imageModeConvert = imMode        } else {          var rcMode = curRectMode;          renderContext.rectMode(0);          renderContext.rect(this.params[0], this.params[1], this.params[2], this.params[3]);          curRectMode = rcMode        } else if (this.kind === 31) {          var elMode = curEllipseMode;          renderContext.ellipseMode(0);          renderContext.ellipse(this.params[0], this.params[1], this.params[2], this.params[3]);          curEllipseMode = elMode        } else if (this.kind === 32) {          var eMode = curEllipseMode;          renderContext.ellipseMode(0);          renderContext.arc(this.params[0], this.params[1], this.params[2], this.params[3], this.params[4], this.params[5]);          curEllipseMode = eMode        } else if (this.kind === 41) if (this.params.length === 1) renderContext.box(this.params[0]);        else renderContext.box(this.params[0], this.params[1], this.params[2]);        else if (this.kind === 40) renderContext.sphere(this.params[0])      },      pre: function(renderContext) {        if (this.matrix) {          renderContext.pushMatrix();          renderContext.transform(this.matrix)        }        if (this.style) {          renderContext.pushStyle();          this.styles(renderContext)        }      },      post: function(renderContext) {        if (this.matrix) renderContext.popMatrix();        if (this.style) renderContext.popStyle()      },      styles: function(renderContext) {        if (this.stroke) {          renderContext.stroke(this.strokeColor);          renderContext.strokeWeight(this.strokeWeight);          renderContext.strokeCap(this.strokeCap);          renderContext.strokeJoin(this.strokeJoin)        } else renderContext.noStroke();        if (this.fill) renderContext.fill(this.fillColor);        else renderContext.noFill()      },      getChild: function(child) {        var i, j;        if (typeof child === "number") return this.children[child];        var found;        if (child === "" || this.name === child) return this;        if (this.nameTable.length > 0) {          for (i = 0, j = this.nameTable.length; i < j || found; i++) if (this.nameTable[i].getName === child) {            found = this.nameTable[i];            break          }          if (found) return found        }        for (i = 0, j = this.children.length; i < j; i++) {          found = this.children[i].getChild(child);          if (found) return found        }        return null      },      getChildCount: function() {        return this.children.length      },      addChild: function(child) {        this.children.push(child);        child.parent = this;        if (child.getName() !== null) this.addName(child.getName(), child)      },      addName: function(name, shape) {        if (this.parent !== null) this.parent.addName(name, shape);        else this.nameTable.push([name, shape])      },      translate: function() {        if (arguments.length === 2) {          this.checkMatrix(2);          this.matrix.translate(arguments[0], arguments[1])        } else {          this.checkMatrix(3);          this.matrix.translate(arguments[0], arguments[1], 0)        }      },      checkMatrix: function(dimensions) {        if (this.matrix === null) if (dimensions === 2) this.matrix = new p.PMatrix2D;        else this.matrix = new p.PMatrix3D;        else if (dimensions === 3 && this.matrix instanceof p.PMatrix2D) this.matrix = new p.PMatrix3D      },      rotateX: function(angle) {        this.rotate(angle, 1, 0, 0)      },      rotateY: function(angle) {        this.rotate(angle, 0, 1, 0)      },      rotateZ: function(angle) {        this.rotate(angle, 0, 0, 1)      },      rotate: function() {        if (arguments.length === 1) {          this.checkMatrix(2);          this.matrix.rotate(arguments[0])        } else {          this.checkMatrix(3);          this.matrix.rotate(arguments[0], arguments[1], arguments[2], arguments[3])        }      },      scale: function() {        if (arguments.length === 2) {          this.checkMatrix(2);          this.matrix.scale(arguments[0], arguments[1])        } else if (arguments.length === 3) {          this.checkMatrix(2);          this.matrix.scale(arguments[0], arguments[1], arguments[2])        } else {          this.checkMatrix(2);          this.matrix.scale(arguments[0])        }      },      resetMatrix: function() {        this.checkMatrix(2);        this.matrix.reset()      },      applyMatrix: function(matrix) {        if (arguments.length === 1) this.applyMatrix(matrix.elements[0], matrix.elements[1], 0, matrix.elements[2], matrix.elements[3], matrix.elements[4], 0, matrix.elements[5], 0, 0, 1, 0, 0, 0, 0, 1);        else if (arguments.length === 6) {          this.checkMatrix(2);          this.matrix.apply(arguments[0], arguments[1], arguments[2], 0, arguments[3], arguments[4], arguments[5], 0, 0, 0, 1, 0, 0, 0, 0, 1)        } else if (arguments.length === 16) {          this.checkMatrix(3);          this.matrix.apply(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6], arguments[7], arguments[8], arguments[9], arguments[10], arguments[11], arguments[12], arguments[13], arguments[14], arguments[15])        }      }    };    var PShapeSVG = p.PShapeSVG = function() {      p.PShape.call(this);      if (arguments.length === 1) {        this.element = arguments[0];        this.vertexCodes = [];        this.vertices = [];        this.opacity = 1;        this.stroke = false;        this.strokeColor = 4278190080;        this.strokeWeight = 1;        this.strokeCap = 'butt';        this.strokeJoin = 'miter';        this.strokeGradient = null;        this.strokeGradientPaint = null;        this.strokeName = null;        this.strokeOpacity = 1;        this.fill = true;        this.fillColor = 4278190080;        this.fillGradient = null;        this.fillGradientPaint = null;        this.fillName = null;        this.fillOpacity = 1;        if (this.element.getName() !== "svg") throw "root is not <svg>, it's <" + this.element.getName() + ">";      } else if (arguments.length === 2) if (typeof arguments[1] === "string") {        if (arguments[1].indexOf(".svg") > -1) {          this.element = new p.XMLElement(p, arguments[1]);          this.vertexCodes = [];          this.vertices = [];          this.opacity = 1;          this.stroke = false;          this.strokeColor = 4278190080;          this.strokeWeight = 1;          this.strokeCap = 'butt';          this.strokeJoin = 'miter';          this.strokeGradient = "";          this.strokeGradientPaint = "";          this.strokeName = "";          this.strokeOpacity = 1;          this.fill = true;          this.fillColor = 4278190080;          this.fillGradient = null;          this.fillGradientPaint = null;          this.fillOpacity = 1        }      } else if (arguments[0]) {        this.element = arguments[1];        this.vertexCodes = arguments[0].vertexCodes.slice();        this.vertices = arguments[0].vertices.slice();        this.stroke = arguments[0].stroke;        this.strokeColor = arguments[0].strokeColor;        this.strokeWeight = arguments[0].strokeWeight;        this.strokeCap = arguments[0].strokeCap;        this.strokeJoin = arguments[0].strokeJoin;        this.strokeGradient = arguments[0].strokeGradient;        this.strokeGradientPaint = arguments[0].strokeGradientPaint;        this.strokeName = arguments[0].strokeName;        this.fill = arguments[0].fill;        this.fillColor = arguments[0].fillColor;        this.fillGradient = arguments[0].fillGradient;        this.fillGradientPaint = arguments[0].fillGradientPaint;        this.fillName = arguments[0].fillName;        this.strokeOpacity = arguments[0].strokeOpacity;        this.fillOpacity = arguments[0].fillOpacity;        this.opacity = arguments[0].opacity      }      this.name = this.element.getStringAttribute("id");      var displayStr = this.element.getStringAttribute("display", "inline");      this.visible = displayStr !== "none";      var str = this.element.getAttribute("transform");      if (str) this.matrix = this.parseMatrix(str);      var viewBoxStr = this.element.getStringAttribute("viewBox");      if (viewBoxStr !== null) {        var viewBox = viewBoxStr.split(" ");        this.width = viewBox[2];        this.height = viewBox[3]      }      var unitWidth = this.element.getStringAttribute("width");      var unitHeight = this.element.getStringAttribute("height");      if (unitWidth !== null) {        this.width = this.parseUnitSize(unitWidth);        this.height = this.parseUnitSize(unitHeight)      } else if (this.width === 0 || this.height === 0) {        this.width = 1;        this.height = 1;        throw "The width and/or height is not " + "readable in the <svg> tag of this file.";      }      this.parseColors(this.element);      this.parseChildren(this.element)    };    PShapeSVG.prototype = new PShape;    PShapeSVG.prototype.parseMatrix = function() {      function getCoords(s) {        var m = [];        s.replace(/\((.*?)\)/, function() {          return function(all, params) {            m = params.replace(/,+/g, " ").split(/\s+/)          }        }());        return m      }      return function(str) {        this.checkMatrix(2);        var pieces = [];        str.replace(/\s*(\w+)\((.*?)\)/g, function(all) {          pieces.push(p.trim(all))        });        if (pieces.length === 0) return null;        for (var i = 0, j = pieces.length; i < j; i++) {          var m = getCoords(pieces[i]);          if (pieces[i].indexOf("matrix") !== -1) this.matrix.set(m[0], m[2], m[4], m[1], m[3], m[5]);          else if (pieces[i].indexOf("translate") !== -1) {            var tx = m[0];            var ty = m.length === 2 ? m[1] : 0;            this.matrix.translate(tx, ty)          } else if (pieces[i].indexOf("scale") !== -1) {            var sx = m[0];            var sy = m.length === 2 ? m[1] : m[0];            this.matrix.scale(sx, sy)          } else if (pieces[i].indexOf("rotate") !== -1) {            var angle = m[0];            if (m.length === 1) this.matrix.rotate(p.radians(angle));            else if (m.length === 3) {              this.matrix.translate(m[1], m[2]);              this.matrix.rotate(p.radians(m[0]));              this.matrix.translate(-m[1], -m[2])            }          } else if (pieces[i].indexOf("skewX") !== -1) this.matrix.skewX(parseFloat(m[0]));          else if (pieces[i].indexOf("skewY") !== -1) this.matrix.skewY(m[0]);          else if (pieces[i].indexOf("shearX") !== -1) this.matrix.shearX(m[0]);          else if (pieces[i].indexOf("shearY") !== -1) this.matrix.shearY(m[0])        }        return this.matrix      }    }();    PShapeSVG.prototype.parseChildren = function(element) {      var newelement = element.getChildren();      var children = new p.PShape;      for (var i = 0, j = newelement.length; i < j; i++) {        var kid = this.parseChild(newelement[i]);        if (kid) children.addChild(kid)      }      this.children.push(children)    };    PShapeSVG.prototype.getName = function() {      return this.name    };    PShapeSVG.prototype.parseChild = function(elem) {      var name = elem.getName();      var shape;      if (name === "g") shape = new PShapeSVG(this, elem);      else if (name === "defs") shape = new PShapeSVG(this, elem);      else if (name === "line") {        shape = new PShapeSVG(this, elem);        shape.parseLine()      } else if (name === "circle") {        shape = new PShapeSVG(this, elem);        shape.parseEllipse(true)      } else if (name === "ellipse") {        shape = new PShapeSVG(this, elem);        shape.parseEllipse(false)      } else if (name === "rect") {        shape = new PShapeSVG(this, elem);        shape.parseRect()      } else if (name === "polygon") {        shape = new PShapeSVG(this, elem);        shape.parsePoly(true)      } else if (name === "polyline") {        shape = new PShapeSVG(this, elem);        shape.parsePoly(false)      } else if (name === "path") {        shape = new PShapeSVG(this, elem);        shape.parsePath()      } else if (name === "radialGradient") unimplemented("PShapeSVG.prototype.parseChild, name = radialGradient");      else if (name === "linearGradient") unimplemented("PShapeSVG.prototype.parseChild, name = linearGradient");      else if (name === "text") unimplemented("PShapeSVG.prototype.parseChild, name = text");      else if (name === "filter") unimplemented("PShapeSVG.prototype.parseChild, name = filter");      else if (name === "mask") unimplemented("PShapeSVG.prototype.parseChild, name = mask");      else nop();      return shape    };    PShapeSVG.prototype.parsePath = function() {      this.family = 21;      this.kind = 0;      var pathDataChars = [];      var c;      var pathData = p.trim(this.element.getStringAttribute("d").replace(/[\s,]+/g, " "));      if (pathData === null) return;      pathData = p.__toCharArray(pathData);      var cx = 0,        cy = 0,        ctrlX = 0,        ctrlY = 0,        ctrlX1 = 0,        ctrlX2 = 0,        ctrlY1 = 0,        ctrlY2 = 0,        endX = 0,        endY = 0,        ppx = 0,        ppy = 0,        px = 0,        py = 0,        i = 0,        valOf = 0;      var str = "";      var tmpArray = [];      var flag = false;      var lastInstruction;      var command;      var j, k;      while (i < pathData.length) {        valOf = pathData[i].valueOf();        if (valOf >= 65 && valOf <= 90 || valOf >= 97 && valOf <= 122) {          j = i;          i++;          if (i < pathData.length) {            tmpArray = [];            valOf = pathData[i].valueOf();            while (! (valOf >= 65 && valOf <= 90 || valOf >= 97 && valOf <= 100 || valOf >= 102 && valOf <= 122) && flag === false) {              if (valOf === 32) {                if (str !== "") {                  tmpArray.push(parseFloat(str));                  str = ""                }                i++              } else if (valOf === 45) if (pathData[i - 1].valueOf() === 101) {                str += pathData[i].toString();                i++              } else {                if (str !== "") tmpArray.push(parseFloat(str));                str = pathData[i].toString();                i++              } else {                str += pathData[i].toString();                i++              }              if (i === pathData.length) flag = true;              else valOf = pathData[i].valueOf()            }          }          if (str !== "") {            tmpArray.push(parseFloat(str));            str = ""          }          command = pathData[j];          valOf = command.valueOf();          if (valOf === 77) {            if (tmpArray.length >= 2 && tmpArray.length % 2 === 0) {              cx = tmpArray[0];              cy = tmpArray[1];              this.parsePathMoveto(cx, cy);              if (tmpArray.length > 2) for (j = 2, k = tmpArray.length; j < k; j += 2) {                cx = tmpArray[j];                cy = tmpArray[j + 1];                this.parsePathLineto(cx, cy)              }            }          } else if (valOf === 109) {            if (tmpArray.length >= 2 && tmpArray.length % 2 === 0) {              cx += tmpArray[0];              cy += tmpArray[1];              this.parsePathMoveto(cx, cy);              if (tmpArray.length > 2) for (j = 2, k = tmpArray.length; j < k; j += 2) {                cx += tmpArray[j];                cy += tmpArray[j + 1];                this.parsePathLineto(cx, cy)              }            }          } else if (valOf === 76) {            if (tmpArray.length >= 2 && tmpArray.length % 2 === 0) for (j = 0, k = tmpArray.length; j < k; j += 2) {              cx = tmpArray[j];              cy = tmpArray[j + 1];              this.parsePathLineto(cx, cy)            }          } else if (valOf === 108) {            if (tmpArray.length >= 2 && tmpArray.length % 2 === 0) for (j = 0, k = tmpArray.length; j < k; j += 2) {              cx += tmpArray[j];              cy += tmpArray[j + 1];              this.parsePathLineto(cx, cy)            }          } else if (valOf === 72) for (j = 0, k = tmpArray.length; j < k; j++) {            cx = tmpArray[j];            this.parsePathLineto(cx, cy)          } else if (valOf === 104) for (j = 0, k = tmpArray.length; j < k; j++) {            cx += tmpArray[j];            this.parsePathLineto(cx, cy)          } else if (valOf === 86) for (j = 0, k = tmpArray.length; j < k; j++) {            cy = tmpArray[j];            this.parsePathLineto(cx, cy)          } else if (valOf === 118) for (j = 0, k = tmpArray.length; j < k; j++) {            cy += tmpArray[j];            this.parsePathLineto(cx, cy)          } else if (valOf === 67) {            if (tmpArray.length >= 6 && tmpArray.length % 6 === 0) for (j = 0, k = tmpArray.length; j < k; j += 6) {              ctrlX1 = tmpArray[j];              ctrlY1 = tmpArray[j + 1];              ctrlX2 = tmpArray[j + 2];              ctrlY2 = tmpArray[j + 3];              endX = tmpArray[j + 4];              endY = tmpArray[j + 5];              this.parsePathCurveto(ctrlX1, ctrlY1, ctrlX2, ctrlY2, endX, endY);              cx = endX;              cy = endY            }          } else if (valOf === 99) {            if (tmpArray.length >= 6 && tmpArray.length % 6 === 0) for (j = 0, k = tmpArray.length; j < k; j += 6) {              ctrlX1 = cx + tmpArray[j];              ctrlY1 = cy + tmpArray[j + 1];              ctrlX2 = cx + tmpArray[j + 2];              ctrlY2 = cy + tmpArray[j + 3];              endX = cx + tmpArray[j + 4];              endY = cy + tmpArray[j + 5];              this.parsePathCurveto(ctrlX1, ctrlY1, ctrlX2, ctrlY2, endX, endY);              cx = endX;              cy = endY            }          } else if (valOf === 83) {            if (tmpArray.length >= 4 && tmpArray.length % 4 === 0) for (j = 0, k = tmpArray.length; j < k; j += 4) {              if (lastInstruction.toLowerCase() === "c" || lastInstruction.toLowerCase() === "s") {                ppx = this.vertices[this.vertices.length - 2][0];                ppy = this.vertices[this.vertices.length - 2][1];                px = this.vertices[this.vertices.length - 1][0];                py = this.vertices[this.vertices.length - 1][1];                ctrlX1 = px + (px - ppx);                ctrlY1 = py + (py - ppy)              } else {                ctrlX1 = this.vertices[this.vertices.length - 1][0];                ctrlY1 = this.vertices[this.vertices.length - 1][1]              }              ctrlX2 = tmpArray[j];              ctrlY2 = tmpArray[j + 1];              endX = tmpArray[j + 2];              endY = tmpArray[j + 3];              this.parsePathCurveto(ctrlX1, ctrlY1, ctrlX2, ctrlY2, endX, endY);              cx = endX;              cy = endY            }          } else if (valOf === 115) {            if (tmpArray.length >= 4 && tmpArray.length % 4 === 0) for (j = 0, k = tmpArray.length; j < k; j += 4) {              if (lastInstruction.toLowerCase() === "c" || lastInstruction.toLowerCase() === "s") {                ppx = this.vertices[this.vertices.length - 2][0];                ppy = this.vertices[this.vertices.length - 2][1];                px = this.vertices[this.vertices.length - 1][0];                py = this.vertices[this.vertices.length - 1][1];                ctrlX1 = px + (px - ppx);                ctrlY1 = py + (py - ppy)              } else {                ctrlX1 = this.vertices[this.vertices.length - 1][0];                ctrlY1 = this.vertices[this.vertices.length - 1][1]              }              ctrlX2 = cx + tmpArray[j];              ctrlY2 = cy + tmpArray[j + 1];              endX = cx + tmpArray[j + 2];              endY = cy + tmpArray[j + 3];              this.parsePathCurveto(ctrlX1, ctrlY1, ctrlX2, ctrlY2, endX, endY);              cx = endX;              cy = endY            }          } else if (valOf === 81) {            if (tmpArray.length >= 4 && tmpArray.length % 4 === 0) for (j = 0, k = tmpArray.length; j < k; j += 4) {              ctrlX = tmpArray[j];              ctrlY = tmpArray[j + 1];              endX = tmpArray[j + 2];              endY = tmpArray[j + 3];              this.parsePathQuadto(cx, cy, ctrlX, ctrlY, endX, endY);              cx = endX;              cy = endY            }          } else if (valOf === 113) {            if (tmpArray.length >= 4 && tmpArray.length % 4 === 0) for (j = 0, k = tmpArray.length; j < k; j += 4) {              ctrlX = cx + tmpArray[j];              ctrlY = cy + tmpArray[j + 1];              endX = cx + tmpArray[j + 2];              endY = cy + tmpArray[j + 3];              this.parsePathQuadto(cx, cy, ctrlX, ctrlY, endX, endY);              cx = endX;              cy = endY            }          } else if (valOf === 84) {            if (tmpArray.length >= 2 && tmpArray.length % 2 === 0) for (j = 0, k = tmpArray.length; j < k; j += 2) {              if (lastInstruction.toLowerCase() === "q" || lastInstruction.toLowerCase() === "t") {                ppx = this.vertices[this.vertices.length - 2][0];                ppy = this.vertices[this.vertices.length - 2][1];                px = this.vertices[this.vertices.length - 1][0];                py = this.vertices[this.vertices.length - 1][1];                ctrlX = px + (px - ppx);                ctrlY = py + (py - ppy)              } else {                ctrlX = cx;                ctrlY = cy              }              endX = tmpArray[j];              endY = tmpArray[j + 1];              this.parsePathQuadto(cx, cy, ctrlX, ctrlY, endX, endY);              cx = endX;              cy = endY            }          } else if (valOf === 116) {            if (tmpArray.length >= 2 && tmpArray.length % 2 === 0) for (j = 0, k = tmpArray.length; j < k; j += 2) {              if (lastInstruction.toLowerCase() === "q" || lastInstruction.toLowerCase() === "t") {                ppx = this.vertices[this.vertices.length - 2][0];                ppy = this.vertices[this.vertices.length - 2][1];                px = this.vertices[this.vertices.length - 1][0];                py = this.vertices[this.vertices.length - 1][1];                ctrlX = px + (px - ppx);                ctrlY = py + (py - ppy)              } else {                ctrlX = cx;                ctrlY = cy              }              endX = cx + tmpArray[j];              endY = cy + tmpArray[j + 1];              this.parsePathQuadto(cx, cy, ctrlX, ctrlY, endX, endY);              cx = endX;              cy = endY            }          } else if (valOf === 90 || valOf === 122) this.close = true;          lastInstruction = command.toString()        } else i++      }    };    PShapeSVG.prototype.parsePathQuadto = function(x1, y1, cx, cy, x2, y2) {      if (this.vertices.length > 0) {        this.parsePathCode(1);        this.parsePathVertex(x1 + (cx - x1) * 2 / 3, y1 + (cy - y1) * 2 / 3);        this.parsePathVertex(x2 + (cx - x2) * 2 / 3, y2 + (cy - y2) * 2 / 3);        this.parsePathVertex(x2, y2)      } else throw "Path must start with M/m";    };    PShapeSVG.prototype.parsePathCurveto = function(x1, y1, x2, y2, x3, y3) {      if (this.vertices.length > 0) {        this.parsePathCode(1);        this.parsePathVertex(x1, y1);        this.parsePathVertex(x2, y2);        this.parsePathVertex(x3, y3)      } else throw "Path must start with M/m";    };    PShapeSVG.prototype.parsePathLineto = function(px, py) {      if (this.vertices.length > 0) {        this.parsePathCode(0);        this.parsePathVertex(px, py);        this.vertices[this.vertices.length - 1]["moveTo"] = false      } else throw "Path must start with M/m";    };    PShapeSVG.prototype.parsePathMoveto = function(px, py) {      if (this.vertices.length > 0) this.parsePathCode(3);      this.parsePathCode(0);      this.parsePathVertex(px, py);      this.vertices[this.vertices.length - 1]["moveTo"] = true    };    PShapeSVG.prototype.parsePathVertex = function(x, y) {      var verts = [];      verts[0] = x;      verts[1] = y;      this.vertices.push(verts)    };    PShapeSVG.prototype.parsePathCode = function(what) {      this.vertexCodes.push(what)    };    PShapeSVG.prototype.parsePoly = function(val) {      this.family = 21;      this.close = val;      var pointsAttr = p.trim(this.element.getStringAttribute("points").replace(/[,\s]+/g, " "));      if (pointsAttr !== null) {        var pointsBuffer = pointsAttr.split(" ");        if (pointsBuffer.length % 2 === 0) for (var i = 0, j = pointsBuffer.length; i < j; i++) {          var verts = [];          verts[0] = pointsBuffer[i];          verts[1] = pointsBuffer[++i];          this.vertices.push(verts)        } else throw "Error parsing polygon points: odd number of coordinates provided";      }    };    PShapeSVG.prototype.parseRect = function() {      this.kind = 30;      this.family = 1;      this.params = [];      this.params[0] = this.element.getFloatAttribute("x");      this.params[1] = this.element.getFloatAttribute("y");      this.params[2] = this.element.getFloatAttribute("width");      this.params[3] = this.element.getFloatAttribute("height");      if (this.params[2] < 0 || this.params[3] < 0) throw "svg error: negative width or height found while parsing <rect>";    };    PShapeSVG.prototype.parseEllipse = function(val) {      this.kind = 31;      this.family = 1;      this.params = [];      this.params[0] = this.element.getFloatAttribute("cx") | 0;      this.params[1] = this.element.getFloatAttribute("cy") | 0;      var rx, ry;      if (val) {        rx = ry = this.element.getFloatAttribute("r");        if (rx < 0) throw "svg error: negative radius found while parsing <circle>";      } else {        rx = this.element.getFloatAttribute("rx");        ry = this.element.getFloatAttribute("ry");        if (rx < 0 || ry < 0) throw "svg error: negative x-axis radius or y-axis radius found while parsing <ellipse>";      }      this.params[0] -= rx;      this.params[1] -= ry;      this.params[2] = rx * 2;      this.params[3] = ry * 2    };    PShapeSVG.prototype.parseLine = function() {      this.kind = 4;      this.family = 1;      this.params = [];      this.params[0] = this.element.getFloatAttribute("x1");      this.params[1] = this.element.getFloatAttribute("y1");      this.params[2] = this.element.getFloatAttribute("x2");      this.params[3] = this.element.getFloatAttribute("y2")    };    PShapeSVG.prototype.parseColors = function(element) {      if (element.hasAttribute("opacity")) this.setOpacity(element.getAttribute("opacity"));      if (element.hasAttribute("stroke")) this.setStroke(element.getAttribute("stroke"));      if (element.hasAttribute("stroke-width")) this.setStrokeWeight(element.getAttribute("stroke-width"));      if (element.hasAttribute("stroke-linejoin")) this.setStrokeJoin(element.getAttribute("stroke-linejoin"));      if (element.hasAttribute("stroke-linecap")) this.setStrokeCap(element.getStringAttribute("stroke-linecap"));      if (element.hasAttribute("fill")) this.setFill(element.getStringAttribute("fill"));      if (element.hasAttribute("style")) {        var styleText = element.getStringAttribute("style");        var styleTokens = styleText.toString().split(";");        for (var i = 0, j = styleTokens.length; i < j; i++) {          var tokens = p.trim(styleTokens[i].split(":"));          if (tokens[0] === "fill") this.setFill(tokens[1]);          else if (tokens[0] === "fill-opacity") this.setFillOpacity(tokens[1]);          else if (tokens[0] === "stroke") this.setStroke(tokens[1]);          else if (tokens[0] === "stroke-width") this.setStrokeWeight(tokens[1]);          else if (tokens[0] === "stroke-linecap") this.setStrokeCap(tokens[1]);          else if (tokens[0] === "stroke-linejoin") this.setStrokeJoin(tokens[1]);          else if (tokens[0] === "stroke-opacity") this.setStrokeOpacity(tokens[1]);          else if (tokens[0] === "opacity") this.setOpacity(tokens[1])        }      }    };    PShapeSVG.prototype.setFillOpacity = function(opacityText) {      this.fillOpacity = parseFloat(opacityText);      this.fillColor = this.fillOpacity * 255 << 24 | this.fillColor & 16777215    };    PShapeSVG.prototype.setFill = function(fillText) {      var opacityMask = this.fillColor & 4278190080;      if (fillText === "none") this.fill = false;      else if (fillText.indexOf("#") === 0) {        this.fill = true;        if (fillText.length === 4) fillText = fillText.replace(/#(.)(.)(.)/, "#$1$1$2$2$3$3");        this.fillColor = opacityMask | parseInt(fillText.substring(1), 16) & 16777215      } else if (fillText.indexOf("rgb") === 0) {        this.fill = true;        this.fillColor = opacityMask | this.parseRGB(fillText)      } else if (fillText.indexOf("url(#") === 0) this.fillName = fillText.substring(5, fillText.length - 1);      else if (colors[fillText]) {        this.fill = true;        this.fillColor = opacityMask | parseInt(colors[fillText].substring(1), 16) & 16777215      }    };    PShapeSVG.prototype.setOpacity = function(opacity) {      this.strokeColor = parseFloat(opacity) * 255 << 24 | this.strokeColor & 16777215;      this.fillColor = parseFloat(opacity) * 255 << 24 | this.fillColor & 16777215    };    PShapeSVG.prototype.setStroke = function(strokeText) {      var opacityMask = this.strokeColor & 4278190080;      if (strokeText === "none") this.stroke = false;      else if (strokeText.charAt(0) === "#") {        this.stroke = true;        if (strokeText.length === 4) strokeText = strokeText.replace(/#(.)(.)(.)/, "#$1$1$2$2$3$3");        this.strokeColor = opacityMask | parseInt(strokeText.substring(1), 16) & 16777215      } else if (strokeText.indexOf("rgb") === 0) {        this.stroke = true;        this.strokeColor = opacityMask | this.parseRGB(strokeText)      } else if (strokeText.indexOf("url(#") === 0) this.strokeName = strokeText.substring(5, strokeText.length - 1);      else if (colors[strokeText]) {        this.stroke = true;        this.strokeColor = opacityMask | parseInt(colors[strokeText].substring(1), 16) & 16777215      }    };    PShapeSVG.prototype.setStrokeWeight = function(weight) {      this.strokeWeight = this.parseUnitSize(weight)    };    PShapeSVG.prototype.setStrokeJoin = function(linejoin) {      if (linejoin === "miter") this.strokeJoin = 'miter';      else if (linejoin === "round") this.strokeJoin = 'round';      else if (linejoin === "bevel") this.strokeJoin = 'bevel'    };    PShapeSVG.prototype.setStrokeCap = function(linecap) {      if (linecap === "butt") this.strokeCap = 'butt';      else if (linecap === "round") this.strokeCap = 'round';      else if (linecap === "square") this.strokeCap = 'square'    };    PShapeSVG.prototype.setStrokeOpacity = function(opacityText) {      this.strokeOpacity = parseFloat(opacityText);      this.strokeColor = this.strokeOpacity * 255 << 24 | this.strokeColor & 16777215    };    PShapeSVG.prototype.parseRGB = function(color) {      var sub = color.substring(color.indexOf("(") + 1, color.indexOf(")"));      var values = sub.split(", ");      return values[0] << 16 | values[1] << 8 | values[2]    };    PShapeSVG.prototype.parseUnitSize = function(text) {      var len = text.length - 2;      if (len < 0) return text;      if (text.indexOf("pt") === len) return parseFloat(text.substring(0, len)) * 1.25;      if (text.indexOf("pc") === len) return parseFloat(text.substring(0, len)) * 15;      if (text.indexOf("mm") === len) return parseFloat(text.substring(0, len)) * 3.543307;      if (text.indexOf("cm") === len) return parseFloat(text.substring(0, len)) * 35.43307;      if (text.indexOf("in") === len) return parseFloat(text.substring(0, len)) * 90;      if (text.indexOf("px") === len) return parseFloat(text.substring(0, len));      return parseFloat(text)    };    p.shape = function(shape, x, y, width, height) {      if (arguments.length >= 1 && arguments[0] !== null) if (shape.isVisible()) {        p.pushMatrix();        if (curShapeMode === 3) if (arguments.length === 5) {          p.translate(x - width / 2, y - height / 2);          p.scale(width / shape.getWidth(), height / shape.getHeight())        } else if (arguments.length === 3) p.translate(x - shape.getWidth() / 2, -shape.getHeight() / 2);        else p.translate(-shape.getWidth() / 2, -shape.getHeight() / 2);        else if (curShapeMode === 0) if (arguments.length === 5) {          p.translate(x, y);          p.scale(width / shape.getWidth(), height / shape.getHeight())        } else {          if (arguments.length === 3) p.translate(x, y)        } else if (curShapeMode === 1) if (arguments.length === 5) {          width -= x;          height -= y;          p.translate(x, y);          p.scale(width / shape.getWidth(), height / shape.getHeight())        } else if (arguments.length === 3) p.translate(x, y);        shape.draw(p);        if (arguments.length === 1 && curShapeMode === 3 || arguments.length > 1) p.popMatrix()      }    };    p.shapeMode = function(mode) {      curShapeMode = mode    };    p.loadShape = function(filename) {      if (arguments.length === 1) if (filename.indexOf(".svg") > -1) return new PShapeSVG(null, filename);      return null    };    var XMLAttribute = function(fname, n, nameSpace, v, t) {      this.fullName = fname || "";      this.name = n || "";      this.namespace = nameSpace || "";      this.value = v;      this.type = t    };    XMLAttribute.prototype = {      getName: function() {        return this.name      },      getFullName: function() {        return this.fullName      },      getNamespace: function() {        return this.namespace      },      getValue: function() {        return this.value      },      getType: function() {        return this.type      },      setValue: function(newval) {        this.value = newval      }    };    var XMLElement = p.XMLElement = function(selector, uri, sysid, line) {      this.attributes = [];      this.children = [];      this.fullName = null;      this.name = null;      this.namespace = "";      this.content = null;      this.parent = null;      this.lineNr = "";      this.systemID = "";      this.type = "ELEMENT";      if (selector) if (typeof selector === "string") if (uri === undef && selector.indexOf("<") > -1) this.parse(selector);      else {        this.fullName = selector;        this.namespace = uri;        this.systemId = sysid;        this.lineNr = line      } else this.parse(uri)    };    XMLElement.prototype = {      parse: function(textstring) {        var xmlDoc;        try {          var extension = textstring.substring(textstring.length - 4);          if (extension === ".xml" || extension === ".svg") textstring = ajax(textstring);          xmlDoc = (new DOMParser).parseFromString(textstring, "text/xml");          var elements = xmlDoc.documentElement;          if (elements) this.parseChildrenRecursive(null, elements);          else throw "Error loading document";          return this        } catch(e) {          throw e;        }      },      parseChildrenRecursive: function(parent, elementpath) {        var xmlelement, xmlattribute, tmpattrib, l, m, child;        if (!parent) {          this.fullName = elementpath.localName;          this.name = elementpath.nodeName;          xmlelement = this        } else {          xmlelement = new XMLElement(elementpath.nodeName);          xmlelement.parent = parent        }        if (elementpath.nodeType === 3 && elementpath.textContent !== "") return this.createPCDataElement(elementpath.textContent);        if (elementpath.nodeType === 4) return this.createCDataElement(elementpath.textContent);        if (elementpath.attributes) for (l = 0, m = elementpath.attributes.length; l < m; l++) {          tmpattrib = elementpath.attributes[l];          xmlattribute = new XMLAttribute(tmpattrib.getname, tmpattrib.nodeName, tmpattrib.namespaceURI, tmpattrib.nodeValue, tmpattrib.nodeType);          xmlelement.attributes.push(xmlattribute)        }        if (elementpath.childNodes) for (l = 0, m = elementpath.childNodes.length; l < m; l++) {          var node = elementpath.childNodes[l];          child = xmlelement.parseChildrenRecursive(xmlelement, node);          if (child !== null) xmlelement.children.push(child)        }        return xmlelement      },      createElement: function(fullname, namespaceuri, sysid, line) {        if (sysid === undef) return new XMLElement(fullname, namespaceuri);        return new XMLElement(fullname, namespaceuri, sysid, line)      },      createPCDataElement: function(content, isCDATA) {        if (content.replace(/^\s+$/g, "") === "") return null;        var pcdata = new XMLElement;        pcdata.type = "TEXT";        pcdata.content = content;        return pcdata      },      createCDataElement: function(content) {        var cdata = this.createPCDataElement(content);        if (cdata === null) return null;        cdata.type = "CDATA";        var htmlentities = {          "<": "<",          ">": ">",          "'": "'",          '"': """        },          entity;        for (entity in htmlentities) if (!Object.hasOwnProperty(htmlentities, entity)) content = content.replace(new RegExp(entity, "g"), htmlentities[entity]);        cdata.cdata = content;        return cdata      },      hasAttribute: function() {        if (arguments.length === 1) return this.getAttribute(arguments[0]) !== null;        if (arguments.length === 2) return this.getAttribute(arguments[0], arguments[1]) !== null      },      equals: function(other) {        if (! (other instanceof XMLElement)) return false;        var i, j;        if (this.fullName !== other.fullName) return false;        if (this.attributes.length !== other.getAttributeCount()) return false;        if (this.attributes.length !== other.attributes.length) return false;        var attr_name, attr_ns, attr_value, attr_type, attr_other;        for (i = 0, j = this.attributes.length; i < j; i++) {          attr_name = this.attributes[i].getName();          attr_ns = this.attributes[i].getNamespace();          attr_other = other.findAttribute(attr_name, attr_ns);          if (attr_other === null) return false;          if (this.attributes[i].getValue() !== attr_other.getValue()) return false;          if (this.attributes[i].getType() !== attr_other.getType()) return false        }        if (this.children.length !== other.getChildCount()) return false;        if (this.children.length > 0) {          var child1, child2;          for (i = 0, j = this.children.length; i < j; i++) {            child1 = this.getChild(i);            child2 = other.getChild(i);            if (!child1.equals(child2)) return false          }          return true        }        return this.content === other.content      },      getContent: function() {        if (this.type === "TEXT" || this.type === "CDATA") return this.content;        var children = this.children;        if (children.length === 1 && (children[0].type === "TEXT" || children[0].type === "CDATA")) return children[0].content;        return null      },      getAttribute: function() {        var attribute;        if (arguments.length === 2) {          attribute = this.findAttribute(arguments[0]);          if (attribute) return attribute.getValue();          return arguments[1]        } else if (arguments.length === 1) {          attribute = this.findAttribute(arguments[0]);          if (attribute) return attribute.getValue();          return null        } else if (arguments.length === 3) {          attribute = this.findAttribute(arguments[0], arguments[1]);          if (attribute) return attribute.getValue();          return arguments[2]        }      },      getStringAttribute: function() {        if (arguments.length === 1) return this.getAttribute(arguments[0]);        if (arguments.length === 2) return this.getAttribute(arguments[0], arguments[1]);        return this.getAttribute(arguments[0], arguments[1], arguments[2])      },      getString: function(attributeName) {        return this.getStringAttribute(attributeName)      },      getFloatAttribute: function() {        if (arguments.length === 1) return parseFloat(this.getAttribute(arguments[0], 0));        if (arguments.length === 2) return this.getAttribute(arguments[0], arguments[1]);        return this.getAttribute(arguments[0], arguments[1], arguments[2])      },      getFloat: function(attributeName) {        return this.getFloatAttribute(attributeName)      },      getIntAttribute: function() {        if (arguments.length === 1) return this.getAttribute(arguments[0], 0);        if (arguments.length === 2) return this.getAttribute(arguments[0], arguments[1]);        return this.getAttribute(arguments[0], arguments[1], arguments[2])      },      getInt: function(attributeName) {        return this.getIntAttribute(attributeName)      },      hasChildren: function() {        return this.children.length > 0      },      addChild: function(child) {        if (child !== null) {          child.parent = this;          this.children.push(child)        }      },      insertChild: function(child, index) {        if (child) {          if (child.getLocalName() === null && !this.hasChildren()) {            var lastChild = this.children[this.children.length - 1];            if (lastChild.getLocalName() === null) {              lastChild.setContent(lastChild.getContent() + child.getContent());              return            }          }          child.parent = this;          this.children.splice(index, 0, child)        }      },      getChild: function(selector) {        if (typeof selector === "number") return this.children[selector];        if (selector.indexOf("/") !== -1) return this.getChildRecursive(selector.split("/"), 0);        var kid, kidName;        for (var i = 0, j = this.getChildCount(); i < j; i++) {          kid = this.getChild(i);          kidName = kid.getName();          if (kidName !== null && kidName === selector) return kid        }        return null      },      getChildren: function() {        if (arguments.length === 1) {          if (typeof arguments[0] === "number") return this.getChild(arguments[0]);          if (arguments[0].indexOf("/") !== -1) return this.getChildrenRecursive(arguments[0].split("/"), 0);          var matches = [];          var kid, kidName;          for (var i = 0, j = this.getChildCount(); i < j; i++) {            kid = this.getChild(i);            kidName = kid.getName();            if (kidName !== null && kidName === arguments[0]) matches.push(kid)          }          return matches        }        return this.children      },      getChildCount: function() {        return this.children.length      },      getChildRecursive: function(items, offset) {        if (offset === items.length) return this;        var kid, kidName, matchName = items[offset];        for (var i = 0, j = this.getChildCount(); i < j; i++) {          kid = this.getChild(i);          kidName = kid.getName();          if (kidName !== null && kidName === matchName) return kid.getChildRecursive(items, offset + 1)        }        return null      },      getChildrenRecursive: function(items, offset) {        if (offset === items.length - 1) return this.getChildren(items[offset]);        var matches = this.getChildren(items[offset]);        var kidMatches = [];        for (var i = 0; i < matches.length; i++) kidMatches = kidMatches.concat(matches[i].getChildrenRecursive(items, offset + 1));        return kidMatches      },      isLeaf: function() {        return !this.hasChildren()      },      listChildren: function() {        var arr = [];        for (var i = 0, j = this.children.length; i < j; i++) arr.push(this.getChild(i).getName());        return arr      },      removeAttribute: function(name, namespace) {        this.namespace = namespace || "";        for (var i = 0, j = this.attributes.length; i < j; i++) if (this.attributes[i].getName() === name && this.attributes[i].getNamespace() === this.namespace) {          this.attributes.splice(i, 1);          break        }      },      removeChild: function(child) {        if (child) for (var i = 0, j = this.children.length; i < j; i++) if (this.children[i].equals(child)) {          this.children.splice(i, 1);          break        }      },      removeChildAtIndex: function(index) {        if (this.children.length > index) this.children.splice(index, 1)      },      findAttribute: function(name, namespace) {        this.namespace = namespace || "";        for (var i = 0, j = this.attributes.length; i < j; i++) if (this.attributes[i].getName() === name && this.attributes[i].getNamespace() === this.namespace) return this.attributes[i];        return null      },      setAttribute: function() {        var attr;        if (arguments.length === 3) {          var index = arguments[0].indexOf(":");          var name = arguments[0].substring(index + 1);          attr = this.findAttribute(name, arguments[1]);          if (attr) attr.setValue(arguments[2]);          else {            attr = new XMLAttribute(arguments[0], name, arguments[1], arguments[2], "CDATA");            this.attributes.push(attr)          }        } else {          attr = this.findAttribute(arguments[0]);          if (attr) attr.setValue(arguments[1]);          else {            attr = new XMLAttribute(arguments[0], arguments[0], null, arguments[1], "CDATA");            this.attributes.push(attr)          }        }      },      setString: function(attribute, value) {        this.setAttribute(attribute, value)      },      setInt: function(attribute, value) {        this.setAttribute(attribute, value)      },      setFloat: function(attribute, value) {        this.setAttribute(attribute, value)      },      setContent: function(content) {        if (this.children.length > 0) Processing.debug("Tried to set content for XMLElement with children");        this.content = content      },      setName: function() {        if (arguments.length === 1) {          this.name = arguments[0];          this.fullName = arguments[0];          this.namespace = null        } else {          var index = arguments[0].indexOf(":");          if (arguments[1] === null || index < 0) this.name = arguments[0];          else this.name = arguments[0].substring(index + 1);          this.fullName = arguments[0];          this.namespace = arguments[1]        }      },      getName: function() {        return this.fullName      },      getLocalName: function() {        return this.name      },      getAttributeCount: function() {        return this.attributes.length      },      toString: function() {        if (this.type === "TEXT") return this.content;        if (this.type === "CDATA") return this.cdata;        var tagstring = this.fullName;        var xmlstring = "<" + tagstring;        var a, c;        for (a = 0; a < this.attributes.length; a++) {          var attr = this.attributes[a];          xmlstring += " " + attr.getName() + "=" + '"' + attr.getValue() + '"'        }        if (this.children.length === 0) if (this.content === "") xmlstring += "/>";        else xmlstring += ">" + this.content + "</" + tagstring + ">";        else {          xmlstring += ">";          for (c = 0; c < this.children.length; c++) xmlstring += this.children[c].toString();          xmlstring += "</" + tagstring + ">"        }        return xmlstring      }    };    XMLElement.parse = function(xmlstring) {      var element = new XMLElement;      element.parse(xmlstring);      return element    };    var XML = p.XML = p.XMLElement;    p.loadXML = function(uri) {      return new XML(p, uri)    };    var printMatrixHelper = function(elements) {      var big = 0;      for (var i = 0; i < elements.length; i++) if (i !== 0) big = Math.max(big, Math.abs(elements[i]));      else big = Math.abs(elements[i]);      var digits = (big + "").indexOf(".");      if (digits === 0) digits = 1;      else if (digits === -1) digits = (big + "").length;      return digits    };    var PMatrix2D = p.PMatrix2D = function() {      if (arguments.length === 0) this.reset();      else if (arguments.length === 1 && arguments[0] instanceof PMatrix2D) this.set(arguments[0].array());      else if (arguments.length === 6) this.set(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5])    };    PMatrix2D.prototype = {      set: function() {        if (arguments.length === 6) {          var a = arguments;          this.set([a[0], a[1], a[2], a[3], a[4], a[5]])        } else if (arguments.length === 1 && arguments[0] instanceof PMatrix2D) this.elements = arguments[0].array();        else if (arguments.length === 1 && arguments[0] instanceof Array) this.elements = arguments[0].slice()      },      get: function() {        var outgoing = new PMatrix2D;        outgoing.set(this.elements);        return outgoing      },      reset: function() {        this.set([1, 0, 0, 0, 1, 0])      },      array: function array() {        return this.elements.slice()      },      translate: function(tx, ty) {        this.elements[2] = tx * this.elements[0] + ty * this.elements[1] + this.elements[2];        this.elements[5] = tx * this.elements[3] + ty * this.elements[4] + this.elements[5]      },      invTranslate: function(tx, ty) {        this.translate(-tx, -ty)      },      transpose: function() {},      mult: function(source, target) {        var x, y;        if (source instanceof        PVector) {          x = source.x;          y = source.y;          if (!target) target = new PVector        } else if (source instanceof Array) {          x = source[0];          y = source[1];          if (!target) target = []        }        if (target instanceof Array) {          target[0] = this.elements[0] * x + this.elements[1] * y + this.elements[2];          target[1] = this.elements[3] * x + this.elements[4] * y + this.elements[5]        } else if (target instanceof PVector) {          target.x = this.elements[0] * x + this.elements[1] * y + this.elements[2];          target.y = this.elements[3] * x + this.elements[4] * y + this.elements[5];          target.z = 0        }        return target      },      multX: function(x, y) {        return x * this.elements[0] + y * this.elements[1] + this.elements[2]      },      multY: function(x, y) {        return x * this.elements[3] + y * this.elements[4] + this.elements[5]      },      skewX: function(angle) {        this.apply(1, 0, 1, angle, 0, 0)      },      skewY: function(angle) {        this.apply(1, 0, 1, 0, angle, 0)      },      shearX: function(angle) {        this.apply(1, 0, 1, Math.tan(angle), 0, 0)      },      shearY: function(angle) {        this.apply(1, 0, 1, 0, Math.tan(angle), 0)      },      determinant: function() {        return this.elements[0] * this.elements[4] - this.elements[1] * this.elements[3]      },      invert: function() {        var d = this.determinant();        if (Math.abs(d) > -2147483648) {          var old00 = this.elements[0];          var old01 = this.elements[1];          var old02 = this.elements[2];          var old10 = this.elements[3];          var old11 = this.elements[4];          var old12 = this.elements[5];          this.elements[0] = old11 / d;          this.elements[3] = -old10 / d;          this.elements[1] = -old01 / d;          this.elements[4] = old00 / d;          this.elements[2] = (old01 * old12 - old11 * old02) / d;          this.elements[5] = (old10 * old02 - old00 * old12) / d;          return true        }        return false      },      scale: function(sx, sy) {        if (sx && !sy) sy = sx;        if (sx && sy) {          this.elements[0] *= sx;          this.elements[1] *= sy;          this.elements[3] *= sx;          this.elements[4] *= sy        }      },      invScale: function(sx, sy) {        if (sx && !sy) sy = sx;        this.scale(1 / sx, 1 / sy)      },      apply: function() {        var source;        if (arguments.length === 1 && arguments[0] instanceof PMatrix2D) source = arguments[0].array();        else if (arguments.length === 6) source = Array.prototype.slice.call(arguments);        else if (arguments.length === 1 && arguments[0] instanceof Array) source = arguments[0];        var result = [0, 0, this.elements[2], 0, 0, this.elements[5]];        var e = 0;        for (var row = 0; row < 2; row++) for (var col = 0; col < 3; col++, e++) result[e] += this.elements[row * 3 + 0] * source[col + 0] + this.elements[row * 3 + 1] * source[col + 3];        this.elements = result.slice()      },      preApply: function() {        var source;        if (arguments.length === 1 && arguments[0] instanceof PMatrix2D) source = arguments[0].array();        else if (arguments.length === 6) source = Array.prototype.slice.call(arguments);        else if (arguments.length === 1 && arguments[0] instanceof Array) source = arguments[0];        var result = [0, 0, source[2], 0, 0, source[5]];        result[2] = source[2] + this.elements[2] * source[0] + this.elements[5] * source[1];        result[5] = source[5] + this.elements[2] * source[3] + this.elements[5] * source[4];        result[0] = this.elements[0] * source[0] + this.elements[3] * source[1];        result[3] = this.elements[0] * source[3] + this.elements[3] * source[4];        result[1] = this.elements[1] * source[0] + this.elements[4] * source[1];        result[4] = this.elements[1] * source[3] + this.elements[4] * source[4];        this.elements = result.slice()      },      rotate: function(angle) {        var c = Math.cos(angle);        var s = Math.sin(angle);        var temp1 = this.elements[0];        var temp2 = this.elements[1];        this.elements[0] = c * temp1 + s * temp2;        this.elements[1] = -s * temp1 + c * temp2;        temp1 = this.elements[3];        temp2 = this.elements[4];        this.elements[3] = c * temp1 + s * temp2;        this.elements[4] = -s * temp1 + c * temp2      },      rotateZ: function(angle) {        this.rotate(angle)      },      invRotateZ: function(angle) {        this.rotateZ(angle - Math.PI)      },      print: function() {        var digits = printMatrixHelper(this.elements);        var output = "" + p.nfs(this.elements[0], digits, 4) + " " + p.nfs(this.elements[1], digits, 4) + " " + p.nfs(this.elements[2], digits, 4) + "\n" + p.nfs(this.elements[3], digits, 4) + " " + p.nfs(this.elements[4], digits, 4) + " " + p.nfs(this.elements[5], digits, 4) + "\n\n";        p.println(output)      }    };    var PMatrix3D = p.PMatrix3D = function() {      this.reset()    };    PMatrix3D.prototype = {      set: function() {        if (arguments.length === 16) this.elements = Array.prototype.slice.call(arguments);        else if (arguments.length === 1 && arguments[0] instanceof PMatrix3D) this.elements = arguments[0].array();        else if (arguments.length === 1 && arguments[0] instanceof Array) this.elements = arguments[0].slice()      },      get: function() {        var outgoing = new PMatrix3D;        outgoing.set(this.elements);        return outgoing      },      reset: function() {        this.elements = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]      },      array: function array() {        return this.elements.slice()      },      translate: function(tx, ty, tz) {        if (tz === undef) tz = 0;        this.elements[3] += tx * this.elements[0] + ty * this.elements[1] + tz * this.elements[2];        this.elements[7] += tx * this.elements[4] + ty * this.elements[5] + tz * this.elements[6];        this.elements[11] += tx * this.elements[8] + ty * this.elements[9] + tz * this.elements[10];        this.elements[15] += tx * this.elements[12] + ty * this.elements[13] + tz * this.elements[14]      },      transpose: function() {        var temp = this.elements[4];        this.elements[4] = this.elements[1];        this.elements[1] = temp;        temp = this.elements[8];        this.elements[8] = this.elements[2];        this.elements[2] = temp;        temp = this.elements[6];        this.elements[6] = this.elements[9];        this.elements[9] = temp;        temp = this.elements[3];        this.elements[3] = this.elements[12];        this.elements[12] = temp;        temp = this.elements[7];        this.elements[7] = this.elements[13];        this.elements[13] = temp;        temp = this.elements[11];        this.elements[11] = this.elements[14];        this.elements[14] = temp      },      mult: function(source, target) {        var x, y, z, w;        if (source instanceof        PVector) {          x = source.x;          y = source.y;          z = source.z;          w = 1;          if (!target) target = new PVector        } else if (source instanceof Array) {          x = source[0];          y = source[1];          z = source[2];          w = source[3] || 1;          if (!target || target.length !== 3 && target.length !== 4) target = [0, 0, 0]        }        if (target instanceof Array) if (target.length === 3) {          target[0] = this.elements[0] * x + this.elements[1] * y + this.elements[2] * z + this.elements[3];          target[1] = this.elements[4] * x + this.elements[5] * y + this.elements[6] * z + this.elements[7];          target[2] = this.elements[8] * x + this.elements[9] * y + this.elements[10] * z + this.elements[11]        } else if (target.length === 4) {          target[0] = this.elements[0] * x + this.elements[1] * y + this.elements[2] * z + this.elements[3] * w;          target[1] = this.elements[4] * x + this.elements[5] * y + this.elements[6] * z + this.elements[7] * w;          target[2] = this.elements[8] * x + this.elements[9] * y + this.elements[10] * z + this.elements[11] * w;          target[3] = this.elements[12] * x + this.elements[13] * y + this.elements[14] * z + this.elements[15] * w        }        if (target instanceof PVector) {          target.x = this.elements[0] * x + this.elements[1] * y + this.elements[2] * z + this.elements[3];          target.y = this.elements[4] * x + this.elements[5] * y + this.elements[6] * z + this.elements[7];          target.z = this.elements[8] * x + this.elements[9] * y + this.elements[10] * z + this.elements[11]        }        return target      },      preApply: function() {        var source;        if (arguments.length === 1 && arguments[0] instanceof PMatrix3D) source = arguments[0].array();        else if (arguments.length === 16) source = Array.prototype.slice.call(arguments);        else if (arguments.length === 1 && arguments[0] instanceof Array) source = arguments[0];        var result = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];        var e = 0;        for (var row = 0; row < 4; row++) for (var col = 0; col < 4; col++, e++) result[e] += this.elements[col + 0] * source[row * 4 + 0] + this.elements[col + 4] * source[row * 4 + 1] + this.elements[col + 8] * source[row * 4 + 2] + this.elements[col + 12] * source[row * 4 + 3];        this.elements = result.slice()      },      apply: function() {        var source;        if (arguments.length === 1 && arguments[0] instanceof PMatrix3D) source = arguments[0].array();        else if (arguments.length === 16) source = Array.prototype.slice.call(arguments);        else if (arguments.length === 1 && arguments[0] instanceof Array) source = arguments[0];        var result = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];        var e = 0;        for (var row = 0; row < 4; row++) for (var col = 0; col < 4; col++, e++) result[e] += this.elements[row * 4 + 0] * source[col + 0] + this.elements[row * 4 + 1] * source[col + 4] + this.elements[row * 4 + 2] * source[col + 8] + this.elements[row * 4 + 3] * source[col + 12];        this.elements = result.slice()      },      rotate: function(angle, v0, v1, v2) {        if (!v1) this.rotateZ(angle);        else {          var c = p.cos(angle);          var s = p.sin(angle);          var t = 1 - c;          this.apply(t * v0 * v0 + c, t * v0 * v1 - s * v2, t * v0 * v2 + s * v1, 0, t * v0 * v1 + s * v2, t * v1 * v1 + c, t * v1 * v2 - s * v0, 0, t * v0 * v2 - s * v1, t * v1 * v2 + s * v0, t * v2 * v2 + c, 0, 0, 0, 0, 1)        }      },      invApply: function() {        if (inverseCopy === undef) inverseCopy = new PMatrix3D;        var a = arguments;        inverseCopy.set(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15]);        if (!inverseCopy.invert()) return false;        this.preApply(inverseCopy);        return true      },      rotateX: function(angle) {        var c = p.cos(angle);        var s = p.sin(angle);        this.apply([1, 0, 0, 0, 0, c, -s, 0, 0, s, c, 0, 0, 0, 0, 1])      },      rotateY: function(angle) {        var c = p.cos(angle);        var s = p.sin(angle);        this.apply([c,          0, s, 0, 0, 1, 0, 0, -s, 0, c, 0, 0, 0, 0, 1])      },      rotateZ: function(angle) {        var c = Math.cos(angle);        var s = Math.sin(angle);        this.apply([c, -s, 0, 0, s, c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1])      },      scale: function(sx, sy, sz) {        if (sx && !sy && !sz) sy = sz = sx;        else if (sx && sy && !sz) sz = 1;        if (sx && sy && sz) {          this.elements[0] *= sx;          this.elements[1] *= sy;          this.elements[2] *= sz;          this.elements[4] *= sx;          this.elements[5] *= sy;          this.elements[6] *= sz;          this.elements[8] *= sx;          this.elements[9] *= sy;          this.elements[10] *= sz;          this.elements[12] *= sx;          this.elements[13] *= sy;          this.elements[14] *= sz        }      },      skewX: function(angle) {        var t = Math.tan(angle);        this.apply(1, t, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)      },      skewY: function(angle) {        var t = Math.tan(angle);        this.apply(1, 0, 0, 0, t, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)      },      shearX: function(angle) {        var t = Math.tan(angle);        this.apply(1, t, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)      },      shearY: function(angle) {        var t = Math.tan(angle);        this.apply(1, 0, 0, 0, t, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)      },      multX: function(x, y, z, w) {        if (!z) return this.elements[0] * x + this.elements[1] * y + this.elements[3];        if (!w) return this.elements[0] * x + this.elements[1] * y + this.elements[2] * z + this.elements[3];        return this.elements[0] * x + this.elements[1] * y + this.elements[2] * z + this.elements[3] * w      },      multY: function(x, y, z, w) {        if (!z) return this.elements[4] * x + this.elements[5] * y + this.elements[7];        if (!w) return this.elements[4] * x + this.elements[5] * y + this.elements[6] * z + this.elements[7];        return this.elements[4] * x + this.elements[5] * y + this.elements[6] * z + this.elements[7] * w      },      multZ: function(x, y, z, w) {        if (!w) return this.elements[8] * x + this.elements[9] * y + this.elements[10] * z + this.elements[11];        return this.elements[8] * x + this.elements[9] * y + this.elements[10] * z + this.elements[11] * w      },      multW: function(x, y, z, w) {        if (!w) return this.elements[12] * x + this.elements[13] * y + this.elements[14] * z + this.elements[15];        return this.elements[12] * x + this.elements[13] * y + this.elements[14] * z + this.elements[15] * w      },      invert: function() {        var fA0 = this.elements[0] * this.elements[5] - this.elements[1] * this.elements[4];        var fA1 = this.elements[0] * this.elements[6] - this.elements[2] * this.elements[4];        var fA2 = this.elements[0] * this.elements[7] - this.elements[3] * this.elements[4];        var fA3 = this.elements[1] * this.elements[6] - this.elements[2] * this.elements[5];        var fA4 = this.elements[1] * this.elements[7] - this.elements[3] * this.elements[5];        var fA5 = this.elements[2] * this.elements[7] - this.elements[3] * this.elements[6];        var fB0 = this.elements[8] * this.elements[13] - this.elements[9] * this.elements[12];        var fB1 = this.elements[8] * this.elements[14] - this.elements[10] * this.elements[12];        var fB2 = this.elements[8] * this.elements[15] - this.elements[11] * this.elements[12];        var fB3 = this.elements[9] * this.elements[14] - this.elements[10] * this.elements[13];        var fB4 = this.elements[9] * this.elements[15] - this.elements[11] * this.elements[13];        var fB5 = this.elements[10] * this.elements[15] - this.elements[11] * this.elements[14];        var fDet = fA0 * fB5 - fA1 * fB4 + fA2 * fB3 + fA3 * fB2 - fA4 * fB1 + fA5 * fB0;        if (Math.abs(fDet) <= 1.0E-9) return false;        var kInv = [];        kInv[0] = +this.elements[5] * fB5 - this.elements[6] * fB4 + this.elements[7] * fB3;        kInv[4] = -this.elements[4] * fB5 + this.elements[6] * fB2 - this.elements[7] * fB1;        kInv[8] = +this.elements[4] * fB4 - this.elements[5] * fB2 + this.elements[7] * fB0;        kInv[12] = -this.elements[4] * fB3 + this.elements[5] * fB1 - this.elements[6] * fB0;        kInv[1] = -this.elements[1] * fB5 + this.elements[2] * fB4 - this.elements[3] * fB3;        kInv[5] = +this.elements[0] * fB5 - this.elements[2] * fB2 + this.elements[3] * fB1;        kInv[9] = -this.elements[0] * fB4 + this.elements[1] * fB2 - this.elements[3] * fB0;        kInv[13] = +this.elements[0] * fB3 - this.elements[1] * fB1 + this.elements[2] * fB0;        kInv[2] = +this.elements[13] * fA5 - this.elements[14] * fA4 + this.elements[15] * fA3;        kInv[6] = -this.elements[12] * fA5 + this.elements[14] * fA2 - this.elements[15] * fA1;        kInv[10] = +this.elements[12] * fA4 - this.elements[13] * fA2 + this.elements[15] * fA0;        kInv[14] = -this.elements[12] * fA3 + this.elements[13] * fA1 - this.elements[14] * fA0;        kInv[3] = -this.elements[9] * fA5 + this.elements[10] * fA4 - this.elements[11] * fA3;        kInv[7] = +this.elements[8] * fA5 - this.elements[10] * fA2 + this.elements[11] * fA1;        kInv[11] = -this.elements[8] * fA4 + this.elements[9] * fA2 - this.elements[11] * fA0;        kInv[15] = +this.elements[8] * fA3 - this.elements[9] * fA1 + this.elements[10] * fA0;        var fInvDet = 1 / fDet;        kInv[0] *= fInvDet;        kInv[1] *= fInvDet;        kInv[2] *= fInvDet;        kInv[3] *= fInvDet;        kInv[4] *= fInvDet;        kInv[5] *= fInvDet;        kInv[6] *= fInvDet;        kInv[7] *= fInvDet;        kInv[8] *= fInvDet;        kInv[9] *= fInvDet;        kInv[10] *= fInvDet;        kInv[11] *= fInvDet;        kInv[12] *= fInvDet;        kInv[13] *= fInvDet;        kInv[14] *= fInvDet;        kInv[15] *= fInvDet;        this.elements = kInv.slice();        return true      },      toString: function() {        var str = "";        for (var i = 0; i < 15; i++) str += this.elements[i] + ", ";        str += this.elements[15];        return str      },      print: function() {        var digits = printMatrixHelper(this.elements);        var output = "" + p.nfs(this.elements[0], digits, 4) + " " + p.nfs(this.elements[1], digits, 4) + " " + p.nfs(this.elements[2], digits, 4) + " " + p.nfs(this.elements[3], digits, 4) + "\n" + p.nfs(this.elements[4], digits, 4) + " " + p.nfs(this.elements[5], digits, 4) + " " + p.nfs(this.elements[6], digits, 4) + " " + p.nfs(this.elements[7], digits, 4) + "\n" + p.nfs(this.elements[8], digits, 4) + " " + p.nfs(this.elements[9], digits, 4) + " " + p.nfs(this.elements[10], digits, 4) + " " + p.nfs(this.elements[11], digits, 4) + "\n" + p.nfs(this.elements[12], digits, 4) + " " + p.nfs(this.elements[13], digits, 4) + " " + p.nfs(this.elements[14], digits, 4) + " " + p.nfs(this.elements[15], digits, 4) + "\n\n";        p.println(output)      },      invTranslate: function(tx, ty, tz) {        this.preApply(1, 0, 0, -tx, 0, 1, 0, -ty, 0, 0, 1, -tz, 0, 0, 0, 1)      },      invRotateX: function(angle) {        var c = Math.cos(-angle);        var s = Math.sin(-angle);        this.preApply([1, 0, 0, 0, 0, c, -s, 0, 0, s, c, 0, 0, 0, 0, 1])      },      invRotateY: function(angle) {        var c = Math.cos(-angle);        var s = Math.sin(-angle);        this.preApply([c, 0, s, 0, 0, 1, 0, 0, -s, 0, c, 0, 0, 0, 0, 1])      },      invRotateZ: function(angle) {        var c = Math.cos(-angle);        var s = Math.sin(-angle);        this.preApply([c, -s, 0, 0, s, c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1])      },      invScale: function(x, y, z) {        this.preApply([1 / x, 0, 0, 0, 0, 1 / y, 0, 0, 0, 0, 1 / z, 0, 0, 0, 0, 1])      }    };    var PMatrixStack = p.PMatrixStack = function() {      this.matrixStack = []    };    PMatrixStack.prototype.load = function() {      var tmpMatrix = drawing.$newPMatrix();      if (arguments.length === 1) tmpMatrix.set(arguments[0]);      else tmpMatrix.set(arguments);      this.matrixStack.push(tmpMatrix)    };    Drawing2D.prototype.$newPMatrix = function() {      return new PMatrix2D    };    Drawing3D.prototype.$newPMatrix = function() {      return new PMatrix3D    };    PMatrixStack.prototype.push = function() {      this.matrixStack.push(this.peek())    };    PMatrixStack.prototype.pop = function() {      return this.matrixStack.pop()    };    PMatrixStack.prototype.peek = function() {      var tmpMatrix = drawing.$newPMatrix();      tmpMatrix.set(this.matrixStack[this.matrixStack.length - 1]);      return tmpMatrix    };    PMatrixStack.prototype.mult = function(matrix) {      this.matrixStack[this.matrixStack.length - 1].apply(matrix)    };    p.split = function(str, delim) {      return str.split(delim)    };    p.splitTokens = function(str, tokens) {      if (tokens === undef) return str.split(/\s+/g);      var chars = tokens.split(/()/g),        buffer = "",        len = str.length,        i, c, tokenized = [];      for (i = 0; i < len; i++) {        c = str[i];        if (chars.indexOf(c) > -1) {          if (buffer !== "") tokenized.push(buffer);          buffer = ""        } else buffer += c      }      if (buffer !== "") tokenized.push(buffer);      return tokenized    };    p.append = function(array, element) {      array[array.length] = element;      return array    };    p.concat = function(array1, array2) {      return array1.concat(array2)    };    p.sort = function(array, numElem) {      var ret = [];      if (array.length > 0) {        var elemsToCopy = numElem > 0 ? numElem : array.length;        for (var i = 0; i < elemsToCopy; i++) ret.push(array[i]);        if (typeof array[0] === "string") ret.sort();        else ret.sort(function(a, b) {          return a - b        });        if (numElem > 0) for (var j = ret.length; j < array.length; j++) ret.push(array[j])      }      return ret    };    p.splice = function(array, value, index) {      if (value.length === 0) return array;      if (value instanceof Array) for (var i = 0, j = index; i < value.length; j++, i++) array.splice(j, 0, value[i]);      else array.splice(index, 0, value);      return array    };    p.subset = function(array, offset, length) {      var end = length !== undef ? offset + length : array.length;      return array.slice(offset, end)    };    p.join = function(array, seperator) {      return array.join(seperator)    };    p.shorten = function(ary) {      var newary = [];      var len = ary.length;      for (var i = 0; i < len; i++) newary[i] = ary[i];      newary.pop();      return newary    };    p.expand = function(ary, targetSize) {      var temp = ary.slice(0),        newSize = targetSize || ary.length * 2;      temp.length = newSize;      return temp    };    p.arrayCopy = function() {      var src, srcPos = 0,        dest, destPos = 0,        length;      if (arguments.length === 2) {        src = arguments[0];        dest = arguments[1];        length = src.length      } else if (arguments.length === 3) {        src = arguments[0];        dest = arguments[1];        length = arguments[2]      } else if (arguments.length === 5) {        src = arguments[0];        srcPos = arguments[1];        dest = arguments[2];        destPos = arguments[3];        length = arguments[4]      }      for (var i = srcPos, j = destPos; i < length + srcPos; i++, j++) if (dest[j] !== undef) dest[j] = src[i];      else throw "array index out of bounds exception";    };    p.reverse = function(array) {      return array.reverse()    };    p.mix = function(a, b, f) {      return a + ((b - a) * f >> 8)    };    p.peg = function(n) {      return n < 0 ? 0 : n > 255 ? 255 : n    };    p.modes = function() {      var ALPHA_MASK = 4278190080,        RED_MASK = 16711680,        GREEN_MASK = 65280,        BLUE_MASK = 255,        min = Math.min,        max = Math.max;      function applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb) {        var a = min(((c1 & 4278190080) >>> 24) + f, 255) << 24;        var r = ar + ((cr - ar) * f >> 8);        r = (r < 0 ? 0 : r > 255 ? 255 : r) << 16;        var g = ag + ((cg - ag) * f >> 8);        g = (g < 0 ? 0 : g > 255 ? 255 : g) << 8;        var b = ab + ((cb - ab) * f >> 8);        b = b < 0 ? 0 : b > 255 ? 255 : b;        return a | r | g | b      }      return {        replace: function(c1, c2) {          return c2        },        blend: function(c1, c2) {          var f = (c2 & ALPHA_MASK) >>> 24,            ar = c1 & RED_MASK,            ag = c1 & GREEN_MASK,            ab = c1 & BLUE_MASK,            br = c2 & RED_MASK,            bg = c2 & GREEN_MASK,            bb = c2 & BLUE_MASK;          return min(((c1 & ALPHA_MASK) >>> 24) + f, 255) << 24 | ar + ((br - ar) * f >> 8) & RED_MASK | ag + ((bg - ag) * f >> 8) & GREEN_MASK | ab + ((bb - ab) * f >> 8) & BLUE_MASK        },        add: function(c1, c2) {          var f = (c2 & ALPHA_MASK) >>> 24;          return min(((c1 & ALPHA_MASK) >>> 24) + f, 255) << 24 | min((c1 & RED_MASK) + ((c2 & RED_MASK) >> 8) * f, RED_MASK) & RED_MASK | min((c1 & GREEN_MASK) + ((c2 & GREEN_MASK) >> 8) * f, GREEN_MASK) & GREEN_MASK | min((c1 & BLUE_MASK) + ((c2 & BLUE_MASK) * f >> 8), BLUE_MASK)        },        subtract: function(c1, c2) {          var f = (c2 & ALPHA_MASK) >>> 24;          return min(((c1 & ALPHA_MASK) >>> 24) + f, 255) << 24 | max((c1 & RED_MASK) - ((c2 & RED_MASK) >> 8) * f, GREEN_MASK) & RED_MASK | max((c1 & GREEN_MASK) - ((c2 & GREEN_MASK) >> 8) * f, BLUE_MASK) & GREEN_MASK | max((c1 & BLUE_MASK) - ((c2 & BLUE_MASK) * f >> 8), 0)        },        lightest: function(c1, c2) {          var f = (c2 & ALPHA_MASK) >>> 24;          return min(((c1 & ALPHA_MASK) >>> 24) + f, 255) << 24 | max(c1 & RED_MASK, ((c2 & RED_MASK) >> 8) * f) & RED_MASK | max(c1 & GREEN_MASK, ((c2 & GREEN_MASK) >> 8) * f) & GREEN_MASK | max(c1 & BLUE_MASK, (c2 & BLUE_MASK) * f >> 8)        },        darkest: function(c1, c2) {          var f = (c2 & ALPHA_MASK) >>> 24,            ar = c1 & RED_MASK,            ag = c1 & GREEN_MASK,            ab = c1 & BLUE_MASK,            br = min(c1 & RED_MASK, ((c2 & RED_MASK) >> 8) * f),            bg = min(c1 & GREEN_MASK, ((c2 & GREEN_MASK) >> 8) * f),            bb = min(c1 & BLUE_MASK, (c2 & BLUE_MASK) * f >> 8);          return min(((c1 & ALPHA_MASK) >>> 24) + f, 255) << 24 | ar + ((br - ar) * f >> 8) & RED_MASK | ag + ((bg - ag) * f >> 8) & GREEN_MASK | ab + ((bb - ab) * f >> 8) & BLUE_MASK        },        difference: function(c1, c2) {          var f = (c2 & ALPHA_MASK) >>> 24,            ar = (c1 & RED_MASK) >> 16,            ag = (c1 & GREEN_MASK) >> 8,            ab = c1 & BLUE_MASK,            br = (c2 & RED_MASK) >> 16,            bg = (c2 & GREEN_MASK) >> 8,            bb = c2 & BLUE_MASK,            cr = ar > br ? ar - br : br - ar,          cg = ag > bg ? ag - bg : bg - ag,          cb = ab > bb ? ab - bb : bb - ab;          return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb)        },        exclusion: function(c1, c2) {          var f = (c2 & ALPHA_MASK) >>> 24,            ar = (c1 & RED_MASK) >> 16,            ag = (c1 & GREEN_MASK) >> 8,            ab = c1 & BLUE_MASK,            br = (c2 & RED_MASK) >> 16,            bg = (c2 & GREEN_MASK) >> 8,            bb = c2 & BLUE_MASK,            cr = ar + br - (ar * br >> 7),            cg = ag + bg - (ag * bg >> 7),            cb = ab + bb - (ab * bb >> 7);          return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb)        },        multiply: function(c1, c2) {          var f = (c2 & ALPHA_MASK) >>> 24,            ar = (c1 & RED_MASK) >> 16,            ag = (c1 & GREEN_MASK) >> 8,            ab = c1 & BLUE_MASK,            br = (c2 & RED_MASK) >> 16,            bg = (c2 & GREEN_MASK) >> 8,            bb = c2 & BLUE_MASK,            cr = ar * br >> 8,            cg = ag * bg >> 8,            cb = ab * bb >> 8;          return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb)        },        screen: function(c1, c2) {          var f = (c2 & ALPHA_MASK) >>> 24,            ar = (c1 & RED_MASK) >> 16,            ag = (c1 & GREEN_MASK) >> 8,            ab = c1 & BLUE_MASK,            br = (c2 & RED_MASK) >> 16,            bg = (c2 & GREEN_MASK) >> 8,            bb = c2 & BLUE_MASK,            cr = 255 - ((255 - ar) * (255 - br) >> 8),            cg = 255 - ((255 - ag) * (255 - bg) >> 8),            cb = 255 - ((255 - ab) * (255 - bb) >> 8);          return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb)        },        hard_light: function(c1, c2) {          var f = (c2 & ALPHA_MASK) >>> 24,            ar = (c1 & RED_MASK) >> 16,            ag = (c1 & GREEN_MASK) >> 8,            ab = c1 & BLUE_MASK,            br = (c2 & RED_MASK) >> 16,            bg = (c2 & GREEN_MASK) >> 8,            bb = c2 & BLUE_MASK,            cr = br < 128 ? ar * br >> 7 : 255 - ((255 - ar) * (255 - br) >> 7),          cg = bg < 128 ? ag * bg >> 7 : 255 - ((255 - ag) * (255 - bg) >> 7),          cb = bb < 128 ? ab * bb >> 7 : 255 - ((255 - ab) * (255 - bb) >> 7);          return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb)        },        soft_light: function(c1, c2) {          var f = (c2 & ALPHA_MASK) >>> 24,            ar = (c1 & RED_MASK) >> 16,            ag = (c1 & GREEN_MASK) >> 8,            ab = c1 & BLUE_MASK,            br = (c2 & RED_MASK) >> 16,            bg = (c2 & GREEN_MASK) >> 8,            bb = c2 & BLUE_MASK,            cr = (ar * br >> 7) + (ar * ar >> 8) - (ar * ar * br >> 15),            cg = (ag * bg >> 7) + (ag * ag >> 8) - (ag * ag * bg >> 15),            cb = (ab * bb >> 7) + (ab * ab >> 8) - (ab * ab * bb >> 15);          return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb)        },        overlay: function(c1, c2) {          var f = (c2 & ALPHA_MASK) >>> 24,            ar = (c1 & RED_MASK) >> 16,            ag = (c1 & GREEN_MASK) >> 8,            ab = c1 & BLUE_MASK,            br = (c2 & RED_MASK) >> 16,            bg = (c2 & GREEN_MASK) >> 8,            bb = c2 & BLUE_MASK,            cr = ar < 128 ? ar * br >> 7 : 255 - ((255 - ar) * (255 - br) >> 7),          cg = ag < 128 ? ag * bg >> 7 : 255 - ((255 - ag) * (255 - bg) >> 7),          cb = ab < 128 ? ab * bb >> 7 : 255 - ((255 - ab) * (255 - bb) >> 7);          return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb)        },        dodge: function(c1, c2) {          var f = (c2 & ALPHA_MASK) >>> 24,            ar = (c1 & RED_MASK) >> 16,            ag = (c1 & GREEN_MASK) >> 8,            ab = c1 & BLUE_MASK,            br = (c2 & RED_MASK) >> 16,            bg = (c2 & GREEN_MASK) >> 8,            bb = c2 & BLUE_MASK;          var cr = 255;          if (br !== 255) {            cr = (ar << 8) / (255 - br);            cr = cr < 0 ? 0 : cr > 255 ? 255 : cr          }          var cg = 255;          if (bg !== 255) {            cg = (ag << 8) / (255 - bg);            cg = cg < 0 ? 0 : cg > 255 ? 255 : cg          }          var cb = 255;          if (bb !== 255) {            cb = (ab << 8) / (255 - bb);            cb = cb < 0 ? 0 : cb > 255 ? 255 : cb          }          return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb)        },        burn: function(c1, c2) {          var f = (c2 & ALPHA_MASK) >>> 24,            ar = (c1 & RED_MASK) >> 16,            ag = (c1 & GREEN_MASK) >> 8,            ab = c1 & BLUE_MASK,            br = (c2 & RED_MASK) >> 16,            bg = (c2 & GREEN_MASK) >> 8,            bb = c2 & BLUE_MASK;          var cr = 0;          if (br !== 0) {            cr = (255 - ar << 8) / br;            cr = 255 - (cr < 0 ? 0 : cr > 255 ? 255 : cr)          }          var cg = 0;          if (bg !== 0) {            cg = (255 - ag << 8) / bg;            cg = 255 - (cg < 0 ? 0 : cg > 255 ? 255 : cg)          }          var cb = 0;          if (bb !== 0) {            cb = (255 - ab << 8) / bb;            cb = 255 - (cb < 0 ? 0 : cb > 255 ? 255 : cb)          }          return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb)        }      }    }();    function color$4(aValue1, aValue2, aValue3, aValue4) {      var r, g, b, a;      if (curColorMode === 3) {        var rgb = p.color.toRGB(aValue1, aValue2, aValue3);        r = rgb[0];        g = rgb[1];        b = rgb[2]      } else {        r = Math.round(255 * (aValue1 / colorModeX));        g = Math.round(255 * (aValue2 / colorModeY));        b = Math.round(255 * (aValue3 / colorModeZ))      }      a = Math.round(255 * (aValue4 / colorModeA));      r = r < 0 ? 0 : r;      g = g < 0 ? 0 : g;      b = b < 0 ? 0 : b;      a = a < 0 ? 0 : a;      r = r > 255 ? 255 : r;      g = g > 255 ? 255 : g;      b = b > 255 ? 255 : b;      a = a > 255 ? 255 : a;      return a << 24 & 4278190080 | r << 16 & 16711680 | g << 8 & 65280 | b & 255    }    function color$2(aValue1, aValue2) {      var a;      if (aValue1 & 4278190080) {        a = Math.round(255 * (aValue2 / colorModeA));        a = a > 255 ? 255 : a;        a = a < 0 ? 0 : a;        return aValue1 - (aValue1 & 4278190080) + (a << 24 & 4278190080)      }      if (curColorMode === 1) return color$4(aValue1, aValue1, aValue1, aValue2);      if (curColorMode === 3) return color$4(0, 0, aValue1 / colorModeX * colorModeZ, aValue2)    }    function color$1(aValue1) {      if (aValue1 <= colorModeX && aValue1 >= 0) {        if (curColorMode === 1) return color$4(aValue1, aValue1, aValue1, colorModeA);        if (curColorMode === 3) return color$4(0, 0, aValue1 / colorModeX * colorModeZ, colorModeA)      }      if (aValue1) {        if (aValue1 > 2147483647) aValue1 -= 4294967296;        return aValue1      }    }    p.color = function(aValue1, aValue2, aValue3, aValue4) {      if (aValue1 !== undef && aValue2 !== undef && aValue3 !== undef && aValue4 !== undef) return color$4(aValue1, aValue2, aValue3, aValue4);      if (aValue1 !== undef && aValue2 !== undef && aValue3 !== undef) return color$4(aValue1, aValue2, aValue3, colorModeA);      if (aValue1 !== undef && aValue2 !== undef) return color$2(aValue1, aValue2);      if (typeof aValue1 === "number") return color$1(aValue1);      return color$4(colorModeX, colorModeY, colorModeZ, colorModeA)    };    p.color.toString = function(colorInt) {      return "rgba(" + ((colorInt >> 16) & 255) + "," + ((colorInt >> 8) & 255) + "," + (colorInt & 255) + "," + ((colorInt >> 24) & 255) / 255 + ")"    };    p.color.toInt = function(r, g, b, a) {      return a << 24 & 4278190080 | r << 16 & 16711680 | g << 8 & 65280 | b & 255    };    p.color.toArray = function(colorInt) {      return [(colorInt >> 16) & 255, (colorInt >> 8) & 255, colorInt & 255, (colorInt >> 24) & 255]    };    p.color.toGLArray = function(colorInt) {      return [((colorInt & 16711680) >>> 16) / 255, ((colorInt >> 8) & 255) / 255, (colorInt & 255) / 255, ((colorInt >> 24) & 255) / 255]    };    p.color.toRGB = function(h, s, b) {      h = h > colorModeX ? colorModeX : h;      s = s > colorModeY ? colorModeY : s;      b = b > colorModeZ ? colorModeZ : b;      h = h / colorModeX * 360;      s = s / colorModeY * 100;      b = b / colorModeZ * 100;      var br = Math.round(b / 100 * 255);      if (s === 0) return [br, br, br];      var hue = h % 360;      var f = hue % 60;      var p = Math.round(b * (100 - s) / 1E4 * 255);      var q = Math.round(b * (6E3 - s * f) / 6E5 * 255);      var t = Math.round(b * (6E3 - s * (60 - f)) / 6E5 * 255);      switch (Math.floor(hue / 60)) {      case 0:        return [br, t, p];      case 1:        return [q, br, p];      case 2:        return [p, br, t];      case 3:        return [p, q, br];      case 4:        return [t, p, br];      case 5:        return [br, p, q]      }    };    function colorToHSB(colorInt) {      var red, green, blue;      red = ((colorInt >> 16) & 255) / 255;      green = ((colorInt >> 8) & 255) / 255;      blue = (colorInt & 255) / 255;      var max = p.max(p.max(red, green), blue),        min = p.min(p.min(red, green), blue),        hue, saturation;      if (min === max) return [0, 0, max * colorModeZ];      saturation = (max - min) / max;      if (red === max) hue = (green - blue) / (max - min);      else if (green === max) hue = 2 + (blue - red) / (max - min);      else hue = 4 + (red - green) / (max - min);      hue /= 6;      if (hue < 0) hue += 1;      else if (hue > 1) hue -= 1;      return [hue * colorModeX, saturation * colorModeY, max * colorModeZ]    }    p.brightness = function(colInt) {      return colorToHSB(colInt)[2]    };    p.saturation = function(colInt) {      return colorToHSB(colInt)[1]    };    p.hue = function(colInt) {      return colorToHSB(colInt)[0]    };    p.red = function(aColor) {      return ((aColor >> 16) & 255) / 255 * colorModeX    };    p.green = function(aColor) {      return ((aColor & 65280) >>> 8) / 255 * colorModeY    };    p.blue = function(aColor) {      return (aColor & 255) / 255 * colorModeZ    };    p.alpha = function(aColor) {      return ((aColor >> 24) & 255) / 255 * colorModeA    };    p.lerpColor = function(c1, c2, amt) {      var r, g, b, a, r1, g1, b1, a1, r2, g2, b2, a2;      var hsb1, hsb2, rgb, h, s;      var colorBits1 = p.color(c1);      var colorBits2 = p.color(c2);      if (curColorMode === 3) {        hsb1 = colorToHSB(colorBits1);        a1 = ((colorBits1 >> 24) & 255) / colorModeA;        hsb2 = colorToHSB(colorBits2);        a2 = ((colorBits2 & 4278190080) >>> 24) / colorModeA;        h = p.lerp(hsb1[0], hsb2[0], amt);        s = p.lerp(hsb1[1], hsb2[1], amt);        b = p.lerp(hsb1[2], hsb2[2], amt);        rgb = p.color.toRGB(h, s, b);        a = p.lerp(a1, a2, amt) * colorModeA;        return a << 24 & 4278190080 | (rgb[0] & 255) << 16 | (rgb[1] & 255) << 8 | rgb[2] & 255      }      r1 = (colorBits1 >> 16) & 255;      g1 = (colorBits1 >> 8) & 255;      b1 = colorBits1 & 255;      a1 = ((colorBits1 >> 24) & 255) / colorModeA;      r2 = (colorBits2 & 16711680) >>> 16;      g2 = (colorBits2 >> 8) & 255;      b2 = colorBits2 & 255;      a2 = ((colorBits2 >> 24) & 255) / colorModeA;      r = p.lerp(r1, r2, amt) | 0;      g = p.lerp(g1, g2, amt) | 0;      b = p.lerp(b1, b2, amt) | 0;      a = p.lerp(a1, a2, amt) * colorModeA;      return a << 24 & 4278190080 | r << 16 & 16711680 | g << 8 & 65280 | b & 255    };    p.colorMode = function() {      curColorMode = arguments[0];      if (arguments.length > 1) {        colorModeX = arguments[1];        colorModeY = arguments[2] || arguments[1];        colorModeZ = arguments[3] || arguments[1];        colorModeA = arguments[4] || arguments[1]      }    };    p.blendColor = function(c1, c2, mode) {      if (mode === 0) return p.modes.replace(c1, c2);      else if (mode === 1) return p.modes.blend(c1, c2);      else if (mode === 2) return p.modes.add(c1, c2);      else if (mode === 4) return p.modes.subtract(c1, c2);      else if (mode === 8) return p.modes.lightest(c1, c2);      else if (mode === 16) return p.modes.darkest(c1, c2);      else if (mode === 32) return p.modes.difference(c1, c2);      else if (mode === 64) return p.modes.exclusion(c1, c2);      else if (mode === 128) return p.modes.multiply(c1, c2);      else if (mode === 256) return p.modes.screen(c1, c2);      else if (mode === 1024) return p.modes.hard_light(c1, c2);      else if (mode === 2048) return p.modes.soft_light(c1, c2);      else if (mode === 512) return p.modes.overlay(c1, c2);      else if (mode === 4096) return p.modes.dodge(c1, c2);      else if (mode === 8192) return p.modes.burn(c1, c2)    };    function saveContext() {      curContext.save()    }    function restoreContext() {      curContext.restore();      isStrokeDirty = true;      isFillDirty = true    }    p.printMatrix = function() {      modelView.print()    };    Drawing2D.prototype.translate = function(x, y) {      modelView.translate(x, y);      modelViewInv.invTranslate(x, y);      curContext.translate(x, y)    };    Drawing3D.prototype.translate = function(x, y, z) {      modelView.translate(x, y, z);      modelViewInv.invTranslate(x, y, z)    };    Drawing2D.prototype.scale = function(x, y) {      modelView.scale(x, y);      modelViewInv.invScale(x, y);      curContext.scale(x, y || x)    };    Drawing3D.prototype.scale = function(x, y, z) {      modelView.scale(x, y, z);      modelViewInv.invScale(x, y, z)    };    Drawing2D.prototype.transform = function(pmatrix) {      var e = pmatrix.array();      curContext.transform(e[0], e[3], e[1], e[4], e[2], e[5])    };    Drawing3D.prototype.transformm = function(pmatrix3d) {      throw "p.transform is currently not supported in 3D mode";    };    Drawing2D.prototype.pushMatrix = function() {      userMatrixStack.load(modelView);      userReverseMatrixStack.load(modelViewInv);      saveContext()    };    Drawing3D.prototype.pushMatrix = function() {      userMatrixStack.load(modelView);      userReverseMatrixStack.load(modelViewInv)    };    Drawing2D.prototype.popMatrix = function() {      modelView.set(userMatrixStack.pop());      modelViewInv.set(userReverseMatrixStack.pop());      restoreContext()    };    Drawing3D.prototype.popMatrix = function() {      modelView.set(userMatrixStack.pop());      modelViewInv.set(userReverseMatrixStack.pop())    };    Drawing2D.prototype.resetMatrix = function() {      modelView.reset();      modelViewInv.reset();      curContext.setTransform(1, 0, 0, 1, 0, 0)    };    Drawing3D.prototype.resetMatrix = function() {      modelView.reset();      modelViewInv.reset()    };    DrawingShared.prototype.applyMatrix = function() {      var a = arguments;      modelView.apply(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15]);      modelViewInv.invApply(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15])    };    Drawing2D.prototype.applyMatrix = function() {      var a = arguments;      for (var cnt = a.length; cnt < 16; cnt++) a[cnt] = 0;      a[10] = a[15] = 1;      DrawingShared.prototype.applyMatrix.apply(this, a)    };    p.rotateX = function(angleInRadians) {      modelView.rotateX(angleInRadians);      modelViewInv.invRotateX(angleInRadians)    };    Drawing2D.prototype.rotateZ = function() {      throw "rotateZ() is not supported in 2D mode. Use rotate(float) instead.";    };    Drawing3D.prototype.rotateZ = function(angleInRadians) {      modelView.rotateZ(angleInRadians);      modelViewInv.invRotateZ(angleInRadians)    };    p.rotateY = function(angleInRadians) {      modelView.rotateY(angleInRadians);      modelViewInv.invRotateY(angleInRadians)    };    Drawing2D.prototype.rotate = function(angleInRadians) {      modelView.rotateZ(angleInRadians);      modelViewInv.invRotateZ(angleInRadians);      curContext.rotate(angleInRadians)    };    Drawing3D.prototype.rotate = function(angleInRadians) {      p.rotateZ(angleInRadians)    };    Drawing2D.prototype.shearX = function(angleInRadians) {      modelView.shearX(angleInRadians);      curContext.transform(1, 0, angleInRadians, 1, 0, 0)    };    Drawing3D.prototype.shearX = function(angleInRadians) {      modelView.shearX(angleInRadians)    };    Drawing2D.prototype.shearY = function(angleInRadians) {      modelView.shearY(angleInRadians);      curContext.transform(1, angleInRadians, 0, 1, 0, 0)    };    Drawing3D.prototype.shearY = function(angleInRadians) {      modelView.shearY(angleInRadians)    };    p.pushStyle = function() {      saveContext();      p.pushMatrix();      var newState = {        "doFill": doFill,        "currentFillColor": currentFillColor,        "doStroke": doStroke,        "currentStrokeColor": currentStrokeColor,        "curTint": curTint,        "curRectMode": curRectMode,        "curColorMode": curColorMode,        "colorModeX": colorModeX,        "colorModeZ": colorModeZ,        "colorModeY": colorModeY,        "colorModeA": colorModeA,        "curTextFont": curTextFont,        "horizontalTextAlignment": horizontalTextAlignment,        "verticalTextAlignment": verticalTextAlignment,        "textMode": textMode,        "curFontName": curFontName,        "curTextSize": curTextSize,        "curTextAscent": curTextAscent,        "curTextDescent": curTextDescent,        "curTextLeading": curTextLeading      };      styleArray.push(newState)    };    p.popStyle = function() {      var oldState = styleArray.pop();      if (oldState) {        restoreContext();        p.popMatrix();        doFill = oldState.doFill;        currentFillColor = oldState.currentFillColor;        doStroke = oldState.doStroke;        currentStrokeColor = oldState.currentStrokeColor;        curTint = oldState.curTint;        curRectMode = oldState.curRectMode;        curColorMode = oldState.curColorMode;        colorModeX = oldState.colorModeX;        colorModeZ = oldState.colorModeZ;        colorModeY = oldState.colorModeY;        colorModeA = oldState.colorModeA;        curTextFont = oldState.curTextFont;        curFontName = oldState.curFontName;        curTextSize = oldState.curTextSize;        horizontalTextAlignment = oldState.horizontalTextAlignment;        verticalTextAlignment = oldState.verticalTextAlignment;        textMode = oldState.textMode;        curTextAscent = oldState.curTextAscent;        curTextDescent = oldState.curTextDescent;        curTextLeading = oldState.curTextLeading      } else throw "Too many popStyle() without enough pushStyle()";    };    p.year = function() {      return (new Date).getFullYear()    };    p.month = function() {      return (new Date).getMonth() + 1    };    p.day = function() {      return (new Date).getDate()    };    p.hour = function() {      return (new Date).getHours()    };    p.minute = function() {      return (new Date).getMinutes()    };    p.second = function() {      return (new Date).getSeconds()    };    p.millis = function() {      return Date.now() - start    };    function redrawHelper() {      var sec = (Date.now() - timeSinceLastFPS) / 1E3;      framesSinceLastFPS++;      var fps = framesSinceLastFPS / sec;      if (sec > 0.5) {        timeSinceLastFPS = Date.now();        framesSinceLastFPS = 0;        p.__frameRate = fps      }      p.frameCount++    }    Drawing2D.prototype.redraw = function() {      redrawHelper();      curContext.lineWidth = lineWidth;      var pmouseXLastEvent = p.pmouseX,        pmouseYLastEvent = p.pmouseY;      p.pmouseX = pmouseXLastFrame;      p.pmouseY = pmouseYLastFrame;      saveContext();      p.draw();      restoreContext();      pmouseXLastFrame = p.mouseX;      pmouseYLastFrame = p.mouseY;      p.pmouseX = pmouseXLastEvent;      p.pmouseY = pmouseYLastEvent    };    Drawing3D.prototype.redraw = function() {      redrawHelper();      var pmouseXLastEvent = p.pmouseX,        pmouseYLastEvent = p.pmouseY;      p.pmouseX = pmouseXLastFrame;      p.pmouseY = pmouseYLastFrame;      curContext.clear(curContext.DEPTH_BUFFER_BIT);      curContextCache = {        attributes: {},        locations: {}      };      p.noLights();      p.lightFalloff(1, 0, 0);      p.shininess(1);      p.ambient(255, 255, 255);      p.specular(0, 0, 0);      p.emissive(0, 0, 0);      p.camera();      p.draw();      pmouseXLastFrame = p.mouseX;      pmouseYLastFrame = p.mouseY;      p.pmouseX = pmouseXLastEvent;      p.pmouseY = pmouseYLastEvent    };    p.noLoop = function() {      doLoop = false;      loopStarted = false;      clearInterval(looping);      curSketch.onPause()    };    p.loop = function() {      if (loopStarted) return;      timeSinceLastFPS = Date.now();      framesSinceLastFPS = 0;      looping = window.setInterval(function() {        try {          curSketch.onFrameStart();          p.redraw();          curSketch.onFrameEnd()        } catch(e_loop) {          window.clearInterval(looping);          throw e_loop;        }      },      curMsPerFrame);      doLoop = true;      loopStarted = true;      curSketch.onLoop()    };    p.frameRate = function(aRate) {      curFrameRate = aRate;      curMsPerFrame = 1E3 / curFrameRate;      if (doLoop) {        p.noLoop();        p.loop()      }    };    var eventHandlers = [];    function attachEventHandler(elem, type, fn) {      if (elem.addEventListener) elem.addEventListener(type, fn, false);      else elem.attachEvent("on" + type, fn);      eventHandlers.push({        elem: elem,        type: type,        fn: fn      })    }    function detachEventHandler(eventHandler) {      var elem = eventHandler.elem,        type = eventHandler.type,        fn = eventHandler.fn;      if (elem.removeEventListener) elem.removeEventListener(type, fn, false);      else if (elem.detachEvent) elem.detachEvent("on" + type, fn)    }    p.exit = function() {      window.clearInterval(looping);      removeInstance(p.externals.canvas.id);      delete curElement.onmousedown;      for (var lib in Processing.lib) if (Processing.lib.hasOwnProperty(lib)) if (Processing.lib[lib].hasOwnProperty("detach")) Processing.lib[lib].detach(p);      var i = eventHandlers.length;      while (i--) detachEventHandler(eventHandlers[i]);      curSketch.onExit()    };    p.cursor = function() {      if (arguments.length > 1 || arguments.length === 1 && arguments[0] instanceof p.PImage) {        var image = arguments[0],          x, y;        if (arguments.length >= 3) {          x = arguments[1];          y = arguments[2];          if (x < 0 || y < 0 || y >= image.height || x >= image.width) throw "x and y must be non-negative and less than the dimensions of the image";        } else {          x = image.width >>> 1;          y = image.height >>> 1        }        var imageDataURL = image.toDataURL();        var style = 'url("' + imageDataURL + '") ' + x + " " + y + ", default";        curCursor = curElement.style.cursor = style      } else if (arguments.length === 1) {        var mode = arguments[0];        curCursor = curElement.style.cursor = mode      } else curCursor = curElement.style.cursor = oldCursor    };    p.noCursor = function() {      curCursor = curElement.style.cursor = PConstants.NOCURSOR    };    p.link = function(href, target) {      if (target !== undef) window.open(href, target);      else window.location = href    };    p.beginDraw = nop;    p.endDraw = nop;    Drawing2D.prototype.toImageData = function(x, y, w, h) {      x = x !== undef ? x : 0;      y = y !== undef ? y : 0;      w = w !== undef ? w : p.width;      h = h !== undef ? h : p.height;      return curContext.getImageData(x, y, w, h)    };    Drawing3D.prototype.toImageData = function(x, y, w, h) {      x = x !== undef ? x : 0;      y = y !== undef ? y : 0;      w = w !== undef ? w : p.width;      h = h !== undef ? h : p.height;      var c = document.createElement("canvas"),        ctx = c.getContext("2d"),        obj = ctx.createImageData(w, h),        uBuff = new Uint8Array(w * h * 4);      curContext.readPixels(x, y, w, h, curContext.RGBA, curContext.UNSIGNED_BYTE, uBuff);      for (var i = 0, ul = uBuff.length, obj_data = obj.data; i < ul; i++) obj_data[i] = uBuff[(h - 1 - Math.floor(i / 4 / w)) * w * 4 + i % (w * 4)];      return obj    };    p.status = function(text) {      window.status = text    };    p.binary = function(num, numBits) {      var bit;      if (numBits > 0) bit = numBits;      else if (num instanceof Char) {        bit = 16;        num |= 0      } else {        bit = 32;        while (bit > 1 && !(num >>> bit - 1 & 1)) bit--      }      var result = "";      while (bit > 0) result += num >>> --bit & 1 ? "1" : "0";      return result    };    p.unbinary = function(binaryString) {      var i = binaryString.length - 1,        mask = 1,        result = 0;      while (i >= 0) {        var ch = binaryString[i--];        if (ch !== "0" && ch !== "1") throw "the value passed into unbinary was not an 8 bit binary number";        if (ch === "1") result += mask;        mask <<= 1      }      return result    };    function nfCoreScalar(value, plus, minus, leftDigits, rightDigits, group) {      var sign = value < 0 ? minus : plus;      var autoDetectDecimals = rightDigits === 0;      var rightDigitsOfDefault = rightDigits === undef || rightDigits < 0 ? 0 : rightDigits;      var absValue = Math.abs(value);      if (autoDetectDecimals) {        rightDigitsOfDefault = 1;        absValue *= 10;        while (Math.abs(Math.round(absValue) - absValue) > 1.0E-6 && rightDigitsOfDefault < 7) {          ++rightDigitsOfDefault;          absValue *= 10        }      } else if (rightDigitsOfDefault !== 0) absValue *= Math.pow(10, rightDigitsOfDefault);      var number, doubled = absValue * 2;      if (Math.floor(absValue) === absValue) number = absValue;      else if (Math.floor(doubled) === doubled) {        var floored = Math.floor(absValue);        number = floored + floored % 2      } else number = Math.round(absValue);      var buffer = "";      var totalDigits = leftDigits + rightDigitsOfDefault;      while (totalDigits > 0 || number > 0) {        totalDigits--;        buffer = "" + number % 10 + buffer;        number = Math.floor(number / 10)      }      if (group !== undef) {        var i = buffer.length - 3 - rightDigitsOfDefault;        while (i > 0) {          buffer = buffer.substring(0, i) + group + buffer.substring(i);          i -= 3        }      }      if (rightDigitsOfDefault > 0) return sign + buffer.substring(0, buffer.length - rightDigitsOfDefault) + "." + buffer.substring(buffer.length - rightDigitsOfDefault, buffer.length);      return sign + buffer    }    function nfCore(value, plus, minus, leftDigits, rightDigits, group) {      if (value instanceof Array) {        var arr = [];        for (var i = 0, len = value.length; i < len; i++) arr.push(nfCoreScalar(value[i], plus, minus, leftDigits, rightDigits, group));        return arr      }      return nfCoreScalar(value, plus, minus, leftDigits, rightDigits, group)    }    p.nf = function(value, leftDigits, rightDigits) {      return nfCore(value, "", "-", leftDigits, rightDigits)    };    p.nfs = function(value, leftDigits, rightDigits) {      return nfCore(value, " ", "-", leftDigits, rightDigits)    };    p.nfp = function(value, leftDigits, rightDigits) {      return nfCore(value, "+", "-", leftDigits, rightDigits)    };    p.nfc = function(value, leftDigits, rightDigits) {      return nfCore(value, "", "-", leftDigits, rightDigits, ",")    };    var decimalToHex = function(d, padding) {      padding = padding === undef || padding === null ? padding = 8 : padding;      if (d < 0) d = 4294967295 + d + 1;      var hex = Number(d).toString(16).toUpperCase();      while (hex.length < padding) hex = "0" + hex;      if (hex.length >= padding) hex = hex.substring(hex.length - padding, hex.length);      return hex    };    p.hex = function(value, len) {      if (arguments.length === 1) if (value instanceof Char) len = 4;      else len = 8;      return decimalToHex(value, len)    };    function unhexScalar(hex) {      var value = parseInt("0x" + hex, 16);      if (value > 2147483647) value -= 4294967296;      return value    }    p.unhex = function(hex) {      if (hex instanceof Array) {        var arr = [];        for (var i = 0; i < hex.length; i++) arr.push(unhexScalar(hex[i]));        return arr      }      return unhexScalar(hex)    };    p.loadStrings = function(filename) {      if (localStorage[filename]) return localStorage[filename].split("\n");      var filecontent = ajax(filename);      if (typeof filecontent !== "string" || filecontent === "") return [];      filecontent = filecontent.replace(/(\r\n?)/g, "\n").replace(/\n$/, "");      return filecontent.split("\n")    };    p.saveStrings = function(filename, strings) {      localStorage[filename] = strings.join("\n")    };    p.loadBytes = function(url) {      var string = ajax(url);      var ret = [];      for (var i = 0; i < string.length; i++) ret.push(string.charCodeAt(i));      return ret    };    function removeFirstArgument(args) {      return Array.prototype.slice.call(args, 1)    }    p.matchAll = function(aString, aRegExp) {      var results = [],        latest;      var regexp = new RegExp(aRegExp, "g");      while ((latest = regexp.exec(aString)) !== null) {        results.push(latest);        if (latest[0].length === 0)++regexp.lastIndex      }      return results.length > 0 ? results : null    };    p.__contains = function(subject, subStr) {      if (typeof subject !== "string") return subject.contains.apply(subject, removeFirstArgument(arguments));      return subject !== null && subStr !== null && typeof subStr === "string" && subject.indexOf(subStr) > -1    };    p.__replaceAll = function(subject, regex, replacement) {      if (typeof subject !== "string") return subject.replaceAll.apply(subject, removeFirstArgument(arguments));      return subject.replace(new RegExp(regex, "g"), replacement)    };    p.__replaceFirst = function(subject, regex, replacement) {      if (typeof subject !== "string") return subject.replaceFirst.apply(subject, removeFirstArgument(arguments));      return subject.replace(new RegExp(regex, ""), replacement)    };    p.__replace = function(subject, what, replacement) {      if (typeof subject !== "string") return subject.replace.apply(subject, removeFirstArgument(arguments));      if (what instanceof RegExp) return subject.replace(what, replacement);      if (typeof what !== "string") what = what.toString();      if (what === "") return subject;      var i = subject.indexOf(what);      if (i < 0) return subject;      var j = 0,        result = "";      do {        result += subject.substring(j, i) + replacement;        j = i + what.length      } while ((i = subject.indexOf(what, j)) >= 0);      return result + subject.substring(j)    };    p.__equals = function(subject, other) {      if (subject.equals instanceof      Function) return subject.equals.apply(subject, removeFirstArgument(arguments));      return subject.valueOf() === other.valueOf()    };    p.__equalsIgnoreCase = function(subject, other) {      if (typeof subject !== "string") return subject.equalsIgnoreCase.apply(subject, removeFirstArgument(arguments));      return subject.toLowerCase() === other.toLowerCase()    };    p.__toCharArray = function(subject) {      if (typeof subject !== "string") return subject.toCharArray.apply(subject, removeFirstArgument(arguments));      var chars = [];      for (var i = 0, len = subject.length; i < len; ++i) chars[i] = new Char(subject.charAt(i));      return chars    };    p.__split = function(subject, regex, limit) {      if (typeof subject !== "string") return subject.split.apply(subject, removeFirstArgument(arguments));      var pattern = new RegExp(regex);      if (limit === undef || limit < 1) return subject.split(pattern);      var result = [],        currSubject = subject,        pos;      while ((pos = currSubject.search(pattern)) !== -1 && result.length < limit - 1) {        var match = pattern.exec(currSubject).toString();        result.push(currSubject.substring(0, pos));        currSubject = currSubject.substring(pos + match.length)      }      if (pos !== -1 || currSubject !== "") result.push(currSubject);      return result    };    p.__codePointAt = function(subject, idx) {      var code = subject.charCodeAt(idx),        hi, low;      if (55296 <= code && code <= 56319) {        hi = code;        low = subject.charCodeAt(idx + 1);        return (hi - 55296) * 1024 + (low - 56320) + 65536      }      return code    };    p.match = function(str, regexp) {      return str.match(regexp)    };    p.__matches = function(str, regexp) {      return (new RegExp(regexp)).test(str)    };    p.__startsWith = function(subject, prefix, toffset) {      if (typeof subject !== "string") return subject.startsWith.apply(subject, removeFirstArgument(arguments));      toffset = toffset || 0;      if (toffset < 0 || toffset > subject.length) return false;      return prefix === "" || prefix === subject ? true : subject.indexOf(prefix) === toffset    };    p.__endsWith = function(subject, suffix) {      if (typeof subject !== "string") return subject.endsWith.apply(subject, removeFirstArgument(arguments));      var suffixLen = suffix ? suffix.length : 0;      return suffix === "" || suffix === subject ? true : subject.indexOf(suffix) === subject.length - suffixLen    };    p.__hashCode = function(subject) {      if (subject.hashCode instanceof      Function) return subject.hashCode.apply(subject, removeFirstArgument(arguments));      return virtHashCode(subject)    };    p.__printStackTrace = function(subject) {      p.println("Exception: " + subject.toString())    };    var logBuffer = [];    p.println = function(message) {      var bufferLen = logBuffer.length;      if (bufferLen) {        Processing.logger.log(logBuffer.join(""));        logBuffer.length = 0      }      if (arguments.length === 0 && bufferLen === 0) Processing.logger.log("");      else if (arguments.length !== 0) Processing.logger.log(message)    };    p.print = function(message) {      logBuffer.push(message)    };    p.str = function(val) {      if (val instanceof Array) {        var arr = [];        for (var i = 0; i < val.length; i++) arr.push(val[i].toString() + "");        return arr      }      return val.toString() + ""    };    p.trim = function(str) {      if (str instanceof Array) {        var arr = [];        for (var i = 0; i < str.length; i++) arr.push(str[i].replace(/^\s*/, "").replace(/\s*$/, "").replace(/\r*$/, ""));        return arr      }      return str.replace(/^\s*/, "").replace(/\s*$/, "").replace(/\r*$/, "")    };    function booleanScalar(val) {      if (typeof val === "number") return val !== 0;      if (typeof val === "boolean") return val;      if (typeof val === "string") return val.toLowerCase() === "true";      if (val instanceof Char) return val.code === 49 || val.code === 84 || val.code === 116    }    p.parseBoolean = function(val) {      if (val instanceof Array) {        var ret = [];        for (var i = 0; i < val.length; i++) ret.push(booleanScalar(val[i]));        return ret      }      return booleanScalar(val)    };    p.parseByte = function(what) {      if (what instanceof Array) {        var bytes = [];        for (var i = 0; i < what.length; i++) bytes.push(0 - (what[i] & 128) | what[i] & 127);        return bytes      }      return 0 - (what & 128) | what & 127    };    p.parseChar = function(key) {      if (typeof key === "number") return new Char(String.fromCharCode(key & 65535));      if (key instanceof Array) {        var ret = [];        for (var i = 0; i < key.length; i++) ret.push(new Char(String.fromCharCode(key[i] & 65535)));        return ret      }      throw "char() may receive only one argument of type int, byte, int[], or byte[].";    };    function floatScalar(val) {      if (typeof val === "number") return val;      if (typeof val === "boolean") return val ? 1 : 0;      if (typeof val === "string") return parseFloat(val);      if (val instanceof Char) return val.code    }    p.parseFloat = function(val) {      if (val instanceof      Array) {        var ret = [];        for (var i = 0; i < val.length; i++) ret.push(floatScalar(val[i]));        return ret      }      return floatScalar(val)    };    function intScalar(val, radix) {      if (typeof val === "number") return val & 4294967295;      if (typeof val === "boolean") return val ? 1 : 0;      if (typeof val === "string") {        var number = parseInt(val, radix || 10);        return number & 4294967295      }      if (val instanceof Char) return val.code    }    p.parseInt = function(val, radix) {      if (val instanceof Array) {        var ret = [];        for (var i = 0; i < val.length; i++) if (typeof val[i] === "string" && !/^\s*[+\-]?\d+\s*$/.test(val[i])) ret.push(0);        else ret.push(intScalar(val[i], radix));        return ret      }      return intScalar(val, radix)    };    p.__int_cast = function(val) {      return 0 | val    };    p.__instanceof = function(obj, type) {      if (typeof type !== "function") throw "Function is expected as type argument for instanceof operator";      if (typeof obj === "string") return type === Object || type === String;      if (obj instanceof type) return true;      if (typeof obj !== "object" || obj === null) return false;      var objType = obj.constructor;      if (type.$isInterface) {        var interfaces = [];        while (objType) {          if (objType.$interfaces) interfaces = interfaces.concat(objType.$interfaces);          objType = objType.$base        }        while (interfaces.length > 0) {          var i = interfaces.shift();          if (i === type) return true;          if (i.$interfaces) interfaces = interfaces.concat(i.$interfaces)        }        return false      }      while (objType.hasOwnProperty("$base")) {        objType = objType.$base;        if (objType === type) return true      }      return false    };    p.abs = Math.abs;    p.ceil = Math.ceil;    p.constrain = function(aNumber, aMin, aMax) {      return aNumber > aMax ? aMax : aNumber < aMin ? aMin : aNumber    };    p.dist = function() {      var dx, dy, dz;      if (arguments.length === 4) {        dx = arguments[0] - arguments[2];        dy = arguments[1] - arguments[3];        return Math.sqrt(dx * dx + dy * dy)      }      if (arguments.length === 6) {        dx = arguments[0] - arguments[3];        dy = arguments[1] - arguments[4];        dz = arguments[2] - arguments[5];        return Math.sqrt(dx * dx + dy * dy + dz * dz)      }    };    p.exp = Math.exp;    p.floor = Math.floor;    p.lerp = function(value1, value2, amt) {      return (value2 - value1) * amt + value1    };    p.log = Math.log;    p.mag = function(a, b, c) {      if (c) return Math.sqrt(a * a + b * b + c * c);      return Math.sqrt(a * a + b * b)    };    p.map = function(value, istart, istop, ostart, ostop) {      return ostart + (ostop - ostart) * ((value - istart) / (istop - istart))    };    p.max = function() {      if (arguments.length === 2) return arguments[0] < arguments[1] ? arguments[1] : arguments[0];      var numbers = arguments.length === 1 ? arguments[0] : arguments;      if (! ("length" in numbers && numbers.length > 0)) throw "Non-empty array is expected";      var max = numbers[0],        count = numbers.length;      for (var i = 1; i < count; ++i) if (max < numbers[i]) max = numbers[i];      return max    };    p.min = function() {      if (arguments.length === 2) return arguments[0] < arguments[1] ? arguments[0] : arguments[1];      var numbers = arguments.length === 1 ? arguments[0] : arguments;      if (! ("length" in numbers && numbers.length > 0)) throw "Non-empty array is expected";      var min = numbers[0],        count = numbers.length;      for (var i = 1; i < count; ++i) if (min > numbers[i]) min = numbers[i];      return min    };    p.norm = function(aNumber, low, high) {      return (aNumber - low) / (high - low)    };    p.pow = Math.pow;    p.round = Math.round;    p.sq = function(aNumber) {      return aNumber * aNumber    };    p.sqrt = Math.sqrt;    p.acos = Math.acos;    p.asin = Math.asin;    p.atan = Math.atan;    p.atan2 = Math.atan2;    p.cos = Math.cos;    p.degrees = function(aAngle) {      return aAngle * 180 / Math.PI    };    p.radians = function(aAngle) {      return aAngle / 180 * Math.PI    };    p.sin = Math.sin;    p.tan = Math.tan;    var currentRandom = Math.random;    p.random = function() {      if (arguments.length === 0) return currentRandom();      if (arguments.length === 1) return currentRandom() * arguments[0];      var aMin = arguments[0],        aMax = arguments[1];      return currentRandom() * (aMax - aMin) + aMin    };    function Marsaglia(i1, i2) {      var z = i1 || 362436069,        w = i2 || 521288629;      var nextInt = function() {        z = 36969 * (z & 65535) + (z >>> 16) & 4294967295;        w = 18E3 * (w & 65535) + (w >>> 16) & 4294967295;        return ((z & 65535) << 16 | w & 65535) & 4294967295      };      this.nextDouble = function() {        var i = nextInt() / 4294967296;        return i < 0 ? 1 + i : i      };      this.nextInt = nextInt    }    Marsaglia.createRandomized = function() {      var now = new Date;      return new Marsaglia(now / 6E4 & 4294967295, now & 4294967295)    };    p.randomSeed = function(seed) {      currentRandom = (new Marsaglia(seed)).nextDouble    };    p.Random = function(seed) {      var haveNextNextGaussian = false,        nextNextGaussian, random;      this.nextGaussian = function() {        if (haveNextNextGaussian) {          haveNextNextGaussian = false;          return nextNextGaussian        }        var v1, v2, s;        do {          v1 = 2 * random() - 1;          v2 = 2 * random() - 1;          s = v1 * v1 + v2 * v2        } while (s >= 1 || s === 0);        var multiplier = Math.sqrt(-2 * Math.log(s) / s);        nextNextGaussian = v2 * multiplier;        haveNextNextGaussian = true;        return v1 * multiplier      };      random = seed === undef ? Math.random : (new Marsaglia(seed)).nextDouble    };    function PerlinNoise(seed) {      var rnd = seed !== undef ? new Marsaglia(seed) : Marsaglia.createRandomized();      var i, j;      var perm = new Uint8Array(512);      for (i = 0; i < 256; ++i) perm[i] = i;      for (i = 0; i < 256; ++i) {        var t = perm[j = rnd.nextInt() & 255];        perm[j] = perm[i];        perm[i] = t      }      for (i = 0; i < 256; ++i) perm[i + 256] = perm[i];      function grad3d(i, x, y, z) {        var h = i & 15;        var u = h < 8 ? x : y,        v = h < 4 ? y : h === 12 || h === 14 ? x : z;        return ((h & 1) === 0 ? u : -u) + ((h & 2) === 0 ? v : -v)      }      function grad2d(i, x, y) {        var v = (i & 1) === 0 ? x : y;        return (i & 2) === 0 ? -v : v      }      function grad1d(i, x) {        return (i & 1) === 0 ? -x : x      }      function lerp(t, a, b) {        return a + t * (b - a)      }      this.noise3d = function(x, y, z) {        var X = Math.floor(x) & 255,          Y = Math.floor(y) & 255,          Z = Math.floor(z) & 255;        x -= Math.floor(x);        y -= Math.floor(y);        z -= Math.floor(z);        var fx = (3 - 2 * x) * x * x,          fy = (3 - 2 * y) * y * y,          fz = (3 - 2 * z) * z * z;        var p0 = perm[X] + Y,          p00 = perm[p0] + Z,          p01 = perm[p0 + 1] + Z,          p1 = perm[X + 1] + Y,          p10 = perm[p1] + Z,          p11 = perm[p1 + 1] + Z;        return lerp(fz, lerp(fy, lerp(fx, grad3d(perm[p00], x, y, z), grad3d(perm[p10], x - 1, y, z)), lerp(fx, grad3d(perm[p01], x, y - 1, z), grad3d(perm[p11], x - 1, y - 1, z))), lerp(fy, lerp(fx, grad3d(perm[p00 + 1], x, y, z - 1), grad3d(perm[p10 + 1], x - 1, y, z - 1)), lerp(fx, grad3d(perm[p01 + 1], x, y - 1, z - 1), grad3d(perm[p11 + 1], x - 1, y - 1, z - 1))))      };      this.noise2d = function(x, y) {        var X = Math.floor(x) & 255,          Y = Math.floor(y) & 255;        x -= Math.floor(x);        y -= Math.floor(y);        var fx = (3 - 2 * x) * x * x,          fy = (3 - 2 * y) * y * y;        var p0 = perm[X] + Y,          p1 = perm[X + 1] + Y;        return lerp(fy, lerp(fx, grad2d(perm[p0], x, y), grad2d(perm[p1], x - 1, y)), lerp(fx, grad2d(perm[p0 + 1], x, y - 1), grad2d(perm[p1 + 1], x - 1, y - 1)))      };      this.noise1d = function(x) {        var X = Math.floor(x) & 255;        x -= Math.floor(x);        var fx = (3 - 2 * x) * x * x;        return lerp(fx, grad1d(perm[X], x), grad1d(perm[X + 1], x - 1))      }    }    var noiseProfile = {      generator: undef,      octaves: 4,      fallout: 0.5,      seed: undef    };    p.noise = function(x, y, z) {      if (noiseProfile.generator === undef) noiseProfile.generator = new PerlinNoise(noiseProfile.seed);      var generator = noiseProfile.generator;      var effect = 1,        k = 1,        sum = 0;      for (var i = 0; i < noiseProfile.octaves; ++i) {        effect *= noiseProfile.fallout;        switch (arguments.length) {        case 1:          sum += effect * (1 + generator.noise1d(k * x)) / 2;          break;        case 2:          sum += effect * (1 + generator.noise2d(k * x, k * y)) / 2;          break;        case 3:          sum += effect * (1 + generator.noise3d(k * x, k * y, k * z)) / 2;          break        }        k *= 2      }      return sum    };    p.noiseDetail = function(octaves, fallout) {      noiseProfile.octaves = octaves;      if (fallout !== undef) noiseProfile.fallout = fallout    };    p.noiseSeed = function(seed) {      noiseProfile.seed = seed;      noiseProfile.generator = undef    };    DrawingShared.prototype.size = function(aWidth, aHeight, aMode) {      if (doStroke) p.stroke(0);      if (doFill) p.fill(255);      var savedProperties = {        fillStyle: curContext.fillStyle,        strokeStyle: curContext.strokeStyle,        lineCap: curContext.lineCap,        lineJoin: curContext.lineJoin      };      if (curElement.style.length > 0) {        curElement.style.removeProperty("width");        curElement.style.removeProperty("height")      }      curElement.width = p.width = aWidth || 100;      curElement.height = p.height = aHeight || 100;      for (var prop in savedProperties) if (savedProperties.hasOwnProperty(prop)) curContext[prop] = savedProperties[prop];      p.textFont(curTextFont);      p.background();      maxPixelsCached = Math.max(1E3, aWidth * aHeight * 0.05);      p.externals.context = curContext;      for (var i = 0; i < 720; i++) {        sinLUT[i] = p.sin(i * (Math.PI / 180) * 0.5);        cosLUT[i] = p.cos(i * (Math.PI / 180) * 0.5)      }    };    Drawing2D.prototype.size = function(aWidth, aHeight, aMode) {      if (curContext === undef) {        curContext = curElement.getContext("2d");        userMatrixStack = new PMatrixStack;        userReverseMatrixStack = new PMatrixStack;        modelView = new PMatrix2D;        modelViewInv = new PMatrix2D      }      DrawingShared.prototype.size.apply(this, arguments)    };    Drawing3D.prototype.size = function() {      var size3DCalled = false;      return function size(aWidth, aHeight, aMode) {        if (size3DCalled) throw "Multiple calls to size() for 3D renders are not allowed.";        size3DCalled = true;        function getGLContext(canvas) {          var ctxNames = ["experimental-webgl", "webgl", "webkit-3d"],            gl;          for (var i = 0, l = ctxNames.length; i < l; i++) {            gl = canvas.getContext(ctxNames[i], {              antialias: false,              preserveDrawingBuffer: true            });            if (gl) break          }          return gl        }        try {          curElement.width = p.width = aWidth || 100;          curElement.height = p.height = aHeight || 100;          curContext = getGLContext(curElement);          canTex = curContext.createTexture();          textTex = curContext.createTexture()        } catch(e_size) {          Processing.debug(e_size)        }        if (!curContext) throw "WebGL context is not supported on this browser.";        curContext.viewport(0, 0, curElement.width, curElement.height);        curContext.enable(curContext.DEPTH_TEST);        curContext.enable(curContext.BLEND);        curContext.blendFunc(curContext.SRC_ALPHA, curContext.ONE_MINUS_SRC_ALPHA);        programObject2D = createProgramObject(curContext, vertexShaderSrc2D, fragmentShaderSrc2D);        programObjectUnlitShape = createProgramObject(curContext, vertexShaderSrcUnlitShape, fragmentShaderSrcUnlitShape);        p.strokeWeight(1);        programObject3D = createProgramObject(curContext, vertexShaderSrc3D, fragmentShaderSrc3D);        curContext.useProgram(programObject3D);        uniformi("usingTexture3d", programObject3D, "usingTexture", usingTexture);        p.lightFalloff(1, 0, 0);        p.shininess(1);        p.ambient(255, 255, 255);        p.specular(0, 0, 0);        p.emissive(0, 0, 0);        boxBuffer = curContext.createBuffer();        curContext.bindBuffer(curContext.ARRAY_BUFFER, boxBuffer);        curContext.bufferData(curContext.ARRAY_BUFFER, boxVerts, curContext.STATIC_DRAW);        boxNormBuffer = curContext.createBuffer();        curContext.bindBuffer(curContext.ARRAY_BUFFER, boxNormBuffer);        curContext.bufferData(curContext.ARRAY_BUFFER, boxNorms, curContext.STATIC_DRAW);        boxOutlineBuffer = curContext.createBuffer();        curContext.bindBuffer(curContext.ARRAY_BUFFER, boxOutlineBuffer);        curContext.bufferData(curContext.ARRAY_BUFFER, boxOutlineVerts, curContext.STATIC_DRAW);        rectBuffer = curContext.createBuffer();        curContext.bindBuffer(curContext.ARRAY_BUFFER, rectBuffer);        curContext.bufferData(curContext.ARRAY_BUFFER, rectVerts, curContext.STATIC_DRAW);        rectNormBuffer = curContext.createBuffer();        curContext.bindBuffer(curContext.ARRAY_BUFFER, rectNormBuffer);        curContext.bufferData(curContext.ARRAY_BUFFER, rectNorms, curContext.STATIC_DRAW);        sphereBuffer = curContext.createBuffer();        lineBuffer = curContext.createBuffer();        fillBuffer = curContext.createBuffer();        fillColorBuffer = curContext.createBuffer();        strokeColorBuffer = curContext.createBuffer();        shapeTexVBO = curContext.createBuffer();        pointBuffer = curContext.createBuffer();        curContext.bindBuffer(curContext.ARRAY_BUFFER, pointBuffer);        curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array([0, 0, 0]), curContext.STATIC_DRAW);        textBuffer = curContext.createBuffer();        curContext.bindBuffer(curContext.ARRAY_BUFFER, textBuffer);        curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array([1, 1, 0, -1, 1, 0, -1, -1, 0, 1, -1, 0]), curContext.STATIC_DRAW);        textureBuffer = curContext.createBuffer();        curContext.bindBuffer(curContext.ARRAY_BUFFER, textureBuffer);        curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array([0, 0, 1, 0, 1, 1, 0, 1]), curContext.STATIC_DRAW);        indexBuffer = curContext.createBuffer();        curContext.bindBuffer(curContext.ELEMENT_ARRAY_BUFFER, indexBuffer);        curContext.bufferData(curContext.ELEMENT_ARRAY_BUFFER, new Uint16Array([0, 1, 2, 2, 3, 0]), curContext.STATIC_DRAW);        cam = new PMatrix3D;        cameraInv = new PMatrix3D;        modelView = new PMatrix3D;        modelViewInv = new PMatrix3D;        projection = new PMatrix3D;        p.camera();        p.perspective();        userMatrixStack = new PMatrixStack;        userReverseMatrixStack = new PMatrixStack;        curveBasisMatrix = new PMatrix3D;        curveToBezierMatrix = new PMatrix3D;        curveDrawMatrix = new PMatrix3D;        bezierDrawMatrix = new PMatrix3D;        bezierBasisInverse = new PMatrix3D;        bezierBasisMatrix = new PMatrix3D;        bezierBasisMatrix.set(-1, 3, -3, 1, 3, -6, 3, 0, -3, 3, 0, 0, 1, 0, 0, 0);        DrawingShared.prototype.size.apply(this, arguments)      }    }();    Drawing2D.prototype.ambientLight = DrawingShared.prototype.a3DOnlyFunction;    Drawing3D.prototype.ambientLight = function(r, g, b, x, y, z) {      if (lightCount === 8) throw "can only create " + 8 + " lights";      var pos = new PVector(x, y, z);      var view = new PMatrix3D;      view.scale(1, -1, 1);      view.apply(modelView.array());      view.mult(pos, pos);      var col = color$4(r, g, b, 0);      var normalizedCol = [((col >> 16) & 255) / 255, ((col >> 8) & 255) / 255, (col & 255) / 255];      curContext.useProgram(programObject3D);      uniformf("uLights.color.3d." + lightCount, programObject3D, "uLights" + lightCount + ".color", normalizedCol);      uniformf("uLights.position.3d." + lightCount, programObject3D, "uLights" + lightCount + ".position", pos.array());      uniformi("uLights.type.3d." + lightCount, programObject3D, "uLights" + lightCount + ".type", 0);      uniformi("uLightCount3d", programObject3D, "uLightCount", ++lightCount)    };    Drawing2D.prototype.directionalLight = DrawingShared.prototype.a3DOnlyFunction;    Drawing3D.prototype.directionalLight = function(r, g, b, nx, ny, nz) {      if (lightCount === 8) throw "can only create " + 8 + " lights";      curContext.useProgram(programObject3D);      var mvm = new PMatrix3D;      mvm.scale(1, -1, 1);      mvm.apply(modelView.array());      mvm = mvm.array();      var dir = [mvm[0] * nx + mvm[4] * ny + mvm[8] * nz, mvm[1] * nx + mvm[5] * ny + mvm[9] * nz, mvm[2] * nx + mvm[6] * ny + mvm[10] * nz];      var col = color$4(r, g, b, 0);      var normalizedCol = [((col >> 16) & 255) / 255, ((col >> 8) & 255) / 255, (col & 255) / 255];      uniformf("uLights.color.3d." + lightCount, programObject3D, "uLights" + lightCount + ".color", normalizedCol);      uniformf("uLights.position.3d." + lightCount, programObject3D, "uLights" + lightCount + ".position", dir);      uniformi("uLights.type.3d." + lightCount, programObject3D, "uLights" + lightCount + ".type", 1);      uniformi("uLightCount3d", programObject3D, "uLightCount", ++lightCount)    };    Drawing2D.prototype.lightFalloff = DrawingShared.prototype.a3DOnlyFunction;    Drawing3D.prototype.lightFalloff = function(constant, linear, quadratic) {      curContext.useProgram(programObject3D);      uniformf("uFalloff3d", programObject3D, "uFalloff", [constant, linear, quadratic])    };    Drawing2D.prototype.lightSpecular = DrawingShared.prototype.a3DOnlyFunction;    Drawing3D.prototype.lightSpecular = function(r, g, b) {      var col = color$4(r, g, b, 0);      var normalizedCol = [((col >> 16) & 255) / 255, ((col >> 8) & 255) / 255, (col & 255) / 255];      curContext.useProgram(programObject3D);      uniformf("uSpecular3d", programObject3D, "uSpecular", normalizedCol)    };    p.lights = function() {      p.ambientLight(128, 128, 128);      p.directionalLight(128, 128, 128, 0, 0, -1);      p.lightFalloff(1, 0, 0);      p.lightSpecular(0, 0, 0)    };    Drawing2D.prototype.pointLight = DrawingShared.prototype.a3DOnlyFunction;    Drawing3D.prototype.pointLight = function(r, g, b, x, y, z) {      if (lightCount === 8) throw "can only create " + 8 + " lights";      var pos = new PVector(x, y, z);      var view = new PMatrix3D;      view.scale(1, -1, 1);      view.apply(modelView.array());      view.mult(pos, pos);      var col = color$4(r, g, b, 0);      var normalizedCol = [((col >> 16) & 255) / 255, ((col >> 8) & 255) / 255, (col & 255) / 255];      curContext.useProgram(programObject3D);      uniformf("uLights.color.3d." + lightCount, programObject3D, "uLights" + lightCount + ".color", normalizedCol);      uniformf("uLights.position.3d." + lightCount, programObject3D, "uLights" + lightCount + ".position", pos.array());      uniformi("uLights.type.3d." + lightCount, programObject3D, "uLights" + lightCount + ".type", 2);      uniformi("uLightCount3d", programObject3D, "uLightCount", ++lightCount)    };    Drawing2D.prototype.noLights = DrawingShared.prototype.a3DOnlyFunction;    Drawing3D.prototype.noLights = function() {      lightCount = 0;      curContext.useProgram(programObject3D);      uniformi("uLightCount3d", programObject3D, "uLightCount", lightCount)    };    Drawing2D.prototype.spotLight = DrawingShared.prototype.a3DOnlyFunction;    Drawing3D.prototype.spotLight = function(r, g, b, x, y, z, nx, ny, nz, angle, concentration) {      if (lightCount === 8) throw "can only create " + 8 + " lights";      curContext.useProgram(programObject3D);      var pos = new PVector(x, y, z);      var mvm = new PMatrix3D;      mvm.scale(1, -1, 1);      mvm.apply(modelView.array());      mvm.mult(pos, pos);      mvm = mvm.array();      var dir = [mvm[0] * nx + mvm[4] * ny + mvm[8] * nz, mvm[1] *        nx + mvm[5] * ny + mvm[9] * nz, mvm[2] * nx + mvm[6] * ny + mvm[10] * nz];      var col = color$4(r, g, b, 0);      var normalizedCol = [((col >> 16) & 255) / 255, ((col >> 8) & 255) / 255, (col & 255) / 255];      uniformf("uLights.color.3d." + lightCount, programObject3D, "uLights" + lightCount + ".color", normalizedCol);      uniformf("uLights.position.3d." + lightCount, programObject3D, "uLights" + lightCount + ".position", pos.array());      uniformf("uLights.direction.3d." + lightCount, programObject3D, "uLights" + lightCount + ".direction", dir);      uniformf("uLights.concentration.3d." + lightCount, programObject3D, "uLights" + lightCount + ".concentration", concentration);      uniformf("uLights.angle.3d." + lightCount, programObject3D, "uLights" + lightCount + ".angle", angle);      uniformi("uLights.type.3d." + lightCount, programObject3D, "uLights" + lightCount + ".type", 3);      uniformi("uLightCount3d", programObject3D, "uLightCount", ++lightCount)    };    Drawing2D.prototype.beginCamera = function() {      throw "beginCamera() is not available in 2D mode";    };    Drawing3D.prototype.beginCamera = function() {      if (manipulatingCamera) throw "You cannot call beginCamera() again before calling endCamera()";      manipulatingCamera = true;      modelView = cameraInv;      modelViewInv = cam    };    Drawing2D.prototype.endCamera = function() {      throw "endCamera() is not available in 2D mode";    };    Drawing3D.prototype.endCamera = function() {      if (!manipulatingCamera) throw "You cannot call endCamera() before calling beginCamera()";      modelView.set(cam);      modelViewInv.set(cameraInv);      manipulatingCamera = false    };    p.camera = function(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ) {      if (eyeX === undef) {        cameraX = p.width / 2;        cameraY = p.height / 2;        cameraZ = cameraY / Math.tan(cameraFOV / 2);        eyeX = cameraX;        eyeY = cameraY;        eyeZ = cameraZ;        centerX = cameraX;        centerY = cameraY;        centerZ = 0;        upX = 0;        upY = 1;        upZ = 0      }      var z = new PVector(eyeX - centerX, eyeY - centerY, eyeZ - centerZ);      var y = new PVector(upX, upY, upZ);      z.normalize();      var x = PVector.cross(y, z);      y = PVector.cross(z, x);      x.normalize();      y.normalize();      var xX = x.x,        xY = x.y,        xZ = x.z;      var yX = y.x,        yY = y.y,        yZ = y.z;      var zX = z.x,        zY = z.y,        zZ = z.z;      cam.set(xX, xY, xZ, 0, yX, yY, yZ, 0, zX, zY, zZ, 0, 0, 0, 0, 1);      cam.translate(-eyeX, -eyeY, -eyeZ);      cameraInv.reset();      cameraInv.invApply(xX, xY, xZ, 0, yX, yY, yZ, 0, zX, zY, zZ, 0, 0, 0, 0, 1);      cameraInv.translate(eyeX, eyeY, eyeZ);      modelView.set(cam);      modelViewInv.set(cameraInv)    };    p.perspective = function(fov, aspect, near, far) {      if (arguments.length === 0) {        cameraY = curElement.height / 2;        cameraZ = cameraY / Math.tan(cameraFOV / 2);        cameraNear = cameraZ / 10;        cameraFar = cameraZ * 10;        cameraAspect = p.width / p.height;        fov = cameraFOV;        aspect = cameraAspect;        near = cameraNear;        far = cameraFar      }      var yMax, yMin, xMax, xMin;      yMax = near * Math.tan(fov / 2);      yMin = -yMax;      xMax = yMax * aspect;      xMin = yMin * aspect;      p.frustum(xMin, xMax, yMin, yMax, near, far)    };    Drawing2D.prototype.frustum = function() {      throw "Processing.js: frustum() is not supported in 2D mode";    };    Drawing3D.prototype.frustum = function(left, right, bottom, top, near, far) {      frustumMode = true;      projection = new PMatrix3D;      projection.set(2 * near / (right - left), 0, (right + left) / (right - left), 0, 0, 2 * near / (top - bottom), (top + bottom) / (top - bottom), 0, 0, 0, -(far + near) / (far - near), -(2 * far * near) / (far - near), 0, 0, -1, 0);      var proj = new PMatrix3D;      proj.set(projection);      proj.transpose();      curContext.useProgram(programObject2D);      uniformMatrix("projection2d", programObject2D, "uProjection", false, proj.array());      curContext.useProgram(programObject3D);      uniformMatrix("projection3d", programObject3D, "uProjection", false, proj.array());      curContext.useProgram(programObjectUnlitShape);      uniformMatrix("uProjectionUS", programObjectUnlitShape, "uProjection", false, proj.array())    };    p.ortho = function(left, right, bottom, top, near, far) {      if (arguments.length === 0) {        left = 0;        right = p.width;        bottom = 0;        top = p.height;        near = -10;        far = 10      }      var x = 2 / (right - left);      var y = 2 / (top - bottom);      var z = -2 / (far - near);      var tx = -(right + left) / (right - left);      var ty = -(top + bottom) / (top - bottom);      var tz = -(far + near) / (far - near);      projection = new PMatrix3D;      projection.set(x, 0, 0, tx, 0, y, 0, ty, 0, 0, z, tz, 0, 0, 0, 1);      var proj = new PMatrix3D;      proj.set(projection);      proj.transpose();      curContext.useProgram(programObject2D);      uniformMatrix("projection2d", programObject2D, "uProjection", false, proj.array());      curContext.useProgram(programObject3D);      uniformMatrix("projection3d", programObject3D, "uProjection", false, proj.array());      curContext.useProgram(programObjectUnlitShape);      uniformMatrix("uProjectionUS", programObjectUnlitShape, "uProjection", false, proj.array());      frustumMode = false    };    p.printProjection = function() {      projection.print()    };    p.printCamera = function() {      cam.print()    };    Drawing2D.prototype.box = DrawingShared.prototype.a3DOnlyFunction;    Drawing3D.prototype.box = function(w, h, d) {      if (!h || !d) h = d = w;      var model = new PMatrix3D;      model.scale(w, h, d);      var view = new PMatrix3D;      view.scale(1, -1, 1);      view.apply(modelView.array());      view.transpose();      if (doFill) {        curContext.useProgram(programObject3D);        uniformMatrix("model3d", programObject3D, "uModel", false, model.array());        uniformMatrix("view3d", programObject3D, "uView", false, view.array());        curContext.enable(curContext.POLYGON_OFFSET_FILL);        curContext.polygonOffset(1, 1);        uniformf("color3d", programObject3D, "uColor", fillStyle);        if (lightCount > 0) {          var v = new PMatrix3D;          v.set(view);          var m = new PMatrix3D;          m.set(model);          v.mult(m);          var normalMatrix = new PMatrix3D;          normalMatrix.set(v);          normalMatrix.invert();          normalMatrix.transpose();          uniformMatrix("uNormalTransform3d", programObject3D, "uNormalTransform", false, normalMatrix.array());          vertexAttribPointer("aNormal3d", programObject3D, "aNormal", 3, boxNormBuffer)        } else disableVertexAttribPointer("aNormal3d", programObject3D, "aNormal");        vertexAttribPointer("aVertex3d", programObject3D, "aVertex", 3, boxBuffer);        disableVertexAttribPointer("aColor3d", programObject3D, "aColor");        disableVertexAttribPointer("aTexture3d", programObject3D, "aTexture");        curContext.drawArrays(curContext.TRIANGLES, 0, boxVerts.length / 3);        curContext.disable(curContext.POLYGON_OFFSET_FILL)      }      if (lineWidth > 0 && doStroke) {        curContext.useProgram(programObject2D);        uniformMatrix("uModel2d", programObject2D, "uModel", false, model.array());        uniformMatrix("uView2d", programObject2D, "uView", false, view.array());        uniformf("uColor2d", programObject2D, "uColor", strokeStyle);        uniformi("uIsDrawingText2d", programObject2D, "uIsDrawingText", false);        vertexAttribPointer("vertex2d", programObject2D, "aVertex", 3, boxOutlineBuffer);        disableVertexAttribPointer("aTextureCoord2d", programObject2D, "aTextureCoord");        curContext.drawArrays(curContext.LINES, 0, boxOutlineVerts.length / 3)      }    };    var initSphere = function() {      var i;      sphereVerts = [];      for (i = 0; i < sphereDetailU; i++) {        sphereVerts.push(0);        sphereVerts.push(-1);        sphereVerts.push(0);        sphereVerts.push(sphereX[i]);        sphereVerts.push(sphereY[i]);        sphereVerts.push(sphereZ[i])      }      sphereVerts.push(0);      sphereVerts.push(-1);      sphereVerts.push(0);      sphereVerts.push(sphereX[0]);      sphereVerts.push(sphereY[0]);      sphereVerts.push(sphereZ[0]);      var v1, v11, v2;      var voff = 0;      for (i = 2; i < sphereDetailV; i++) {        v1 = v11 = voff;        voff += sphereDetailU;        v2 = voff;        for (var j = 0; j < sphereDetailU; j++) {          sphereVerts.push(sphereX[v1]);          sphereVerts.push(sphereY[v1]);          sphereVerts.push(sphereZ[v1++]);          sphereVerts.push(sphereX[v2]);          sphereVerts.push(sphereY[v2]);          sphereVerts.push(sphereZ[v2++])        }        v1 = v11;        v2 = voff;        sphereVerts.push(sphereX[v1]);        sphereVerts.push(sphereY[v1]);        sphereVerts.push(sphereZ[v1]);        sphereVerts.push(sphereX[v2]);        sphereVerts.push(sphereY[v2]);        sphereVerts.push(sphereZ[v2])      }      for (i = 0; i < sphereDetailU; i++) {        v2 = voff + i;        sphereVerts.push(sphereX[v2]);        sphereVerts.push(sphereY[v2]);        sphereVerts.push(sphereZ[v2]);        sphereVerts.push(0);        sphereVerts.push(1);        sphereVerts.push(0)      }      sphereVerts.push(sphereX[voff]);      sphereVerts.push(sphereY[voff]);      sphereVerts.push(sphereZ[voff]);      sphereVerts.push(0);      sphereVerts.push(1);      sphereVerts.push(0);      curContext.bindBuffer(curContext.ARRAY_BUFFER, sphereBuffer);      curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(sphereVerts), curContext.STATIC_DRAW)    };    p.sphereDetail = function(ures, vres) {      var i;      if (arguments.length === 1) ures = vres = arguments[0];      if (ures < 3) ures = 3;      if (vres < 2) vres = 2;      if (ures === sphereDetailU && vres === sphereDetailV) return;      var delta = 720 / ures;      var cx = new Float32Array(ures);      var cz = new Float32Array(ures);      for (i = 0; i < ures; i++) {        cx[i] = cosLUT[i * delta % 720 | 0];        cz[i] = sinLUT[i * delta % 720 | 0]      }      var vertCount = ures * (vres - 1) + 2;      var currVert = 0;      sphereX = new Float32Array(vertCount);      sphereY = new Float32Array(vertCount);      sphereZ = new Float32Array(vertCount);      var angle_step = 720 * 0.5 / vres;      var angle = angle_step;      for (i = 1; i < vres; i++) {        var curradius = sinLUT[angle % 720 | 0];        var currY = -cosLUT[angle % 720 | 0];        for (var j = 0; j < ures; j++) {          sphereX[currVert] = cx[j] * curradius;          sphereY[currVert] = currY;          sphereZ[currVert++] = cz[j] * curradius        }        angle += angle_step      }      sphereDetailU = ures;      sphereDetailV = vres;      initSphere()    };    Drawing2D.prototype.sphere = DrawingShared.prototype.a3DOnlyFunction;    Drawing3D.prototype.sphere = function() {      var sRad = arguments[0];      if (sphereDetailU < 3 || sphereDetailV < 2) p.sphereDetail(30);      var model = new PMatrix3D;      model.scale(sRad, sRad, sRad);      var view = new PMatrix3D;      view.scale(1, -1, 1);      view.apply(modelView.array());      view.transpose();      if (doFill) {        if (lightCount > 0) {          var v = new PMatrix3D;          v.set(view);          var m = new PMatrix3D;          m.set(model);          v.mult(m);          var normalMatrix = new PMatrix3D;          normalMatrix.set(v);          normalMatrix.invert();          normalMatrix.transpose();          uniformMatrix("uNormalTransform3d", programObject3D, "uNormalTransform", false, normalMatrix.array());          vertexAttribPointer("aNormal3d", programObject3D, "aNormal", 3, sphereBuffer)        } else disableVertexAttribPointer("aNormal3d", programObject3D, "aNormal");        curContext.useProgram(programObject3D);        disableVertexAttribPointer("aTexture3d", programObject3D, "aTexture");        uniformMatrix("uModel3d", programObject3D, "uModel", false, model.array());        uniformMatrix("uView3d", programObject3D, "uView", false, view.array());        vertexAttribPointer("aVertex3d", programObject3D, "aVertex", 3, sphereBuffer);        disableVertexAttribPointer("aColor3d", programObject3D, "aColor");        curContext.enable(curContext.POLYGON_OFFSET_FILL);        curContext.polygonOffset(1, 1);        uniformf("uColor3d", programObject3D, "uColor", fillStyle);        curContext.drawArrays(curContext.TRIANGLE_STRIP, 0, sphereVerts.length / 3);        curContext.disable(curContext.POLYGON_OFFSET_FILL)      }      if (lineWidth > 0 && doStroke) {        curContext.useProgram(programObject2D);        uniformMatrix("uModel2d", programObject2D, "uModel", false, model.array());        uniformMatrix("uView2d", programObject2D, "uView", false, view.array());        vertexAttribPointer("aVertex2d", programObject2D, "aVertex", 3, sphereBuffer);        disableVertexAttribPointer("aTextureCoord2d", programObject2D, "aTextureCoord");        uniformf("uColor2d", programObject2D, "uColor", strokeStyle);        uniformi("uIsDrawingText", programObject2D, "uIsDrawingText", false);        curContext.drawArrays(curContext.LINE_STRIP, 0, sphereVerts.length / 3)      }    };    p.modelX = function(x, y, z) {      var mv = modelView.array();      var ci = cameraInv.array();      var ax = mv[0] * x + mv[1] * y + mv[2] * z + mv[3];      var ay = mv[4] * x + mv[5] * y + mv[6] * z + mv[7];      var az = mv[8] * x + mv[9] * y + mv[10] * z + mv[11];      var aw = mv[12] * x + mv[13] * y + mv[14] * z + mv[15];      var ox = ci[0] * ax + ci[1] * ay + ci[2] * az + ci[3] * aw;      var ow = ci[12] * ax + ci[13] * ay + ci[14] * az + ci[15] * aw;      return ow !== 0 ? ox / ow : ox    };    p.modelY = function(x, y, z) {      var mv = modelView.array();      var ci = cameraInv.array();      var ax = mv[0] * x + mv[1] * y + mv[2] * z + mv[3];      var ay = mv[4] * x + mv[5] * y + mv[6] * z + mv[7];      var az = mv[8] * x + mv[9] * y + mv[10] * z + mv[11];      var aw = mv[12] * x + mv[13] * y + mv[14] * z + mv[15];      var oy = ci[4] * ax + ci[5] * ay + ci[6] * az + ci[7] * aw;      var ow = ci[12] * ax + ci[13] * ay + ci[14] * az + ci[15] * aw;      return ow !== 0 ? oy / ow : oy    };    p.modelZ = function(x, y, z) {      var mv = modelView.array();      var ci = cameraInv.array();      var ax = mv[0] * x + mv[1] * y + mv[2] * z + mv[3];      var ay = mv[4] * x + mv[5] * y + mv[6] * z + mv[7];      var az = mv[8] * x + mv[9] * y + mv[10] * z + mv[11];      var aw = mv[12] * x + mv[13] * y + mv[14] * z + mv[15];      var oz = ci[8] * ax + ci[9] * ay + ci[10] * az + ci[11] * aw;      var ow = ci[12] * ax + ci[13] * ay + ci[14] * az + ci[15] * aw;      return ow !== 0 ? oz / ow : oz    };    Drawing2D.prototype.ambient = DrawingShared.prototype.a3DOnlyFunction;    Drawing3D.prototype.ambient = function(v1, v2, v3) {      curContext.useProgram(programObject3D);      uniformi("uUsingMat3d", programObject3D, "uUsingMat", true);      var col = p.color(v1, v2, v3);      uniformf("uMaterialAmbient3d", programObject3D, "uMaterialAmbient", p.color.toGLArray(col).slice(0, 3))    };    Drawing2D.prototype.emissive = DrawingShared.prototype.a3DOnlyFunction;    Drawing3D.prototype.emissive = function(v1, v2, v3) {      curContext.useProgram(programObject3D);      uniformi("uUsingMat3d", programObject3D, "uUsingMat", true);      var col = p.color(v1, v2, v3);      uniformf("uMaterialEmissive3d", programObject3D, "uMaterialEmissive", p.color.toGLArray(col).slice(0, 3))    };    Drawing2D.prototype.shininess = DrawingShared.prototype.a3DOnlyFunction;    Drawing3D.prototype.shininess = function(shine) {      curContext.useProgram(programObject3D);      uniformi("uUsingMat3d", programObject3D, "uUsingMat", true);      uniformf("uShininess3d", programObject3D, "uShininess", shine)    };    Drawing2D.prototype.specular = DrawingShared.prototype.a3DOnlyFunction;    Drawing3D.prototype.specular = function(v1, v2, v3) {      curContext.useProgram(programObject3D);      uniformi("uUsingMat3d", programObject3D, "uUsingMat", true);      var col = p.color(v1, v2, v3);      uniformf("uMaterialSpecular3d", programObject3D, "uMaterialSpecular", p.color.toGLArray(col).slice(0, 3))    };    p.screenX = function(x, y, z) {      var mv = modelView.array();      if (mv.length === 16) {        var ax = mv[0] * x + mv[1] * y + mv[2] * z + mv[3];        var ay = mv[4] * x + mv[5] * y + mv[6] * z + mv[7];        var az = mv[8] * x + mv[9] * y + mv[10] * z + mv[11];        var aw = mv[12] * x + mv[13] * y + mv[14] * z + mv[15];        var pj = projection.array();        var ox = pj[0] * ax + pj[1] * ay + pj[2] * az + pj[3] * aw;        var ow = pj[12] * ax + pj[13] * ay + pj[14] * az + pj[15] * aw;        if (ow !== 0) ox /= ow;        return p.width * (1 + ox) / 2      }      return modelView.multX(x, y)    };    p.screenY = function screenY(x, y, z) {      var mv = modelView.array();      if (mv.length === 16) {        var ax = mv[0] * x + mv[1] * y + mv[2] * z + mv[3];        var ay = mv[4] * x + mv[5] * y + mv[6] * z + mv[7];        var az = mv[8] * x + mv[9] * y + mv[10] * z + mv[11];        var aw = mv[12] * x + mv[13] * y + mv[14] * z + mv[15];        var pj = projection.array();        var oy = pj[4] * ax + pj[5] * ay + pj[6] * az + pj[7] * aw;        var ow = pj[12] * ax + pj[13] * ay + pj[14] * az + pj[15] * aw;        if (ow !== 0) oy /= ow;        return p.height * (1 + oy) / 2      }      return modelView.multY(x, y)    };    p.screenZ = function screenZ(x, y, z) {      var mv = modelView.array();      if (mv.length !== 16) return 0;      var pj = projection.array();      var ax = mv[0] * x + mv[1] * y + mv[2] * z + mv[3];      var ay = mv[4] * x + mv[5] * y + mv[6] * z + mv[7];      var az = mv[8] * x + mv[9] * y + mv[10] * z + mv[11];      var aw = mv[12] * x + mv[13] * y + mv[14] * z + mv[15];      var oz = pj[8] * ax + pj[9] * ay + pj[10] * az + pj[11] * aw;      var ow = pj[12] * ax + pj[13] * ay + pj[14] * az + pj[15] * aw;      if (ow !== 0) oz /= ow;      return (oz + 1) / 2    };    DrawingShared.prototype.fill = function() {      var color = p.color(arguments[0], arguments[1], arguments[2], arguments[3]);      if (color === currentFillColor && doFill) return;      doFill = true;      currentFillColor = color    };    Drawing2D.prototype.fill = function() {      DrawingShared.prototype.fill.apply(this, arguments);      isFillDirty = true    };    Drawing3D.prototype.fill = function() {      DrawingShared.prototype.fill.apply(this, arguments);      fillStyle = p.color.toGLArray(currentFillColor)    };    function executeContextFill() {      if (doFill) {        if (isFillDirty) {          curContext.fillStyle = p.color.toString(currentFillColor);          isFillDirty = false        }        curContext.fill()      }    }    p.noFill = function() {      doFill = false    };    DrawingShared.prototype.stroke = function() {      var color = p.color(arguments[0], arguments[1], arguments[2], arguments[3]);      if (color === currentStrokeColor && doStroke) return;      doStroke = true;      currentStrokeColor = color    };    Drawing2D.prototype.stroke = function() {      DrawingShared.prototype.stroke.apply(this, arguments);      isStrokeDirty = true    };    Drawing3D.prototype.stroke = function() {      DrawingShared.prototype.stroke.apply(this, arguments);      strokeStyle = p.color.toGLArray(currentStrokeColor)    };    function executeContextStroke() {      if (doStroke) {        if (isStrokeDirty) {          curContext.strokeStyle = p.color.toString(currentStrokeColor);          isStrokeDirty = false        }        curContext.stroke()      }    }    p.noStroke = function() {      doStroke = false    };    DrawingShared.prototype.strokeWeight = function(w) {      lineWidth = w    };    Drawing2D.prototype.strokeWeight = function(w) {      DrawingShared.prototype.strokeWeight.apply(this, arguments);      curContext.lineWidth = w    };    Drawing3D.prototype.strokeWeight = function(w) {      DrawingShared.prototype.strokeWeight.apply(this, arguments);      curContext.useProgram(programObject2D);      uniformf("pointSize2d", programObject2D, "uPointSize", w);      curContext.useProgram(programObjectUnlitShape);      uniformf("pointSizeUnlitShape", programObjectUnlitShape, "uPointSize", w);      curContext.lineWidth(w)    };    p.strokeCap = function(value) {      drawing.$ensureContext().lineCap = value    };    p.strokeJoin = function(value) {      drawing.$ensureContext().lineJoin = value    };    Drawing2D.prototype.smooth = function() {      renderSmooth = true;      var style = curElement.style;      style.setProperty("image-rendering", "optimizeQuality", "important");      style.setProperty("-ms-interpolation-mode", "bicubic", "important");      if (curContext.hasOwnProperty("mozImageSmoothingEnabled")) curContext.mozImageSmoothingEnabled = true    };    Drawing3D.prototype.smooth = function() {      renderSmooth = true    };    Drawing2D.prototype.noSmooth = function() {      renderSmooth = false;      var style = curElement.style;      style.setProperty("image-rendering", "optimizeSpeed", "important");      style.setProperty("image-rendering", "-moz-crisp-edges", "important");      style.setProperty("image-rendering", "-webkit-optimize-contrast", "important");      style.setProperty("image-rendering", "optimize-contrast", "important");      style.setProperty("-ms-interpolation-mode", "nearest-neighbor", "important");      if (curContext.hasOwnProperty("mozImageSmoothingEnabled")) curContext.mozImageSmoothingEnabled = false    };    Drawing3D.prototype.noSmooth = function() {      renderSmooth = false    };    Drawing2D.prototype.point = function(x, y) {      if (!doStroke) return;      x = Math.round(x);      y = Math.round(y);      curContext.fillStyle = p.color.toString(currentStrokeColor);      isFillDirty = true;      if (lineWidth > 1) {        curContext.beginPath();        curContext.arc(x, y, lineWidth / 2, 0, 6.283185307179586, false);        curContext.fill()      } else curContext.fillRect(x, y, 1, 1)    };    Drawing3D.prototype.point = function(x, y, z) {      var model = new PMatrix3D;      model.translate(x, y, z || 0);      model.transpose();      var view = new PMatrix3D;      view.scale(1, -1, 1);      view.apply(modelView.array());      view.transpose();      curContext.useProgram(programObject2D);      uniformMatrix("uModel2d", programObject2D, "uModel", false, model.array());      uniformMatrix("uView2d", programObject2D, "uView", false, view.array());      if (lineWidth > 0 && doStroke) {        uniformf("uColor2d", programObject2D, "uColor", strokeStyle);        uniformi("uIsDrawingText2d", programObject2D, "uIsDrawingText", false);        uniformi("uSmooth2d", programObject2D, "uSmooth", renderSmooth);        vertexAttribPointer("aVertex2d", programObject2D, "aVertex", 3, pointBuffer);        disableVertexAttribPointer("aTextureCoord2d", programObject2D, "aTextureCoord");        curContext.drawArrays(curContext.POINTS, 0, 1)      }    };    p.beginShape = function(type) {      curShape = type;      curvePoints = [];      vertArray = []    };    Drawing2D.prototype.vertex = function(x, y, moveTo) {      var vert = [];      if (firstVert) firstVert = false;      vert["isVert"] = true;      vert[0] = x;      vert[1] = y;      vert[2] = 0;      vert[3] = 0;      vert[4] = 0;      vert[5] = currentFillColor;      vert[6] = currentStrokeColor;      vertArray.push(vert);      if (moveTo) vertArray[vertArray.length - 1]["moveTo"] = moveTo    };    Drawing3D.prototype.vertex = function(x, y, z, u, v) {      var vert = [];      if (firstVert) firstVert = false;      vert["isVert"] = true;      if (v === undef && usingTexture) {        v = u;        u = z;        z = 0      }      if (u !== undef && v !== undef) {        if (curTextureMode === 2) {          u /= curTexture.width;          v /= curTexture.height        }        u = u > 1 ? 1 : u;        u = u < 0 ? 0 : u;        v = v > 1 ? 1 : v;        v = v < 0 ? 0 : v      }      vert[0] = x;      vert[1] = y;      vert[2] = z || 0;      vert[3] = u || 0;      vert[4] = v || 0;      vert[5] = fillStyle[0];      vert[6] = fillStyle[1];      vert[7] = fillStyle[2];      vert[8] = fillStyle[3];      vert[9] = strokeStyle[0];      vert[10] = strokeStyle[1];      vert[11] = strokeStyle[2];      vert[12] = strokeStyle[3];      vert[13] = normalX;      vert[14] = normalY;      vert[15] = normalZ;      vertArray.push(vert)    };    var point3D = function(vArray, cArray) {      var view = new PMatrix3D;      view.scale(1, -1, 1);      view.apply(modelView.array());      view.transpose();      curContext.useProgram(programObjectUnlitShape);      uniformMatrix("uViewUS", programObjectUnlitShape, "uView", false, view.array());      uniformi("uSmoothUS", programObjectUnlitShape, "uSmooth", renderSmooth);      vertexAttribPointer("aVertexUS", programObjectUnlitShape, "aVertex", 3, pointBuffer);      curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(vArray), curContext.STREAM_DRAW);      vertexAttribPointer("aColorUS", programObjectUnlitShape, "aColor", 4, fillColorBuffer);      curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(cArray), curContext.STREAM_DRAW);      curContext.drawArrays(curContext.POINTS, 0, vArray.length / 3)    };    var line3D = function(vArray, mode, cArray) {      var ctxMode;      if (mode === "LINES") ctxMode = curContext.LINES;      else if (mode === "LINE_LOOP") ctxMode = curContext.LINE_LOOP;      else ctxMode = curContext.LINE_STRIP;      var view = new PMatrix3D;      view.scale(1, -1, 1);      view.apply(modelView.array());      view.transpose();      curContext.useProgram(programObjectUnlitShape);      uniformMatrix("uViewUS", programObjectUnlitShape, "uView", false, view.array());      vertexAttribPointer("aVertexUS", programObjectUnlitShape, "aVertex", 3, lineBuffer);      curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(vArray), curContext.STREAM_DRAW);      vertexAttribPointer("aColorUS", programObjectUnlitShape, "aColor", 4, strokeColorBuffer);      curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(cArray), curContext.STREAM_DRAW);      curContext.drawArrays(ctxMode, 0, vArray.length / 3)    };    var fill3D = function(vArray, mode, cArray, tArray) {      var ctxMode;      if (mode === "TRIANGLES") ctxMode = curContext.TRIANGLES;      else if (mode === "TRIANGLE_FAN") ctxMode = curContext.TRIANGLE_FAN;      else ctxMode = curContext.TRIANGLE_STRIP;      var view = new PMatrix3D;      view.scale(1, -1, 1);      view.apply(modelView.array());      view.transpose();      curContext.useProgram(programObject3D);      uniformMatrix("model3d", programObject3D, "uModel", false, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);      uniformMatrix("view3d", programObject3D, "uView", false, view.array());      curContext.enable(curContext.POLYGON_OFFSET_FILL);      curContext.polygonOffset(1, 1);      uniformf("color3d", programObject3D, "uColor", [-1, 0, 0, 0]);      vertexAttribPointer("vertex3d", programObject3D, "aVertex", 3, fillBuffer);      curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(vArray), curContext.STREAM_DRAW);      if (usingTexture && curTint !== null) curTint3d(cArray);      vertexAttribPointer("aColor3d", programObject3D, "aColor", 4, fillColorBuffer);      curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(cArray), curContext.STREAM_DRAW);      disableVertexAttribPointer("aNormal3d", programObject3D, "aNormal");      if (usingTexture) {        uniformi("uUsingTexture3d", programObject3D, "uUsingTexture", usingTexture);        vertexAttribPointer("aTexture3d", programObject3D, "aTexture", 2, shapeTexVBO);        curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(tArray), curContext.STREAM_DRAW)      }      curContext.drawArrays(ctxMode, 0, vArray.length / 3);      curContext.disable(curContext.POLYGON_OFFSET_FILL)    };    function fillStrokeClose() {      executeContextFill();      executeContextStroke();      curContext.closePath()    }    Drawing2D.prototype.endShape = function(mode) {      if (vertArray.length === 0) return;      var closeShape = mode === 2;      if (closeShape) vertArray.push(vertArray[0]);      var lineVertArray = [];      var fillVertArray = [];      var colorVertArray = [];      var strokeVertArray = [];      var texVertArray = [];      var cachedVertArray;      firstVert = true;      var i, j, k;      var vertArrayLength = vertArray.length;      for (i = 0; i < vertArrayLength; i++) {        cachedVertArray = vertArray[i];        for (j = 0; j < 3; j++) fillVertArray.push(cachedVertArray[j])      }      for (i = 0; i < vertArrayLength; i++) {        cachedVertArray = vertArray[i];        for (j = 5; j < 9; j++) colorVertArray.push(cachedVertArray[j])      }      for (i = 0; i < vertArrayLength; i++) {        cachedVertArray = vertArray[i];        for (j = 9; j < 13; j++) strokeVertArray.push(cachedVertArray[j])      }      for (i = 0; i < vertArrayLength; i++) {        cachedVertArray = vertArray[i];        texVertArray.push(cachedVertArray[3]);        texVertArray.push(cachedVertArray[4])      }      if (isCurve && (curShape === 20 || curShape === undef)) {        if (vertArrayLength > 3) {          var b = [],            s = 1 - curTightness;          curContext.beginPath();          curContext.moveTo(vertArray[1][0], vertArray[1][1]);          for (i = 1; i + 2 < vertArrayLength; i++) {            cachedVertArray = vertArray[i];            b[0] = [cachedVertArray[0], cachedVertArray[1]];            b[1] = [cachedVertArray[0] + (s * vertArray[i + 1][0] - s * vertArray[i - 1][0]) / 6, cachedVertArray[1] + (s * vertArray[i + 1][1] - s * vertArray[i - 1][1]) / 6];            b[2] = [vertArray[i + 1][0] + (s * vertArray[i][0] - s * vertArray[i + 2][0]) / 6, vertArray[i + 1][1] + (s * vertArray[i][1] - s * vertArray[i + 2][1]) / 6];            b[3] = [vertArray[i + 1][0], vertArray[i + 1][1]];            curContext.bezierCurveTo(b[1][0], b[1][1], b[2][0], b[2][1], b[3][0], b[3][1])          }          fillStrokeClose()        }      } else if (isBezier && (curShape === 20 || curShape === undef)) {        curContext.beginPath();        for (i = 0; i < vertArrayLength; i++) {          cachedVertArray = vertArray[i];          if (vertArray[i]["isVert"]) if (vertArray[i]["moveTo"]) curContext.moveTo(cachedVertArray[0], cachedVertArray[1]);          else curContext.lineTo(cachedVertArray[0], cachedVertArray[1]);          else curContext.bezierCurveTo(vertArray[i][0], vertArray[i][1], vertArray[i][2], vertArray[i][3], vertArray[i][4], vertArray[i][5])        }        fillStrokeClose()      } else if (curShape === 2) for (i = 0; i < vertArrayLength; i++) {        cachedVertArray = vertArray[i];        if (doStroke) p.stroke(cachedVertArray[6]);        p.point(cachedVertArray[0], cachedVertArray[1])      } else if (curShape === 4) for (i = 0; i + 1 < vertArrayLength; i += 2) {        cachedVertArray = vertArray[i];        if (doStroke) p.stroke(vertArray[i + 1][6]);        p.line(cachedVertArray[0], cachedVertArray[1], vertArray[i + 1][0], vertArray[i + 1][1])      } else if (curShape === 9) for (i = 0; i + 2 < vertArrayLength; i += 3) {        cachedVertArray = vertArray[i];        curContext.beginPath();        curContext.moveTo(cachedVertArray[0], cachedVertArray[1]);        curContext.lineTo(vertArray[i + 1][0], vertArray[i + 1][1]);        curContext.lineTo(vertArray[i + 2][0], vertArray[i + 2][1]);        curContext.lineTo(cachedVertArray[0], cachedVertArray[1]);        if (doFill) {          p.fill(vertArray[i + 2][5]);          executeContextFill()        }        if (doStroke) {          p.stroke(vertArray[i + 2][6]);          executeContextStroke()        }        curContext.closePath()      } else if (curShape === 10) for (i = 0; i + 1 < vertArrayLength; i++) {        cachedVertArray = vertArray[i];        curContext.beginPath();        curContext.moveTo(vertArray[i + 1][0], vertArray[i + 1][1]);        curContext.lineTo(cachedVertArray[0], cachedVertArray[1]);        if (doStroke) p.stroke(vertArray[i + 1][6]);        if (doFill) p.fill(vertArray[i + 1][5]);        if (i + 2 < vertArrayLength) {          curContext.lineTo(vertArray[i + 2][0], vertArray[i + 2][1]);          if (doStroke) p.stroke(vertArray[i + 2][6]);          if (doFill) p.fill(vertArray[i + 2][5])        }        fillStrokeClose()      } else if (curShape === 11) {        if (vertArrayLength > 2) {          curContext.beginPath();          curContext.moveTo(vertArray[0][0], vertArray[0][1]);          curContext.lineTo(vertArray[1][0], vertArray[1][1]);          curContext.lineTo(vertArray[2][0], vertArray[2][1]);          if (doFill) {            p.fill(vertArray[2][5]);            executeContextFill()          }          if (doStroke) {            p.stroke(vertArray[2][6]);            executeContextStroke()          }          curContext.closePath();          for (i = 3; i < vertArrayLength; i++) {            cachedVertArray = vertArray[i];            curContext.beginPath();            curContext.moveTo(vertArray[0][0], vertArray[0][1]);            curContext.lineTo(vertArray[i - 1][0], vertArray[i - 1][1]);            curContext.lineTo(cachedVertArray[0], cachedVertArray[1]);            if (doFill) {              p.fill(cachedVertArray[5]);              executeContextFill()            }            if (doStroke) {              p.stroke(cachedVertArray[6]);              executeContextStroke()            }            curContext.closePath()          }        }      } else if (curShape === 16) for (i = 0; i + 3 < vertArrayLength; i += 4) {        cachedVertArray = vertArray[i];        curContext.beginPath();        curContext.moveTo(cachedVertArray[0], cachedVertArray[1]);        for (j = 1; j < 4; j++) curContext.lineTo(vertArray[i + j][0], vertArray[i + j][1]);        curContext.lineTo(cachedVertArray[0], cachedVertArray[1]);        if (doFill) {          p.fill(vertArray[i + 3][5]);          executeContextFill()        }        if (doStroke) {          p.stroke(vertArray[i + 3][6]);          executeContextStroke()        }        curContext.closePath()      } else if (curShape === 17) {        if (vertArrayLength > 3) for (i = 0; i + 1 < vertArrayLength; i += 2) {          cachedVertArray = vertArray[i];          curContext.beginPath();          if (i + 3 < vertArrayLength) {            curContext.moveTo(vertArray[i + 2][0], vertArray[i + 2][1]);            curContext.lineTo(cachedVertArray[0], cachedVertArray[1]);            curContext.lineTo(vertArray[i + 1][0], vertArray[i + 1][1]);            curContext.lineTo(vertArray[i + 3][0], vertArray[i + 3][1]);            if (doFill) p.fill(vertArray[i + 3][5]);            if (doStroke) p.stroke(vertArray[i + 3][6])          } else {            curContext.moveTo(cachedVertArray[0], cachedVertArray[1]);            curContext.lineTo(vertArray[i + 1][0], vertArray[i + 1][1])          }          fillStrokeClose()        }      } else {        curContext.beginPath();        curContext.moveTo(vertArray[0][0], vertArray[0][1]);        for (i = 1; i < vertArrayLength; i++) {          cachedVertArray = vertArray[i];          if (cachedVertArray["isVert"]) if (cachedVertArray["moveTo"]) curContext.moveTo(cachedVertArray[0], cachedVertArray[1]);          else curContext.lineTo(cachedVertArray[0], cachedVertArray[1])        }        fillStrokeClose()      }      isCurve = false;      isBezier = false;      curveVertArray = [];      curveVertCount = 0;      if (closeShape) vertArray.pop()    };    Drawing3D.prototype.endShape = function(mode) {      if (vertArray.length === 0) return;      var closeShape = mode === 2;      var lineVertArray = [];      var fillVertArray = [];      var colorVertArray = [];      var strokeVertArray = [];      var texVertArray = [];      var cachedVertArray;      firstVert = true;      var i, j, k;      var vertArrayLength = vertArray.length;      for (i = 0; i < vertArrayLength; i++) {        cachedVertArray = vertArray[i];        for (j = 0; j < 3; j++) fillVertArray.push(cachedVertArray[j])      }      for (i = 0; i < vertArrayLength; i++) {        cachedVertArray = vertArray[i];        for (j = 5; j < 9; j++) colorVertArray.push(cachedVertArray[j])      }      for (i = 0; i < vertArrayLength; i++) {        cachedVertArray = vertArray[i];        for (j = 9; j < 13; j++) strokeVertArray.push(cachedVertArray[j])      }      for (i = 0; i < vertArrayLength; i++) {        cachedVertArray = vertArray[i];        texVertArray.push(cachedVertArray[3]);        texVertArray.push(cachedVertArray[4])      }      if (closeShape) {        fillVertArray.push(vertArray[0][0]);        fillVertArray.push(vertArray[0][1]);        fillVertArray.push(vertArray[0][2]);        for (i = 5; i < 9; i++) colorVertArray.push(vertArray[0][i]);        for (i = 9; i < 13; i++) strokeVertArray.push(vertArray[0][i]);        texVertArray.push(vertArray[0][3]);        texVertArray.push(vertArray[0][4])      }      if (isCurve && (curShape === 20 || curShape === undef)) {        lineVertArray = fillVertArray;        if (doStroke) line3D(lineVertArray, null, strokeVertArray);        if (doFill) fill3D(fillVertArray, null, colorVertArray)      } else if (isBezier && (curShape === 20 || curShape === undef)) {        lineVertArray = fillVertArray;        lineVertArray.splice(lineVertArray.length - 3);        strokeVertArray.splice(strokeVertArray.length - 4);        if (doStroke) line3D(lineVertArray, null, strokeVertArray);        if (doFill) fill3D(fillVertArray, "TRIANGLES", colorVertArray)      } else {        if (curShape === 2) {          for (i = 0; i < vertArrayLength; i++) {            cachedVertArray = vertArray[i];            for (j = 0; j < 3; j++) lineVertArray.push(cachedVertArray[j])          }          point3D(lineVertArray, strokeVertArray)        } else if (curShape === 4) {          for (i = 0; i < vertArrayLength; i++) {            cachedVertArray = vertArray[i];            for (j = 0; j < 3; j++) lineVertArray.push(cachedVertArray[j])          }          for (i = 0; i < vertArrayLength; i++) {            cachedVertArray = vertArray[i];            for (j = 5; j < 9; j++) colorVertArray.push(cachedVertArray[j])          }          line3D(lineVertArray, "LINES", strokeVertArray)        } else if (curShape === 9) {          if (vertArrayLength > 2) for (i = 0; i + 2 < vertArrayLength; i += 3) {            fillVertArray = [];            texVertArray = [];            lineVertArray = [];            colorVertArray = [];            strokeVertArray = [];            for (j = 0; j < 3; j++) for (k = 0; k < 3; k++) {              lineVertArray.push(vertArray[i + j][k]);              fillVertArray.push(vertArray[i + j][k])            }            for (j = 0; j < 3; j++) for (k = 3; k < 5; k++) texVertArray.push(vertArray[i + j][k]);            for (j = 0; j < 3; j++) for (k = 5; k < 9; k++) {              colorVertArray.push(vertArray[i + j][k]);              strokeVertArray.push(vertArray[i + j][k + 4])            }            if (doStroke) line3D(lineVertArray, "LINE_LOOP", strokeVertArray);            if (doFill || usingTexture) fill3D(fillVertArray, "TRIANGLES", colorVertArray, texVertArray)          }        } else if (curShape === 10) {          if (vertArrayLength > 2) for (i = 0; i + 2 < vertArrayLength; i++) {            lineVertArray = [];            fillVertArray = [];            strokeVertArray = [];            colorVertArray = [];            texVertArray = [];            for (j = 0; j < 3; j++) for (k = 0; k < 3; k++) {              lineVertArray.push(vertArray[i + j][k]);              fillVertArray.push(vertArray[i + j][k])            }            for (j = 0; j < 3; j++) for (k = 3; k < 5; k++) texVertArray.push(vertArray[i + j][k]);            for (j = 0; j < 3; j++) for (k = 5; k < 9; k++) {              strokeVertArray.push(vertArray[i + j][k + 4]);              colorVertArray.push(vertArray[i + j][k])            }            if (doFill || usingTexture) fill3D(fillVertArray, "TRIANGLE_STRIP", colorVertArray, texVertArray);            if (doStroke) line3D(lineVertArray, "LINE_LOOP", strokeVertArray)          }        } else if (curShape === 11) {          if (vertArrayLength > 2) {            for (i = 0; i < 3; i++) {              cachedVertArray = vertArray[i];              for (j = 0; j < 3; j++) lineVertArray.push(cachedVertArray[j])            }            for (i = 0; i < 3; i++) {              cachedVertArray = vertArray[i];              for (j = 9; j < 13; j++) strokeVertArray.push(cachedVertArray[j])            }            if (doStroke) line3D(lineVertArray, "LINE_LOOP", strokeVertArray);            for (i = 2; i + 1 < vertArrayLength; i++) {              lineVertArray = [];              strokeVertArray = [];              lineVertArray.push(vertArray[0][0]);              lineVertArray.push(vertArray[0][1]);              lineVertArray.push(vertArray[0][2]);              strokeVertArray.push(vertArray[0][9]);              strokeVertArray.push(vertArray[0][10]);              strokeVertArray.push(vertArray[0][11]);              strokeVertArray.push(vertArray[0][12]);              for (j = 0; j < 2; j++) for (k = 0; k < 3; k++) lineVertArray.push(vertArray[i + j][k]);              for (j = 0; j < 2; j++) for (k = 9; k < 13; k++) strokeVertArray.push(vertArray[i + j][k]);              if (doStroke) line3D(lineVertArray, "LINE_STRIP", strokeVertArray)            }            if (doFill || usingTexture) fill3D(fillVertArray, "TRIANGLE_FAN", colorVertArray, texVertArray)          }        } else if (curShape === 16) for (i = 0; i + 3 < vertArrayLength; i += 4) {          lineVertArray = [];          for (j = 0; j < 4; j++) {            cachedVertArray = vertArray[i + j];            for (k = 0; k < 3; k++) lineVertArray.push(cachedVertArray[k])          }          if (doStroke) line3D(lineVertArray, "LINE_LOOP", strokeVertArray);          if (doFill) {            fillVertArray = [];            colorVertArray = [];            texVertArray = [];            for (j = 0; j < 3; j++) fillVertArray.push(vertArray[i][j]);            for (j = 5; j < 9; j++) colorVertArray.push(vertArray[i][j]);            for (j = 0; j < 3; j++) fillVertArray.push(vertArray[i + 1][j]);            for (j = 5; j < 9; j++) colorVertArray.push(vertArray[i + 1][j]);            for (j = 0; j < 3; j++) fillVertArray.push(vertArray[i + 3][j]);            for (j = 5; j < 9; j++) colorVertArray.push(vertArray[i + 3][j]);            for (j = 0; j < 3; j++) fillVertArray.push(vertArray[i + 2][j]);            for (j = 5; j < 9; j++) colorVertArray.push(vertArray[i + 2][j]);            if (usingTexture) {              texVertArray.push(vertArray[i + 0][3]);              texVertArray.push(vertArray[i + 0][4]);              texVertArray.push(vertArray[i + 1][3]);              texVertArray.push(vertArray[i + 1][4]);              texVertArray.push(vertArray[i + 3][3]);              texVertArray.push(vertArray[i + 3][4]);              texVertArray.push(vertArray[i + 2][3]);              texVertArray.push(vertArray[i + 2][4])            }            fill3D(fillVertArray, "TRIANGLE_STRIP", colorVertArray, texVertArray)          }        } else if (curShape === 17) {          var tempArray = [];          if (vertArrayLength > 3) {            for (i = 0; i < 2; i++) {              cachedVertArray = vertArray[i];              for (j = 0; j < 3; j++) lineVertArray.push(cachedVertArray[j])            }            for (i = 0; i < 2; i++) {              cachedVertArray = vertArray[i];              for (j = 9; j < 13; j++) strokeVertArray.push(cachedVertArray[j])            }            line3D(lineVertArray, "LINE_STRIP", strokeVertArray);            if (vertArrayLength > 4 && vertArrayLength % 2 > 0) {              tempArray = fillVertArray.splice(fillVertArray.length - 3);              vertArray.pop()            }            for (i = 0; i + 3 < vertArrayLength; i += 2) {              lineVertArray = [];              strokeVertArray = [];              for (j = 0; j < 3; j++) lineVertArray.push(vertArray[i + 1][j]);              for (j = 0; j < 3; j++) lineVertArray.push(vertArray[i + 3][j]);              for (j = 0; j < 3; j++) lineVertArray.push(vertArray[i + 2][j]);              for (j = 0; j < 3; j++) lineVertArray.push(vertArray[i + 0][j]);              for (j = 9; j < 13; j++) strokeVertArray.push(vertArray[i + 1][j]);              for (j = 9; j < 13; j++) strokeVertArray.push(vertArray[i + 3][j]);              for (j = 9; j < 13; j++) strokeVertArray.push(vertArray[i + 2][j]);              for (j = 9; j < 13; j++) strokeVertArray.push(vertArray[i + 0][j]);              if (doStroke) line3D(lineVertArray, "LINE_STRIP", strokeVertArray)            }            if (doFill || usingTexture) fill3D(fillVertArray, "TRIANGLE_LIST", colorVertArray, texVertArray)          }        } else if (vertArrayLength === 1) {          for (j = 0; j < 3; j++) lineVertArray.push(vertArray[0][j]);          for (j = 9; j < 13; j++) strokeVertArray.push(vertArray[0][j]);          point3D(lineVertArray, strokeVertArray)        } else {          for (i = 0; i < vertArrayLength; i++) {            cachedVertArray = vertArray[i];            for (j = 0; j < 3; j++) lineVertArray.push(cachedVertArray[j]);            for (j = 5; j < 9; j++) strokeVertArray.push(cachedVertArray[j])          }          if (doStroke && closeShape) line3D(lineVertArray, "LINE_LOOP", strokeVertArray);          else if (doStroke && !closeShape) line3D(lineVertArray, "LINE_STRIP", strokeVertArray);          if (doFill || usingTexture) fill3D(fillVertArray, "TRIANGLE_FAN", colorVertArray, texVertArray)        }        usingTexture = false;        curContext.useProgram(programObject3D);        uniformi("usingTexture3d", programObject3D, "uUsingTexture", usingTexture)      }      isCurve = false;      isBezier = false;      curveVertArray = [];      curveVertCount = 0    };    var splineForward = function(segments, matrix) {      var f = 1 / segments;      var ff = f * f;      var fff = ff * f;      matrix.set(0, 0, 0, 1, fff, ff, f, 0, 6 * fff, 2 * ff, 0, 0, 6 * fff, 0, 0, 0)    };    var curveInit = function() {      if (!curveDrawMatrix) {        curveBasisMatrix = new PMatrix3D;        curveDrawMatrix = new PMatrix3D;        curveInited = true      }      var s = curTightness;      curveBasisMatrix.set((s - 1) / 2, (s + 3) / 2, (-3 - s) / 2, (1 - s) / 2, 1 - s, (-5 - s) / 2, s + 2, (s - 1) / 2, (s - 1) / 2, 0, (1 - s) / 2, 0, 0, 1, 0, 0);      splineForward(curveDet, curveDrawMatrix);      if (!bezierBasisInverse) curveToBezierMatrix = new PMatrix3D;      curveToBezierMatrix.set(curveBasisMatrix);      curveToBezierMatrix.preApply(bezierBasisInverse);      curveDrawMatrix.apply(curveBasisMatrix)    };    Drawing2D.prototype.bezierVertex = function() {      isBezier = true;      var vert = [];      if (firstVert) throw "vertex() must be used at least once before calling bezierVertex()";      for (var i = 0; i < arguments.length; i++) vert[i] = arguments[i];      vertArray.push(vert);      vertArray[vertArray.length - 1]["isVert"] = false    };    Drawing3D.prototype.bezierVertex = function() {      isBezier = true;      var vert = [];      if (firstVert) throw "vertex() must be used at least once before calling bezierVertex()";      if (arguments.length === 9) {        if (bezierDrawMatrix === undef) bezierDrawMatrix = new PMatrix3D;        var lastPoint = vertArray.length - 1;        splineForward(bezDetail, bezierDrawMatrix);        bezierDrawMatrix.apply(bezierBasisMatrix);        var draw = bezierDrawMatrix.array();        var x1 = vertArray[lastPoint][0],          y1 = vertArray[lastPoint][1],          z1 = vertArray[lastPoint][2];        var xplot1 = draw[4] * x1 + draw[5] * arguments[0] + draw[6] * arguments[3] + draw[7] * arguments[6];        var xplot2 = draw[8] * x1 + draw[9] * arguments[0] + draw[10] * arguments[3] + draw[11] * arguments[6];        var xplot3 = draw[12] * x1 + draw[13] * arguments[0] + draw[14] * arguments[3] + draw[15] * arguments[6];        var yplot1 = draw[4] * y1 + draw[5] * arguments[1] + draw[6] * arguments[4] + draw[7] * arguments[7];        var yplot2 = draw[8] * y1 + draw[9] * arguments[1] + draw[10] * arguments[4] + draw[11] * arguments[7];        var yplot3 = draw[12] * y1 + draw[13] * arguments[1] + draw[14] * arguments[4] + draw[15] * arguments[7];        var zplot1 = draw[4] * z1 + draw[5] * arguments[2] + draw[6] * arguments[5] + draw[7] * arguments[8];        var zplot2 = draw[8] * z1 + draw[9] * arguments[2] + draw[10] * arguments[5] + draw[11] * arguments[8];        var zplot3 = draw[12] * z1 + draw[13] * arguments[2] + draw[14] * arguments[5] + draw[15] * arguments[8];        for (var j = 0; j < bezDetail; j++) {          x1 += xplot1;          xplot1 += xplot2;          xplot2 += xplot3;          y1 += yplot1;          yplot1 += yplot2;          yplot2 += yplot3;          z1 += zplot1;          zplot1 += zplot2;          zplot2 += zplot3;          p.vertex(x1, y1, z1)        }        p.vertex(arguments[6], arguments[7], arguments[8])      }    };    p.texture = function(pimage) {      var curContext = drawing.$ensureContext();      if (pimage.__texture) curContext.bindTexture(curContext.TEXTURE_2D, pimage.__texture);      else if (pimage.localName === "canvas") {        curContext.bindTexture(curContext.TEXTURE_2D, canTex);        curContext.texImage2D(curContext.TEXTURE_2D, 0, curContext.RGBA, curContext.RGBA, curContext.UNSIGNED_BYTE, pimage);        curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_MAG_FILTER, curContext.LINEAR);        curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_MIN_FILTER, curContext.LINEAR);        curContext.generateMipmap(curContext.TEXTURE_2D);        curTexture.width = pimage.width;        curTexture.height = pimage.height      } else {        var texture = curContext.createTexture(),          cvs = document.createElement("canvas"),          cvsTextureCtx = cvs.getContext("2d"),          pot;        if (pimage.width & pimage.width - 1 === 0) cvs.width = pimage.width;        else {          pot = 1;          while (pot < pimage.width) pot *= 2;          cvs.width = pot        }        if (pimage.height & pimage.height - 1 === 0) cvs.height = pimage.height;        else {          pot = 1;          while (pot < pimage.height) pot *= 2;          cvs.height = pot        }        cvsTextureCtx.drawImage(pimage.sourceImg, 0, 0, pimage.width, pimage.height, 0, 0, cvs.width, cvs.height);        curContext.bindTexture(curContext.TEXTURE_2D, texture);        curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_MIN_FILTER, curContext.LINEAR_MIPMAP_LINEAR);        curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_MAG_FILTER, curContext.LINEAR);        curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_WRAP_T, curContext.CLAMP_TO_EDGE);        curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_WRAP_S, curContext.CLAMP_TO_EDGE);        curContext.texImage2D(curContext.TEXTURE_2D, 0, curContext.RGBA, curContext.RGBA, curContext.UNSIGNED_BYTE, cvs);        curContext.generateMipmap(curContext.TEXTURE_2D);        pimage.__texture = texture;        curTexture.width = pimage.width;        curTexture.height = pimage.height      }      usingTexture = true;      curContext.useProgram(programObject3D);      uniformi("usingTexture3d", programObject3D, "uUsingTexture", usingTexture)    };    p.textureMode = function(mode) {      curTextureMode = mode    };    var curveVertexSegment = function(x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4) {      var x0 = x2;      var y0 = y2;      var z0 = z2;      var draw = curveDrawMatrix.array();      var xplot1 = draw[4] * x1 + draw[5] * x2 + draw[6] * x3 + draw[7] * x4;      var xplot2 = draw[8] * x1 + draw[9] * x2 + draw[10] * x3 + draw[11] * x4;      var xplot3 = draw[12] * x1 + draw[13] * x2 + draw[14] * x3 + draw[15] * x4;      var yplot1 = draw[4] * y1 + draw[5] * y2 + draw[6] * y3 + draw[7] * y4;      var yplot2 = draw[8] * y1 + draw[9] * y2 + draw[10] * y3 + draw[11] * y4;      var yplot3 = draw[12] * y1 + draw[13] * y2 + draw[14] * y3 + draw[15] * y4;      var zplot1 = draw[4] * z1 + draw[5] * z2 + draw[6] * z3 + draw[7] * z4;      var zplot2 = draw[8] * z1 + draw[9] * z2 + draw[10] * z3 + draw[11] * z4;      var zplot3 = draw[12] * z1 + draw[13] * z2 + draw[14] * z3 + draw[15] * z4;      p.vertex(x0, y0, z0);      for (var j = 0; j < curveDet; j++) {        x0 += xplot1;        xplot1 += xplot2;        xplot2 += xplot3;        y0 += yplot1;        yplot1 += yplot2;        yplot2 += yplot3;        z0 += zplot1;        zplot1 += zplot2;        zplot2 += zplot3;        p.vertex(x0, y0, z0)      }    };    Drawing2D.prototype.curveVertex = function(x, y) {      isCurve = true;      p.vertex(x, y)    };    Drawing3D.prototype.curveVertex = function(x, y, z) {      isCurve = true;      if (!curveInited) curveInit();      var vert = [];      vert[0] = x;      vert[1] = y;      vert[2] = z;      curveVertArray.push(vert);      curveVertCount++;      if (curveVertCount > 3) curveVertexSegment(curveVertArray[curveVertCount - 4][0], curveVertArray[curveVertCount - 4][1], curveVertArray[curveVertCount - 4][2], curveVertArray[curveVertCount - 3][0], curveVertArray[curveVertCount - 3][1], curveVertArray[curveVertCount - 3][2], curveVertArray[curveVertCount - 2][0], curveVertArray[curveVertCount - 2][1], curveVertArray[curveVertCount - 2][2], curveVertArray[curveVertCount - 1][0], curveVertArray[curveVertCount - 1][1], curveVertArray[curveVertCount - 1][2])    };    Drawing2D.prototype.curve = function(x1, y1, x2, y2, x3, y3, x4, y4) {      p.beginShape();      p.curveVertex(x1, y1);      p.curveVertex(x2, y2);      p.curveVertex(x3, y3);      p.curveVertex(x4, y4);      p.endShape()    };    Drawing3D.prototype.curve = function(x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4) {      if (z4 !== undef) {        p.beginShape();        p.curveVertex(x1, y1, z1);        p.curveVertex(x2, y2, z2);        p.curveVertex(x3, y3, z3);        p.curveVertex(x4, y4, z4);        p.endShape();        return      }      p.beginShape();      p.curveVertex(x1, y1);      p.curveVertex(z1, x2);      p.curveVertex(y2, z2);      p.curveVertex(x3, y3);      p.endShape()    };    p.curveTightness = function(tightness) {      curTightness = tightness    };    p.curveDetail = function(detail) {      curveDet = detail;      curveInit()    };    p.rectMode = function(aRectMode) {      curRectMode = aRectMode    };    p.imageMode = function(mode) {      switch (mode) {      case 0:        imageModeConvert = imageModeCorner;        break;      case 1:        imageModeConvert = imageModeCorners;        break;      case 3:        imageModeConvert = imageModeCenter;        break;      default:        throw "Invalid imageMode";      }    };    p.ellipseMode = function(aEllipseMode) {      curEllipseMode = aEllipseMode    };    p.arc = function(x, y, width, height, start, stop) {      if (width <= 0 || stop < start) return;      if (curEllipseMode === 1) {        width = width - x;        height = height - y      } else if (curEllipseMode === 2) {        x = x - width;        y = y - height;        width = width * 2;        height = height * 2      } else if (curEllipseMode === 3) {        x = x - width / 2;        y = y - height / 2      }      while (start < 0) {        start += 6.283185307179586;        stop += 6.283185307179586      }      if (stop - start > 6.283185307179586) {        start = 0;        stop = 6.283185307179586      }      var hr = width / 2,        vr = height / 2,        centerX = x + hr,        centerY = y + vr,        startLUT = 0 | 0.5 + start * p.RAD_TO_DEG * 2,        stopLUT = 0 | 0.5 + stop * p.RAD_TO_DEG * 2,        i, j;      if (doFill) {        var savedStroke = doStroke;        doStroke = false;        p.beginShape();        p.vertex(centerX, centerY);        for (i = startLUT; i <= stopLUT; i++) {          j = i % 720;          p.vertex(centerX + cosLUT[j] * hr, centerY + sinLUT[j] * vr)        }        p.endShape(2);        doStroke = savedStroke      }      if (doStroke) {        var savedFill = doFill;        doFill = false;        p.beginShape();        for (i = startLUT; i <= stopLUT; i++) {          j = i % 720;          p.vertex(centerX + cosLUT[j] * hr, centerY + sinLUT[j] * vr)        }        p.endShape();        doFill = savedFill      }    };    Drawing2D.prototype.line = function(x1, y1, x2, y2) {      if (!doStroke) return;      x1 = Math.round(x1);      x2 = Math.round(x2);      y1 = Math.round(y1);      y2 = Math.round(y2);      if (x1 === x2 && y1 === y2) {        p.point(x1, y1);        return      }      var swap = undef,        lineCap = undef,        drawCrisp = true,        currentModelView = modelView.array(),        identityMatrix = [1, 0, 0, 0, 1, 0];      for (var i = 0; i < 6 && drawCrisp; i++) drawCrisp = currentModelView[i] === identityMatrix[i];      if (drawCrisp) {        if (x1 === x2) {          if (y1 > y2) {            swap = y1;            y1 = y2;            y2 = swap          }          y2++;          if (lineWidth % 2 === 1) curContext.translate(0.5, 0)        } else if (y1 === y2) {          if (x1 > x2) {            swap = x1;            x1 = x2;            x2 = swap          }          x2++;          if (lineWidth % 2 === 1) curContext.translate(0, 0.5)        }        if (lineWidth === 1) {          lineCap = curContext.lineCap;          curContext.lineCap = "butt"        }      }      curContext.beginPath();      curContext.moveTo(x1 || 0, y1 || 0);      curContext.lineTo(x2 || 0, y2 || 0);      executeContextStroke();      if (drawCrisp) {        if (x1 === x2 && lineWidth % 2 === 1) curContext.translate(-0.5, 0);        else if (y1 === y2 && lineWidth % 2 === 1) curContext.translate(0, -0.5);        if (lineWidth === 1) curContext.lineCap = lineCap      }    };    Drawing3D.prototype.line = function(x1, y1, z1, x2, y2, z2) {      if (y2 === undef || z2 === undef) {        z2 = 0;        y2 = x2;        x2 = z1;        z1 = 0      }      if (x1 === x2 && y1 === y2 && z1 === z2) {        p.point(x1, y1, z1);        return      }      var lineVerts = [x1, y1, z1, x2, y2, z2];      var view = new PMatrix3D;      view.scale(1, -1, 1);      view.apply(modelView.array());      view.transpose();      if (lineWidth > 0 && doStroke) {        curContext.useProgram(programObject2D);        uniformMatrix("uModel2d", programObject2D, "uModel", false, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);        uniformMatrix("uView2d", programObject2D, "uView", false, view.array());        uniformf("uColor2d", programObject2D, "uColor", strokeStyle);        uniformi("uIsDrawingText", programObject2D, "uIsDrawingText", false);        vertexAttribPointer("aVertex2d", programObject2D, "aVertex", 3, lineBuffer);        disableVertexAttribPointer("aTextureCoord2d", programObject2D, "aTextureCoord");        curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(lineVerts), curContext.STREAM_DRAW);        curContext.drawArrays(curContext.LINES, 0, 2)      }    };    Drawing2D.prototype.bezier = function() {      if (arguments.length !== 8) throw "You must use 8 parameters for bezier() in 2D mode";      p.beginShape();      p.vertex(arguments[0], arguments[1]);      p.bezierVertex(arguments[2], arguments[3], arguments[4], arguments[5], arguments[6], arguments[7]);      p.endShape()    };    Drawing3D.prototype.bezier = function() {      if (arguments.length !== 12) throw "You must use 12 parameters for bezier() in 3D mode";      p.beginShape();      p.vertex(arguments[0], arguments[1], arguments[2]);      p.bezierVertex(arguments[3], arguments[4], arguments[5], arguments[6], arguments[7], arguments[8], arguments[9], arguments[10], arguments[11]);      p.endShape()    };    p.bezierDetail = function(detail) {      bezDetail = detail    };    p.bezierPoint = function(a, b, c, d, t) {      return (1 - t) * (1 - t) * (1 - t) * a + 3 * (1 - t) * (1 - t) * t * b + 3 * (1 - t) * t * t * c + t * t * t * d    };    p.bezierTangent = function(a, b, c, d, t) {      return 3 * t * t * (-a + 3 * b - 3 * c + d) + 6 * t * (a - 2 * b + c) + 3 * (-a + b)    };    p.curvePoint = function(a, b, c, d, t) {      return 0.5 * (2 * b + (-a + c) * t + (2 * a - 5 * b + 4 * c - d) * t * t + (-a + 3 * b - 3 * c + d) * t * t * t)    };    p.curveTangent = function(a, b, c, d, t) {      return 0.5 * (-a + c + 2 * (2 * a - 5 * b + 4 * c - d) * t + 3 * (-a + 3 * b - 3 * c + d) * t * t)    };    p.triangle = function(x1, y1, x2, y2, x3, y3) {      p.beginShape(9);      p.vertex(x1, y1, 0);      p.vertex(x2, y2, 0);      p.vertex(x3, y3, 0);      p.endShape()    };    p.quad = function(x1, y1, x2, y2, x3, y3, x4, y4) {      p.beginShape(16);      p.vertex(x1, y1, 0);      p.vertex(x2, y2, 0);      p.vertex(x3, y3, 0);      p.vertex(x4, y4, 0);      p.endShape()    };    var roundedRect$2d = function(x, y, width, height, tl, tr, br, bl) {      if (bl === undef) {        tr = tl;        br = tl;        bl = tl      }      var halfWidth = width / 2,        halfHeight = height / 2;      if (tl > halfWidth || tl > halfHeight) tl = Math.min(halfWidth, halfHeight);      if (tr > halfWidth || tr > halfHeight) tr = Math.min(halfWidth, halfHeight);      if (br > halfWidth || br > halfHeight) br = Math.min(halfWidth, halfHeight);      if (bl > halfWidth || bl > halfHeight) bl = Math.min(halfWidth, halfHeight);      if (!doFill || doStroke) curContext.translate(0.5, 0.5);      curContext.beginPath();      curContext.moveTo(x + tl, y);      curContext.lineTo(x + width - tr, y);      curContext.quadraticCurveTo(x + width, y, x + width, y + tr);      curContext.lineTo(x + width, y + height - br);      curContext.quadraticCurveTo(x + width, y + height, x + width - br, y + height);      curContext.lineTo(x + bl, y + height);      curContext.quadraticCurveTo(x, y + height, x, y + height - bl);      curContext.lineTo(x, y + tl);      curContext.quadraticCurveTo(x, y, x + tl, y);      if (!doFill || doStroke) curContext.translate(-0.5, -0.5);      executeContextFill();      executeContextStroke()    };    Drawing2D.prototype.rect = function(x, y, width, height, tl, tr, br, bl) {      if (!width && !height) return;      if (curRectMode === 1) {        width -= x;        height -= y      } else if (curRectMode === 2) {        width *= 2;        height *= 2;        x -= width / 2;        y -= height / 2      } else if (curRectMode === 3) {        x -= width / 2;        y -= height / 2      }      x = Math.round(x);      y = Math.round(y);      width = Math.round(width);      height = Math.round(height);      if (tl !== undef) {        roundedRect$2d(x, y, width, height, tl, tr, br, bl);        return      }      if (doStroke && lineWidth % 2 === 1) curContext.translate(0.5, 0.5);      curContext.beginPath();      curContext.rect(x, y, width, height);      executeContextFill();      executeContextStroke();      if (doStroke && lineWidth % 2 === 1) curContext.translate(-0.5, -0.5)    };    Drawing3D.prototype.rect = function(x, y, width, height, tl, tr, br, bl) {      if (tl !== undef) throw "rect() with rounded corners is not supported in 3D mode";      if (curRectMode === 1) {        width -= x;        height -= y      } else if (curRectMode === 2) {        width *= 2;        height *= 2;        x -= width / 2;        y -= height / 2      } else if (curRectMode === 3) {        x -= width / 2;        y -= height / 2      }      var model = new PMatrix3D;      model.translate(x, y, 0);      model.scale(width, height, 1);      model.transpose();      var view = new PMatrix3D;      view.scale(1, -1, 1);      view.apply(modelView.array());      view.transpose();      if (lineWidth > 0 && doStroke) {        curContext.useProgram(programObject2D);        uniformMatrix("uModel2d", programObject2D, "uModel", false, model.array());        uniformMatrix("uView2d", programObject2D, "uView", false, view.array());        uniformf("uColor2d", programObject2D, "uColor", strokeStyle);        uniformi("uIsDrawingText2d", programObject2D, "uIsDrawingText", false);        vertexAttribPointer("aVertex2d", programObject2D, "aVertex", 3, rectBuffer);        disableVertexAttribPointer("aTextureCoord2d", programObject2D, "aTextureCoord");        curContext.drawArrays(curContext.LINE_LOOP, 0, rectVerts.length / 3)      }      if (doFill) {        curContext.useProgram(programObject3D);        uniformMatrix("uModel3d", programObject3D, "uModel", false, model.array());        uniformMatrix("uView3d", programObject3D, "uView", false, view.array());        curContext.enable(curContext.POLYGON_OFFSET_FILL);        curContext.polygonOffset(1, 1);        uniformf("color3d", programObject3D, "uColor", fillStyle);        if (lightCount > 0) {          var v = new PMatrix3D;          v.set(view);          var m = new PMatrix3D;          m.set(model);          v.mult(m);          var normalMatrix = new PMatrix3D;          normalMatrix.set(v);          normalMatrix.invert();          normalMatrix.transpose();          uniformMatrix("uNormalTransform3d", programObject3D, "uNormalTransform", false, normalMatrix.array());          vertexAttribPointer("aNormal3d", programObject3D, "aNormal", 3, rectNormBuffer)        } else disableVertexAttribPointer("normal3d", programObject3D, "aNormal");        vertexAttribPointer("vertex3d", programObject3D, "aVertex", 3, rectBuffer);        curContext.drawArrays(curContext.TRIANGLE_FAN, 0, rectVerts.length / 3);        curContext.disable(curContext.POLYGON_OFFSET_FILL)      }    };    Drawing2D.prototype.ellipse = function(x, y, width, height) {      x = x || 0;      y = y || 0;      if (width <= 0 && height <= 0) return;      if (curEllipseMode === 2) {        width *= 2;        height *= 2      } else if (curEllipseMode === 1) {        width = width - x;        height = height - y;        x += width / 2;        y += height / 2      } else if (curEllipseMode === 0) {        x += width / 2;        y += height / 2      }      if (width === height) {        curContext.beginPath();        curContext.arc(x, y, width / 2, 0, 6.283185307179586, false);        executeContextFill();        executeContextStroke()      } else {        var w = width / 2,          h = height / 2,          C = 0.5522847498307933,          c_x = C * w,          c_y = C * h;        p.beginShape();        p.vertex(x + w, y);        p.bezierVertex(x + w, y - c_y, x + c_x, y - h, x, y - h);        p.bezierVertex(x - c_x, y - h, x - w, y - c_y, x - w, y);        p.bezierVertex(x - w, y + c_y, x - c_x, y + h, x, y + h);        p.bezierVertex(x + c_x, y + h, x + w, y + c_y, x + w, y);        p.endShape()      }    };    Drawing3D.prototype.ellipse = function(x, y, width, height) {      x = x || 0;      y = y || 0;      if (width <= 0 && height <= 0) return;      if (curEllipseMode === 2) {        width *= 2;        height *= 2      } else if (curEllipseMode === 1) {        width = width - x;        height = height - y;        x += width / 2;        y += height / 2      } else if (curEllipseMode === 0) {        x += width / 2;        y += height / 2      }      var w = width / 2,        h = height / 2,        C = 0.5522847498307933,        c_x = C * w,        c_y = C * h;      p.beginShape();      p.vertex(x + w, y);      p.bezierVertex(x + w, y - c_y, 0, x + c_x, y - h, 0, x, y - h, 0);      p.bezierVertex(x - c_x, y - h, 0, x - w, y - c_y, 0, x - w, y, 0);      p.bezierVertex(x - w, y + c_y, 0, x - c_x, y + h, 0, x, y + h, 0);      p.bezierVertex(x + c_x, y + h, 0, x + w, y + c_y, 0, x + w, y, 0);      p.endShape();      if (doFill) {        var xAv = 0,          yAv = 0,          i, j;        for (i = 0; i < vertArray.length; i++) {          xAv += vertArray[i][0];          yAv += vertArray[i][1]        }        xAv /= vertArray.length;        yAv /= vertArray.length;        var vert = [],          fillVertArray = [],          colorVertArray = [];        vert[0] = xAv;        vert[1] = yAv;        vert[2] = 0;        vert[3] = 0;        vert[4] = 0;        vert[5] = fillStyle[0];        vert[6] = fillStyle[1];        vert[7] = fillStyle[2];        vert[8] = fillStyle[3];        vert[9] = strokeStyle[0];        vert[10] = strokeStyle[1];        vert[11] = strokeStyle[2];        vert[12] = strokeStyle[3];        vert[13] = normalX;        vert[14] = normalY;        vert[15] = normalZ;        vertArray.unshift(vert);        for (i = 0; i < vertArray.length; i++) {          for (j = 0; j < 3; j++) fillVertArray.push(vertArray[i][j]);          for (j = 5; j < 9; j++) colorVertArray.push(vertArray[i][j])        }        fill3D(fillVertArray, "TRIANGLE_FAN", colorVertArray)      }    };    p.normal = function(nx, ny, nz) {      if (arguments.length !== 3 || !(typeof nx === "number" && typeof ny === "number" && typeof nz === "number")) throw "normal() requires three numeric arguments.";      normalX = nx;      normalY = ny;      normalZ = nz;      if (curShape !== 0) if (normalMode === 0) normalMode = 1;      else if (normalMode === 1) normalMode = 2    };    p.save = function(file, img) {      if (img !== undef) return window.open(img.toDataURL(), "_blank");      return window.open(p.externals.canvas.toDataURL(), "_blank")    };    var saveNumber = 0;    p.saveFrame = function(file) {      if (file === undef) file = "screen-####.png";      var frameFilename = file.replace(/#+/, function(all) {        var s = "" + saveNumber++;        while (s.length < all.length) s = "0" + s;        return s      });      p.save(frameFilename)    };    var utilityContext2d = document.createElement("canvas").getContext("2d");    var canvasDataCache = [undef, undef, undef];    function getCanvasData(obj, w, h) {      var canvasData = canvasDataCache.shift();      if (canvasData === undef) {        canvasData = {};        canvasData.canvas = document.createElement("canvas");        canvasData.context = canvasData.canvas.getContext("2d")      }      canvasDataCache.push(canvasData);      var canvas = canvasData.canvas,        context = canvasData.context,        width = w || obj.width,        height = h || obj.height;      canvas.width = width;      canvas.height = height;      if (!obj) context.clearRect(0, 0, width, height);      else if ("data" in obj) context.putImageData(obj, 0, 0);      else {        context.clearRect(0, 0, width, height);        context.drawImage(obj, 0, 0, width, height)      }      return canvasData    }    function buildPixelsObject(pImage) {      return {        getLength: function(aImg) {          return function() {            if (aImg.isRemote) throw "Image is loaded remotely. Cannot get length.";            else return aImg.imageData.data.length ? aImg.imageData.data.length / 4 : 0          }        }(pImage),        getPixel: function(aImg) {          return function(i) {            var offset = i * 4,              data = aImg.imageData.data;            if (aImg.isRemote) throw "Image is loaded remotely. Cannot get pixels.";            return (data[offset + 3] & 255) << 24 | (data[offset] & 255) << 16 | (data[offset + 1] & 255) << 8 | data[offset + 2] & 255          }        }(pImage),        setPixel: function(aImg) {          return function(i, c) {            var offset = i * 4,              data = aImg.imageData.data;            if (aImg.isRemote) throw "Image is loaded remotely. Cannot set pixel.";            data[offset + 0] = (c >> 16) & 255;            data[offset + 1] = (c >> 8) & 255;            data[offset + 2] = c & 255;            data[offset + 3] = (c >> 24) & 255;            aImg.__isDirty = true          }        }(pImage),        toArray: function(aImg) {          return function() {            var arr = [],              data = aImg.imageData.data,              length = aImg.width * aImg.height;            if (aImg.isRemote) throw "Image is loaded remotely. Cannot get pixels.";            for (var i = 0, offset = 0; i < length; i++, offset += 4) arr.push((data[offset + 3] & 255) << 24 | (data[offset] & 255) << 16 | (data[offset + 1] & 255) << 8 | data[offset + 2] & 255);            return arr          }        }(pImage),        set: function(aImg) {          return function(arr) {            var offset, data, c;            if (this.isRemote) throw "Image is loaded remotely. Cannot set pixels.";            data = aImg.imageData.data;            for (var i = 0, aL = arr.length; i < aL; i++) {              c = arr[i];              offset = i * 4;              data[offset + 0] = (c >> 16) & 255;              data[offset + 1] = (c >> 8) & 255;              data[offset + 2] = c & 255;              data[offset + 3] = (c >> 24) & 255            }            aImg.__isDirty = true          }        }(pImage)      }    }    var PImage = function(aWidth, aHeight, aFormat) {      this.__isDirty = false;      if (aWidth instanceof HTMLImageElement) this.fromHTMLImageData(aWidth);      else if (aHeight || aFormat) {        this.width = aWidth || 1;        this.height = aHeight || 1;        var canvas = this.sourceImg = document.createElement("canvas");        canvas.width = this.width;        canvas.height = this.height;        var imageData = this.imageData = canvas.getContext("2d").createImageData(this.width, this.height);        this.format = aFormat === 2 || aFormat === 4 ? aFormat : 1;        if (this.format === 1) for (var i = 3, data = this.imageData.data, len = data.length; i < len; i += 4) data[i] = 255;        this.__isDirty = true;        this.updatePixels()      } else {        this.width = 0;        this.height = 0;        this.imageData = utilityContext2d.createImageData(1, 1);        this.format = 2      }      this.pixels = buildPixelsObject(this)    };    PImage.prototype = {      __isPImage: true,      updatePixels: function() {        var canvas = this.sourceImg;        if (canvas && canvas instanceof HTMLCanvasElement && this.__isDirty) canvas.getContext("2d").putImageData(this.imageData, 0, 0);        this.__isDirty = false      },      fromHTMLImageData: function(htmlImg) {        var canvasData = getCanvasData(htmlImg);        try {          var imageData = canvasData.context.getImageData(0, 0, htmlImg.width, htmlImg.height);          this.fromImageData(imageData)        } catch(e) {          if (htmlImg.width && htmlImg.height) {            this.isRemote = true;            this.width = htmlImg.width;            this.height = htmlImg.height          }        }        this.sourceImg = htmlImg      },      "get": function(x, y, w, h) {        if (!arguments.length) return p.get(this);        if (arguments.length === 2) return p.get(x, y, this);        if (arguments.length === 4) return p.get(x, y, w, h, this)      },      "set": function(x, y, c) {        p.set(x, y, c, this);        this.__isDirty = true      },      blend: function(srcImg, x, y, width, height, dx, dy, dwidth, dheight, MODE) {        if (arguments.length === 9) p.blend(this, srcImg, x, y, width, height, dx, dy, dwidth, dheight, this);        else if (arguments.length === 10) p.blend(srcImg, x, y, width, height, dx, dy, dwidth, dheight, MODE, this);        delete this.sourceImg      },      copy: function(srcImg, sx, sy, swidth, sheight, dx, dy, dwidth, dheight) {        if (arguments.length === 8) p.blend(this, srcImg, sx, sy, swidth, sheight, dx, dy, dwidth, 0, this);        else if (arguments.length === 9) p.blend(srcImg, sx, sy, swidth, sheight, dx, dy, dwidth, dheight, 0, this);        delete this.sourceImg      },      filter: function(mode, param) {        if (arguments.length === 2) p.filter(mode, param, this);        else if (arguments.length === 1) p.filter(mode, null, this);        delete this.sourceImg      },      save: function(file) {        p.save(file, this)      },      resize: function(w, h) {        if (this.isRemote) throw "Image is loaded remotely. Cannot resize.";        if (this.width !== 0 || this.height !== 0) {          if (w === 0 && h !== 0) w = Math.floor(this.width / this.height * h);          else if (h === 0 && w !== 0) h = Math.floor(this.height / this.width * w);          var canvas = getCanvasData(this.imageData).canvas;          var imageData = getCanvasData(canvas, w, h).context.getImageData(0, 0, w, h);          this.fromImageData(imageData)        }      },      mask: function(mask) {        var obj = this.toImageData(),          i, size;        if (mask instanceof PImage || mask.__isPImage) if (mask.width === this.width && mask.height === this.height) {          mask = mask.toImageData();          for (i = 2, size = this.width * this.height * 4; i < size; i += 4) obj.data[i + 1] = mask.data[i]        } else throw "mask must have the same dimensions as PImage.";        else if (mask instanceof        Array) if (this.width * this.height === mask.length) for (i = 0, size = mask.length; i < size; ++i) obj.data[i * 4 + 3] = mask[i];        else throw "mask array must be the same length as PImage pixels array.";        this.fromImageData(obj)      },      loadPixels: nop,      toImageData: function() {        if (this.isRemote) return this.sourceImg;        if (!this.__isDirty) return this.imageData;        var canvasData = getCanvasData(this.sourceImg);        return canvasData.context.getImageData(0, 0, this.width, this.height)      },      toDataURL: function() {        if (this.isRemote) throw "Image is loaded remotely. Cannot create dataURI.";        var canvasData = getCanvasData(this.imageData);        return canvasData.canvas.toDataURL()      },      fromImageData: function(canvasImg) {        var w = canvasImg.width,          h = canvasImg.height,          canvas = document.createElement("canvas"),          ctx = canvas.getContext("2d");        this.width = canvas.width = w;        this.height = canvas.height = h;        ctx.putImageData(canvasImg, 0, 0);        this.format = 2;        this.imageData = canvasImg;        this.sourceImg = canvas      }    };    p.PImage = PImage;    p.createImage = function(w, h, mode) {      return new PImage(w, h, mode)    };    p.loadImage = function(file, type, callback) {      if (type) file = file + "." + type;      var pimg;      if (curSketch.imageCache.images[file]) {        pimg = new PImage(curSketch.imageCache.images[file]);        pimg.loaded = true;        return pimg      }      pimg = new PImage;      var img = document.createElement("img");      pimg.sourceImg = img;      img.onload = function(aImage, aPImage, aCallback) {        var image = aImage;        var pimg = aPImage;        var callback = aCallback;        return function() {          pimg.fromHTMLImageData(image);          pimg.loaded = true;          if (callback) callback()        }      }(img, pimg, callback);      img.src = file;      return pimg    };    p.requestImage = p.loadImage;    function get$2(x, y) {      var data;      if (x >= p.width || x < 0 || y < 0 || y >= p.height) return 0;      if (isContextReplaced) {        var offset = ((0 | x) + p.width * (0 | y)) * 4;        data = p.imageData.data;        return (data[offset + 3] & 255) << 24 | (data[offset] & 255) << 16 | (data[offset + 1] & 255) << 8 | data[offset + 2] & 255      }      data = p.toImageData(0 | x, 0 | y, 1, 1).data;      return (data[3] & 255) << 24 | (data[0] & 255) << 16 | (data[1] & 255) << 8 | data[2] & 255    }    function get$3(x, y, img) {      if (img.isRemote) throw "Image is loaded remotely. Cannot get x,y.";      var offset = y * img.width * 4 + x * 4,        data = img.imageData.data;      return (data[offset + 3] & 255) << 24 | (data[offset] & 255) << 16 | (data[offset + 1] & 255) << 8 | data[offset + 2] & 255    }    function get$4(x, y, w, h) {      var c = new PImage(w, h, 2);      c.fromImageData(p.toImageData(x, y, w, h));      return c    }    function get$5(x, y, w, h, img) {      if (img.isRemote) throw "Image is loaded remotely. Cannot get x,y,w,h.";      var c = new PImage(w, h, 2),        cData = c.imageData.data,        imgWidth = img.width,        imgHeight = img.height,        imgData = img.imageData.data;      var startRow = Math.max(0, -y),        startColumn = Math.max(0, -x),        stopRow = Math.min(h, imgHeight - y),        stopColumn = Math.min(w, imgWidth - x);      for (var i = startRow; i < stopRow; ++i) {        var sourceOffset = ((y + i) * imgWidth + (x + startColumn)) * 4;        var targetOffset = (i * w + startColumn) * 4;        for (var j = startColumn; j < stopColumn; ++j) {          cData[targetOffset++] = imgData[sourceOffset++];          cData[targetOffset++] = imgData[sourceOffset++];          cData[targetOffset++] = imgData[sourceOffset++];          cData[targetOffset++] = imgData[sourceOffset++]        }      }      c.__isDirty = true;      return c    }    p.get = function(x, y, w, h, img) {      if (img !== undefined) return get$5(x, y, w, h, img);      if (h !== undefined) return get$4(x, y, w, h);      if (w !== undefined) return get$3(x, y, w);      if (y !== undefined) return get$2(x, y);      if (x !== undefined) return get$5(0, 0, x.width, x.height, x);      return get$4(0, 0, p.width, p.height)    };    p.createGraphics = function(w, h, render) {      var pg = new Processing;      pg.size(w, h, render);      pg.background(0, 0);      return pg    };    function resetContext() {      if (isContextReplaced) {        curContext = originalContext;        isContextReplaced = false;        p.updatePixels()      }    }    function SetPixelContextWrapper() {      function wrapFunction(newContext, name) {        function wrapper() {          resetContext();          curContext[name].apply(curContext, arguments)        }        newContext[name] = wrapper      }      function wrapProperty(newContext, name) {        function getter() {          resetContext();          return curContext[name]        }        function setter(value) {          resetContext();          curContext[name] = value        }        p.defineProperty(newContext, name, {          get: getter,          set: setter        })      }      for (var n in curContext) if (typeof curContext[n] === "function") wrapFunction(this, n);      else wrapProperty(this, n)    }    function replaceContext() {      if (isContextReplaced) return;      p.loadPixels();      if (proxyContext === null) {        originalContext = curContext;        proxyContext = new SetPixelContextWrapper      }      isContextReplaced = true;      curContext = proxyContext;      setPixelsCached = 0    }    function set$3(x, y, c) {      if (x < p.width && x >= 0 && y >= 0 && y < p.height) {        replaceContext();        p.pixels.setPixel((0 | x) + p.width * (0 | y), c);        if (++setPixelsCached > maxPixelsCached) resetContext()      }    }    function set$4(x, y, obj, img) {      if (img.isRemote) throw "Image is loaded remotely. Cannot set x,y.";      var c = p.color.toArray(obj);      var offset = y * img.width * 4 + x * 4;      var data = img.imageData.data;      data[offset] = c[0];      data[offset + 1] = c[1];      data[offset + 2] = c[2];      data[offset + 3] = c[3]    }    p.set = function(x, y, obj, img) {      var color, oldFill;      if (arguments.length === 3) if (typeof obj === "number") set$3(x, y, obj);      else {        if (obj instanceof PImage || obj.__isPImage) p.image(obj, x, y)      } else if (arguments.length === 4) set$4(x, y, obj, img)    };    p.imageData = {};    p.pixels = {      getLength: function() {        return p.imageData.data.length ? p.imageData.data.length / 4 : 0      },      getPixel: function(i) {        var offset = i * 4,          data = p.imageData.data;        return data[offset + 3] << 24 & 4278190080 | data[offset + 0] << 16 & 16711680 | data[offset + 1] << 8 & 65280 | data[offset + 2] & 255      },      setPixel: function(i, c) {        var offset = i * 4,          data = p.imageData.data;        data[offset + 0] = (c & 16711680) >>> 16;        data[offset + 1] = (c & 65280) >>> 8;        data[offset + 2] = c & 255;        data[offset + 3] = (c & 4278190080) >>> 24      },      toArray: function() {        var arr = [],          length = p.imageData.width * p.imageData.height,          data = p.imageData.data;        for (var i = 0, offset = 0; i < length; i++, offset += 4) arr.push(data[offset + 3] << 24 & 4278190080 | data[offset + 0] << 16 & 16711680 | data[offset + 1] << 8 & 65280 | data[offset + 2] & 255);        return arr      },      set: function(arr) {        for (var i = 0, aL = arr.length; i < aL; i++) this.setPixel(i, arr[i])      }    };    p.loadPixels = function() {      p.imageData = drawing.$ensureContext().getImageData(0, 0, p.width, p.height)    };    p.updatePixels = function() {      if (p.imageData) drawing.$ensureContext().putImageData(p.imageData, 0, 0)    };    p.hint = function(which) {      var curContext = drawing.$ensureContext();      if (which === 4) {        curContext.disable(curContext.DEPTH_TEST);        curContext.depthMask(false);        curContext.clear(curContext.DEPTH_BUFFER_BIT)      } else if (which === -4) {        curContext.enable(curContext.DEPTH_TEST);        curContext.depthMask(true)      } else if (which === -1 || which === 2) renderSmooth = true;      else if (which === 1) renderSmooth = false    };    var backgroundHelper = function(arg1, arg2, arg3, arg4) {      var obj;      if (arg1 instanceof PImage || arg1.__isPImage) {        obj = arg1;        if (!obj.loaded) throw "Error using image in background(): PImage not loaded.";        if (obj.width !== p.width || obj.height !== p.height) throw "Background image must be the same dimensions as the canvas.";      } else obj = p.color(arg1, arg2, arg3, arg4);      backgroundObj = obj    };    Drawing2D.prototype.background = function(arg1, arg2, arg3, arg4) {      if (arg1 !== undef) backgroundHelper(arg1, arg2, arg3, arg4);      if (backgroundObj instanceof PImage || backgroundObj.__isPImage) {        saveContext();        curContext.setTransform(1, 0, 0, 1, 0, 0);        p.image(backgroundObj, 0, 0);        restoreContext()      } else {        saveContext();        curContext.setTransform(1, 0, 0, 1, 0, 0);        if (p.alpha(backgroundObj) !== colorModeA) curContext.clearRect(0, 0, p.width, p.height);        curContext.fillStyle = p.color.toString(backgroundObj);        curContext.fillRect(0, 0, p.width, p.height);        isFillDirty = true;        restoreContext()      }    };    Drawing3D.prototype.background = function(arg1, arg2, arg3, arg4) {      if (arguments.length > 0) backgroundHelper(arg1, arg2, arg3, arg4);      var c = p.color.toGLArray(backgroundObj);      curContext.clearColor(c[0], c[1], c[2], c[3]);      curContext.clear(curContext.COLOR_BUFFER_BIT | curContext.DEPTH_BUFFER_BIT)    };    Drawing2D.prototype.image = function(img, x, y, w, h) {      x = Math.round(x);      y = Math.round(y);      if (img.width > 0) {        var wid = w || img.width;        var hgt = h || img.height;        var bounds = imageModeConvert(x || 0, y || 0, w || img.width, h || img.height, arguments.length < 4);        var fastImage = !!img.sourceImg && curTint === null;        if (fastImage) {          var htmlElement = img.sourceImg;          if (img.__isDirty) img.updatePixels();          curContext.drawImage(htmlElement, 0, 0, htmlElement.width, htmlElement.height, bounds.x, bounds.y, bounds.w, bounds.h)        } else {          var obj = img.toImageData();          if (curTint !== null) {            curTint(obj);            img.__isDirty = true          }          curContext.drawImage(getCanvasData(obj).canvas, 0, 0, img.width, img.height, bounds.x, bounds.y, bounds.w, bounds.h)        }      }    };    Drawing3D.prototype.image = function(img, x, y, w, h) {      if (img.width > 0) {        x = Math.round(x);        y = Math.round(y);        w = w || img.width;        h = h || img.height;        p.beginShape(p.QUADS);        p.texture(img);        p.vertex(x, y, 0, 0, 0);        p.vertex(x, y + h, 0, 0, h);        p.vertex(x + w, y + h, 0, w, h);        p.vertex(x + w, y, 0, w, 0);        p.endShape()      }    };    p.tint = function(a1, a2, a3, a4) {      var tintColor = p.color(a1, a2, a3, a4);      var r = p.red(tintColor) / colorModeX;      var g = p.green(tintColor) / colorModeY;      var b = p.blue(tintColor) / colorModeZ;      var a = p.alpha(tintColor) / colorModeA;      curTint = function(obj) {        var data = obj.data,          length = 4 * obj.width * obj.height;        for (var i = 0; i < length;) {          data[i++] *= r;          data[i++] *= g;          data[i++] *= b;          data[i++] *= a        }      };      curTint3d = function(data) {        for (var i = 0; i < data.length;) {          data[i++] = r;          data[i++] = g;          data[i++] = b;          data[i++] = a        }      }    };    p.noTint = function() {      curTint = null;      curTint3d = null    };    p.copy = function(src, sx, sy, sw, sh, dx, dy, dw, dh) {      if (dh === undef) {        dh = dw;        dw = dy;        dy = dx;        dx = sh;        sh = sw;        sw = sy;        sy = sx;        sx = src;        src = p      }      p.blend(src, sx, sy, sw, sh, dx, dy, dw, dh, 0)    };    p.blend = function(src, sx, sy, sw, sh, dx, dy, dw, dh, mode, pimgdest) {      if (src.isRemote) throw "Image is loaded remotely. Cannot blend image.";      if (mode === undef) {        mode = dh;        dh = dw;        dw = dy;        dy = dx;        dx = sh;        sh = sw;        sw = sy;        sy = sx;        sx = src;        src = p      }      var sx2 = sx + sw,        sy2 = sy + sh,        dx2 = dx + dw,        dy2 = dy + dh,        dest = pimgdest || p;      if (pimgdest === undef || mode === undef) p.loadPixels();      src.loadPixels();      if (src === p && p.intersect(sx, sy, sx2, sy2, dx, dy, dx2, dy2)) p.blit_resize(p.get(sx, sy, sx2 - sx, sy2 - sy), 0, 0, sx2 - sx - 1, sy2 - sy - 1, dest.imageData.data, dest.width, dest.height, dx, dy, dx2, dy2, mode);      else p.blit_resize(src, sx, sy, sx2, sy2, dest.imageData.data, dest.width, dest.height, dx, dy, dx2, dy2, mode);      if (pimgdest === undef) p.updatePixels()    };    var buildBlurKernel = function(r) {      var radius = p.floor(r * 3.5),        i, radiusi;      radius = radius < 1 ? 1 : radius < 248 ? radius : 248;      if (p.shared.blurRadius !== radius) {        p.shared.blurRadius = radius;        p.shared.blurKernelSize = 1 + (p.shared.blurRadius << 1);        p.shared.blurKernel = new Float32Array(p.shared.blurKernelSize);        var sharedBlurKernal = p.shared.blurKernel;        var sharedBlurKernelSize = p.shared.blurKernelSize;        var sharedBlurRadius = p.shared.blurRadius;        for (i = 0; i < sharedBlurKernelSize; i++) sharedBlurKernal[i] = 0;        var radiusiSquared = (radius - 1) * (radius - 1);        for (i = 1; i < radius; i++) sharedBlurKernal[radius + i] = sharedBlurKernal[radiusi] = radiusiSquared;        sharedBlurKernal[radius] = radius * radius      }    };    var blurARGB = function(r, aImg) {      var sum, cr, cg, cb, ca, c, m;      var read, ri, ym, ymi, bk0;      var wh = aImg.pixels.getLength();      var r2 = new Float32Array(wh);      var g2 = new Float32Array(wh);      var b2 = new Float32Array(wh);      var a2 = new Float32Array(wh);      var yi = 0;      var x, y, i, offset;      buildBlurKernel(r);      var aImgHeight = aImg.height;      var aImgWidth = aImg.width;      var sharedBlurKernelSize = p.shared.blurKernelSize;      var sharedBlurRadius = p.shared.blurRadius;      var sharedBlurKernal = p.shared.blurKernel;      var pix = aImg.imageData.data;      for (y = 0; y < aImgHeight; y++) {        for (x = 0; x < aImgWidth; x++) {          cb = cg = cr = ca = sum = 0;          read = x - sharedBlurRadius;          if (read < 0) {            bk0 = -read;            read = 0          } else {            if (read >= aImgWidth) break;            bk0 = 0          }          for (i = bk0; i < sharedBlurKernelSize; i++) {            if (read >= aImgWidth) break;            offset = (read + yi) * 4;            m = sharedBlurKernal[i];            ca += m * pix[offset + 3];            cr += m * pix[offset];            cg += m * pix[offset + 1];            cb += m * pix[offset + 2];            sum += m;            read++          }          ri = yi + x;          a2[ri] = ca / sum;          r2[ri] = cr / sum;          g2[ri] = cg / sum;          b2[ri] = cb / sum        }        yi += aImgWidth      }      yi = 0;      ym = -sharedBlurRadius;      ymi = ym * aImgWidth;      for (y = 0; y < aImgHeight; y++) {        for (x = 0; x < aImgWidth; x++) {          cb = cg = cr = ca = sum = 0;          if (ym < 0) {            bk0 = ri = -ym;            read = x          } else {            if (ym >= aImgHeight) break;            bk0 = 0;            ri = ym;            read = x + ymi          }          for (i = bk0; i < sharedBlurKernelSize; i++) {            if (ri >= aImgHeight) break;            m = sharedBlurKernal[i];            ca += m * a2[read];            cr += m * r2[read];            cg += m * g2[read];            cb += m * b2[read];            sum += m;            ri++;            read += aImgWidth          }          offset = (x + yi) * 4;          pix[offset] = cr / sum;          pix[offset + 1] = cg / sum;          pix[offset + 2] = cb / sum;          pix[offset + 3] = ca / sum        }        yi += aImgWidth;        ymi += aImgWidth;        ym++      }    };    var dilate = function(isInverted, aImg) {      var currIdx = 0;      var maxIdx = aImg.pixels.getLength();      var out = new Int32Array(maxIdx);      var currRowIdx, maxRowIdx, colOrig, colOut, currLum;      var idxRight, idxLeft, idxUp, idxDown, colRight, colLeft, colUp, colDown, lumRight, lumLeft, lumUp, lumDown;      if (!isInverted) while (currIdx < maxIdx) {        currRowIdx = currIdx;        maxRowIdx = currIdx + aImg.width;        while (currIdx < maxRowIdx) {          colOrig = colOut = aImg.pixels.getPixel(currIdx);          idxLeft = currIdx - 1;          idxRight = currIdx + 1;          idxUp = currIdx - aImg.width;          idxDown = currIdx + aImg.width;          if (idxLeft < currRowIdx) idxLeft = currIdx;          if (idxRight >= maxRowIdx) idxRight = currIdx;          if (idxUp < 0) idxUp = 0;          if (idxDown >= maxIdx) idxDown = currIdx;          colUp = aImg.pixels.getPixel(idxUp);          colLeft = aImg.pixels.getPixel(idxLeft);          colDown = aImg.pixels.getPixel(idxDown);          colRight = aImg.pixels.getPixel(idxRight);          currLum = 77 * (colOrig >> 16 & 255) + 151 * (colOrig >> 8 & 255) + 28 * (colOrig & 255);          lumLeft = 77 * (colLeft >> 16 & 255) + 151 * (colLeft >> 8 & 255) + 28 * (colLeft & 255);          lumRight = 77 * (colRight >> 16 & 255) + 151 * (colRight >> 8 & 255) + 28 * (colRight & 255);          lumUp = 77 * (colUp >> 16 & 255) + 151 * (colUp >> 8 & 255) + 28 * (colUp & 255);          lumDown = 77 * (colDown >> 16 & 255) + 151 * (colDown >> 8 & 255) + 28 * (colDown & 255);          if (lumLeft > currLum) {            colOut = colLeft;            currLum = lumLeft          }          if (lumRight > currLum) {            colOut = colRight;            currLum = lumRight          }          if (lumUp > currLum) {            colOut = colUp;            currLum = lumUp          }          if (lumDown > currLum) {            colOut = colDown;            currLum = lumDown          }          out[currIdx++] = colOut        }      } else while (currIdx < maxIdx) {        currRowIdx = currIdx;        maxRowIdx = currIdx + aImg.width;        while (currIdx < maxRowIdx) {          colOrig = colOut = aImg.pixels.getPixel(currIdx);          idxLeft = currIdx - 1;          idxRight = currIdx + 1;          idxUp = currIdx - aImg.width;          idxDown = currIdx + aImg.width;          if (idxLeft < currRowIdx) idxLeft = currIdx;          if (idxRight >= maxRowIdx) idxRight = currIdx;          if (idxUp < 0) idxUp = 0;          if (idxDown >= maxIdx) idxDown = currIdx;          colUp = aImg.pixels.getPixel(idxUp);          colLeft = aImg.pixels.getPixel(idxLeft);          colDown = aImg.pixels.getPixel(idxDown);          colRight = aImg.pixels.getPixel(idxRight);          currLum = 77 * (colOrig >> 16 & 255) + 151 * (colOrig >> 8 & 255) + 28 * (colOrig & 255);          lumLeft = 77 * (colLeft >> 16 & 255) + 151 * (colLeft >> 8 & 255) + 28 * (colLeft & 255);          lumRight = 77 * (colRight >> 16 & 255) + 151 * (colRight >> 8 & 255) + 28 * (colRight & 255);          lumUp = 77 * (colUp >> 16 & 255) + 151 * (colUp >> 8 & 255) + 28 * (colUp & 255);          lumDown = 77 * (colDown >> 16 & 255) + 151 * (colDown >> 8 & 255) + 28 * (colDown & 255);          if (lumLeft < currLum) {            colOut = colLeft;            currLum = lumLeft          }          if (lumRight < currLum) {            colOut = colRight;            currLum = lumRight          }          if (lumUp < currLum) {            colOut = colUp;            currLum = lumUp          }          if (lumDown < currLum) {            colOut = colDown;            currLum = lumDown          }          out[currIdx++] = colOut        }      }      aImg.pixels.set(out)    };    p.filter = function(kind, param, aImg) {      var img, col, lum, i;      if (arguments.length === 3) {        aImg.loadPixels();        img = aImg      } else {        p.loadPixels();        img = p      }      if (param === undef) param = null;      if (img.isRemote) throw "Image is loaded remotely. Cannot filter image.";      var imglen = img.pixels.getLength();      switch (kind) {      case 11:        var radius = param || 1;        blurARGB(radius, img);        break;      case 12:        if (img.format === 4) {          for (i = 0; i < imglen; i++) {            col = 255 - img.pixels.getPixel(i);            img.pixels.setPixel(i, 4278190080 | col << 16 | col << 8 | col)          }          img.format = 1        } else for (i = 0; i < imglen; i++) {          col = img.pixels.getPixel(i);          lum = 77 * (col >> 16 & 255) + 151 * (col >> 8 & 255) + 28 * (col & 255) >> 8;          img.pixels.setPixel(i, col & 4278190080 | lum << 16 | lum << 8 | lum)        }        break;      case 13:        for (i = 0; i < imglen; i++) img.pixels.setPixel(i, img.pixels.getPixel(i) ^ 16777215);        break;      case 15:        if (param === null) throw "Use filter(POSTERIZE, int levels) instead of filter(POSTERIZE)";        var levels = p.floor(param);        if (levels < 2 || levels > 255) throw "Levels must be between 2 and 255 for filter(POSTERIZE, levels)";        var levels1 = levels - 1;        for (i = 0; i < imglen; i++) {          var rlevel = img.pixels.getPixel(i) >> 16 & 255;          var glevel = img.pixels.getPixel(i) >> 8 & 255;          var blevel = img.pixels.getPixel(i) & 255;          rlevel = (rlevel * levels >> 8) * 255 / levels1;          glevel = (glevel * levels >> 8) * 255 / levels1;          blevel = (blevel * levels >> 8) * 255 / levels1;          img.pixels.setPixel(i, 4278190080 & img.pixels.getPixel(i) | rlevel << 16 | glevel << 8 | blevel)        }        break;      case 14:        for (i = 0; i < imglen; i++) img.pixels.setPixel(i, img.pixels.getPixel(i) | 4278190080);        img.format = 1;        break;      case 16:        if (param === null) param = 0.5;        if (param < 0 || param > 1) throw "Level must be between 0 and 1 for filter(THRESHOLD, level)";        var thresh = p.floor(param * 255);        for (i = 0; i < imglen; i++) {          var max = p.max((img.pixels.getPixel(i) & 16711680) >> 16, p.max((img.pixels.getPixel(i) & 65280) >> 8, img.pixels.getPixel(i) & 255));          img.pixels.setPixel(i, img.pixels.getPixel(i) & 4278190080 | (max < thresh ? 0 : 16777215))        }        break;      case 17:        dilate(true, img);        break;      case 18:        dilate(false, img);        break      }      img.updatePixels()    };    p.shared = {      fracU: 0,      ifU: 0,      fracV: 0,      ifV: 0,      u1: 0,      u2: 0,      v1: 0,      v2: 0,      sX: 0,      sY: 0,      iw: 0,      iw1: 0,      ih1: 0,      ul: 0,      ll: 0,      ur: 0,      lr: 0,      cUL: 0,      cLL: 0,      cUR: 0,      cLR: 0,      srcXOffset: 0,      srcYOffset: 0,      r: 0,      g: 0,      b: 0,      a: 0,      srcBuffer: null,      blurRadius: 0,      blurKernelSize: 0,      blurKernel: null    };    p.intersect = function(sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2) {      var sw = sx2 - sx1 + 1;      var sh = sy2 - sy1 + 1;      var dw = dx2 - dx1 + 1;      var dh = dy2 - dy1 + 1;      if (dx1 < sx1) {        dw += dx1 - sx1;        if (dw > sw) dw = sw      } else {        var w = sw + sx1 - dx1;        if (dw > w) dw = w      }      if (dy1 < sy1) {        dh += dy1 - sy1;        if (dh > sh) dh = sh      } else {        var h = sh + sy1 - dy1;        if (dh > h) dh = h      }      return ! (dw <= 0 || dh <= 0)    };    var blendFuncs = {};    blendFuncs[1] = p.modes.blend;    blendFuncs[2] = p.modes.add;    blendFuncs[4] = p.modes.subtract;    blendFuncs[8] = p.modes.lightest;    blendFuncs[16] = p.modes.darkest;    blendFuncs[0] = p.modes.replace;    blendFuncs[32] = p.modes.difference;    blendFuncs[64] = p.modes.exclusion;    blendFuncs[128] = p.modes.multiply;    blendFuncs[256] = p.modes.screen;    blendFuncs[512] = p.modes.overlay;    blendFuncs[1024] = p.modes.hard_light;    blendFuncs[2048] = p.modes.soft_light;    blendFuncs[4096] = p.modes.dodge;    blendFuncs[8192] = p.modes.burn;    p.blit_resize = function(img, srcX1, srcY1, srcX2, srcY2, destPixels, screenW, screenH, destX1, destY1, destX2, destY2, mode) {      var x, y;      if (srcX1 < 0) srcX1 = 0;      if (srcY1 < 0) srcY1 = 0;      if (srcX2 >= img.width) srcX2 = img.width - 1;      if (srcY2 >= img.height) srcY2 = img.height - 1;      var srcW = srcX2 - srcX1;      var srcH = srcY2 - srcY1;      var destW = destX2 - destX1;      var destH = destY2 - destY1;      if (destW <= 0 || destH <= 0 || srcW <= 0 || srcH <= 0 || destX1 >= screenW || destY1 >= screenH || srcX1 >= img.width || srcY1 >= img.height) return;      var dx = Math.floor(srcW / destW * 32768);      var dy = Math.floor(srcH / destH * 32768);      var pshared = p.shared;      pshared.srcXOffset = Math.floor(destX1 < 0 ? -destX1 * dx : srcX1 * 32768);      pshared.srcYOffset = Math.floor(destY1 < 0 ? -destY1 * dy : srcY1 * 32768);      if (destX1 < 0) {        destW += destX1;        destX1 = 0      }      if (destY1 < 0) {        destH += destY1;        destY1 = 0      }      destW = Math.min(destW, screenW - destX1);      destH = Math.min(destH, screenH - destY1);      var destOffset = destY1 * screenW + destX1;      var destColor;      pshared.srcBuffer = img.imageData.data;      pshared.iw = img.width;      pshared.iw1 = img.width - 1;      pshared.ih1 = img.height - 1;      var filterBilinear = p.filter_bilinear,        filterNewScanline = p.filter_new_scanline,        blendFunc = blendFuncs[mode],        blendedColor, idx, cULoffset, cURoffset, cLLoffset, cLRoffset, ALPHA_MASK = 4278190080,        RED_MASK = 16711680,        GREEN_MASK = 65280,        BLUE_MASK = 255,        PREC_MAXVAL = 32767,        PRECISIONB = 15,        PREC_RED_SHIFT = 1,        PREC_ALPHA_SHIFT = 9,        srcBuffer = pshared.srcBuffer,        min = Math.min;      for (y = 0; y < destH; y++) {        pshared.sX = pshared.srcXOffset;        pshared.fracV = pshared.srcYOffset & PREC_MAXVAL;        pshared.ifV = PREC_MAXVAL - pshared.fracV;        pshared.v1 = (pshared.srcYOffset >> PRECISIONB) * pshared.iw;        pshared.v2 = min((pshared.srcYOffset >> PRECISIONB) + 1, pshared.ih1) * pshared.iw;        for (x = 0; x < destW; x++) {          idx = (destOffset + x) * 4;          destColor = destPixels[idx + 3] << 24 & ALPHA_MASK | destPixels[idx] << 16 & RED_MASK | destPixels[idx + 1] << 8 & GREEN_MASK | destPixels[idx + 2] & BLUE_MASK;          pshared.fracU = pshared.sX & PREC_MAXVAL;          pshared.ifU = PREC_MAXVAL - pshared.fracU;          pshared.ul = pshared.ifU * pshared.ifV >> PRECISIONB;          pshared.ll = pshared.ifU * pshared.fracV >> PRECISIONB;          pshared.ur = pshared.fracU * pshared.ifV >> PRECISIONB;          pshared.lr = pshared.fracU * pshared.fracV >> PRECISIONB;          pshared.u1 = pshared.sX >> PRECISIONB;          pshared.u2 = min(pshared.u1 + 1, pshared.iw1);          cULoffset = (pshared.v1 + pshared.u1) * 4;          cURoffset = (pshared.v1 + pshared.u2) * 4;          cLLoffset = (pshared.v2 + pshared.u1) * 4;          cLRoffset = (pshared.v2 + pshared.u2) * 4;          pshared.cUL = srcBuffer[cULoffset + 3] << 24 & ALPHA_MASK | srcBuffer[cULoffset] << 16 & RED_MASK | srcBuffer[cULoffset + 1] << 8 & GREEN_MASK | srcBuffer[cULoffset + 2] & BLUE_MASK;          pshared.cUR = srcBuffer[cURoffset + 3] << 24 & ALPHA_MASK | srcBuffer[cURoffset] << 16 & RED_MASK | srcBuffer[cURoffset + 1] << 8 & GREEN_MASK | srcBuffer[cURoffset + 2] & BLUE_MASK;          pshared.cLL = srcBuffer[cLLoffset + 3] << 24 & ALPHA_MASK | srcBuffer[cLLoffset] << 16 & RED_MASK | srcBuffer[cLLoffset + 1] << 8 & GREEN_MASK | srcBuffer[cLLoffset + 2] & BLUE_MASK;          pshared.cLR = srcBuffer[cLRoffset + 3] << 24 & ALPHA_MASK | srcBuffer[cLRoffset] << 16 & RED_MASK | srcBuffer[cLRoffset + 1] << 8 & GREEN_MASK | srcBuffer[cLRoffset + 2] & BLUE_MASK;          pshared.r = pshared.ul * ((pshared.cUL & RED_MASK) >> 16) + pshared.ll * ((pshared.cLL & RED_MASK) >> 16) + pshared.ur * ((pshared.cUR & RED_MASK) >> 16) + pshared.lr * ((pshared.cLR & RED_MASK) >> 16) << PREC_RED_SHIFT & RED_MASK;          pshared.g = pshared.ul * (pshared.cUL & GREEN_MASK) + pshared.ll * (pshared.cLL & GREEN_MASK) + pshared.ur * (pshared.cUR & GREEN_MASK) + pshared.lr * (pshared.cLR & GREEN_MASK) >>> PRECISIONB & GREEN_MASK;          pshared.b = pshared.ul * (pshared.cUL & BLUE_MASK) + pshared.ll * (pshared.cLL & BLUE_MASK) + pshared.ur * (pshared.cUR & BLUE_MASK) + pshared.lr * (pshared.cLR & BLUE_MASK) >>> PRECISIONB;          pshared.a = pshared.ul * ((pshared.cUL & ALPHA_MASK) >>> 24) + pshared.ll * ((pshared.cLL & ALPHA_MASK) >>> 24) + pshared.ur * ((pshared.cUR & ALPHA_MASK) >>> 24) + pshared.lr * ((pshared.cLR & ALPHA_MASK) >>> 24) << PREC_ALPHA_SHIFT & ALPHA_MASK;          blendedColor = blendFunc(destColor, pshared.a | pshared.r | pshared.g | pshared.b);          destPixels[idx] = (blendedColor & RED_MASK) >>> 16;          destPixels[idx + 1] = (blendedColor & GREEN_MASK) >>> 8;          destPixels[idx + 2] = blendedColor & BLUE_MASK;          destPixels[idx + 3] = (blendedColor & ALPHA_MASK) >>> 24;          pshared.sX += dx        }        destOffset += screenW;        pshared.srcYOffset += dy      }    };    p.loadFont = function(name, size) {      if (name === undef) throw "font name required in loadFont.";      if (name.indexOf(".svg") === -1) {        if (size === undef) size = curTextFont.size;        return PFont.get(name, size)      }      var font = p.loadGlyphs(name);      return {        name: name,        css: "12px sans-serif",        glyph: true,        units_per_em: font.units_per_em,        horiz_adv_x: 1 / font.units_per_em * font.horiz_adv_x,        ascent: font.ascent,        descent: font.descent,        width: function(str) {          var width = 0;          var len = str.length;          for (var i = 0; i < len; i++) try {            width += parseFloat(p.glyphLook(p.glyphTable[name], str[i]).horiz_adv_x)          } catch(e) {            Processing.debug(e)          }          return width / p.glyphTable[name].units_per_em        }      }    };    p.createFont = function(name, size) {      return p.loadFont(name, size)    };    p.textFont = function(pfont, size) {      if (size !== undef) {        if (!pfont.glyph) pfont = PFont.get(pfont.name, size);        curTextSize = size      }      curTextFont = pfont;      curFontName = curTextFont.name;      curTextAscent = curTextFont.ascent;      curTextDescent = curTextFont.descent;      curTextLeading = curTextFont.leading;      var curContext = drawing.$ensureContext();      curContext.font = curTextFont.css    };    p.textSize = function(size) {      curTextFont = PFont.get(curFontName, size);      curTextSize = size;      curTextAscent = curTextFont.ascent;      curTextDescent = curTextFont.descent;      curTextLeading = curTextFont.leading;      var curContext = drawing.$ensureContext();      curContext.font = curTextFont.css    };    p.textAscent = function() {      return curTextAscent    };    p.textDescent = function() {      return curTextDescent    };    p.textLeading = function(leading) {      curTextLeading = leading    };    p.textAlign = function(xalign, yalign) {      horizontalTextAlignment = xalign;      verticalTextAlignment = yalign || 0    };    function toP5String(obj) {      if (obj instanceof String) return obj;      if (typeof obj === "number") {        if (obj === (0 | obj)) return obj.toString();        return p.nf(obj, 0, 3)      }      if (obj === null || obj === undef) return "";      return obj.toString()    }    Drawing2D.prototype.textWidth = function(str) {      var lines = toP5String(str).split(/\r?\n/g),        width = 0;      var i, linesCount = lines.length;      curContext.font = curTextFont.css;      for (i = 0; i < linesCount; ++i) width = Math.max(width, curTextFont.measureTextWidth(lines[i]));      return width | 0    };    Drawing3D.prototype.textWidth = function(str) {      var lines = toP5String(str).split(/\r?\n/g),        width = 0;      var i, linesCount = lines.length;      if (textcanvas === undef) textcanvas = document.createElement("canvas");      var textContext = textcanvas.getContext("2d");      textContext.font = curTextFont.css;      for (i = 0; i < linesCount; ++i) width = Math.max(width, textContext.measureText(lines[i]).width);      return width | 0    };    p.glyphLook = function(font, chr) {      try {        switch (chr) {        case "1":          return font.one;        case "2":          return font.two;        case "3":          return font.three;        case "4":          return font.four;        case "5":          return font.five;        case "6":          return font.six;        case "7":          return font.seven;        case "8":          return font.eight;        case "9":          return font.nine;        case "0":          return font.zero;        case " ":          return font.space;        case "$":          return font.dollar;        case "!":          return font.exclam;        case '"':          return font.quotedbl;        case "#":          return font.numbersign;        case "%":          return font.percent;        case "&":          return font.ampersand;        case "'":          return font.quotesingle;        case "(":          return font.parenleft;        case ")":          return font.parenright;        case "*":          return font.asterisk;        case "+":          return font.plus;        case ",":          return font.comma;        case "-":          return font.hyphen;        case ".":          return font.period;        case "/":          return font.slash;        case "_":          return font.underscore;        case ":":          return font.colon;        case ";":          return font.semicolon;        case "<":          return font.less;        case "=":          return font.equal;        case ">":          return font.greater;        case "?":          return font.question;        case "@":          return font.at;        case "[":          return font.bracketleft;        case "\\":          return font.backslash;        case "]":          return font.bracketright;        case "^":          return font.asciicircum;        case "`":          return font.grave;        case "{":          return font.braceleft;        case "|":          return font.bar;        case "}":          return font.braceright;        case "~":          return font.asciitilde;        default:          return font[chr]        }      } catch(e) {        Processing.debug(e)      }    };    Drawing2D.prototype.text$line = function(str, x, y, z, align) {      var textWidth = 0,        xOffset = 0;      if (!curTextFont.glyph) {        if (str && "fillText" in curContext) {          if (isFillDirty) {            curContext.fillStyle = p.color.toString(currentFillColor);            isFillDirty = false          }          if (align === 39 || align === 3) {            textWidth = curTextFont.measureTextWidth(str);            if (align === 39) xOffset = -textWidth;            else xOffset = -textWidth / 2          }          curContext.fillText(str, x + xOffset, y)        }      } else {        var font = p.glyphTable[curFontName];        saveContext();        curContext.translate(x, y + curTextSize);        if (align === 39 || align === 3) {          textWidth = font.width(str);          if (align === 39) xOffset = -textWidth;          else xOffset = -textWidth / 2        }        var upem = font.units_per_em,          newScale = 1 / upem * curTextSize;        curContext.scale(newScale, newScale);        for (var i = 0, len = str.length; i < len; i++) try {          p.glyphLook(font, str[i]).draw()        } catch(e) {          Processing.debug(e)        }        restoreContext()      }    };    Drawing3D.prototype.text$line = function(str, x, y, z, align) {      if (textcanvas === undef) textcanvas = document.createElement("canvas");      var oldContext = curContext;      curContext = textcanvas.getContext("2d");      curContext.font = curTextFont.css;      var textWidth = curTextFont.measureTextWidth(str);      textcanvas.width = textWidth;      textcanvas.height = curTextSize;      curContext = textcanvas.getContext("2d");      curContext.font = curTextFont.css;      curContext.textBaseline = "top";      Drawing2D.prototype.text$line(str, 0, 0, 0, 37);      var aspect = textcanvas.width / textcanvas.height;      curContext = oldContext;      curContext.bindTexture(curContext.TEXTURE_2D, textTex);      curContext.texImage2D(curContext.TEXTURE_2D, 0, curContext.RGBA, curContext.RGBA, curContext.UNSIGNED_BYTE, textcanvas);      curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_MAG_FILTER, curContext.LINEAR);      curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_MIN_FILTER, curContext.LINEAR);      curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_WRAP_T, curContext.CLAMP_TO_EDGE);      curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_WRAP_S, curContext.CLAMP_TO_EDGE);      var xOffset = 0;      if (align === 39) xOffset = -textWidth;      else if (align === 3) xOffset = -textWidth / 2;      var model = new PMatrix3D;      var scalefactor = curTextSize * 0.5;      model.translate(x + xOffset - scalefactor / 2, y - scalefactor, z);      model.scale(-aspect * scalefactor, -scalefactor, scalefactor);      model.translate(-1, -1, -1);      model.transpose();      var view = new PMatrix3D;      view.scale(1, -1, 1);      view.apply(modelView.array());      view.transpose();      curContext.useProgram(programObject2D);      vertexAttribPointer("aVertex2d", programObject2D, "aVertex", 3, textBuffer);      vertexAttribPointer("aTextureCoord2d", programObject2D, "aTextureCoord", 2, textureBuffer);      uniformi("uSampler2d", programObject2D, "uSampler", [0]);      uniformi("uIsDrawingText2d", programObject2D, "uIsDrawingText", true);      uniformMatrix("uModel2d", programObject2D, "uModel", false, model.array());      uniformMatrix("uView2d", programObject2D, "uView", false, view.array());      uniformf("uColor2d", programObject2D, "uColor", fillStyle);      curContext.bindBuffer(curContext.ELEMENT_ARRAY_BUFFER, indexBuffer);      curContext.drawElements(curContext.TRIANGLES, 6, curContext.UNSIGNED_SHORT, 0)    };    function text$4(str, x, y, z) {      var lines, linesCount;      if (str.indexOf("\n") < 0) {        lines = [str];        linesCount = 1      } else {        lines = str.split(/\r?\n/g);        linesCount = lines.length      }      var yOffset = 0;      if (verticalTextAlignment === 101) yOffset = curTextAscent + curTextDescent;      else if (verticalTextAlignment === 3) yOffset = curTextAscent / 2 - (linesCount - 1) * curTextLeading / 2;      else if (verticalTextAlignment === 102) yOffset = -(curTextDescent + (linesCount - 1) * curTextLeading);      for (var i = 0; i < linesCount; ++i) {        var line = lines[i];        drawing.text$line(line, x, y + yOffset, z, horizontalTextAlignment);        yOffset += curTextLeading      }    }    function text$6(str, x, y, width, height, z) {      if (str.length === 0 || width === 0 || height === 0) return;      if (curTextSize > height) return;      var spaceMark = -1;      var start = 0;      var lineWidth = 0;      var drawCommands = [];      for (var charPos = 0, len = str.length; charPos < len; charPos++) {        var currentChar = str[charPos];        var spaceChar = currentChar === " ";        var letterWidth = curTextFont.measureTextWidth(currentChar);        if (currentChar !== "\n" && lineWidth + letterWidth <= width) {          if (spaceChar) spaceMark = charPos;          lineWidth += letterWidth        } else {          if (spaceMark + 1 === start) if (charPos > 0) spaceMark = charPos;          else return;          if (currentChar === "\n") {            drawCommands.push({              text: str.substring(start, charPos),              width: lineWidth            });            start = charPos + 1          } else {            drawCommands.push({              text: str.substring(start, spaceMark + 1),              width: lineWidth            });            start = spaceMark + 1          }          lineWidth = 0;          charPos = start - 1        }      }      if (start < len) drawCommands.push({        text: str.substring(start),        width: lineWidth      });      var xOffset = 1,        yOffset = curTextAscent;      if (horizontalTextAlignment === 3) xOffset = width / 2;      else if (horizontalTextAlignment === 39) xOffset = width;      var linesCount = drawCommands.length,        visibleLines = Math.min(linesCount, Math.floor(height / curTextLeading));      if (verticalTextAlignment === 101) yOffset = curTextAscent + curTextDescent;      else if (verticalTextAlignment === 3) yOffset = height / 2 - curTextLeading * (visibleLines / 2 - 1);      else if (verticalTextAlignment === 102) yOffset = curTextDescent + curTextLeading;      var command, drawCommand, leading;      for (command = 0; command < linesCount; command++) {        leading = command * curTextLeading;        if (yOffset + leading > height - curTextDescent) break;        drawCommand = drawCommands[command];        drawing.text$line(drawCommand.text, x + xOffset, y + yOffset + leading, z, horizontalTextAlignment)      }    }    p.text = function() {      if (textMode === 5) return;      if (arguments.length === 3) text$4(toP5String(arguments[0]), arguments[1], arguments[2], 0);      else if (arguments.length === 4) text$4(toP5String(arguments[0]), arguments[1], arguments[2], arguments[3]);      else if (arguments.length === 5) text$6(toP5String(arguments[0]), arguments[1], arguments[2], arguments[3], arguments[4], 0);      else if (arguments.length === 6) text$6(toP5String(arguments[0]), arguments[1], arguments[2], arguments[3], arguments[4], arguments[5])    };    p.textMode = function(mode) {      textMode = mode    };    p.loadGlyphs = function(url) {      var x, y, cx, cy, nx, ny, d, a, lastCom, lenC, horiz_adv_x, getXY = "[0-9\\-]+",        path;      var regex = function(needle, hay) {        var i = 0,          results = [],          latest, regexp = new RegExp(needle, "g");        latest = results[i] = regexp.exec(hay);        while (latest) {          i++;          latest = results[i] = regexp.exec(hay)        }        return results      };      var buildPath = function(d) {        var c = regex("[A-Za-z][0-9\\- ]+|Z", d);        var beforePathDraw = function() {          saveContext();          return drawing.$ensureContext()        };        var afterPathDraw = function() {          executeContextFill();          executeContextStroke();          restoreContext()        };        path = "return {draw:function(){var curContext=beforePathDraw();curContext.beginPath();";        x = 0;        y = 0;        cx = 0;        cy = 0;        nx = 0;        ny = 0;        d = 0;        a = 0;        lastCom = "";        lenC = c.length - 1;        for (var j = 0; j < lenC; j++) {          var com = c[j][0],            xy = regex(getXY, com);          switch (com[0]) {          case "M":            x = parseFloat(xy[0][0]);            y = parseFloat(xy[1][0]);            path += "curContext.moveTo(" + x + "," + -y + ");";            break;          case "L":            x = parseFloat(xy[0][0]);            y = parseFloat(xy[1][0]);            path += "curContext.lineTo(" + x + "," + -y + ");";            break;          case "H":            x = parseFloat(xy[0][0]);            path += "curContext.lineTo(" + x + "," + -y + ");";            break;          case "V":            y = parseFloat(xy[0][0]);            path += "curContext.lineTo(" + x + "," + -y + ");";            break;          case "T":            nx = parseFloat(xy[0][0]);            ny = parseFloat(xy[1][0]);            if (lastCom === "Q" || lastCom === "T") {              d = Math.sqrt(Math.pow(x - cx, 2) + Math.pow(cy - y, 2));              a = Math.PI + Math.atan2(cx - x, cy - y);              cx = x + Math.sin(a) * d;              cy = y + Math.cos(a) * d            } else {              cx = x;              cy = y            }            path += "curContext.quadraticCurveTo(" + cx + "," + -cy + "," + nx + "," + -ny + ");";            x = nx;            y = ny;            break;          case "Q":            cx = parseFloat(xy[0][0]);            cy = parseFloat(xy[1][0]);            nx = parseFloat(xy[2][0]);            ny = parseFloat(xy[3][0]);            path += "curContext.quadraticCurveTo(" + cx + "," + -cy + "," + nx + "," + -ny + ");";            x = nx;            y = ny;            break;          case "Z":            path += "curContext.closePath();";            break          }          lastCom = com[0]        }        path += "afterPathDraw();";        path += "curContext.translate(" + horiz_adv_x + ",0);";        path += "}}";        return (new Function("beforePathDraw", "afterPathDraw", path))(beforePathDraw, afterPathDraw)      };      var parseSVGFont = function(svg) {        var font = svg.getElementsByTagName("font");        p.glyphTable[url].horiz_adv_x = font[0].getAttribute("horiz-adv-x");        var font_face = svg.getElementsByTagName("font-face")[0];        p.glyphTable[url].units_per_em = parseFloat(font_face.getAttribute("units-per-em"));        p.glyphTable[url].ascent = parseFloat(font_face.getAttribute("ascent"));        p.glyphTable[url].descent = parseFloat(font_face.getAttribute("descent"));        var glyph = svg.getElementsByTagName("glyph"),          len = glyph.length;        for (var i = 0; i < len; i++) {          var unicode = glyph[i].getAttribute("unicode");          var name = glyph[i].getAttribute("glyph-name");          horiz_adv_x = glyph[i].getAttribute("horiz-adv-x");          if (horiz_adv_x === null) horiz_adv_x = p.glyphTable[url].horiz_adv_x;          d = glyph[i].getAttribute("d");          if (d !== undef) {            path = buildPath(d);            p.glyphTable[url][name] = {              name: name,              unicode: unicode,              horiz_adv_x: horiz_adv_x,              draw: path.draw            }          }        }      };      var loadXML = function() {        var xmlDoc;        try {          xmlDoc = document.implementation.createDocument("", "", null)        } catch(e_fx_op) {          Processing.debug(e_fx_op.message);          return        }        try {          xmlDoc.async = false;          xmlDoc.load(url);          parseSVGFont(xmlDoc.getElementsByTagName("svg")[0])        } catch(e_sf_ch) {          Processing.debug(e_sf_ch);          try {            var xmlhttp = new window.XMLHttpRequest;            xmlhttp.open("GET", url, false);            xmlhttp.send(null);            parseSVGFont(xmlhttp.responseXML.documentElement)          } catch(e) {            Processing.debug(e_sf_ch)          }        }      };      p.glyphTable[url] = {};      loadXML(url);      return p.glyphTable[url]    };    p.param = function(name) {      var attributeName = "data-processing-" + name;      if (curElement.hasAttribute(attributeName)) return curElement.getAttribute(attributeName);      for (var i = 0, len = curElement.childNodes.length; i < len; ++i) {        var item = curElement.childNodes.item(i);        if (item.nodeType !== 1 || item.tagName.toLowerCase() !== "param") continue;        if (item.getAttribute("name") === name) return item.getAttribute("value")      }      if (curSketch.params.hasOwnProperty(name)) return curSketch.params[name];      return null    };    function wireDimensionalFunctions(mode) {      if (mode === "3D") drawing = new Drawing3D;      else if (mode === "2D") drawing = new Drawing2D;      else drawing = new DrawingPre;      for (var i in DrawingPre.prototype) if (DrawingPre.prototype.hasOwnProperty(i) && i.indexOf("$") < 0) p[i] = drawing[i];      drawing.$init()    }    function createDrawingPreFunction(name) {      return function() {        wireDimensionalFunctions("2D");        return drawing[name].apply(this, arguments)      }    }    DrawingPre.prototype.translate = createDrawingPreFunction("translate");    DrawingPre.prototype.transform = createDrawingPreFunction("transform");    DrawingPre.prototype.scale = createDrawingPreFunction("scale");    DrawingPre.prototype.pushMatrix = createDrawingPreFunction("pushMatrix");    DrawingPre.prototype.popMatrix = createDrawingPreFunction("popMatrix");    DrawingPre.prototype.resetMatrix = createDrawingPreFunction("resetMatrix");    DrawingPre.prototype.applyMatrix = createDrawingPreFunction("applyMatrix");    DrawingPre.prototype.rotate = createDrawingPreFunction("rotate");    DrawingPre.prototype.rotateZ = createDrawingPreFunction("rotateZ");    DrawingPre.prototype.shearX = createDrawingPreFunction("shearX");    DrawingPre.prototype.shearY = createDrawingPreFunction("shearY");    DrawingPre.prototype.redraw = createDrawingPreFunction("redraw");    DrawingPre.prototype.toImageData = createDrawingPreFunction("toImageData");    DrawingPre.prototype.ambientLight = createDrawingPreFunction("ambientLight");    DrawingPre.prototype.directionalLight = createDrawingPreFunction("directionalLight");    DrawingPre.prototype.lightFalloff = createDrawingPreFunction("lightFalloff");    DrawingPre.prototype.lightSpecular = createDrawingPreFunction("lightSpecular");    DrawingPre.prototype.pointLight = createDrawingPreFunction("pointLight");    DrawingPre.prototype.noLights = createDrawingPreFunction("noLights");    DrawingPre.prototype.spotLight = createDrawingPreFunction("spotLight");    DrawingPre.prototype.beginCamera = createDrawingPreFunction("beginCamera");    DrawingPre.prototype.endCamera = createDrawingPreFunction("endCamera");    DrawingPre.prototype.frustum = createDrawingPreFunction("frustum");    DrawingPre.prototype.box = createDrawingPreFunction("box");    DrawingPre.prototype.sphere = createDrawingPreFunction("sphere");    DrawingPre.prototype.ambient = createDrawingPreFunction("ambient");    DrawingPre.prototype.emissive = createDrawingPreFunction("emissive");    DrawingPre.prototype.shininess = createDrawingPreFunction("shininess");    DrawingPre.prototype.specular = createDrawingPreFunction("specular");    DrawingPre.prototype.fill = createDrawingPreFunction("fill");    DrawingPre.prototype.stroke = createDrawingPreFunction("stroke");    DrawingPre.prototype.strokeWeight = createDrawingPreFunction("strokeWeight");    DrawingPre.prototype.smooth = createDrawingPreFunction("smooth");    DrawingPre.prototype.noSmooth = createDrawingPreFunction("noSmooth");    DrawingPre.prototype.point = createDrawingPreFunction("point");    DrawingPre.prototype.vertex = createDrawingPreFunction("vertex");    DrawingPre.prototype.endShape = createDrawingPreFunction("endShape");    DrawingPre.prototype.bezierVertex = createDrawingPreFunction("bezierVertex");    DrawingPre.prototype.curveVertex = createDrawingPreFunction("curveVertex");    DrawingPre.prototype.curve = createDrawingPreFunction("curve");    DrawingPre.prototype.line = createDrawingPreFunction("line");    DrawingPre.prototype.bezier = createDrawingPreFunction("bezier");    DrawingPre.prototype.rect = createDrawingPreFunction("rect");    DrawingPre.prototype.ellipse = createDrawingPreFunction("ellipse");    DrawingPre.prototype.background = createDrawingPreFunction("background");    DrawingPre.prototype.image = createDrawingPreFunction("image");    DrawingPre.prototype.textWidth = createDrawingPreFunction("textWidth");    DrawingPre.prototype.text$line = createDrawingPreFunction("text$line");    DrawingPre.prototype.$ensureContext = createDrawingPreFunction("$ensureContext");    DrawingPre.prototype.$newPMatrix = createDrawingPreFunction("$newPMatrix");    DrawingPre.prototype.size = function(aWidth, aHeight, aMode) {      wireDimensionalFunctions(aMode === 2 ? "3D" : "2D");      p.size(aWidth, aHeight, aMode)    };    DrawingPre.prototype.$init = nop;    Drawing2D.prototype.$init = function() {      p.size(p.width, p.height);      curContext.lineCap = "round";      p.noSmooth();      p.disableContextMenu()    };    Drawing3D.prototype.$init = function() {      p.use3DContext = true;      p.disableContextMenu()    };    DrawingShared.prototype.$ensureContext = function() {      return curContext    };    function calculateOffset(curElement, event) {      var element = curElement,        offsetX = 0,        offsetY = 0;      p.pmouseX = p.mouseX;      p.pmouseY = p.mouseY;      if (element.offsetParent) {        do {          offsetX += element.offsetLeft;          offsetY += element.offsetTop        } while ( !! (element = element.offsetParent))      }      element = curElement;      do {        offsetX -= element.scrollLeft || 0;        offsetY -= element.scrollTop || 0      } while ( !! (element = element.parentNode));      offsetX += stylePaddingLeft;      offsetY += stylePaddingTop;      offsetX += styleBorderLeft;      offsetY += styleBorderTop;      offsetX += window.pageXOffset;      offsetY += window.pageYOffset;      return {        "X": offsetX,        "Y": offsetY      }    }    function updateMousePosition(curElement, event) {      var offset = calculateOffset(curElement, event);      p.mouseX = event.pageX - offset.X;      p.mouseY = event.pageY - offset.Y    }    function addTouchEventOffset(t) {      var offset = calculateOffset(t.changedTouches[0].target, t.changedTouches[0]),        i;      for (i = 0; i < t.touches.length; i++) {        var touch = t.touches[i];        touch.offsetX = touch.pageX - offset.X;        touch.offsetY = touch.pageY - offset.Y      }      for (i = 0; i < t.targetTouches.length; i++) {        var targetTouch = t.targetTouches[i];        targetTouch.offsetX = targetTouch.pageX - offset.X;        targetTouch.offsetY = targetTouch.pageY - offset.Y      }      for (i = 0; i < t.changedTouches.length; i++) {        var changedTouch = t.changedTouches[i];        changedTouch.offsetX = changedTouch.pageX - offset.X;        changedTouch.offsetY = changedTouch.pageY - offset.Y      }      return t    }    attachEventHandler(curElement, "touchstart", function(t) {      curElement.setAttribute("style", "-webkit-user-select: none");      curElement.setAttribute("onclick", "void(0)");      curElement.setAttribute("style", "-webkit-tap-highlight-color:rgba(0,0,0,0)");      for (var i = 0, ehl = eventHandlers.length; i < ehl; i++) {        var type = eventHandlers[i].type;        if (type === "mouseout" || type === "mousemove" || type === "mousedown" || type === "mouseup" || type === "DOMMouseScroll" || type === "mousewheel" || type === "touchstart") detachEventHandler(eventHandlers[i])      }      if (p.touchStart !== undef || p.touchMove !== undef || p.touchEnd !== undef || p.touchCancel !== undef) {        attachEventHandler(curElement, "touchstart", function(t) {          if (p.touchStart !== undef) {            t = addTouchEventOffset(t);            p.touchStart(t)          }        });        attachEventHandler(curElement, "touchmove", function(t) {          if (p.touchMove !== undef) {            t.preventDefault();            t = addTouchEventOffset(t);            p.touchMove(t)          }        });        attachEventHandler(curElement, "touchend", function(t) {          if (p.touchEnd !== undef) {            t = addTouchEventOffset(t);            p.touchEnd(t)          }        });        attachEventHandler(curElement, "touchcancel", function(t) {          if (p.touchCancel !== undef) {            t = addTouchEventOffset(t);            p.touchCancel(t)          }        })      } else {        attachEventHandler(curElement, "touchstart", function(e) {          updateMousePosition(curElement, e.touches[0]);          p.__mousePressed = true;          p.mouseDragging = false;          p.mouseButton = 37;          if (typeof p.mousePressed === "function") p.mousePressed()        });        attachEventHandler(curElement, "touchmove", function(e) {          e.preventDefault();          updateMousePosition(curElement, e.touches[0]);          if (typeof p.mouseMoved === "function" && !p.__mousePressed) p.mouseMoved();          if (typeof p.mouseDragged === "function" && p.__mousePressed) {            p.mouseDragged();            p.mouseDragging = true          }        });        attachEventHandler(curElement, "touchend", function(e) {          p.__mousePressed = false;          if (typeof p.mouseClicked === "function" && !p.mouseDragging) p.mouseClicked();          if (typeof p.mouseReleased === "function") p.mouseReleased()        })      }      curElement.dispatchEvent(t)    });    (function() {      var enabled = true,        contextMenu = function(e) {        e.preventDefault();        e.stopPropagation()      };      p.disableContextMenu = function() {        if (!enabled) return;        attachEventHandler(curElement, "contextmenu", contextMenu);        enabled = false      };      p.enableContextMenu = function() {        if (enabled) return;        detachEventHandler({          elem: curElement,          type: "contextmenu",          fn: contextMenu        });        enabled = true      }    })();    attachEventHandler(curElement, "mousemove", function(e) {      updateMousePosition(curElement, e);      if (typeof p.mouseMoved === "function" && !p.__mousePressed) p.mouseMoved();      if (typeof p.mouseDragged === "function" && p.__mousePressed) {        p.mouseDragged();        p.mouseDragging = true      }    });    attachEventHandler(curElement, "mouseout", function(e) {      if (typeof p.mouseOut === "function") p.mouseOut()    });    attachEventHandler(curElement, "mouseover", function(e) {      updateMousePosition(curElement, e);      if (typeof p.mouseOver === "function") p.mouseOver()    });    curElement.onmousedown = function() {      curElement.focus();      return false    };    attachEventHandler(curElement, "mousedown", function(e) {      p.__mousePressed = true;      p.mouseDragging = false;      switch (e.which) {      case 1:        p.mouseButton = 37;        break;      case 2:        p.mouseButton = 3;        break;      case 3:        p.mouseButton = 39;        break      }      if (typeof p.mousePressed === "function") p.mousePressed()    });    attachEventHandler(curElement, "mouseup", function(e) {      p.__mousePressed = false;      if (typeof p.mouseClicked === "function" && !p.mouseDragging) p.mouseClicked();      if (typeof p.mouseReleased === "function") p.mouseReleased()    });    var mouseWheelHandler = function(e) {      var delta = 0;      if (e.wheelDelta) {        delta = e.wheelDelta / 120;        if (window.opera) delta = -delta      } else if (e.detail) delta = -e.detail / 3;      p.mouseScroll = delta;      if (delta && typeof p.mouseScrolled === "function") p.mouseScrolled()    };    attachEventHandler(document, "DOMMouseScroll", mouseWheelHandler);    attachEventHandler(document, "mousewheel", mouseWheelHandler);    if (!curElement.getAttribute("tabindex")) curElement.setAttribute("tabindex", 0);    function getKeyCode(e) {      var code = e.which || e.keyCode;      switch (code) {      case 13:        return 10;      case 91:      case 93:      case 224:        return 157;      case 57392:        return 17;      case 46:        return 127;      case 45:        return 155      }      return code    }    function getKeyChar(e) {      var c = e.which || e.keyCode;      var anyShiftPressed = e.shiftKey || e.ctrlKey || e.altKey || e.metaKey;      switch (c) {      case 13:        c = anyShiftPressed ? 13 : 10;        break;      case 8:        c = anyShiftPressed ? 127 : 8;        break      }      return new Char(c)    }    function suppressKeyEvent(e) {      if (typeof e.preventDefault === "function") e.preventDefault();      else if (typeof e.stopPropagation === "function") e.stopPropagation();      return false    }    function updateKeyPressed() {      var ch;      for (ch in pressedKeysMap) if (pressedKeysMap.hasOwnProperty(ch)) {        p.__keyPressed = true;        return      }      p.__keyPressed = false    }    function resetKeyPressed() {      p.__keyPressed = false;      pressedKeysMap = [];      lastPressedKeyCode = null    }    function simulateKeyTyped(code, c) {      pressedKeysMap[code] = c;      lastPressedKeyCode = null;      p.key = c;      p.keyCode = code;      p.keyPressed();      p.keyCode = 0;      p.keyTyped();      updateKeyPressed()    }    function handleKeydown(e) {      var code = getKeyCode(e);      if (code === 127) {        simulateKeyTyped(code, new Char(127));        return      }      if (codedKeys.indexOf(code) < 0) {        lastPressedKeyCode = code;        return      }      var c = new Char(65535);      p.key = c;      p.keyCode = code;      pressedKeysMap[code] = c;      p.keyPressed();      lastPressedKeyCode = null;      updateKeyPressed();      return suppressKeyEvent(e)    }    function handleKeypress(e) {      if (lastPressedKeyCode === null) return;      var code = lastPressedKeyCode,        c = getKeyChar(e);      simulateKeyTyped(code, c);      return suppressKeyEvent(e)    }    function handleKeyup(e) {      var code = getKeyCode(e),        c = pressedKeysMap[code];      if (c === undef) return;      p.key = c;      p.keyCode = code;      p.keyReleased();      delete pressedKeysMap[code];      updateKeyPressed()    }    if (!pgraphicsMode) {      if (aCode instanceof Processing.Sketch) curSketch = aCode;      else if (typeof aCode === "function") curSketch = new Processing.Sketch(aCode);      else if (!aCode) curSketch = new Processing.Sketch(function() {});      else curSketch = Processing.compile(aCode);      p.externals.sketch = curSketch;      wireDimensionalFunctions();      curElement.onfocus = function() {        p.focused = true      };      curElement.onblur = function() {        p.focused = false;        if (!curSketch.options.globalKeyEvents) resetKeyPressed()      };      if (curSketch.options.pauseOnBlur) {        attachEventHandler(window, "focus", function() {          if (doLoop) p.loop()        });        attachEventHandler(window, "blur", function() {          if (doLoop && loopStarted) {            p.noLoop();            doLoop = true          }          resetKeyPressed()        })      }      var keyTrigger = curSketch.options.globalKeyEvents ? window : curElement;      attachEventHandler(keyTrigger, "keydown", handleKeydown);      attachEventHandler(keyTrigger, "keypress", handleKeypress);      attachEventHandler(keyTrigger, "keyup", handleKeyup);      for (var i in Processing.lib) if (Processing.lib.hasOwnProperty(i)) if (Processing.lib[i].hasOwnProperty("attach")) Processing.lib[i].attach(p);      else if (Processing.lib[i] instanceof Function) Processing.lib[i].call(this);      var retryInterval = 100;      var executeSketch = function(processing) {        if (! (curSketch.imageCache.pending || PFont.preloading.pending(retryInterval))) {          if (window.opera) {            var link, element, operaCache = curSketch.imageCache.operaCache;            for (link in operaCache) if (operaCache.hasOwnProperty(link)) {              element = operaCache[link];              if (element !== null) document.body.removeChild(element);              delete operaCache[link]            }          }          curSketch.attach(processing, defaultScope);          curSketch.onLoad(processing);          if (processing.setup) {            processing.setup();            processing.resetMatrix();            curSketch.onSetup()          }          resetContext();          if (processing.draw) if (!doLoop) processing.redraw();          else processing.loop()        } else window.setTimeout(function() {          executeSketch(processing)        },        retryInterval)      };      addInstance(this);      executeSketch(p)    } else {      curSketch = new Processing.Sketch;      wireDimensionalFunctions();      p.size = function(w, h, render) {        if (render && render === 2) wireDimensionalFunctions("3D");        else wireDimensionalFunctions("2D");        p.size(w, h, render)      }    }  };  Processing.debug = debug;  Processing.prototype = defaultScope;  function getGlobalMembers() {    var names = ["abs", "acos", "alpha", "ambient", "ambientLight", "append",      "applyMatrix", "arc", "arrayCopy", "asin", "atan", "atan2", "background", "beginCamera", "beginDraw", "beginShape", "bezier", "bezierDetail", "bezierPoint", "bezierTangent", "bezierVertex", "binary", "blend", "blendColor", "blit_resize", "blue", "box", "breakShape", "brightness", "camera", "ceil", "Character", "color", "colorMode", "concat", "constrain", "copy", "cos", "createFont", "createGraphics", "createImage", "cursor", "curve", "curveDetail", "curvePoint", "curveTangent", "curveTightness", "curveVertex", "day", "degrees", "directionalLight",      "disableContextMenu", "dist", "draw", "ellipse", "ellipseMode", "emissive", "enableContextMenu", "endCamera", "endDraw", "endShape", "exit", "exp", "expand", "externals", "fill", "filter", "floor", "focused", "frameCount", "frameRate", "frustum", "get", "glyphLook", "glyphTable", "green", "height", "hex", "hint", "hour", "hue", "image", "imageMode", "intersect", "join", "key", "keyCode", "keyPressed", "keyReleased", "keyTyped", "lerp", "lerpColor", "lightFalloff", "lights", "lightSpecular", "line", "link", "loadBytes", "loadFont", "loadGlyphs",      "loadImage", "loadPixels", "loadShape", "loadXML", "loadStrings", "log", "loop", "mag", "map", "match", "matchAll", "max", "millis", "min", "minute", "mix", "modelX", "modelY", "modelZ", "modes", "month", "mouseButton", "mouseClicked", "mouseDragged", "mouseMoved", "mouseOut", "mouseOver", "mousePressed", "mouseReleased", "mouseScroll", "mouseScrolled", "mouseX", "mouseY", "name", "nf", "nfc", "nfp", "nfs", "noCursor", "noFill", "noise", "noiseDetail", "noiseSeed", "noLights", "noLoop", "norm", "normal", "noSmooth", "noStroke", "noTint", "ortho",      "param", "parseBoolean", "parseByte", "parseChar", "parseFloat", "parseInt", "peg", "perspective", "PImage", "pixels", "PMatrix2D", "PMatrix3D", "PMatrixStack", "pmouseX", "pmouseY", "point", "pointLight", "popMatrix", "popStyle", "pow", "print", "printCamera", "println", "printMatrix", "printProjection", "PShape", "PShapeSVG", "pushMatrix", "pushStyle", "quad", "radians", "random", "Random", "randomSeed", "rect", "rectMode", "red", "redraw", "requestImage", "resetMatrix", "reverse", "rotate", "rotateX", "rotateY", "rotateZ", "round", "saturation",      "save", "saveFrame", "saveStrings", "scale", "screenX", "screenY", "screenZ", "second", "set", "setup", "shape", "shapeMode", "shared", "shearX", "shearY", "shininess", "shorten", "sin", "size", "smooth", "sort", "specular", "sphere", "sphereDetail", "splice", "split", "splitTokens", "spotLight", "sq", "sqrt", "status", "str", "stroke", "strokeCap", "strokeJoin", "strokeWeight", "subset", "tan", "text", "textAlign", "textAscent", "textDescent", "textFont", "textLeading", "textMode", "textSize", "texture", "textureMode", "textWidth", "tint", "toImageData",      "touchCancel", "touchEnd", "touchMove", "touchStart", "translate", "transform", "triangle", "trim", "unbinary", "unhex", "updatePixels", "use3DContext", "vertex", "width", "XMLElement", "XML", "year", "__contains", "__equals", "__equalsIgnoreCase", "__frameRate", "__hashCode", "__int_cast", "__instanceof", "__keyPressed", "__mousePressed", "__printStackTrace", "__replace", "__replaceAll", "__replaceFirst", "__toCharArray", "__split", "__codePointAt", "__startsWith", "__endsWith", "__matches"];    var members = {};    var i, l;    for (i = 0, l = names.length; i < l; ++i) members[names[i]] = null;    for (var lib in Processing.lib) if (Processing.lib.hasOwnProperty(lib)) if (Processing.lib[lib].exports) {      var exportedNames = Processing.lib[lib].exports;      for (i = 0, l = exportedNames.length; i < l; ++i) members[exportedNames[i]] = null    }    return members  }  function parseProcessing(code) {    var globalMembers = getGlobalMembers();    function splitToAtoms(code) {      var atoms = [];      var items = code.split(/([\{\[\(\)\]\}])/);      var result = items[0];      var stack = [];      for (var i = 1; i < items.length; i += 2) {        var item = items[i];        if (item === "[" || item === "{" || item === "(") {          stack.push(result);          result = item        } else if (item === "]" || item === "}" || item === ")") {          var kind = item === "}" ? "A" : item === ")" ? "B" : "C";          var index = atoms.length;          atoms.push(result + item);          result = stack.pop() + '"' + kind + (index + 1) + '"'        }        result += items[i + 1]      }      atoms.unshift(result);      return atoms    }    function injectStrings(code, strings) {      return code.replace(/'(\d+)'/g, function(all, index) {        var val = strings[index];        if (val.charAt(0) === "/") return val;        return /^'((?:[^'\\\n])|(?:\\.[0-9A-Fa-f]*))'$/.test(val) ? "(new $p.Character(" + val + "))" : val      })    }    function trimSpaces(string) {      var m1 = /^\s*/.exec(string),        result;      if (m1[0].length === string.length) result = {        left: m1[0],        middle: "",        right: ""      };      else {        var m2 = /\s*$/.exec(string);        result = {          left: m1[0],          middle: string.substring(m1[0].length, m2.index),          right: m2[0]        }      }      result.untrim = function(t) {        return this.left + t + this.right      };      return result    }    function trim(string) {      return string.replace(/^\s+/, "").replace(/\s+$/, "")    }    function appendToLookupTable(table, array) {      for (var i = 0, l = array.length; i < l; ++i) table[array[i]] = null;      return table    }    function isLookupTableEmpty(table) {      for (var i in table) if (table.hasOwnProperty(i)) return false;      return true    }    function getAtomIndex(templ) {      return templ.substring(2, templ.length - 1)    }    var codeWoExtraCr = code.replace(/\r\n?|\n\r/g, "\n");    var strings = [];    var codeWoStrings = codeWoExtraCr.replace(/("(?:[^"\\\n]|\\.)*")|('(?:[^'\\\n]|\\.)*')|(([\[\(=|&!\^:?]\s*)(\/(?![*\/])(?:[^\/\\\n]|\\.)*\/[gim]*)\b)|(\/\/[^\n]*\n)|(\/\*(?:(?!\*\/)(?:.|\n))*\*\/)/g, function(all, quoted, aposed, regexCtx, prefix, regex, singleComment, comment) {      var index;      if (quoted || aposed) {        index = strings.length;        strings.push(all);        return "'" + index + "'"      }      if (regexCtx) {        index = strings.length;        strings.push(regex);        return prefix + "'" + index + "'"      }      return comment !== "" ? " " : "\n"    });    codeWoStrings = codeWoStrings.replace(/__x([0-9A-F]{4})/g, function(all, hexCode) {      return "__x005F_x" + hexCode    });    codeWoStrings = codeWoStrings.replace(/\$/g, "__x0024");    var genericsWereRemoved;    var codeWoGenerics = codeWoStrings;    var replaceFunc = function(all, before, types, after) {      if ( !! before || !!after) return all;      genericsWereRemoved = true;      return ""    };    do {      genericsWereRemoved = false;      codeWoGenerics = codeWoGenerics.replace(/([<]?)<\s*((?:\?|[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*)(?:\[\])*(?:\s+(?:extends|super)\s+[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*)?(?:\s*,\s*(?:\?|[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*)(?:\[\])*(?:\s+(?:extends|super)\s+[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*)?)*)\s*>([=]?)/g, replaceFunc)    } while (genericsWereRemoved);    var atoms = splitToAtoms(codeWoGenerics);    var replaceContext;    var declaredClasses = {},      currentClassId, classIdSeed = 0;    function addAtom(text, type) {      var lastIndex = atoms.length;      atoms.push(text);      return '"' + type + lastIndex + '"'    }    function generateClassId() {      return "class" + ++classIdSeed    }    function appendClass(class_, classId, scopeId) {      class_.classId = classId;      class_.scopeId = scopeId;      declaredClasses[classId] = class_    }    var transformClassBody, transformInterfaceBody, transformStatementsBlock, transformStatements, transformMain, transformExpression;    var classesRegex = /\b((?:(?:public|private|final|protected|static|abstract)\s+)*)(class|interface)\s+([A-Za-z_$][\w$]*\b)(\s+extends\s+[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*(?:\s*,\s*[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*\b)*)?(\s+implements\s+[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*(?:\s*,\s*[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*\b)*)?\s*("A\d+")/g;    var methodsRegex = /\b((?:(?:public|private|final|protected|static|abstract|synchronized)\s+)*)((?!(?:else|new|return|throw|function|public|private|protected)\b)[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*(?:\s*"C\d+")*)\s*([A-Za-z_$][\w$]*\b)\s*("B\d+")(\s*throws\s+[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*(?:\s*,\s*[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*)*)?\s*("A\d+"|;)/g;    var fieldTest = /^((?:(?:public|private|final|protected|static)\s+)*)((?!(?:else|new|return|throw)\b)[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*(?:\s*"C\d+")*)\s*([A-Za-z_$][\w$]*\b)\s*(?:"C\d+"\s*)*([=,]|$)/;    var cstrsRegex = /\b((?:(?:public|private|final|protected|static|abstract)\s+)*)((?!(?:new|return|throw)\b)[A-Za-z_$][\w$]*\b)\s*("B\d+")(\s*throws\s+[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*(?:\s*,\s*[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*)*)?\s*("A\d+")/g;    var attrAndTypeRegex = /^((?:(?:public|private|final|protected|static)\s+)*)((?!(?:new|return|throw)\b)[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*(?:\s*"C\d+")*)\s*/;    var functionsRegex = /\bfunction(?:\s+([A-Za-z_$][\w$]*))?\s*("B\d+")\s*("A\d+")/g;    function extractClassesAndMethods(code) {      var s = code;      s = s.replace(classesRegex, function(all) {        return addAtom(all, "E")      });      s = s.replace(methodsRegex, function(all) {        return addAtom(all, "D")      });      s = s.replace(functionsRegex, function(all) {        return addAtom(all, "H")      });      return s    }    function extractConstructors(code, className) {      var result = code.replace(cstrsRegex, function(all, attr, name, params, throws_, body) {        if (name !== className) return all;        return addAtom(all, "G")      });      return result    }    function AstParam(name) {      this.name = name    }    AstParam.prototype.toString = function() {      return this.name    };    function AstParams(params, methodArgsParam) {      this.params = params;      this.methodArgsParam = methodArgsParam    }    AstParams.prototype.getNames = function() {      var names = [];      for (var i = 0, l = this.params.length; i < l; ++i) names.push(this.params[i].name);      return names    };    AstParams.prototype.prependMethodArgs = function(body) {      if (!this.methodArgsParam) return body;      return "{\nvar " + this.methodArgsParam.name + " = Array.prototype.slice.call(arguments, " + this.params.length + ");\n" + body.substring(1)    };    AstParams.prototype.toString = function() {      if (this.params.length === 0) return "()";      var result = "(";      for (var i = 0, l = this.params.length; i < l; ++i) result += this.params[i] + ", ";      return result.substring(0, result.length - 2) + ")"    };    function transformParams(params) {      var paramsWoPars = trim(params.substring(1, params.length - 1));      var result = [],        methodArgsParam = null;      if (paramsWoPars !== "") {        var paramList = paramsWoPars.split(",");        for (var i = 0; i < paramList.length; ++i) {          var param = /\b([A-Za-z_$][\w$]*\b)(\s*"[ABC][\d]*")*\s*$/.exec(paramList[i]);          if (i === paramList.length - 1 && paramList[i].indexOf("...") >= 0) {            methodArgsParam = new AstParam(param[1]);            break          }          result.push(new AstParam(param[1]))        }      }      return new AstParams(result, methodArgsParam)    }    function preExpressionTransform(expr) {      var s = expr;      s = s.replace(/\bnew\s+([A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*)(?:\s*"C\d+")+\s*("A\d+")/g, function(all, type, init) {        return init      });      s = s.replace(/\bnew\s+([A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*)(?:\s*"B\d+")\s*("A\d+")/g, function(all, type, init) {        return addAtom(all, "F")      });      s = s.replace(functionsRegex, function(all) {        return addAtom(all, "H")      });      s = s.replace(/\bnew\s+([A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*)\s*("C\d+"(?:\s*"C\d+")*)/g, function(all, type, index) {        var args = index.replace(/"C(\d+)"/g, function(all, j) {          return atoms[j]        }).replace(/\[\s*\]/g, "[null]").replace(/\s*\]\s*\[\s*/g, ", ");        var arrayInitializer = "{" + args.substring(1, args.length - 1) + "}";        var createArrayArgs = "('" + type + "', " + addAtom(arrayInitializer, "A") + ")";        return "$p.createJavaArray" + addAtom(createArrayArgs, "B")      });      s = s.replace(/(\.\s*length)\s*"B\d+"/g, "$1");      s = s.replace(/#([0-9A-Fa-f]{6})\b/g, function(all, digits) {        return "0xFF" + digits      });      s = s.replace(/"B(\d+)"(\s*(?:[\w$']|"B))/g, function(all, index, next) {        var atom = atoms[index];        if (!/^\(\s*[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*\s*(?:"C\d+"\s*)*\)$/.test(atom)) return all;        if (/^\(\s*int\s*\)$/.test(atom)) return "(int)" + next;        var indexParts = atom.split(/"C(\d+)"/g);        if (indexParts.length > 1) if (!/^\[\s*\]$/.test(atoms[indexParts[1]])) return all;        return "" + next      });      s = s.replace(/\(int\)([^,\]\)\}\?\:\*\+\-\/\^\|\%\&\~<\>\=]+)/g, function(all, arg) {        var trimmed = trimSpaces(arg);        return trimmed.untrim("__int_cast(" + trimmed.middle + ")")      });      s = s.replace(/\bsuper(\s*"B\d+")/g, "$$superCstr$1").replace(/\bsuper(\s*\.)/g, "$$super$1");      s = s.replace(/\b0+((\d*)(?:\.[\d*])?(?:[eE][\-\+]?\d+)?[fF]?)\b/, function(all, numberWo0, intPart) {        if (numberWo0 === intPart) return all;        return intPart === "" ? "0" + numberWo0 : numberWo0      });      s = s.replace(/\b(\.?\d+\.?)[fF]\b/g, "$1");      s = s.replace(/([^\s])%([^=\s])/g, "$1 % $2");      s = s.replace(/\b(frameRate|keyPressed|mousePressed)\b(?!\s*"B)/g, "__$1");      s = s.replace(/\b(boolean|byte|char|float|int)\s*"B/g, function(all, name) {        return "parse" + name.substring(0, 1).toUpperCase() + name.substring(1) + '"B'      });      s = s.replace(/\bpixels\b\s*(("C(\d+)")|\.length)?(\s*=(?!=)([^,\]\)\}]+))?/g, function(all, indexOrLength, index, atomIndex, equalsPart, rightSide) {        if (index) {          var atom = atoms[atomIndex];          if (equalsPart) return "pixels.setPixel" + addAtom("(" + atom.substring(1, atom.length - 1) + "," + rightSide + ")", "B");          return "pixels.getPixel" + addAtom("(" + atom.substring(1, atom.length - 1) + ")", "B")        }        if (indexOrLength) return "pixels.getLength" + addAtom("()", "B");        if (equalsPart) return "pixels.set" + addAtom("(" + rightSide + ")", "B");        return "pixels.toArray" + addAtom("()", "B")      });      var repeatJavaReplacement;      function replacePrototypeMethods(all, subject, method, atomIndex) {        var atom = atoms[atomIndex];        repeatJavaReplacement = true;        var trimmed = trimSpaces(atom.substring(1, atom.length - 1));        return "__" + method + (trimmed.middle === "" ? addAtom("(" + subject.replace(/\.\s*$/, "") + ")", "B") : addAtom("(" + subject.replace(/\.\s*$/, "") + "," + trimmed.middle + ")", "B"))      }      do {        repeatJavaReplacement = false;        s = s.replace(/((?:'\d+'|\b[A-Za-z_$][\w$]*\s*(?:"[BC]\d+")*)\s*\.\s*(?:[A-Za-z_$][\w$]*\s*(?:"[BC]\d+"\s*)*\.\s*)*)(replace|replaceAll|replaceFirst|contains|equals|equalsIgnoreCase|hashCode|toCharArray|printStackTrace|split|startsWith|endsWith|codePointAt|matches)\s*"B(\d+)"/g, replacePrototypeMethods)      } while (repeatJavaReplacement);      function replaceInstanceof(all, subject, type) {        repeatJavaReplacement = true;        return "__instanceof" + addAtom("(" + subject + ", " + type + ")", "B")      }      do {        repeatJavaReplacement = false;        s = s.replace(/((?:'\d+'|\b[A-Za-z_$][\w$]*\s*(?:"[BC]\d+")*)\s*(?:\.\s*[A-Za-z_$][\w$]*\s*(?:"[BC]\d+"\s*)*)*)instanceof\s+([A-Za-z_$][\w$]*\s*(?:\.\s*[A-Za-z_$][\w$]*)*)/g, replaceInstanceof)      } while (repeatJavaReplacement);      s = s.replace(/\bthis(\s*"B\d+")/g, "$$constr$1");      return s    }    function AstInlineClass(baseInterfaceName, body) {      this.baseInterfaceName = baseInterfaceName;      this.body = body;      body.owner = this    }    AstInlineClass.prototype.toString = function() {      return "new (" + this.body + ")"    };    function transformInlineClass(class_) {      var m = (new RegExp(/\bnew\s*([A-Za-z_$][\w$]*\s*(?:\.\s*[A-Za-z_$][\w$]*)*)\s*"B\d+"\s*"A(\d+)"/)).exec(class_);      var oldClassId = currentClassId,        newClassId = generateClassId();      currentClassId = newClassId;      var uniqueClassName = m[1] + "$" + newClassId;      var inlineClass = new AstInlineClass(uniqueClassName, transformClassBody(atoms[m[2]], uniqueClassName, "", "implements " + m[1]));      appendClass(inlineClass, newClassId, oldClassId);      currentClassId = oldClassId;      return inlineClass    }    function AstFunction(name, params, body) {      this.name = name;      this.params = params;      this.body = body    }    AstFunction.prototype.toString = function() {      var oldContext = replaceContext;      var names = appendToLookupTable({        "this": null      },      this.params.getNames());      replaceContext = function(subject) {        return names.hasOwnProperty(subject.name) ? subject.name : oldContext(subject)      };      var result = "function";      if (this.name) result += " " + this.name;      var body = this.params.prependMethodArgs(this.body.toString());      result += this.params + " " + body;      replaceContext = oldContext;      return result    };    function transformFunction(class_) {      var m = (new RegExp(/\b([A-Za-z_$][\w$]*)\s*"B(\d+)"\s*"A(\d+)"/)).exec(class_);      return new AstFunction(m[1] !== "function" ? m[1] : null, transformParams(atoms[m[2]]), transformStatementsBlock(atoms[m[3]]))    }    function AstInlineObject(members) {      this.members = members    }    AstInlineObject.prototype.toString = function() {      var oldContext = replaceContext;      replaceContext = function(subject) {        return subject.name === "this" ? "this" : oldContext(subject)      };      var result = "";      for (var i = 0, l = this.members.length; i < l; ++i) {        if (this.members[i].label) result += this.members[i].label + ": ";        result += this.members[i].value.toString() + ", "      }      replaceContext = oldContext;      return result.substring(0, result.length - 2)    };    function transformInlineObject(obj) {      var members = obj.split(",");      for (var i = 0; i < members.length; ++i) {        var label = members[i].indexOf(":");        if (label < 0) members[i] = {          value: transformExpression(members[i])        };        else members[i] = {          label: trim(members[i].substring(0, label)),          value: transformExpression(trim(members[i].substring(label + 1)))        }      }      return new AstInlineObject(members)    }    function expandExpression(expr) {      if (expr.charAt(0) === "(" || expr.charAt(0) === "[") return expr.charAt(0) + expandExpression(expr.substring(1, expr.length - 1)) + expr.charAt(expr.length - 1);      if (expr.charAt(0) === "{") {        if (/^\{\s*(?:[A-Za-z_$][\w$]*|'\d+')\s*:/.test(expr)) return "{" + addAtom(expr.substring(1, expr.length - 1), "I") + "}";        return "[" + expandExpression(expr.substring(1, expr.length - 1)) + "]"      }      var trimmed = trimSpaces(expr);      var result = preExpressionTransform(trimmed.middle);      result = result.replace(/"[ABC](\d+)"/g, function(all, index) {        return expandExpression(atoms[index])      });      return trimmed.untrim(result)    }    function replaceContextInVars(expr) {      return expr.replace(/(\.\s*)?((?:\b[A-Za-z_]|\$)[\w$]*)(\s*\.\s*([A-Za-z_$][\w$]*)(\s*\()?)?/g, function(all, memberAccessSign, identifier, suffix, subMember, callSign) {        if (memberAccessSign) return all;        var subject = {          name: identifier,          member: subMember,          callSign: !!callSign        };        return replaceContext(subject) + (suffix === undef ? "" : suffix)      })    }    function AstExpression(expr, transforms) {      this.expr = expr;      this.transforms = transforms    }    AstExpression.prototype.toString = function() {      var transforms = this.transforms;      var expr = replaceContextInVars(this.expr);      return expr.replace(/"!(\d+)"/g, function(all, index) {        return transforms[index].toString()      })    };    transformExpression = function(expr) {      var transforms = [];      var s = expandExpression(expr);      s = s.replace(/"H(\d+)"/g, function(all, index) {        transforms.push(transformFunction(atoms[index]));        return '"!' + (transforms.length - 1) + '"'      });      s = s.replace(/"F(\d+)"/g, function(all, index) {        transforms.push(transformInlineClass(atoms[index]));        return '"!' + (transforms.length - 1) + '"'      });      s = s.replace(/"I(\d+)"/g, function(all, index) {        transforms.push(transformInlineObject(atoms[index]));        return '"!' + (transforms.length - 1) + '"'      });      return new AstExpression(s, transforms)    };    function AstVarDefinition(name, value, isDefault) {      this.name = name;      this.value = value;      this.isDefault = isDefault    }    AstVarDefinition.prototype.toString = function() {      return this.name + " = " + this.value    };    function transformVarDefinition(def, defaultTypeValue) {      var eqIndex = def.indexOf("=");      var name, value, isDefault;      if (eqIndex < 0) {        name = def;        value = defaultTypeValue;        isDefault = true      } else {        name = def.substring(0, eqIndex);        value = transformExpression(def.substring(eqIndex + 1));        isDefault = false      }      return new AstVarDefinition(trim(name.replace(/(\s*"C\d+")+/g, "")), value, isDefault)    }    function getDefaultValueForType(type) {      if (type === "int" || type === "float") return "0";      if (type === "boolean") return "false";      if (type === "color") return "0x00000000";      return "null"    }    function AstVar(definitions, varType) {      this.definitions = definitions;      this.varType = varType    }    AstVar.prototype.getNames = function() {      var names = [];      for (var i = 0, l = this.definitions.length; i < l; ++i) names.push(this.definitions[i].name);      return names    };    AstVar.prototype.toString = function() {      return "var " + this.definitions.join(",")    };    function AstStatement(expression) {      this.expression = expression    }    AstStatement.prototype.toString = function() {      return this.expression.toString()    };    function transformStatement(statement) {      if (fieldTest.test(statement)) {        var attrAndType = attrAndTypeRegex.exec(statement);        var definitions = statement.substring(attrAndType[0].length).split(",");        var defaultTypeValue = getDefaultValueForType(attrAndType[2]);        for (var i = 0; i < definitions.length; ++i) definitions[i] = transformVarDefinition(definitions[i], defaultTypeValue);        return new AstVar(definitions, attrAndType[2])      }      return new AstStatement(transformExpression(statement))    }    function AstForExpression(initStatement, condition, step) {      this.initStatement = initStatement;      this.condition = condition;      this.step = step    }    AstForExpression.prototype.toString = function() {      return "(" + this.initStatement + "; " + this.condition + "; " + this.step + ")"    };    function AstForInExpression(initStatement, container) {      this.initStatement = initStatement;      this.container = container    }    AstForInExpression.prototype.toString = function() {      var init = this.initStatement.toString();      if (init.indexOf("=") >= 0) init = init.substring(0, init.indexOf("="));      return "(" + init + " in " + this.container + ")"    };    function AstForEachExpression(initStatement, container) {      this.initStatement = initStatement;      this.container = container    }    AstForEachExpression.iteratorId = 0;    AstForEachExpression.prototype.toString = function() {      var init = this.initStatement.toString();      var iterator = "$it" + AstForEachExpression.iteratorId++;      var variableName = init.replace(/^\s*var\s*/, "").split("=")[0];      var initIteratorAndVariable = "var " + iterator + " = new $p.ObjectIterator(" + this.container + "), " + variableName + " = void(0)";      var nextIterationCondition = iterator + ".hasNext() && ((" + variableName + " = " + iterator + ".next()) || true)";      return "(" + initIteratorAndVariable + "; " + nextIterationCondition + ";)"    };    function transformForExpression(expr) {      var content;      if (/\bin\b/.test(expr)) {        content = expr.substring(1, expr.length - 1).split(/\bin\b/g);        return new AstForInExpression(transformStatement(trim(content[0])), transformExpression(content[1]))      }      if (expr.indexOf(":") >= 0 && expr.indexOf(";") < 0) {        content = expr.substring(1, expr.length - 1).split(":");        return new AstForEachExpression(transformStatement(trim(content[0])), transformExpression(content[1]))      }      content = expr.substring(1, expr.length - 1).split(";");      return new AstForExpression(transformStatement(trim(content[0])), transformExpression(content[1]), transformExpression(content[2]))    }    function sortByWeight(array) {      array.sort(function(a, b) {        return b.weight - a.weight      })    }    function AstInnerInterface(name, body, isStatic) {      this.name = name;      this.body = body;      this.isStatic = isStatic;      body.owner = this    }    AstInnerInterface.prototype.toString = function() {      return "" + this.body    };    function AstInnerClass(name, body, isStatic) {      this.name = name;      this.body = body;      this.isStatic = isStatic;      body.owner = this    }    AstInnerClass.prototype.toString = function() {      return "" + this.body    };    function transformInnerClass(class_) {      var m = classesRegex.exec(class_);      classesRegex.lastIndex = 0;      var isStatic = m[1].indexOf("static") >= 0;      var body = atoms[getAtomIndex(m[6])],        innerClass;      var oldClassId = currentClassId,        newClassId = generateClassId();      currentClassId = newClassId;      if (m[2] === "interface") innerClass = new AstInnerInterface(m[3], transformInterfaceBody(body, m[3], m[4]), isStatic);      else innerClass = new AstInnerClass(m[3], transformClassBody(body, m[3], m[4], m[5]), isStatic);      appendClass(innerClass, newClassId, oldClassId);      currentClassId = oldClassId;      return innerClass    }    function AstClassMethod(name, params, body, isStatic) {      this.name = name;      this.params = params;      this.body = body;      this.isStatic = isStatic    }    AstClassMethod.prototype.toString = function() {      var paramNames = appendToLookupTable({},      this.params.getNames());      var oldContext = replaceContext;      replaceContext = function(subject) {        return paramNames.hasOwnProperty(subject.name) ? subject.name : oldContext(subject)      };      var body = this.params.prependMethodArgs(this.body.toString());      var result = "function " + this.methodId + this.params + " " + body + "\n";      replaceContext = oldContext;      return result    };    function transformClassMethod(method) {      var m = methodsRegex.exec(method);      methodsRegex.lastIndex = 0;      var isStatic = m[1].indexOf("static") >= 0;      var body = m[6] !== ";" ? atoms[getAtomIndex(m[6])] : "{}";      return new AstClassMethod(m[3], transformParams(atoms[getAtomIndex(m[4])]), transformStatementsBlock(body), isStatic)    }    function AstClassField(definitions, fieldType, isStatic) {      this.definitions = definitions;      this.fieldType = fieldType;      this.isStatic = isStatic    }    AstClassField.prototype.getNames = function() {      var names = [];      for (var i = 0, l = this.definitions.length; i < l; ++i) names.push(this.definitions[i].name);      return names    };    AstClassField.prototype.toString = function() {      var thisPrefix = replaceContext({        name: "[this]"      });      if (this.isStatic) {        var className = this.owner.name;        var staticDeclarations = [];        for (var i = 0, l = this.definitions.length; i < l; ++i) {          var definition = this.definitions[i];          var name = definition.name,            staticName = className + "." + name;          var declaration = "if(" + staticName + " === void(0)) {\n" + " " + staticName + " = " + definition.value + "; }\n" + "$p.defineProperty(" + thisPrefix + ", " + "'" + name + "', { get: function(){return " + staticName + ";}, " + "set: function(val){" + staticName + " = val;} });\n";          staticDeclarations.push(declaration)        }        return staticDeclarations.join("")      }      return thisPrefix + "." + this.definitions.join("; " + thisPrefix + ".")    };    function transformClassField(statement) {      var attrAndType = attrAndTypeRegex.exec(statement);      var isStatic = attrAndType[1].indexOf("static") >= 0;      var definitions = statement.substring(attrAndType[0].length).split(/,\s*/g);      var defaultTypeValue = getDefaultValueForType(attrAndType[2]);      for (var i = 0; i < definitions.length; ++i) definitions[i] = transformVarDefinition(definitions[i], defaultTypeValue);      return new AstClassField(definitions, attrAndType[2], isStatic)    }    function AstConstructor(params, body) {      this.params = params;      this.body = body    }    AstConstructor.prototype.toString = function() {      var paramNames = appendToLookupTable({},      this.params.getNames());      var oldContext = replaceContext;      replaceContext = function(subject) {        return paramNames.hasOwnProperty(subject.name) ? subject.name : oldContext(subject)      };      var prefix = "function $constr_" + this.params.params.length + this.params.toString();      var body = this.params.prependMethodArgs(this.body.toString());      if (!/\$(superCstr|constr)\b/.test(body)) body = "{\n$superCstr();\n" + body.substring(1);      replaceContext = oldContext;      return prefix + body + "\n"    };    function transformConstructor(cstr) {      var m = (new RegExp(/"B(\d+)"\s*"A(\d+)"/)).exec(cstr);      var params = transformParams(atoms[m[1]]);      return new AstConstructor(params, transformStatementsBlock(atoms[m[2]]))    }    function AstInterfaceBody(name, interfacesNames, methodsNames, fields, innerClasses, misc) {      var i, l;      this.name = name;      this.interfacesNames = interfacesNames;      this.methodsNames = methodsNames;      this.fields = fields;      this.innerClasses = innerClasses;      this.misc = misc;      for (i = 0, l = fields.length; i < l; ++i) fields[i].owner = this    }    AstInterfaceBody.prototype.getMembers = function(classFields, classMethods, classInners) {      if (this.owner.base) this.owner.base.body.getMembers(classFields, classMethods, classInners);      var i, j, l, m;      for (i = 0, l = this.fields.length; i < l; ++i) {        var fieldNames = this.fields[i].getNames();        for (j = 0, m = fieldNames.length; j < m; ++j) classFields[fieldNames[j]] = this.fields[i]      }      for (i = 0, l = this.methodsNames.length; i < l; ++i) {        var methodName = this.methodsNames[i];        classMethods[methodName] = true      }      for (i = 0, l = this.innerClasses.length; i < l; ++i) {        var innerClass = this.innerClasses[i];        classInners[innerClass.name] = innerClass      }    };    AstInterfaceBody.prototype.toString = function() {      function getScopeLevel(p) {        var i = 0;        while (p) {          ++i;          p = p.scope        }        return i      }      var scopeLevel = getScopeLevel(this.owner);      var className = this.name;      var staticDefinitions = "";      var metadata = "";      var thisClassFields = {},        thisClassMethods = {},        thisClassInners = {};      this.getMembers(thisClassFields, thisClassMethods, thisClassInners);      var i, l, j, m;      if (this.owner.interfaces) {        var resolvedInterfaces = [],          resolvedInterface;        for (i = 0, l = this.interfacesNames.length; i < l; ++i) {          if (!this.owner.interfaces[i]) continue;          resolvedInterface = replaceContext({            name: this.interfacesNames[i]          });          resolvedInterfaces.push(resolvedInterface);          staticDefinitions += "$p.extendInterfaceMembers(" + className + ", " + resolvedInterface + ");\n"        }        metadata += className + ".$interfaces = [" + resolvedInterfaces.join(", ") + "];\n"      }      metadata += className + ".$isInterface = true;\n";      metadata += className + ".$methods = ['" + this.methodsNames.join("', '") + "'];\n";      sortByWeight(this.innerClasses);      for (i = 0, l = this.innerClasses.length; i < l; ++i) {        var innerClass = this.innerClasses[i];        if (innerClass.isStatic) staticDefinitions += className + "." + innerClass.name + " = " + innerClass + ";\n"      }      for (i = 0, l = this.fields.length; i < l; ++i) {        var field = this.fields[i];        if (field.isStatic) staticDefinitions += className + "." + field.definitions.join(";\n" + className + ".") + ";\n"      }      return "(function() {\n" + "function " + className + "() { throw 'Unable to create the interface'; }\n" + staticDefinitions + metadata + "return " + className + ";\n" + "})()"    };    transformInterfaceBody = function(body, name, baseInterfaces) {      var declarations = body.substring(1, body.length - 1);      declarations = extractClassesAndMethods(declarations);      declarations = extractConstructors(declarations, name);      var methodsNames = [],        classes = [];      declarations = declarations.replace(/"([DE])(\d+)"/g, function(all, type, index) {        if (type === "D") methodsNames.push(index);        else if (type === "E") classes.push(index);        return ""      });      var fields = declarations.split(/;(?:\s*;)*/g);      var baseInterfaceNames;      var i, l;      if (baseInterfaces !== undef) baseInterfaceNames = baseInterfaces.replace(/^\s*extends\s+(.+?)\s*$/g, "$1").split(/\s*,\s*/g);      for (i = 0, l = methodsNames.length; i < l; ++i) {        var method = transformClassMethod(atoms[methodsNames[i]]);        methodsNames[i] = method.name      }      for (i = 0, l = fields.length - 1; i < l; ++i) {        var field = trimSpaces(fields[i]);        fields[i] = transformClassField(field.middle)      }      var tail = fields.pop();      for (i = 0, l = classes.length; i < l; ++i) classes[i] = transformInnerClass(atoms[classes[i]]);      return new AstInterfaceBody(name, baseInterfaceNames, methodsNames, fields, classes, {        tail: tail      })    };    function AstClassBody(name, baseClassName, interfacesNames, functions, methods, fields, cstrs, innerClasses, misc) {      var i, l;      this.name = name;      this.baseClassName = baseClassName;      this.interfacesNames = interfacesNames;      this.functions = functions;      this.methods = methods;      this.fields = fields;      this.cstrs = cstrs;      this.innerClasses = innerClasses;      this.misc = misc;      for (i = 0, l = fields.length; i < l; ++i) fields[i].owner = this    }    AstClassBody.prototype.getMembers = function(classFields, classMethods, classInners) {      if (this.owner.base) this.owner.base.body.getMembers(classFields, classMethods, classInners);      var i, j, l, m;      for (i = 0, l = this.fields.length; i < l; ++i) {        var fieldNames = this.fields[i].getNames();        for (j = 0, m = fieldNames.length; j < m; ++j) classFields[fieldNames[j]] = this.fields[i]      }      for (i = 0, l = this.methods.length; i < l; ++i) {        var method = this.methods[i];        classMethods[method.name] = method      }      for (i = 0, l = this.innerClasses.length; i < l; ++i) {        var innerClass = this.innerClasses[i];        classInners[innerClass.name] = innerClass      }    };    AstClassBody.prototype.toString = function() {      function getScopeLevel(p) {        var i = 0;        while (p) {          ++i;          p = p.scope        }        return i      }      var scopeLevel = getScopeLevel(this.owner);      var selfId = "$this_" + scopeLevel;      var className = this.name;      var result = "var " + selfId + " = this;\n";      var staticDefinitions = "";      var metadata = "";      var thisClassFields = {},        thisClassMethods = {},        thisClassInners = {};      this.getMembers(thisClassFields, thisClassMethods, thisClassInners);      var oldContext = replaceContext;      replaceContext = function(subject) {        var name = subject.name;        if (name === "this") return subject.callSign || !subject.member ? selfId + ".$self" : selfId;        if (thisClassFields.hasOwnProperty(name)) return thisClassFields[name].isStatic ? className + "." + name : selfId + "." + name;        if (thisClassInners.hasOwnProperty(name)) return selfId + "." + name;        if (thisClassMethods.hasOwnProperty(name)) return thisClassMethods[name].isStatic ? className + "." + name : selfId + ".$self." + name;        return oldContext(subject)      };      var resolvedBaseClassName;      if (this.baseClassName) {        resolvedBaseClassName = oldContext({          name: this.baseClassName        });        result += "var $super = { $upcast: " + selfId + " };\n";        result += "function $superCstr(){" + resolvedBaseClassName + ".apply($super,arguments);if(!('$self' in $super)) $p.extendClassChain($super)}\n";        metadata += className + ".$base = " + resolvedBaseClassName + ";\n"      } else result += "function $superCstr(){$p.extendClassChain(" + selfId + ")}\n";      if (this.owner.base) staticDefinitions += "$p.extendStaticMembers(" + className + ", " + resolvedBaseClassName + ");\n";      var i, l, j, m;      if (this.owner.interfaces) {        var resolvedInterfaces = [],          resolvedInterface;        for (i = 0, l = this.interfacesNames.length; i < l; ++i) {          if (!this.owner.interfaces[i]) continue;          resolvedInterface = oldContext({            name: this.interfacesNames[i]          });          resolvedInterfaces.push(resolvedInterface);          staticDefinitions += "$p.extendInterfaceMembers(" + className + ", " + resolvedInterface + ");\n"        }        metadata += className + ".$interfaces = [" + resolvedInterfaces.join(", ") + "];\n"      }      if (this.functions.length > 0) result += this.functions.join("\n") + "\n";      sortByWeight(this.innerClasses);      for (i = 0, l = this.innerClasses.length; i < l; ++i) {        var innerClass = this.innerClasses[i];        if (innerClass.isStatic) {          staticDefinitions += className + "." + innerClass.name + " = " + innerClass + ";\n";          result += selfId + "." + innerClass.name + " = " + className + "." + innerClass.name + ";\n"        } else result += selfId + "." + innerClass.name + " = " + innerClass + ";\n"      }      for (i = 0, l = this.fields.length; i < l; ++i) {        var field = this.fields[i];        if (field.isStatic) {          staticDefinitions += className + "." + field.definitions.join(";\n" + className + ".") + ";\n";          for (j = 0, m = field.definitions.length; j < m; ++j) {            var fieldName = field.definitions[j].name,              staticName = className + "." + fieldName;            result += "$p.defineProperty(" + selfId + ", '" + fieldName + "', {" + "get: function(){return " + staticName + "}, " + "set: function(val){" + staticName + " = val}});\n"          }        } else result += selfId + "." + field.definitions.join(";\n" + selfId + ".") + ";\n"      }      var methodOverloads = {};      for (i = 0, l = this.methods.length; i < l; ++i) {        var method = this.methods[i];        var overload = methodOverloads[method.name];        var methodId = method.name + "$" + method.params.params.length;        var hasMethodArgs = !!method.params.methodArgsParam;        if (overload) {          ++overload;          methodId += "_" + overload        } else overload = 1;        method.methodId = methodId;        methodOverloads[method.name] = overload;        if (method.isStatic) {          staticDefinitions += method;          staticDefinitions += "$p.addMethod(" + className + ", '" + method.name + "', " + methodId + ", " + hasMethodArgs + ");\n";          result += "$p.addMethod(" + selfId + ", '" + method.name + "', " + methodId + ", " + hasMethodArgs + ");\n"        } else {          result += method;          result += "$p.addMethod(" + selfId + ", '" + method.name + "', " + methodId + ", " + hasMethodArgs + ");\n"        }      }      result += trim(this.misc.tail);      if (this.cstrs.length > 0) result += this.cstrs.join("\n") + "\n";      result += "function $constr() {\n";      var cstrsIfs = [];      for (i = 0, l = this.cstrs.length; i < l; ++i) {        var paramsLength = this.cstrs[i].params.params.length;        var methodArgsPresent = !!this.cstrs[i].params.methodArgsParam;        cstrsIfs.push("if(arguments.length " + (methodArgsPresent ? ">=" : "===") + " " + paramsLength + ") { " + "$constr_" + paramsLength + ".apply(" + selfId + ", arguments); }")      }      if (cstrsIfs.length > 0) result += cstrsIfs.join(" else ") + " else ";      result += "$superCstr();\n}\n";      result += "$constr.apply(null, arguments);\n";      replaceContext = oldContext;      return "(function() {\n" + "function " + className + "() {\n" + result + "}\n" + staticDefinitions + metadata + "return " + className + ";\n" + "})()"    };    transformClassBody = function(body, name, baseName, interfaces) {      var declarations = body.substring(1, body.length - 1);      declarations = extractClassesAndMethods(declarations);      declarations = extractConstructors(declarations, name);      var methods = [],        classes = [],        cstrs = [],        functions = [];      declarations = declarations.replace(/"([DEGH])(\d+)"/g, function(all, type, index) {        if (type === "D") methods.push(index);        else if (type === "E") classes.push(index);        else if (type === "H") functions.push(index);        else cstrs.push(index);        return ""      });      var fields = declarations.replace(/^(?:\s*;)+/, "").split(/;(?:\s*;)*/g);      var baseClassName, interfacesNames;      var i;      if (baseName !== undef) baseClassName = baseName.replace(/^\s*extends\s+([A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*)\s*$/g, "$1");      if (interfaces !== undef) interfacesNames = interfaces.replace(/^\s*implements\s+(.+?)\s*$/g, "$1").split(/\s*,\s*/g);      for (i = 0; i < functions.length; ++i) functions[i] = transformFunction(atoms[functions[i]]);      for (i = 0; i < methods.length; ++i) methods[i] = transformClassMethod(atoms[methods[i]]);      for (i = 0; i < fields.length - 1; ++i) {        var field = trimSpaces(fields[i]);        fields[i] = transformClassField(field.middle)      }      var tail = fields.pop();      for (i = 0; i < cstrs.length; ++i) cstrs[i] = transformConstructor(atoms[cstrs[i]]);      for (i = 0; i < classes.length; ++i) classes[i] = transformInnerClass(atoms[classes[i]]);      return new AstClassBody(name, baseClassName, interfacesNames, functions, methods, fields, cstrs, classes, {        tail: tail      })    };    function AstInterface(name, body) {      this.name = name;      this.body = body;      body.owner = this    }    AstInterface.prototype.toString = function() {      return "var " + this.name + " = " + this.body + ";\n" + "$p." + this.name + " = " + this.name + ";\n"    };    function AstClass(name, body) {      this.name = name;      this.body = body;      body.owner = this    }    AstClass.prototype.toString = function() {      return "var " + this.name + " = " + this.body + ";\n" + "$p." + this.name + " = " + this.name + ";\n"    };    function transformGlobalClass(class_) {      var m = classesRegex.exec(class_);      classesRegex.lastIndex = 0;      var body = atoms[getAtomIndex(m[6])];      var oldClassId = currentClassId,        newClassId = generateClassId();      currentClassId = newClassId;      var globalClass;      if (m[2] === "interface") globalClass = new AstInterface(m[3], transformInterfaceBody(body, m[3], m[4]));      else globalClass = new AstClass(m[3], transformClassBody(body, m[3], m[4], m[5]));      appendClass(globalClass, newClassId, oldClassId);      currentClassId = oldClassId;      return globalClass    }    function AstMethod(name, params, body) {      this.name = name;      this.params = params;      this.body = body    }    AstMethod.prototype.toString = function() {      var paramNames = appendToLookupTable({},      this.params.getNames());      var oldContext = replaceContext;      replaceContext = function(subject) {        return paramNames.hasOwnProperty(subject.name) ? subject.name : oldContext(subject)      };      var body = this.params.prependMethodArgs(this.body.toString());      var result = "function " + this.name + this.params + " " + body + "\n" + "$p." + this.name + " = " + this.name + ";";      replaceContext = oldContext;      return result    };    function transformGlobalMethod(method) {      var m = methodsRegex.exec(method);      var result = methodsRegex.lastIndex = 0;      return new AstMethod(m[3], transformParams(atoms[getAtomIndex(m[4])]), transformStatementsBlock(atoms[getAtomIndex(m[6])]))    }    function preStatementsTransform(statements) {      var s = statements;      s = s.replace(/\b(catch\s*"B\d+"\s*"A\d+")(\s*catch\s*"B\d+"\s*"A\d+")+/g, "$1");      return s    }    function AstForStatement(argument, misc) {      this.argument = argument;      this.misc = misc    }    AstForStatement.prototype.toString = function() {      return this.misc.prefix + this.argument.toString()    };    function AstCatchStatement(argument, misc) {      this.argument = argument;      this.misc = misc    }    AstCatchStatement.prototype.toString = function() {      return this.misc.prefix + this.argument.toString()    };    function AstPrefixStatement(name, argument, misc) {      this.name = name;      this.argument = argument;      this.misc = misc    }    AstPrefixStatement.prototype.toString = function() {      var result = this.misc.prefix;      if (this.argument !== undef) result += this.argument.toString();      return result    };    function AstSwitchCase(expr) {      this.expr = expr    }    AstSwitchCase.prototype.toString = function() {      return "case " + this.expr + ":"    };    function AstLabel(label) {      this.label = label    }    AstLabel.prototype.toString = function() {      return this.label    };    transformStatements = function(statements, transformMethod, transformClass) {      var nextStatement = new RegExp(/\b(catch|for|if|switch|while|with)\s*"B(\d+)"|\b(do|else|finally|return|throw|try|break|continue)\b|("[ADEH](\d+)")|\b(case)\s+([^:]+):|\b([A-Za-z_$][\w$]*\s*:)|(;)/g);      var res = [];      statements = preStatementsTransform(statements);      var lastIndex = 0,        m, space;      while ((m = nextStatement.exec(statements)) !== null) {        if (m[1] !== undef) {          var i = statements.lastIndexOf('"B', nextStatement.lastIndex);          var statementsPrefix = statements.substring(lastIndex, i);          if (m[1] === "for") res.push(new AstForStatement(transformForExpression(atoms[m[2]]), {            prefix: statementsPrefix          }));          else if (m[1] === "catch") res.push(new AstCatchStatement(transformParams(atoms[m[2]]), {            prefix: statementsPrefix          }));          else res.push(new AstPrefixStatement(m[1], transformExpression(atoms[m[2]]), {            prefix: statementsPrefix          }))        } else if (m[3] !== undef) res.push(new AstPrefixStatement(m[3], undef, {          prefix: statements.substring(lastIndex, nextStatement.lastIndex)        }));        else if (m[4] !== undef) {          space = statements.substring(lastIndex, nextStatement.lastIndex - m[4].length);          if (trim(space).length !== 0) continue;          res.push(space);          var kind = m[4].charAt(1),            atomIndex = m[5];          if (kind === "D") res.push(transformMethod(atoms[atomIndex]));          else if (kind === "E") res.push(transformClass(atoms[atomIndex]));          else if (kind === "H") res.push(transformFunction(atoms[atomIndex]));          else res.push(transformStatementsBlock(atoms[atomIndex]))        } else if (m[6] !== undef) res.push(new AstSwitchCase(transformExpression(trim(m[7]))));        else if (m[8] !== undef) {          space = statements.substring(lastIndex, nextStatement.lastIndex - m[8].length);          if (trim(space).length !== 0) continue;          res.push(new AstLabel(statements.substring(lastIndex, nextStatement.lastIndex)))        } else {          var statement = trimSpaces(statements.substring(lastIndex, nextStatement.lastIndex - 1));          res.push(statement.left);          res.push(transformStatement(statement.middle));          res.push(statement.right + ";")        }        lastIndex = nextStatement.lastIndex      }      var statementsTail = trimSpaces(statements.substring(lastIndex));      res.push(statementsTail.left);      if (statementsTail.middle !== "") {        res.push(transformStatement(statementsTail.middle));        res.push(";" + statementsTail.right)      }      return res    };    function getLocalNames(statements) {      var localNames = [];      for (var i = 0, l = statements.length; i < l; ++i) {        var statement = statements[i];        if (statement instanceof AstVar) localNames = localNames.concat(statement.getNames());        else if (statement instanceof AstForStatement && statement.argument.initStatement instanceof AstVar) localNames = localNames.concat(statement.argument.initStatement.getNames());        else if (statement instanceof AstInnerInterface || statement instanceof AstInnerClass || statement instanceof AstInterface || statement instanceof AstClass || statement instanceof AstMethod || statement instanceof AstFunction) localNames.push(statement.name)      }      return appendToLookupTable({},      localNames)    }    function AstStatementsBlock(statements) {      this.statements = statements    }    AstStatementsBlock.prototype.toString = function() {      var localNames = getLocalNames(this.statements);      var oldContext = replaceContext;      if (!isLookupTableEmpty(localNames)) replaceContext = function(subject) {        return localNames.hasOwnProperty(subject.name) ? subject.name : oldContext(subject)      };      var result = "{\n" + this.statements.join("") + "\n}";      replaceContext = oldContext;      return result    };    transformStatementsBlock = function(block) {      var content = trimSpaces(block.substring(1, block.length - 1));      return new AstStatementsBlock(transformStatements(content.middle))    };    function AstRoot(statements) {      this.statements = statements    }    AstRoot.prototype.toString = function() {      var classes = [],        otherStatements = [],        statement;      for (var i = 0, len = this.statements.length; i < len; ++i) {        statement = this.statements[i];        if (statement instanceof AstClass || statement instanceof AstInterface) classes.push(statement);        else otherStatements.push(statement)      }      sortByWeight(classes);      var localNames = getLocalNames(this.statements);      replaceContext = function(subject) {        var name = subject.name;        if (localNames.hasOwnProperty(name)) return name;        if (globalMembers.hasOwnProperty(name) || PConstants.hasOwnProperty(name) || defaultScope.hasOwnProperty(name)) return "$p." + name;        return name      };      var result = "// this code was autogenerated from PJS\n" + "(function($p) {\n" + classes.join("") + "\n" + otherStatements.join("") + "\n})";      replaceContext = null;      return result    };    transformMain = function() {      var statements = extractClassesAndMethods(atoms[0]);      statements = statements.replace(/\bimport\s+[^;]+;/g, "");      return new AstRoot(transformStatements(statements, transformGlobalMethod, transformGlobalClass))    };    function generateMetadata(ast) {      var globalScope = {};      var id, class_;      for (id in declaredClasses) if (declaredClasses.hasOwnProperty(id)) {        class_ = declaredClasses[id];        var scopeId = class_.scopeId,          name = class_.name;        if (scopeId) {          var scope = declaredClasses[scopeId];          class_.scope = scope;          if (scope.inScope === undef) scope.inScope = {};          scope.inScope[name] = class_        } else globalScope[name] = class_      }      function findInScopes(class_, name) {        var parts = name.split(".");        var currentScope = class_.scope,          found;        while (currentScope) {          if (currentScope.hasOwnProperty(parts[0])) {            found = currentScope[parts[0]];            break          }          currentScope = currentScope.scope        }        if (found === undef) found = globalScope[parts[0]];        for (var i = 1, l = parts.length; i < l && found; ++i) found = found.inScope[parts[i]];        return found      }      for (id in declaredClasses) if (declaredClasses.hasOwnProperty(id)) {        class_ = declaredClasses[id];        var baseClassName = class_.body.baseClassName;        if (baseClassName) {          var parent = findInScopes(class_, baseClassName);          if (parent) {            class_.base = parent;            if (!parent.derived) parent.derived = [];            parent.derived.push(class_)          }        }        var interfacesNames = class_.body.interfacesNames,          interfaces = [],          i, l;        if (interfacesNames && interfacesNames.length > 0) {          for (i = 0, l = interfacesNames.length; i < l; ++i) {            var interface_ = findInScopes(class_, interfacesNames[i]);            interfaces.push(interface_);            if (!interface_) continue;            if (!interface_.derived) interface_.derived = [];            interface_.derived.push(class_)          }          if (interfaces.length > 0) class_.interfaces = interfaces        }      }    }    function setWeight(ast) {      var queue = [],        tocheck = {};      var id, scopeId, class_;      for (id in declaredClasses) if (declaredClasses.hasOwnProperty(id)) {        class_ = declaredClasses[id];        if (!class_.inScope && !class_.derived) {          queue.push(id);          class_.weight = 0        } else {          var dependsOn = [];          if (class_.inScope) for (scopeId in class_.inScope) if (class_.inScope.hasOwnProperty(scopeId)) dependsOn.push(class_.inScope[scopeId]);          if (class_.derived) dependsOn = dependsOn.concat(class_.derived);          tocheck[id] = dependsOn        }      }      function removeDependentAndCheck(targetId, from) {        var dependsOn = tocheck[targetId];        if (!dependsOn) return false;        var i = dependsOn.indexOf(from);        if (i < 0) return false;        dependsOn.splice(i, 1);        if (dependsOn.length > 0) return false;        delete tocheck[targetId];        return true      }      while (queue.length > 0) {        id = queue.shift();        class_ = declaredClasses[id];        if (class_.scopeId && removeDependentAndCheck(class_.scopeId, class_)) {          queue.push(class_.scopeId);          declaredClasses[class_.scopeId].weight = class_.weight + 1        }        if (class_.base && removeDependentAndCheck(class_.base.classId, class_)) {          queue.push(class_.base.classId);          class_.base.weight = class_.weight + 1        }        if (class_.interfaces) {          var i, l;          for (i = 0, l = class_.interfaces.length; i < l; ++i) {            if (!class_.interfaces[i] || !removeDependentAndCheck(class_.interfaces[i].classId, class_)) continue;            queue.push(class_.interfaces[i].classId);            class_.interfaces[i].weight = class_.weight + 1          }        }      }    }    var transformed = transformMain();    generateMetadata(transformed);    setWeight(transformed);    var redendered = transformed.toString();    redendered = redendered.replace(/\s*\n(?:[\t ]*\n)+/g, "\n\n");    redendered = redendered.replace(/__x([0-9A-F]{4})/g, function(all, hexCode) {      return String.fromCharCode(parseInt(hexCode, 16))    });    return injectStrings(redendered, strings)  }  function preprocessCode(aCode, sketch) {    var dm = (new RegExp(/\/\*\s*@pjs\s+((?:[^\*]|\*+[^\*\/])*)\*\//g)).exec(aCode);    if (dm && dm.length === 2) {      var jsonItems = [],        directives = dm.splice(1, 2)[0].replace(/\{([\s\S]*?)\}/g, function() {        return function(all, item) {          jsonItems.push(item);          return "{" + (jsonItems.length - 1) + "}"        }      }()).replace("\n", "").replace("\r", "").split(";");      var clean = function(s) {        return s.replace(/^\s*["']?/, "").replace(/["']?\s*$/, "")      };      for (var i = 0, dl = directives.length; i < dl; i++) {        var pair = directives[i].split("=");        if (pair && pair.length === 2) {          var key = clean(pair[0]),            value = clean(pair[1]),            list = [];          if (key === "preload") {            list = value.split(",");            for (var j = 0, jl = list.length; j < jl; j++) {              var imageName = clean(list[j]);              sketch.imageCache.add(imageName)            }          } else if (key === "font") {            list = value.split(",");            for (var x = 0, xl = list.length; x < xl; x++) {              var fontName = clean(list[x]),                index = /^\{(\d*?)\}$/.exec(fontName);              PFont.preloading.add(index ? JSON.parse("{" + jsonItems[index[1]] + "}") : fontName)            }          } else if (key === "pauseOnBlur") sketch.options.pauseOnBlur = value === "true";          else if (key === "globalKeyEvents") sketch.options.globalKeyEvents = value === "true";          else if (key.substring(0, 6) === "param-") sketch.params[key.substring(6)] = value;          else sketch.options[key] = value        }      }    }    return aCode  }  Processing.compile = function(pdeCode) {    var sketch = new Processing.Sketch;    var code = preprocessCode(pdeCode, sketch);    var compiledPde = parseProcessing(code);    sketch.sourceCode = compiledPde;    return sketch  };  var tinylogLite = function() {    var tinylogLite = {},      undef = "undefined",      func = "function",      False = !1,      True = !0,      logLimit = 512,      log = "log";    if (typeof tinylog !== undef && typeof tinylog[log] === func) tinylogLite[log] = tinylog[log];    else if (typeof document !== undef && !document.fake)(function() {      var doc = document,        $div = "div",        $style = "style",        $title = "title",        containerStyles = {        zIndex: 1E4,        position: "fixed",        bottom: "0px",        width: "100%",        height: "15%",        fontFamily: "sans-serif",        color: "#ccc",        backgroundColor: "black"      },        outputStyles = {        position: "relative",        fontFamily: "monospace",        overflow: "auto",        height: "100%",        paddingTop: "5px"      },        resizerStyles = {        height: "5px",        marginTop: "-5px",        cursor: "n-resize",        backgroundColor: "darkgrey"      },        closeButtonStyles = {        position: "absolute",        top: "5px",        right: "20px",        color: "#111",        MozBorderRadius: "4px",        webkitBorderRadius: "4px",        borderRadius: "4px",        cursor: "pointer",        fontWeight: "normal",        textAlign: "center",        padding: "3px 5px",        backgroundColor: "#333",        fontSize: "12px"      },        entryStyles = {        minHeight: "16px"      },        entryTextStyles = {        fontSize: "12px",        margin: "0 8px 0 8px",        maxWidth: "100%",        whiteSpace: "pre-wrap",        overflow: "auto"      },        view = doc.defaultView,        docElem = doc.documentElement,        docElemStyle = docElem[$style],        setStyles = function() {        var i = arguments.length,          elemStyle, styles, style;        while (i--) {          styles = arguments[i--];          elemStyle = arguments[i][$style];          for (style in styles) if (styles.hasOwnProperty(style)) elemStyle[style] = styles[style]        }      },        observer = function(obj, event, handler) {        if (obj.addEventListener) obj.addEventListener(event, handler, False);        else if (obj.attachEvent) obj.attachEvent("on" + event, handler);        return [obj, event, handler]      },        unobserve = function(obj, event, handler) {        if (obj.removeEventListener) obj.removeEventListener(event, handler, False);        else if (obj.detachEvent) obj.detachEvent("on" + event, handler)      },        clearChildren = function(node) {        var children = node.childNodes,          child = children.length;        while (child--) node.removeChild(children.item(0))      },        append = function(to, elem) {        return to.appendChild(elem)      },        createElement = function(localName) {        return doc.createElement(localName)      },        createTextNode = function(text) {        return doc.createTextNode(text)      },        createLog = tinylogLite[log] = function(message) {        var uninit, originalPadding = docElemStyle.paddingBottom,          container = createElement($div),          containerStyle = container[$style],          resizer = append(container, createElement($div)),          output = append(container, createElement($div)),          closeButton = append(container, createElement($div)),          resizingLog = False,          previousHeight = False,          previousScrollTop = False,          messages = 0,          updateSafetyMargin = function() {          docElemStyle.paddingBottom = container.clientHeight + "px"        },          setContainerHeight = function(height) {          var viewHeight = view.innerHeight,            resizerHeight = resizer.clientHeight;          if (height < 0) height = 0;          else if (height + resizerHeight > viewHeight) height = viewHeight - resizerHeight;          containerStyle.height = height / viewHeight * 100 + "%";          updateSafetyMargin()        },          observers = [observer(doc, "mousemove", function(evt) {          if (resizingLog) {            setContainerHeight(view.innerHeight - evt.clientY);            output.scrollTop = previousScrollTop          }        }), observer(doc, "mouseup", function() {          if (resizingLog) resizingLog = previousScrollTop = False        }), observer(resizer, "dblclick", function(evt) {          evt.preventDefault();          if (previousHeight) {            setContainerHeight(previousHeight);            previousHeight = False          } else {            previousHeight = container.clientHeight;            containerStyle.height = "0px"          }        }), observer(resizer, "mousedown", function(evt) {          evt.preventDefault();          resizingLog = True;          previousScrollTop = output.scrollTop        }), observer(resizer, "contextmenu", function() {          resizingLog = False        }), observer(closeButton, "click", function() {          uninit()        })];        uninit = function() {          var i = observers.length;          while (i--) unobserve.apply(tinylogLite, observers[i]);          docElem.removeChild(container);          docElemStyle.paddingBottom = originalPadding;          clearChildren(output);          clearChildren(container);          tinylogLite[log] = createLog        };        setStyles(container, containerStyles, output, outputStyles, resizer, resizerStyles, closeButton, closeButtonStyles);        closeButton[$title] = "Close Log";        append(closeButton, createTextNode("\u2716"));        resizer[$title] = "Double-click to toggle log minimization";        docElem.insertBefore(container, docElem.firstChild);        tinylogLite[log] = function(message) {          if (messages === logLimit) output.removeChild(output.firstChild);          else messages++;          var entry = append(output, createElement($div)),            entryText = append(entry, createElement($div));          entry[$title] = (new Date).toLocaleTimeString();          setStyles(entry, entryStyles, entryText, entryTextStyles);          append(entryText, createTextNode(message));          output.scrollTop = output.scrollHeight        };        tinylogLite[log](message);        updateSafetyMargin()      }    })();    else if (typeof print === func) tinylogLite[log] = print;    return tinylogLite  }();  Processing.logger = tinylogLite;  Processing.version = "1.4.1";  Processing.lib = {};  Processing.registerLibrary = function(name, desc) {    Processing.lib[name] = desc;    if (desc.hasOwnProperty("init")) desc.init(defaultScope)  };  Processing.instances = processingInstances;  Processing.getInstanceById = function(name) {    return processingInstances[processingInstanceIds[name]]  };  Processing.Sketch = function(attachFunction) {    this.attachFunction = attachFunction;    this.options = {      pauseOnBlur: false,      globalKeyEvents: false    };    this.onLoad = nop;    this.onSetup = nop;    this.onPause = nop;    this.onLoop = nop;    this.onFrameStart = nop;    this.onFrameEnd = nop;    this.onExit = nop;    this.params = {};    this.imageCache = {      pending: 0,      images: {},      operaCache: {},      add: function(href, img) {        if (this.images[href]) return;        if (!isDOMPresent) this.images[href] = null;        if (!img) {          img = new Image;          img.onload = function(owner) {            return function() {              owner.pending--            }          }(this);          this.pending++;          img.src = href        }        this.images[href] = img;        if (window.opera) {          var div = document.createElement("div");          div.appendChild(img);          div.style.position = "absolute";          div.style.opacity = 0;          div.style.width = "1px";          div.style.height = "1px";          if (!this.operaCache[href]) {            document.body.appendChild(div);            this.operaCache[href] = div          }        }      }    };    this.sourceCode = undefined;    this.attach = function(processing) {      if (typeof this.attachFunction === "function") this.attachFunction(processing);      else if (this.sourceCode) {        var func = (new Function("return (" + this.sourceCode + ");"))();        func(processing);        this.attachFunction = func      } else throw "Unable to attach sketch to the processing instance";    };    this.toString = function() {      var i;      var code = "((function(Sketch) {\n";      code += "var sketch = new Sketch(\n" + this.sourceCode + ");\n";      for (i in this.options) if (this.options.hasOwnProperty(i)) {        var value = this.options[i];        code += "sketch.options." + i + " = " + (typeof value === "string" ? '"' + value + '"' : "" + value) + ";\n"      }      for (i in this.imageCache) if (this.options.hasOwnProperty(i)) code += 'sketch.imageCache.add("' + i + '");\n';      code += "return sketch;\n})(Processing.Sketch))";      return code    }  };  var loadSketchFromSources = function(canvas, sources) {    var code = [],      errors = [],      sourcesCount = sources.length,      loaded = 0;    function ajaxAsync(url, callback) {      var xhr = new XMLHttpRequest;      xhr.onreadystatechange = function() {        if (xhr.readyState === 4) {          var error;          if (xhr.status !== 200 && xhr.status !== 0) error = "Invalid XHR status " + xhr.status;          else if (xhr.responseText === "") if ("withCredentials" in new XMLHttpRequest && (new XMLHttpRequest).withCredentials === false && window.location.protocol === "file:") error = "XMLHttpRequest failure, possibly due to a same-origin policy violation. You can try loading this page in another browser, or load it from http://localhost using a local webserver. See the Processing.js README for a more detailed explanation of this problem and solutions.";          else error = "File is empty.";          callback(xhr.responseText, error)        }      };      xhr.open("GET", url, true);      if (xhr.overrideMimeType) xhr.overrideMimeType("application/json");      xhr.setRequestHeader("If-Modified-Since", "Fri, 01 Jan 1960 00:00:00 GMT");      xhr.send(null)    }    function loadBlock(index, filename) {      function callback(block, error) {        code[index] = block;        ++loaded;        if (error) errors.push(filename + " ==> " + error);        if (loaded === sourcesCount) if (errors.length === 0) try {          return new Processing(canvas, code.join("\n"))        } catch(e) {          throw "Processing.js: Unable to execute pjs sketch: " + e;        } else throw "Processing.js: Unable to load pjs sketch files: " + errors.join("\n");      }      if (filename.charAt(0) === "#") {        var scriptElement = document.getElementById(filename.substring(1));        if (scriptElement) callback(scriptElement.text || scriptElement.textContent);        else callback("", "Unable to load pjs sketch: element with id '" + filename.substring(1) + "' was not found");        return      }      ajaxAsync(filename, callback)    }    for (var i = 0; i < sourcesCount; ++i) loadBlock(i, sources[i])  };  var init = function() {    document.removeEventListener("DOMContentLoaded", init, false);    processingInstances = [];    var canvas = document.getElementsByTagName("canvas"),      filenames;    for (var i = 0, l = canvas.length; i < l; i++) {      var processingSources = canvas[i].getAttribute("data-processing-sources");      if (processingSources === null) {        processingSources = canvas[i].getAttribute("data-src");        if (processingSources === null) processingSources = canvas[i].getAttribute("datasrc")      }      if (processingSources) {        filenames = processingSources.split(/\s+/g);        for (var j = 0; j < filenames.length;) if (filenames[j]) j++;        else filenames.splice(j, 1);        loadSketchFromSources(canvas[i], filenames)      }    }    var s, last, source, instance, nodelist = document.getElementsByTagName("script"),      scripts = [];    for (s = nodelist.length - 1; s >= 0; s--) scripts.push(nodelist[s]);    for (s = 0, last = scripts.length; s < last; s++) {      var script = scripts[s];      if (!script.getAttribute) continue;      var type = script.getAttribute("type");      if (type && (type.toLowerCase() === "text/processing" || type.toLowerCase() === "application/processing")) {        var target = script.getAttribute("data-processing-target");        canvas = undef;        if (target) canvas = document.getElementById(target);        else {          var nextSibling = script.nextSibling;          while (nextSibling && nextSibling.nodeType !== 1) nextSibling = nextSibling.nextSibling;          if (nextSibling && nextSibling.nodeName.toLowerCase() === "canvas") canvas = nextSibling        }        if (canvas) {          if (script.getAttribute("src")) {            filenames = script.getAttribute("src").split(/\s+/);            loadSketchFromSources(canvas, filenames);            continue          }          source = script.textContent || script.text;          instance = new Processing(canvas, source)        }      }    }  };  Processing.reload = function() {    if (processingInstances.length > 0) for (var i = processingInstances.length - 1; i >= 0; i--) if (processingInstances[i]) processingInstances[i].exit();    init()  };  Processing.loadSketchFromSources = loadSketchFromSources;  Processing.disableInit = function() {    if (isDOMPresent) document.removeEventListener("DOMContentLoaded", init, false)  };  if (isDOMPresent) {    window["Processing"] = Processing;    document.addEventListener("DOMContentLoaded", init, false)  } else this.Processing = Processing})(window, window.document, Math);
 |