| 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);
 
 
  |