processing.js 422 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203
  1. /***
  2. P R O C E S S I N G . J S - 1.4.1
  3. a port of the Processing visualization language
  4. Processing.js is licensed under the MIT License, see LICENSE.
  5. For a list of copyright holders, please refer to AUTHORS.
  6. http://processingjs.org
  7. ***/
  8. (function(window, document, Math, undef) {
  9. var nop = function() {};
  10. var debug = function() {
  11. if ("console" in window) return function(msg) {
  12. window.console.log("Processing.js: " + msg)
  13. };
  14. return nop
  15. }();
  16. var ajax = function(url) {
  17. var xhr = new XMLHttpRequest;
  18. xhr.open("GET", url, false);
  19. if (xhr.overrideMimeType) xhr.overrideMimeType("text/plain");
  20. xhr.setRequestHeader("If-Modified-Since", "Fri, 01 Jan 1960 00:00:00 GMT");
  21. xhr.send(null);
  22. if (xhr.status !== 200 && xhr.status !== 0) throw "XMLHttpRequest failed, status code " + xhr.status;
  23. return xhr.responseText
  24. };
  25. var isDOMPresent = "document" in this && !("fake" in this.document);
  26. document.head = document.head || document.getElementsByTagName("head")[0];
  27. function setupTypedArray(name, fallback) {
  28. if (name in window) return window[name];
  29. if (typeof window[fallback] === "function") return window[fallback];
  30. return function(obj) {
  31. if (obj instanceof Array) return obj;
  32. if (typeof obj === "number") {
  33. var arr = [];
  34. arr.length = obj;
  35. return arr
  36. }
  37. }
  38. }
  39. if (document.documentMode >= 9 && !document.doctype) throw "The doctype directive is missing. The recommended doctype in Internet Explorer is the HTML5 doctype: <!DOCTYPE html>";
  40. var Float32Array = setupTypedArray("Float32Array", "WebGLFloatArray"),
  41. Int32Array = setupTypedArray("Int32Array", "WebGLIntArray"),
  42. Uint16Array = setupTypedArray("Uint16Array", "WebGLUnsignedShortArray"),
  43. Uint8Array = setupTypedArray("Uint8Array", "WebGLUnsignedByteArray");
  44. var PConstants = {
  45. X: 0,
  46. Y: 1,
  47. Z: 2,
  48. R: 3,
  49. G: 4,
  50. B: 5,
  51. A: 6,
  52. U: 7,
  53. V: 8,
  54. NX: 9,
  55. NY: 10,
  56. NZ: 11,
  57. EDGE: 12,
  58. SR: 13,
  59. SG: 14,
  60. SB: 15,
  61. SA: 16,
  62. SW: 17,
  63. TX: 18,
  64. TY: 19,
  65. TZ: 20,
  66. VX: 21,
  67. VY: 22,
  68. VZ: 23,
  69. VW: 24,
  70. AR: 25,
  71. AG: 26,
  72. AB: 27,
  73. DR: 3,
  74. DG: 4,
  75. DB: 5,
  76. DA: 6,
  77. SPR: 28,
  78. SPG: 29,
  79. SPB: 30,
  80. SHINE: 31,
  81. ER: 32,
  82. EG: 33,
  83. EB: 34,
  84. BEEN_LIT: 35,
  85. VERTEX_FIELD_COUNT: 36,
  86. P2D: 1,
  87. JAVA2D: 1,
  88. WEBGL: 2,
  89. P3D: 2,
  90. OPENGL: 2,
  91. PDF: 0,
  92. DXF: 0,
  93. OTHER: 0,
  94. WINDOWS: 1,
  95. MAXOSX: 2,
  96. LINUX: 3,
  97. EPSILON: 1.0E-4,
  98. MAX_FLOAT: 3.4028235E38,
  99. MIN_FLOAT: -3.4028235E38,
  100. MAX_INT: 2147483647,
  101. MIN_INT: -2147483648,
  102. PI: Math.PI,
  103. TWO_PI: 2 * Math.PI,
  104. HALF_PI: Math.PI / 2,
  105. THIRD_PI: Math.PI / 3,
  106. QUARTER_PI: Math.PI / 4,
  107. DEG_TO_RAD: Math.PI / 180,
  108. RAD_TO_DEG: 180 / Math.PI,
  109. WHITESPACE: " \t\n\r\u000c\u00a0",
  110. RGB: 1,
  111. ARGB: 2,
  112. HSB: 3,
  113. ALPHA: 4,
  114. CMYK: 5,
  115. TIFF: 0,
  116. TARGA: 1,
  117. JPEG: 2,
  118. GIF: 3,
  119. BLUR: 11,
  120. GRAY: 12,
  121. INVERT: 13,
  122. OPAQUE: 14,
  123. POSTERIZE: 15,
  124. THRESHOLD: 16,
  125. ERODE: 17,
  126. DILATE: 18,
  127. REPLACE: 0,
  128. BLEND: 1 << 0,
  129. ADD: 1 << 1,
  130. SUBTRACT: 1 << 2,
  131. LIGHTEST: 1 << 3,
  132. DARKEST: 1 << 4,
  133. DIFFERENCE: 1 << 5,
  134. EXCLUSION: 1 << 6,
  135. MULTIPLY: 1 << 7,
  136. SCREEN: 1 << 8,
  137. OVERLAY: 1 << 9,
  138. HARD_LIGHT: 1 << 10,
  139. SOFT_LIGHT: 1 << 11,
  140. DODGE: 1 << 12,
  141. BURN: 1 << 13,
  142. ALPHA_MASK: 4278190080,
  143. RED_MASK: 16711680,
  144. GREEN_MASK: 65280,
  145. BLUE_MASK: 255,
  146. CUSTOM: 0,
  147. ORTHOGRAPHIC: 2,
  148. PERSPECTIVE: 3,
  149. POINT: 2,
  150. POINTS: 2,
  151. LINE: 4,
  152. LINES: 4,
  153. TRIANGLE: 8,
  154. TRIANGLES: 9,
  155. TRIANGLE_STRIP: 10,
  156. TRIANGLE_FAN: 11,
  157. QUAD: 16,
  158. QUADS: 16,
  159. QUAD_STRIP: 17,
  160. POLYGON: 20,
  161. PATH: 21,
  162. RECT: 30,
  163. ELLIPSE: 31,
  164. ARC: 32,
  165. SPHERE: 40,
  166. BOX: 41,
  167. GROUP: 0,
  168. PRIMITIVE: 1,
  169. GEOMETRY: 3,
  170. VERTEX: 0,
  171. BEZIER_VERTEX: 1,
  172. CURVE_VERTEX: 2,
  173. BREAK: 3,
  174. CLOSESHAPE: 4,
  175. OPEN: 1,
  176. CLOSE: 2,
  177. CORNER: 0,
  178. CORNERS: 1,
  179. RADIUS: 2,
  180. CENTER_RADIUS: 2,
  181. CENTER: 3,
  182. DIAMETER: 3,
  183. CENTER_DIAMETER: 3,
  184. BASELINE: 0,
  185. TOP: 101,
  186. BOTTOM: 102,
  187. NORMAL: 1,
  188. NORMALIZED: 1,
  189. IMAGE: 2,
  190. MODEL: 4,
  191. SHAPE: 5,
  192. SQUARE: "butt",
  193. ROUND: "round",
  194. PROJECT: "square",
  195. MITER: "miter",
  196. BEVEL: "bevel",
  197. AMBIENT: 0,
  198. DIRECTIONAL: 1,
  199. SPOT: 3,
  200. BACKSPACE: 8,
  201. TAB: 9,
  202. ENTER: 10,
  203. RETURN: 13,
  204. ESC: 27,
  205. DELETE: 127,
  206. CODED: 65535,
  207. SHIFT: 16,
  208. CONTROL: 17,
  209. ALT: 18,
  210. CAPSLK: 20,
  211. PGUP: 33,
  212. PGDN: 34,
  213. END: 35,
  214. HOME: 36,
  215. LEFT: 37,
  216. UP: 38,
  217. RIGHT: 39,
  218. DOWN: 40,
  219. F1: 112,
  220. F2: 113,
  221. F3: 114,
  222. F4: 115,
  223. F5: 116,
  224. F6: 117,
  225. F7: 118,
  226. F8: 119,
  227. F9: 120,
  228. F10: 121,
  229. F11: 122,
  230. F12: 123,
  231. NUMLK: 144,
  232. META: 157,
  233. INSERT: 155,
  234. ARROW: "default",
  235. CROSS: "crosshair",
  236. HAND: "pointer",
  237. MOVE: "move",
  238. TEXT: "text",
  239. WAIT: "wait",
  240. NOCURSOR: "url('data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=='), auto",
  241. DISABLE_OPENGL_2X_SMOOTH: 1,
  242. ENABLE_OPENGL_2X_SMOOTH: -1,
  243. ENABLE_OPENGL_4X_SMOOTH: 2,
  244. ENABLE_NATIVE_FONTS: 3,
  245. DISABLE_DEPTH_TEST: 4,
  246. ENABLE_DEPTH_TEST: -4,
  247. ENABLE_DEPTH_SORT: 5,
  248. DISABLE_DEPTH_SORT: -5,
  249. DISABLE_OPENGL_ERROR_REPORT: 6,
  250. ENABLE_OPENGL_ERROR_REPORT: -6,
  251. ENABLE_ACCURATE_TEXTURES: 7,
  252. DISABLE_ACCURATE_TEXTURES: -7,
  253. HINT_COUNT: 10,
  254. SINCOS_LENGTH: 720,
  255. PRECISIONB: 15,
  256. PRECISIONF: 1 << 15,
  257. PREC_MAXVAL: (1 << 15) - 1,
  258. PREC_ALPHA_SHIFT: 24 - 15,
  259. PREC_RED_SHIFT: 16 - 15,
  260. NORMAL_MODE_AUTO: 0,
  261. NORMAL_MODE_SHAPE: 1,
  262. NORMAL_MODE_VERTEX: 2,
  263. MAX_LIGHTS: 8
  264. };
  265. function virtHashCode(obj) {
  266. if (typeof obj === "string") {
  267. var hash = 0;
  268. for (var i = 0; i < obj.length; ++i) hash = hash * 31 + obj.charCodeAt(i) & 4294967295;
  269. return hash
  270. }
  271. if (typeof obj !== "object") return obj & 4294967295;
  272. if (obj.hashCode instanceof Function) return obj.hashCode();
  273. if (obj.$id === undef) obj.$id = Math.floor(Math.random() * 65536) - 32768 << 16 | Math.floor(Math.random() * 65536);
  274. return obj.$id
  275. }
  276. function virtEquals(obj, other) {
  277. if (obj === null || other === null) return obj === null && other === null;
  278. if (typeof obj === "string") return obj === other;
  279. if (typeof obj !== "object") return obj === other;
  280. if (obj.equals instanceof Function) return obj.equals(other);
  281. return obj === other
  282. }
  283. var ObjectIterator = function(obj) {
  284. if (obj.iterator instanceof
  285. Function) return obj.iterator();
  286. if (obj instanceof Array) {
  287. var index = -1;
  288. this.hasNext = function() {
  289. return ++index < obj.length
  290. };
  291. this.next = function() {
  292. return obj[index]
  293. }
  294. } else throw "Unable to iterate: " + obj;
  295. };
  296. var ArrayList = function() {
  297. function Iterator(array) {
  298. var index = 0;
  299. this.hasNext = function() {
  300. return index < array.length
  301. };
  302. this.next = function() {
  303. return array[index++]
  304. };
  305. this.remove = function() {
  306. array.splice(index, 1)
  307. }
  308. }
  309. function ArrayList(a) {
  310. var array;
  311. if (a instanceof ArrayList) array = a.toArray();
  312. else {
  313. array = [];
  314. if (typeof a === "number") array.length = a > 0 ? a : 0
  315. }
  316. this.get = function(i) {
  317. return array[i]
  318. };
  319. this.contains = function(item) {
  320. return this.indexOf(item) > -1
  321. };
  322. this.indexOf = function(item) {
  323. for (var i = 0, len = array.length; i < len; ++i) if (virtEquals(item, array[i])) return i;
  324. return -1
  325. };
  326. this.lastIndexOf = function(item) {
  327. for (var i = array.length - 1; i >= 0; --i) if (virtEquals(item, array[i])) return i;
  328. return -1
  329. };
  330. this.add = function() {
  331. if (arguments.length === 1) array.push(arguments[0]);
  332. else if (arguments.length === 2) {
  333. var arg0 = arguments[0];
  334. if (typeof arg0 === "number") if (arg0 >= 0 && arg0 <= array.length) array.splice(arg0, 0, arguments[1]);
  335. else throw arg0 + " is not a valid index";
  336. else throw typeof arg0 + " is not a number";
  337. } else throw "Please use the proper number of parameters.";
  338. };
  339. this.addAll = function(arg1, arg2) {
  340. var it;
  341. if (typeof arg1 === "number") {
  342. if (arg1 < 0 || arg1 > array.length) throw "Index out of bounds for addAll: " + arg1 + " greater or equal than " + array.length;
  343. it = new ObjectIterator(arg2);
  344. while (it.hasNext()) array.splice(arg1++, 0, it.next())
  345. } else {
  346. it = new ObjectIterator(arg1);
  347. while (it.hasNext()) array.push(it.next())
  348. }
  349. };
  350. this.set = function() {
  351. if (arguments.length === 2) {
  352. var arg0 = arguments[0];
  353. if (typeof arg0 === "number") if (arg0 >= 0 && arg0 < array.length) array.splice(arg0, 1, arguments[1]);
  354. else throw arg0 + " is not a valid index.";
  355. else throw typeof arg0 + " is not a number";
  356. } else throw "Please use the proper number of parameters.";
  357. };
  358. this.size = function() {
  359. return array.length
  360. };
  361. this.clear = function() {
  362. array.length = 0
  363. };
  364. this.remove = function(item) {
  365. if (typeof item === "number") return array.splice(item, 1)[0];
  366. item = this.indexOf(item);
  367. if (item > -1) {
  368. array.splice(item, 1);
  369. return true
  370. }
  371. return false
  372. };
  373. this.removeAll = function(c) {
  374. var i, x, item, newList = new ArrayList;
  375. newList.addAll(this);
  376. this.clear();
  377. for (i = 0, x = 0; i < newList.size(); i++) {
  378. item = newList.get(i);
  379. if (!c.contains(item)) this.add(x++, item)
  380. }
  381. if (this.size() < newList.size()) return true;
  382. return false
  383. };
  384. this.isEmpty = function() {
  385. return !array.length
  386. };
  387. this.clone = function() {
  388. return new ArrayList(this)
  389. };
  390. this.toArray = function() {
  391. return array.slice(0)
  392. };
  393. this.iterator = function() {
  394. return new Iterator(array)
  395. }
  396. }
  397. return ArrayList
  398. }();
  399. var HashMap = function() {
  400. function HashMap() {
  401. if (arguments.length === 1 && arguments[0] instanceof HashMap) return arguments[0].clone();
  402. var initialCapacity = arguments.length > 0 ? arguments[0] : 16;
  403. var loadFactor = arguments.length > 1 ? arguments[1] : 0.75;
  404. var buckets = [];
  405. buckets.length = initialCapacity;
  406. var count = 0;
  407. var hashMap = this;
  408. function getBucketIndex(key) {
  409. var index = virtHashCode(key) % buckets.length;
  410. return index < 0 ? buckets.length + index : index
  411. }
  412. function ensureLoad() {
  413. if (count <= loadFactor * buckets.length) return;
  414. var allEntries = [];
  415. for (var i = 0; i < buckets.length; ++i) if (buckets[i] !== undef) allEntries = allEntries.concat(buckets[i]);
  416. var newBucketsLength = buckets.length * 2;
  417. buckets = [];
  418. buckets.length = newBucketsLength;
  419. for (var j = 0; j < allEntries.length; ++j) {
  420. var index = getBucketIndex(allEntries[j].key);
  421. var bucket = buckets[index];
  422. if (bucket === undef) buckets[index] = bucket = [];
  423. bucket.push(allEntries[j])
  424. }
  425. }
  426. function Iterator(conversion, removeItem) {
  427. var bucketIndex = 0;
  428. var itemIndex = -1;
  429. var endOfBuckets = false;
  430. var currentItem;
  431. function findNext() {
  432. while (!endOfBuckets) {
  433. ++itemIndex;
  434. if (bucketIndex >= buckets.length) endOfBuckets = true;
  435. else if (buckets[bucketIndex] === undef || itemIndex >= buckets[bucketIndex].length) {
  436. itemIndex = -1;
  437. ++bucketIndex
  438. } else return
  439. }
  440. }
  441. this.hasNext = function() {
  442. return !endOfBuckets
  443. };
  444. this.next = function() {
  445. currentItem = conversion(buckets[bucketIndex][itemIndex]);
  446. findNext();
  447. return currentItem
  448. };
  449. this.remove = function() {
  450. if (currentItem !== undef) {
  451. removeItem(currentItem);
  452. --itemIndex;
  453. findNext()
  454. }
  455. };
  456. findNext()
  457. }
  458. function Set(conversion, isIn, removeItem) {
  459. this.clear = function() {
  460. hashMap.clear()
  461. };
  462. this.contains = function(o) {
  463. return isIn(o)
  464. };
  465. this.containsAll = function(o) {
  466. var it = o.iterator();
  467. while (it.hasNext()) if (!this.contains(it.next())) return false;
  468. return true
  469. };
  470. this.isEmpty = function() {
  471. return hashMap.isEmpty()
  472. };
  473. this.iterator = function() {
  474. return new Iterator(conversion, removeItem)
  475. };
  476. this.remove = function(o) {
  477. if (this.contains(o)) {
  478. removeItem(o);
  479. return true
  480. }
  481. return false
  482. };
  483. this.removeAll = function(c) {
  484. var it = c.iterator();
  485. var changed = false;
  486. while (it.hasNext()) {
  487. var item = it.next();
  488. if (this.contains(item)) {
  489. removeItem(item);
  490. changed = true
  491. }
  492. }
  493. return true
  494. };
  495. this.retainAll = function(c) {
  496. var it = this.iterator();
  497. var toRemove = [];
  498. while (it.hasNext()) {
  499. var entry = it.next();
  500. if (!c.contains(entry)) toRemove.push(entry)
  501. }
  502. for (var i = 0; i < toRemove.length; ++i) removeItem(toRemove[i]);
  503. return toRemove.length > 0
  504. };
  505. this.size = function() {
  506. return hashMap.size()
  507. };
  508. this.toArray = function() {
  509. var result = [];
  510. var it = this.iterator();
  511. while (it.hasNext()) result.push(it.next());
  512. return result
  513. }
  514. }
  515. function Entry(pair) {
  516. this._isIn = function(map) {
  517. return map === hashMap && pair.removed === undef
  518. };
  519. this.equals = function(o) {
  520. return virtEquals(pair.key, o.getKey())
  521. };
  522. this.getKey = function() {
  523. return pair.key
  524. };
  525. this.getValue = function() {
  526. return pair.value
  527. };
  528. this.hashCode = function(o) {
  529. return virtHashCode(pair.key)
  530. };
  531. this.setValue = function(value) {
  532. var old = pair.value;
  533. pair.value = value;
  534. return old
  535. }
  536. }
  537. this.clear = function() {
  538. count = 0;
  539. buckets = [];
  540. buckets.length = initialCapacity
  541. };
  542. this.clone = function() {
  543. var map = new HashMap;
  544. map.putAll(this);
  545. return map
  546. };
  547. this.containsKey = function(key) {
  548. var index = getBucketIndex(key);
  549. var bucket = buckets[index];
  550. if (bucket === undef) return false;
  551. for (var i = 0; i < bucket.length; ++i) if (virtEquals(bucket[i].key, key)) return true;
  552. return false
  553. };
  554. this.containsValue = function(value) {
  555. for (var i = 0; i < buckets.length; ++i) {
  556. var bucket = buckets[i];
  557. if (bucket === undef) continue;
  558. for (var j = 0; j < bucket.length; ++j) if (virtEquals(bucket[j].value, value)) return true
  559. }
  560. return false
  561. };
  562. this.entrySet = function() {
  563. return new Set(function(pair) {
  564. return new Entry(pair)
  565. },
  566. function(pair) {
  567. return pair instanceof Entry && pair._isIn(hashMap)
  568. },
  569. function(pair) {
  570. return hashMap.remove(pair.getKey())
  571. })
  572. };
  573. this.get = function(key) {
  574. var index = getBucketIndex(key);
  575. var bucket = buckets[index];
  576. if (bucket === undef) return null;
  577. for (var i = 0; i < bucket.length; ++i) if (virtEquals(bucket[i].key, key)) return bucket[i].value;
  578. return null
  579. };
  580. this.isEmpty = function() {
  581. return count === 0
  582. };
  583. this.keySet = function() {
  584. return new Set(function(pair) {
  585. return pair.key
  586. },
  587. function(key) {
  588. return hashMap.containsKey(key)
  589. },
  590. function(key) {
  591. return hashMap.remove(key)
  592. })
  593. };
  594. this.values = function() {
  595. return new Set(function(pair) {
  596. return pair.value
  597. },
  598. function(value) {
  599. return hashMap.containsValue(value)
  600. },
  601. function(value) {
  602. return hashMap.removeByValue(value)
  603. })
  604. };
  605. this.put = function(key, value) {
  606. var index = getBucketIndex(key);
  607. var bucket = buckets[index];
  608. if (bucket === undef) {
  609. ++count;
  610. buckets[index] = [{
  611. key: key,
  612. value: value
  613. }];
  614. ensureLoad();
  615. return null
  616. }
  617. for (var i = 0; i < bucket.length; ++i) if (virtEquals(bucket[i].key, key)) {
  618. var previous = bucket[i].value;
  619. bucket[i].value = value;
  620. return previous
  621. }++count;
  622. bucket.push({
  623. key: key,
  624. value: value
  625. });
  626. ensureLoad();
  627. return null
  628. };
  629. this.putAll = function(m) {
  630. var it = m.entrySet().iterator();
  631. while (it.hasNext()) {
  632. var entry = it.next();
  633. this.put(entry.getKey(), entry.getValue())
  634. }
  635. };
  636. this.remove = function(key) {
  637. var index = getBucketIndex(key);
  638. var bucket = buckets[index];
  639. if (bucket === undef) return null;
  640. for (var i = 0; i < bucket.length; ++i) if (virtEquals(bucket[i].key, key)) {
  641. --count;
  642. var previous = bucket[i].value;
  643. bucket[i].removed = true;
  644. if (bucket.length > 1) bucket.splice(i, 1);
  645. else buckets[index] = undef;
  646. return previous
  647. }
  648. return null
  649. };
  650. this.removeByValue = function(value) {
  651. var bucket, i, ilen, pair;
  652. for (bucket in buckets) if (buckets.hasOwnProperty(bucket)) for (i = 0, ilen = buckets[bucket].length; i < ilen; i++) {
  653. pair = buckets[bucket][i];
  654. if (pair.value === value) {
  655. buckets[bucket].splice(i, 1);
  656. return true
  657. }
  658. }
  659. return false
  660. };
  661. this.size = function() {
  662. return count
  663. }
  664. }
  665. return HashMap
  666. }();
  667. var PVector = function() {
  668. function PVector(x, y, z) {
  669. this.x = x || 0;
  670. this.y = y || 0;
  671. this.z = z || 0
  672. }
  673. PVector.dist = function(v1, v2) {
  674. return v1.dist(v2)
  675. };
  676. PVector.dot = function(v1, v2) {
  677. return v1.dot(v2)
  678. };
  679. PVector.cross = function(v1, v2) {
  680. return v1.cross(v2)
  681. };
  682. PVector.angleBetween = function(v1, v2) {
  683. return Math.acos(v1.dot(v2) / (v1.mag() * v2.mag()))
  684. };
  685. PVector.prototype = {
  686. set: function(v, y, z) {
  687. if (arguments.length === 1) this.set(v.x || v[0] || 0, v.y || v[1] || 0, v.z || v[2] || 0);
  688. else {
  689. this.x = v;
  690. this.y = y;
  691. this.z = z
  692. }
  693. },
  694. get: function() {
  695. return new PVector(this.x, this.y, this.z)
  696. },
  697. mag: function() {
  698. var x = this.x,
  699. y = this.y,
  700. z = this.z;
  701. return Math.sqrt(x * x + y * y + z * z)
  702. },
  703. add: function(v, y, z) {
  704. if (arguments.length === 1) {
  705. this.x += v.x;
  706. this.y += v.y;
  707. this.z += v.z
  708. } else {
  709. this.x += v;
  710. this.y += y;
  711. this.z += z
  712. }
  713. },
  714. sub: function(v, y, z) {
  715. if (arguments.length === 1) {
  716. this.x -= v.x;
  717. this.y -= v.y;
  718. this.z -= v.z
  719. } else {
  720. this.x -= v;
  721. this.y -= y;
  722. this.z -= z
  723. }
  724. },
  725. mult: function(v) {
  726. if (typeof v === "number") {
  727. this.x *= v;
  728. this.y *= v;
  729. this.z *= v
  730. } else {
  731. this.x *= v.x;
  732. this.y *= v.y;
  733. this.z *= v.z
  734. }
  735. },
  736. div: function(v) {
  737. if (typeof v === "number") {
  738. this.x /= v;
  739. this.y /= v;
  740. this.z /= v
  741. } else {
  742. this.x /= v.x;
  743. this.y /= v.y;
  744. this.z /= v.z
  745. }
  746. },
  747. dist: function(v) {
  748. var dx = this.x - v.x,
  749. dy = this.y - v.y,
  750. dz = this.z - v.z;
  751. return Math.sqrt(dx * dx + dy * dy + dz * dz)
  752. },
  753. dot: function(v, y, z) {
  754. if (arguments.length === 1) return this.x * v.x + this.y * v.y + this.z * v.z;
  755. return this.x * v + this.y * y + this.z * z
  756. },
  757. cross: function(v) {
  758. var x = this.x,
  759. y = this.y,
  760. z = this.z;
  761. return new PVector(y * v.z - v.y * z, z * v.x - v.z * x, x * v.y - v.x * y)
  762. },
  763. normalize: function() {
  764. var m = this.mag();
  765. if (m > 0) this.div(m)
  766. },
  767. limit: function(high) {
  768. if (this.mag() > high) {
  769. this.normalize();
  770. this.mult(high)
  771. }
  772. },
  773. heading2D: function() {
  774. return -Math.atan2(-this.y, this.x)
  775. },
  776. toString: function() {
  777. return "[" + this.x + ", " + this.y + ", " + this.z + "]"
  778. },
  779. array: function() {
  780. return [this.x, this.y, this.z]
  781. }
  782. };
  783. function createPVectorMethod(method) {
  784. return function(v1, v2) {
  785. var v = v1.get();
  786. v[method](v2);
  787. return v
  788. }
  789. }
  790. for (var method in PVector.prototype) if (PVector.prototype.hasOwnProperty(method) && !PVector.hasOwnProperty(method)) PVector[method] = createPVectorMethod(method);
  791. return PVector
  792. }();
  793. function DefaultScope() {}
  794. DefaultScope.prototype = PConstants;
  795. var defaultScope = new DefaultScope;
  796. defaultScope.ArrayList = ArrayList;
  797. defaultScope.HashMap = HashMap;
  798. defaultScope.PVector = PVector;
  799. defaultScope.ObjectIterator = ObjectIterator;
  800. defaultScope.PConstants = PConstants;
  801. defaultScope.defineProperty = function(obj, name, desc) {
  802. if ("defineProperty" in Object) Object.defineProperty(obj, name, desc);
  803. else {
  804. if (desc.hasOwnProperty("get")) obj.__defineGetter__(name, desc.get);
  805. if (desc.hasOwnProperty("set")) obj.__defineSetter__(name, desc.set)
  806. }
  807. };
  808. function overloadBaseClassFunction(object, name, basefn) {
  809. if (!object.hasOwnProperty(name) || typeof object[name] !== "function") {
  810. object[name] = basefn;
  811. return
  812. }
  813. var fn = object[name];
  814. if ("$overloads" in fn) {
  815. fn.$defaultOverload = basefn;
  816. return
  817. }
  818. if (! ("$overloads" in basefn) && fn.length === basefn.length) return;
  819. var overloads, defaultOverload;
  820. if ("$overloads" in basefn) {
  821. overloads = basefn.$overloads.slice(0);
  822. overloads[fn.length] = fn;
  823. defaultOverload = basefn.$defaultOverload
  824. } else {
  825. overloads = [];
  826. overloads[basefn.length] = basefn;
  827. overloads[fn.length] = fn;
  828. defaultOverload = fn
  829. }
  830. var hubfn = function() {
  831. var fn = hubfn.$overloads[arguments.length] || ("$methodArgsIndex" in hubfn && arguments.length > hubfn.$methodArgsIndex ? hubfn.$overloads[hubfn.$methodArgsIndex] : null) || hubfn.$defaultOverload;
  832. return fn.apply(this, arguments)
  833. };
  834. hubfn.$overloads = overloads;
  835. if ("$methodArgsIndex" in basefn) hubfn.$methodArgsIndex = basefn.$methodArgsIndex;
  836. hubfn.$defaultOverload = defaultOverload;
  837. hubfn.name = name;
  838. object[name] = hubfn
  839. }
  840. function extendClass(subClass, baseClass) {
  841. function extendGetterSetter(propertyName) {
  842. defaultScope.defineProperty(subClass, propertyName, {
  843. get: function() {
  844. return baseClass[propertyName]
  845. },
  846. set: function(v) {
  847. baseClass[propertyName] = v
  848. },
  849. enumerable: true
  850. })
  851. }
  852. var properties = [];
  853. for (var propertyName in baseClass) if (typeof baseClass[propertyName] === "function") overloadBaseClassFunction(subClass, propertyName, baseClass[propertyName]);
  854. else if (propertyName.charAt(0) !== "$" && !(propertyName in subClass)) properties.push(propertyName);
  855. while (properties.length > 0) extendGetterSetter(properties.shift());
  856. subClass.$super = baseClass
  857. }
  858. defaultScope.extendClassChain = function(base) {
  859. var path = [base];
  860. for (var self = base.$upcast; self; self = self.$upcast) {
  861. extendClass(self, base);
  862. path.push(self);
  863. base = self
  864. }
  865. while (path.length > 0) path.pop().$self = base
  866. };
  867. defaultScope.extendStaticMembers = function(derived, base) {
  868. extendClass(derived, base)
  869. };
  870. defaultScope.extendInterfaceMembers = function(derived, base) {
  871. extendClass(derived, base)
  872. };
  873. defaultScope.addMethod = function(object, name, fn, hasMethodArgs) {
  874. var existingfn = object[name];
  875. if (existingfn || hasMethodArgs) {
  876. var args = fn.length;
  877. if ("$overloads" in existingfn) existingfn.$overloads[args] = fn;
  878. else {
  879. var hubfn = function() {
  880. var fn = hubfn.$overloads[arguments.length] || ("$methodArgsIndex" in hubfn && arguments.length > hubfn.$methodArgsIndex ? hubfn.$overloads[hubfn.$methodArgsIndex] : null) || hubfn.$defaultOverload;
  881. return fn.apply(this, arguments)
  882. };
  883. var overloads = [];
  884. if (existingfn) overloads[existingfn.length] = existingfn;
  885. overloads[args] = fn;
  886. hubfn.$overloads = overloads;
  887. hubfn.$defaultOverload = existingfn || fn;
  888. if (hasMethodArgs) hubfn.$methodArgsIndex = args;
  889. hubfn.name = name;
  890. object[name] = hubfn
  891. }
  892. } else object[name] = fn
  893. };
  894. function isNumericalJavaType(type) {
  895. if (typeof type !== "string") return false;
  896. return ["byte", "int", "char", "color", "float", "long", "double"].indexOf(type) !== -1
  897. }
  898. defaultScope.createJavaArray = function(type, bounds) {
  899. var result = null,
  900. defaultValue = null;
  901. if (typeof type === "string") if (type === "boolean") defaultValue = false;
  902. else if (isNumericalJavaType(type)) defaultValue = 0;
  903. if (typeof bounds[0] === "number") {
  904. var itemsCount = 0 | bounds[0];
  905. if (bounds.length <= 1) {
  906. result = [];
  907. result.length = itemsCount;
  908. for (var i = 0; i < itemsCount; ++i) result[i] = defaultValue
  909. } else {
  910. result = [];
  911. var newBounds = bounds.slice(1);
  912. for (var j = 0; j < itemsCount; ++j) result.push(defaultScope.createJavaArray(type, newBounds))
  913. }
  914. }
  915. return result
  916. };
  917. var colors = {
  918. aliceblue: "#f0f8ff",
  919. antiquewhite: "#faebd7",
  920. aqua: "#00ffff",
  921. aquamarine: "#7fffd4",
  922. azure: "#f0ffff",
  923. beige: "#f5f5dc",
  924. bisque: "#ffe4c4",
  925. black: "#000000",
  926. blanchedalmond: "#ffebcd",
  927. blue: "#0000ff",
  928. blueviolet: "#8a2be2",
  929. brown: "#a52a2a",
  930. burlywood: "#deb887",
  931. cadetblue: "#5f9ea0",
  932. chartreuse: "#7fff00",
  933. chocolate: "#d2691e",
  934. coral: "#ff7f50",
  935. cornflowerblue: "#6495ed",
  936. cornsilk: "#fff8dc",
  937. crimson: "#dc143c",
  938. cyan: "#00ffff",
  939. darkblue: "#00008b",
  940. darkcyan: "#008b8b",
  941. darkgoldenrod: "#b8860b",
  942. darkgray: "#a9a9a9",
  943. darkgreen: "#006400",
  944. darkkhaki: "#bdb76b",
  945. darkmagenta: "#8b008b",
  946. darkolivegreen: "#556b2f",
  947. darkorange: "#ff8c00",
  948. darkorchid: "#9932cc",
  949. darkred: "#8b0000",
  950. darksalmon: "#e9967a",
  951. darkseagreen: "#8fbc8f",
  952. darkslateblue: "#483d8b",
  953. darkslategray: "#2f4f4f",
  954. darkturquoise: "#00ced1",
  955. darkviolet: "#9400d3",
  956. deeppink: "#ff1493",
  957. deepskyblue: "#00bfff",
  958. dimgray: "#696969",
  959. dodgerblue: "#1e90ff",
  960. firebrick: "#b22222",
  961. floralwhite: "#fffaf0",
  962. forestgreen: "#228b22",
  963. fuchsia: "#ff00ff",
  964. gainsboro: "#dcdcdc",
  965. ghostwhite: "#f8f8ff",
  966. gold: "#ffd700",
  967. goldenrod: "#daa520",
  968. gray: "#808080",
  969. green: "#008000",
  970. greenyellow: "#adff2f",
  971. honeydew: "#f0fff0",
  972. hotpink: "#ff69b4",
  973. indianred: "#cd5c5c",
  974. indigo: "#4b0082",
  975. ivory: "#fffff0",
  976. khaki: "#f0e68c",
  977. lavender: "#e6e6fa",
  978. lavenderblush: "#fff0f5",
  979. lawngreen: "#7cfc00",
  980. lemonchiffon: "#fffacd",
  981. lightblue: "#add8e6",
  982. lightcoral: "#f08080",
  983. lightcyan: "#e0ffff",
  984. lightgoldenrodyellow: "#fafad2",
  985. lightgrey: "#d3d3d3",
  986. lightgreen: "#90ee90",
  987. lightpink: "#ffb6c1",
  988. lightsalmon: "#ffa07a",
  989. lightseagreen: "#20b2aa",
  990. lightskyblue: "#87cefa",
  991. lightslategray: "#778899",
  992. lightsteelblue: "#b0c4de",
  993. lightyellow: "#ffffe0",
  994. lime: "#00ff00",
  995. limegreen: "#32cd32",
  996. linen: "#faf0e6",
  997. magenta: "#ff00ff",
  998. maroon: "#800000",
  999. mediumaquamarine: "#66cdaa",
  1000. mediumblue: "#0000cd",
  1001. mediumorchid: "#ba55d3",
  1002. mediumpurple: "#9370d8",
  1003. mediumseagreen: "#3cb371",
  1004. mediumslateblue: "#7b68ee",
  1005. mediumspringgreen: "#00fa9a",
  1006. mediumturquoise: "#48d1cc",
  1007. mediumvioletred: "#c71585",
  1008. midnightblue: "#191970",
  1009. mintcream: "#f5fffa",
  1010. mistyrose: "#ffe4e1",
  1011. moccasin: "#ffe4b5",
  1012. navajowhite: "#ffdead",
  1013. navy: "#000080",
  1014. oldlace: "#fdf5e6",
  1015. olive: "#808000",
  1016. olivedrab: "#6b8e23",
  1017. orange: "#ffa500",
  1018. orangered: "#ff4500",
  1019. orchid: "#da70d6",
  1020. palegoldenrod: "#eee8aa",
  1021. palegreen: "#98fb98",
  1022. paleturquoise: "#afeeee",
  1023. palevioletred: "#d87093",
  1024. papayawhip: "#ffefd5",
  1025. peachpuff: "#ffdab9",
  1026. peru: "#cd853f",
  1027. pink: "#ffc0cb",
  1028. plum: "#dda0dd",
  1029. powderblue: "#b0e0e6",
  1030. purple: "#800080",
  1031. red: "#ff0000",
  1032. rosybrown: "#bc8f8f",
  1033. royalblue: "#4169e1",
  1034. saddlebrown: "#8b4513",
  1035. salmon: "#fa8072",
  1036. sandybrown: "#f4a460",
  1037. seagreen: "#2e8b57",
  1038. seashell: "#fff5ee",
  1039. sienna: "#a0522d",
  1040. silver: "#c0c0c0",
  1041. skyblue: "#87ceeb",
  1042. slateblue: "#6a5acd",
  1043. slategray: "#708090",
  1044. snow: "#fffafa",
  1045. springgreen: "#00ff7f",
  1046. steelblue: "#4682b4",
  1047. tan: "#d2b48c",
  1048. teal: "#008080",
  1049. thistle: "#d8bfd8",
  1050. tomato: "#ff6347",
  1051. turquoise: "#40e0d0",
  1052. violet: "#ee82ee",
  1053. wheat: "#f5deb3",
  1054. white: "#ffffff",
  1055. whitesmoke: "#f5f5f5",
  1056. yellow: "#ffff00",
  1057. yellowgreen: "#9acd32"
  1058. };
  1059. (function(Processing) {
  1060. var unsupportedP5 = ("open() createOutput() createInput() BufferedReader selectFolder() " + "dataPath() createWriter() selectOutput() beginRecord() " + "saveStream() endRecord() selectInput() saveBytes() createReader() " + "beginRaw() endRaw() PrintWriter delay()").split(" "),
  1061. count = unsupportedP5.length,
  1062. prettyName, p5Name;
  1063. function createUnsupportedFunc(n) {
  1064. return function() {
  1065. throw "Processing.js does not support " + n + ".";
  1066. }
  1067. }
  1068. while (count--) {
  1069. prettyName = unsupportedP5[count];
  1070. p5Name = prettyName.replace("()", "");
  1071. Processing[p5Name] = createUnsupportedFunc(prettyName)
  1072. }
  1073. })(defaultScope);
  1074. defaultScope.defineProperty(defaultScope, "screenWidth", {
  1075. get: function() {
  1076. return window.innerWidth
  1077. }
  1078. });
  1079. defaultScope.defineProperty(defaultScope, "screenHeight", {
  1080. get: function() {
  1081. return window.innerHeight
  1082. }
  1083. });
  1084. defaultScope.defineProperty(defaultScope, "online", {
  1085. get: function() {
  1086. return true
  1087. }
  1088. });
  1089. var processingInstances = [];
  1090. var processingInstanceIds = {};
  1091. var removeInstance = function(id) {
  1092. processingInstances.splice(processingInstanceIds[id], 1);
  1093. delete processingInstanceIds[id]
  1094. };
  1095. var addInstance = function(processing) {
  1096. if (processing.externals.canvas.id === undef || !processing.externals.canvas.id.length) processing.externals.canvas.id = "__processing" + processingInstances.length;
  1097. processingInstanceIds[processing.externals.canvas.id] = processingInstances.length;
  1098. processingInstances.push(processing)
  1099. };
  1100. function computeFontMetrics(pfont) {
  1101. var emQuad = 250,
  1102. correctionFactor = pfont.size / emQuad,
  1103. canvas = document.createElement("canvas");
  1104. canvas.width = 2 * emQuad;
  1105. canvas.height = 2 * emQuad;
  1106. canvas.style.opacity = 0;
  1107. var cfmFont = pfont.getCSSDefinition(emQuad + "px", "normal"),
  1108. ctx = canvas.getContext("2d");
  1109. ctx.font = cfmFont;
  1110. var protrusions = "dbflkhyjqpg";
  1111. canvas.width = ctx.measureText(protrusions).width;
  1112. ctx.font = cfmFont;
  1113. var leadDiv = document.createElement("div");
  1114. leadDiv.style.position = "absolute";
  1115. leadDiv.style.opacity = 0;
  1116. leadDiv.style.fontFamily = '"' + pfont.name + '"';
  1117. leadDiv.style.fontSize = emQuad + "px";
  1118. leadDiv.innerHTML = protrusions + "<br/>" + protrusions;
  1119. document.body.appendChild(leadDiv);
  1120. var w = canvas.width,
  1121. h = canvas.height,
  1122. baseline = h / 2;
  1123. ctx.fillStyle = "white";
  1124. ctx.fillRect(0, 0, w, h);
  1125. ctx.fillStyle = "black";
  1126. ctx.fillText(protrusions, 0, baseline);
  1127. var pixelData = ctx.getImageData(0, 0, w, h).data;
  1128. var i = 0,
  1129. w4 = w * 4,
  1130. len = pixelData.length;
  1131. while (++i < len && pixelData[i] === 255) nop();
  1132. var ascent = Math.round(i / w4);
  1133. i = len - 1;
  1134. while (--i > 0 && pixelData[i] === 255) nop();
  1135. var descent = Math.round(i / w4);
  1136. pfont.ascent = correctionFactor * (baseline - ascent);
  1137. pfont.descent = correctionFactor * (descent - baseline);
  1138. if (document.defaultView.getComputedStyle) {
  1139. var leadDivHeight = document.defaultView.getComputedStyle(leadDiv, null).getPropertyValue("height");
  1140. leadDivHeight = correctionFactor * leadDivHeight.replace("px", "");
  1141. if (leadDivHeight >= pfont.size * 2) pfont.leading = Math.round(leadDivHeight / 2)
  1142. }
  1143. document.body.removeChild(leadDiv);
  1144. if (pfont.caching) return ctx
  1145. }
  1146. function PFont(name, size) {
  1147. if (name === undef) name = "";
  1148. this.name = name;
  1149. if (size === undef) size = 0;
  1150. this.size = size;
  1151. this.glyph = false;
  1152. this.ascent = 0;
  1153. this.descent = 0;
  1154. this.leading = 1.2 * size;
  1155. var illegalIndicator = name.indexOf(" Italic Bold");
  1156. if (illegalIndicator !== -1) name = name.substring(0, illegalIndicator);
  1157. this.style = "normal";
  1158. var italicsIndicator = name.indexOf(" Italic");
  1159. if (italicsIndicator !== -1) {
  1160. name = name.substring(0, italicsIndicator);
  1161. this.style = "italic"
  1162. }
  1163. this.weight = "normal";
  1164. var boldIndicator = name.indexOf(" Bold");
  1165. if (boldIndicator !== -1) {
  1166. name = name.substring(0, boldIndicator);
  1167. this.weight = "bold"
  1168. }
  1169. this.family = "sans-serif";
  1170. if (name !== undef) switch (name) {
  1171. case "sans-serif":
  1172. case "serif":
  1173. case "monospace":
  1174. case "fantasy":
  1175. case "cursive":
  1176. this.family = name;
  1177. break;
  1178. default:
  1179. this.family = '"' + name + '", sans-serif';
  1180. break
  1181. }
  1182. this.context2d = computeFontMetrics(this);
  1183. this.css = this.getCSSDefinition();
  1184. if (this.context2d) this.context2d.font = this.css
  1185. }
  1186. PFont.prototype.caching = true;
  1187. PFont.prototype.getCSSDefinition = function(fontSize, lineHeight) {
  1188. if (fontSize === undef) fontSize = this.size + "px";
  1189. if (lineHeight === undef) lineHeight = this.leading + "px";
  1190. var components = [this.style, "normal", this.weight, fontSize + "/" + lineHeight, this.family];
  1191. return components.join(" ")
  1192. };
  1193. PFont.prototype.measureTextWidth = function(string) {
  1194. return this.context2d.measureText(string).width
  1195. };
  1196. PFont.prototype.measureTextWidthFallback = function(string) {
  1197. var canvas = document.createElement("canvas"),
  1198. ctx = canvas.getContext("2d");
  1199. ctx.font = this.css;
  1200. return ctx.measureText(string).width
  1201. };
  1202. PFont.PFontCache = {
  1203. length: 0
  1204. };
  1205. PFont.get = function(fontName, fontSize) {
  1206. fontSize = (fontSize * 10 + 0.5 | 0) / 10;
  1207. var cache = PFont.PFontCache,
  1208. idx = fontName + "/" + fontSize;
  1209. if (!cache[idx]) {
  1210. cache[idx] = new PFont(fontName, fontSize);
  1211. cache.length++;
  1212. if (cache.length === 50) {
  1213. PFont.prototype.measureTextWidth = PFont.prototype.measureTextWidthFallback;
  1214. PFont.prototype.caching = false;
  1215. var entry;
  1216. for (entry in cache) if (entry !== "length") cache[entry].context2d = null;
  1217. return new PFont(fontName, fontSize)
  1218. }
  1219. if (cache.length === 400) {
  1220. PFont.PFontCache = {};
  1221. PFont.get = PFont.getFallback;
  1222. return new PFont(fontName, fontSize)
  1223. }
  1224. }
  1225. return cache[idx]
  1226. };
  1227. PFont.getFallback = function(fontName, fontSize) {
  1228. return new PFont(fontName, fontSize)
  1229. };
  1230. PFont.list = function() {
  1231. return ["sans-serif", "serif", "monospace", "fantasy", "cursive"]
  1232. };
  1233. PFont.preloading = {
  1234. template: {},
  1235. initialized: false,
  1236. initialize: function() {
  1237. var generateTinyFont = function() {
  1238. 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#";
  1239. var expand = function(input) {
  1240. return "AAAAAAAA".substr(~~input ? 7 - input : 6)
  1241. };
  1242. return encoded.replace(/[#237]/g, expand)
  1243. };
  1244. var fontface = document.createElement("style");
  1245. fontface.setAttribute("type", "text/css");
  1246. fontface.innerHTML = "@font-face {\n" + ' font-family: "PjsEmptyFont";' + "\n" + " src: url('data:application/x-font-ttf;base64," + generateTinyFont() + "')\n" + " format('truetype');\n" + "}";
  1247. document.head.appendChild(fontface);
  1248. var element = document.createElement("span");
  1249. element.style.cssText = 'position: absolute; top: 0; left: 0; opacity: 0; font-family: "PjsEmptyFont", fantasy;';
  1250. element.innerHTML = "AAAAAAAA";
  1251. document.body.appendChild(element);
  1252. this.template = element;
  1253. this.initialized = true
  1254. },
  1255. getElementWidth: function(element) {
  1256. return document.defaultView.getComputedStyle(element, "").getPropertyValue("width")
  1257. },
  1258. timeAttempted: 0,
  1259. pending: function(intervallength) {
  1260. if (!this.initialized) this.initialize();
  1261. var element, computedWidthFont, computedWidthRef = this.getElementWidth(this.template);
  1262. for (var i = 0; i < this.fontList.length; i++) {
  1263. element = this.fontList[i];
  1264. computedWidthFont = this.getElementWidth(element);
  1265. if (this.timeAttempted < 4E3 && computedWidthFont === computedWidthRef) {
  1266. this.timeAttempted += intervallength;
  1267. return true
  1268. } else {
  1269. document.body.removeChild(element);
  1270. this.fontList.splice(i--, 1);
  1271. this.timeAttempted = 0
  1272. }
  1273. }
  1274. if (this.fontList.length === 0) return false;
  1275. return true
  1276. },
  1277. fontList: [],
  1278. addedList: {},
  1279. add: function(fontSrc) {
  1280. if (!this.initialized) this.initialize();
  1281. var fontName = typeof fontSrc === "object" ? fontSrc.fontFace : fontSrc,
  1282. fontUrl = typeof fontSrc === "object" ? fontSrc.url : fontSrc;
  1283. if (this.addedList[fontName]) return;
  1284. var style = document.createElement("style");
  1285. style.setAttribute("type", "text/css");
  1286. style.innerHTML = "@font-face{\n font-family: '" + fontName + "';\n src: url('" + fontUrl + "');\n}\n";
  1287. document.head.appendChild(style);
  1288. this.addedList[fontName] = true;
  1289. var element = document.createElement("span");
  1290. element.style.cssText = "position: absolute; top: 0; left: 0; opacity: 0;";
  1291. element.style.fontFamily = '"' + fontName + '", "PjsEmptyFont", fantasy';
  1292. element.innerHTML = "AAAAAAAA";
  1293. document.body.appendChild(element);
  1294. this.fontList.push(element)
  1295. }
  1296. };
  1297. defaultScope.PFont = PFont;
  1298. var Processing = this.Processing = function(aCanvas, aCode) {
  1299. if (! (this instanceof
  1300. Processing)) throw "called Processing constructor as if it were a function: missing 'new'.";
  1301. var curElement, pgraphicsMode = aCanvas === undef && aCode === undef;
  1302. if (pgraphicsMode) curElement = document.createElement("canvas");
  1303. else curElement = typeof aCanvas === "string" ? document.getElementById(aCanvas) : aCanvas;
  1304. if (! (curElement instanceof HTMLCanvasElement)) throw "called Processing constructor without passing canvas element reference or id.";
  1305. function unimplemented(s) {
  1306. Processing.debug("Unimplemented - " + s)
  1307. }
  1308. var p = this;
  1309. p.externals = {
  1310. canvas: curElement,
  1311. context: undef,
  1312. sketch: undef
  1313. };
  1314. p.name = "Processing.js Instance";
  1315. p.use3DContext = false;
  1316. p.focused = false;
  1317. p.breakShape = false;
  1318. p.glyphTable = {};
  1319. p.pmouseX = 0;
  1320. p.pmouseY = 0;
  1321. p.mouseX = 0;
  1322. p.mouseY = 0;
  1323. p.mouseButton = 0;
  1324. p.mouseScroll = 0;
  1325. p.mouseClicked = undef;
  1326. p.mouseDragged = undef;
  1327. p.mouseMoved = undef;
  1328. p.mousePressed = undef;
  1329. p.mouseReleased = undef;
  1330. p.mouseScrolled = undef;
  1331. p.mouseOver = undef;
  1332. p.mouseOut = undef;
  1333. p.touchStart = undef;
  1334. p.touchEnd = undef;
  1335. p.touchMove = undef;
  1336. p.touchCancel = undef;
  1337. p.key = undef;
  1338. p.keyCode = undef;
  1339. p.keyPressed = nop;
  1340. p.keyReleased = nop;
  1341. p.keyTyped = nop;
  1342. p.draw = undef;
  1343. p.setup = undef;
  1344. p.__mousePressed = false;
  1345. p.__keyPressed = false;
  1346. p.__frameRate = 60;
  1347. p.frameCount = 0;
  1348. p.width = 100;
  1349. p.height = 100;
  1350. var curContext, curSketch, drawing, online = true,
  1351. doFill = true,
  1352. fillStyle = [1, 1, 1, 1],
  1353. currentFillColor = 4294967295,
  1354. isFillDirty = true,
  1355. doStroke = true,
  1356. strokeStyle = [0, 0, 0, 1],
  1357. currentStrokeColor = 4278190080,
  1358. isStrokeDirty = true,
  1359. lineWidth = 1,
  1360. loopStarted = false,
  1361. renderSmooth = false,
  1362. doLoop = true,
  1363. looping = 0,
  1364. curRectMode = 0,
  1365. curEllipseMode = 3,
  1366. normalX = 0,
  1367. normalY = 0,
  1368. normalZ = 0,
  1369. normalMode = 0,
  1370. curFrameRate = 60,
  1371. curMsPerFrame = 1E3 / curFrameRate,
  1372. curCursor = 'default',
  1373. oldCursor = curElement.style.cursor,
  1374. curShape = 20,
  1375. curShapeCount = 0,
  1376. curvePoints = [],
  1377. curTightness = 0,
  1378. curveDet = 20,
  1379. curveInited = false,
  1380. backgroundObj = -3355444,
  1381. bezDetail = 20,
  1382. colorModeA = 255,
  1383. colorModeX = 255,
  1384. colorModeY = 255,
  1385. colorModeZ = 255,
  1386. pathOpen = false,
  1387. mouseDragging = false,
  1388. pmouseXLastFrame = 0,
  1389. pmouseYLastFrame = 0,
  1390. curColorMode = 1,
  1391. curTint = null,
  1392. curTint3d = null,
  1393. getLoaded = false,
  1394. start = Date.now(),
  1395. timeSinceLastFPS = start,
  1396. framesSinceLastFPS = 0,
  1397. textcanvas, curveBasisMatrix, curveToBezierMatrix, curveDrawMatrix, bezierDrawMatrix, bezierBasisInverse, bezierBasisMatrix, curContextCache = {
  1398. attributes: {},
  1399. locations: {}
  1400. },
  1401. programObject3D, programObject2D, programObjectUnlitShape, boxBuffer, boxNormBuffer, boxOutlineBuffer, rectBuffer, rectNormBuffer, sphereBuffer, lineBuffer, fillBuffer, fillColorBuffer, strokeColorBuffer, pointBuffer, shapeTexVBO, canTex, textTex, curTexture = {
  1402. width: 0,
  1403. height: 0
  1404. },
  1405. curTextureMode = 2,
  1406. usingTexture = false,
  1407. textBuffer, textureBuffer, indexBuffer, horizontalTextAlignment = 37,
  1408. verticalTextAlignment = 0,
  1409. textMode = 4,
  1410. curFontName = "Arial",
  1411. curTextSize = 12,
  1412. curTextAscent = 9,
  1413. curTextDescent = 2,
  1414. curTextLeading = 14,
  1415. curTextFont = PFont.get(curFontName, curTextSize),
  1416. originalContext, proxyContext = null,
  1417. isContextReplaced = false,
  1418. setPixelsCached, maxPixelsCached = 1E3,
  1419. pressedKeysMap = [],
  1420. lastPressedKeyCode = null,
  1421. codedKeys = [16,
  1422. 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];
  1423. var stylePaddingLeft, stylePaddingTop, styleBorderLeft, styleBorderTop;
  1424. if (document.defaultView && document.defaultView.getComputedStyle) {
  1425. stylePaddingLeft = parseInt(document.defaultView.getComputedStyle(curElement, null)["paddingLeft"], 10) || 0;
  1426. stylePaddingTop = parseInt(document.defaultView.getComputedStyle(curElement, null)["paddingTop"], 10) || 0;
  1427. styleBorderLeft = parseInt(document.defaultView.getComputedStyle(curElement, null)["borderLeftWidth"], 10) || 0;
  1428. styleBorderTop = parseInt(document.defaultView.getComputedStyle(curElement, null)["borderTopWidth"], 10) || 0
  1429. }
  1430. var lightCount = 0;
  1431. var sphereDetailV = 0,
  1432. sphereDetailU = 0,
  1433. sphereX = [],
  1434. sphereY = [],
  1435. sphereZ = [],
  1436. sinLUT = new Float32Array(720),
  1437. cosLUT = new Float32Array(720),
  1438. sphereVerts, sphereNorms;
  1439. var cam, cameraInv, modelView, modelViewInv, userMatrixStack, userReverseMatrixStack, inverseCopy, projection, manipulatingCamera = false,
  1440. frustumMode = false,
  1441. cameraFOV = 60 * (Math.PI / 180),
  1442. cameraX = p.width / 2,
  1443. cameraY = p.height / 2,
  1444. cameraZ = cameraY / Math.tan(cameraFOV / 2),
  1445. cameraNear = cameraZ / 10,
  1446. cameraFar = cameraZ * 10,
  1447. cameraAspect = p.width / p.height;
  1448. var vertArray = [],
  1449. curveVertArray = [],
  1450. curveVertCount = 0,
  1451. isCurve = false,
  1452. isBezier = false,
  1453. firstVert = true;
  1454. var curShapeMode = 0;
  1455. var styleArray = [];
  1456. 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,
  1457. 0.5, -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5]);
  1458. 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]);
  1459. 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,
  1460. 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]);
  1461. var rectVerts = new Float32Array([0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0]);
  1462. var rectNorms = new Float32Array([0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1]);
  1463. 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);" + "}";
  1464. 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;" + "}";
  1465. 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;" + "}";
  1466. 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;" + " }" + "}";
  1467. var webglMaxTempsWorkaround = /Windows/.test(navigator.userAgent);
  1468. 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 );" + "}";
  1469. 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;" + " }" + "}";
  1470. function uniformf(cacheId, programObj, varName, varValue) {
  1471. var varLocation = curContextCache.locations[cacheId];
  1472. if (varLocation === undef) {
  1473. varLocation = curContext.getUniformLocation(programObj, varName);
  1474. curContextCache.locations[cacheId] = varLocation
  1475. }
  1476. if (varLocation !== null) if (varValue.length === 4) curContext.uniform4fv(varLocation, varValue);
  1477. else if (varValue.length === 3) curContext.uniform3fv(varLocation, varValue);
  1478. else if (varValue.length === 2) curContext.uniform2fv(varLocation, varValue);
  1479. else curContext.uniform1f(varLocation, varValue)
  1480. }
  1481. function uniformi(cacheId, programObj, varName, varValue) {
  1482. var varLocation = curContextCache.locations[cacheId];
  1483. if (varLocation === undef) {
  1484. varLocation = curContext.getUniformLocation(programObj, varName);
  1485. curContextCache.locations[cacheId] = varLocation
  1486. }
  1487. if (varLocation !== null) if (varValue.length === 4) curContext.uniform4iv(varLocation, varValue);
  1488. else if (varValue.length === 3) curContext.uniform3iv(varLocation, varValue);
  1489. else if (varValue.length === 2) curContext.uniform2iv(varLocation, varValue);
  1490. else curContext.uniform1i(varLocation, varValue)
  1491. }
  1492. function uniformMatrix(cacheId, programObj, varName, transpose, matrix) {
  1493. var varLocation = curContextCache.locations[cacheId];
  1494. if (varLocation === undef) {
  1495. varLocation = curContext.getUniformLocation(programObj, varName);
  1496. curContextCache.locations[cacheId] = varLocation
  1497. }
  1498. if (varLocation !== -1) if (matrix.length === 16) curContext.uniformMatrix4fv(varLocation, transpose, matrix);
  1499. else if (matrix.length === 9) curContext.uniformMatrix3fv(varLocation, transpose, matrix);
  1500. else curContext.uniformMatrix2fv(varLocation, transpose, matrix)
  1501. }
  1502. function vertexAttribPointer(cacheId, programObj, varName, size, VBO) {
  1503. var varLocation = curContextCache.attributes[cacheId];
  1504. if (varLocation === undef) {
  1505. varLocation = curContext.getAttribLocation(programObj, varName);
  1506. curContextCache.attributes[cacheId] = varLocation
  1507. }
  1508. if (varLocation !== -1) {
  1509. curContext.bindBuffer(curContext.ARRAY_BUFFER, VBO);
  1510. curContext.vertexAttribPointer(varLocation, size, curContext.FLOAT, false, 0, 0);
  1511. curContext.enableVertexAttribArray(varLocation)
  1512. }
  1513. }
  1514. function disableVertexAttribPointer(cacheId, programObj, varName) {
  1515. var varLocation = curContextCache.attributes[cacheId];
  1516. if (varLocation === undef) {
  1517. varLocation = curContext.getAttribLocation(programObj, varName);
  1518. curContextCache.attributes[cacheId] = varLocation
  1519. }
  1520. if (varLocation !== -1) curContext.disableVertexAttribArray(varLocation)
  1521. }
  1522. var createProgramObject = function(curContext, vetexShaderSource, fragmentShaderSource) {
  1523. var vertexShaderObject = curContext.createShader(curContext.VERTEX_SHADER);
  1524. curContext.shaderSource(vertexShaderObject, vetexShaderSource);
  1525. curContext.compileShader(vertexShaderObject);
  1526. if (!curContext.getShaderParameter(vertexShaderObject, curContext.COMPILE_STATUS)) throw curContext.getShaderInfoLog(vertexShaderObject);
  1527. var fragmentShaderObject = curContext.createShader(curContext.FRAGMENT_SHADER);
  1528. curContext.shaderSource(fragmentShaderObject, fragmentShaderSource);
  1529. curContext.compileShader(fragmentShaderObject);
  1530. if (!curContext.getShaderParameter(fragmentShaderObject, curContext.COMPILE_STATUS)) throw curContext.getShaderInfoLog(fragmentShaderObject);
  1531. var programObject = curContext.createProgram();
  1532. curContext.attachShader(programObject, vertexShaderObject);
  1533. curContext.attachShader(programObject, fragmentShaderObject);
  1534. curContext.linkProgram(programObject);
  1535. if (!curContext.getProgramParameter(programObject, curContext.LINK_STATUS)) throw "Error linking shaders.";
  1536. return programObject
  1537. };
  1538. var imageModeCorner = function(x, y, w, h, whAreSizes) {
  1539. return {
  1540. x: x,
  1541. y: y,
  1542. w: w,
  1543. h: h
  1544. }
  1545. };
  1546. var imageModeConvert = imageModeCorner;
  1547. var imageModeCorners = function(x, y, w, h, whAreSizes) {
  1548. return {
  1549. x: x,
  1550. y: y,
  1551. w: whAreSizes ? w : w - x,
  1552. h: whAreSizes ? h : h - y
  1553. }
  1554. };
  1555. var imageModeCenter = function(x, y, w, h, whAreSizes) {
  1556. return {
  1557. x: x - w / 2,
  1558. y: y - h / 2,
  1559. w: w,
  1560. h: h
  1561. }
  1562. };
  1563. var DrawingShared = function() {};
  1564. var Drawing2D = function() {};
  1565. var Drawing3D = function() {};
  1566. var DrawingPre = function() {};
  1567. Drawing2D.prototype = new DrawingShared;
  1568. Drawing2D.prototype.constructor = Drawing2D;
  1569. Drawing3D.prototype = new DrawingShared;
  1570. Drawing3D.prototype.constructor = Drawing3D;
  1571. DrawingPre.prototype = new DrawingShared;
  1572. DrawingPre.prototype.constructor = DrawingPre;
  1573. DrawingShared.prototype.a3DOnlyFunction = nop;
  1574. var charMap = {};
  1575. var Char = p.Character = function(chr) {
  1576. if (typeof chr === "string" && chr.length === 1) this.code = chr.charCodeAt(0);
  1577. else if (typeof chr === "number") this.code = chr;
  1578. else if (chr instanceof Char) this.code = chr;
  1579. else this.code = NaN;
  1580. return charMap[this.code] === undef ? charMap[this.code] = this : charMap[this.code]
  1581. };
  1582. Char.prototype.toString = function() {
  1583. return String.fromCharCode(this.code)
  1584. };
  1585. Char.prototype.valueOf = function() {
  1586. return this.code
  1587. };
  1588. var PShape = p.PShape = function(family) {
  1589. this.family = family || 0;
  1590. this.visible = true;
  1591. this.style = true;
  1592. this.children = [];
  1593. this.nameTable = [];
  1594. this.params = [];
  1595. this.name = "";
  1596. this.image = null;
  1597. this.matrix = null;
  1598. this.kind = null;
  1599. this.close = null;
  1600. this.width = null;
  1601. this.height = null;
  1602. this.parent = null
  1603. };
  1604. PShape.prototype = {
  1605. isVisible: function() {
  1606. return this.visible
  1607. },
  1608. setVisible: function(visible) {
  1609. this.visible = visible
  1610. },
  1611. disableStyle: function() {
  1612. this.style = false;
  1613. for (var i = 0, j = this.children.length; i < j; i++) this.children[i].disableStyle()
  1614. },
  1615. enableStyle: function() {
  1616. this.style = true;
  1617. for (var i = 0, j = this.children.length; i < j; i++) this.children[i].enableStyle()
  1618. },
  1619. getFamily: function() {
  1620. return this.family
  1621. },
  1622. getWidth: function() {
  1623. return this.width
  1624. },
  1625. getHeight: function() {
  1626. return this.height
  1627. },
  1628. setName: function(name) {
  1629. this.name = name
  1630. },
  1631. getName: function() {
  1632. return this.name
  1633. },
  1634. draw: function(renderContext) {
  1635. renderContext = renderContext || p;
  1636. if (this.visible) {
  1637. this.pre(renderContext);
  1638. this.drawImpl(renderContext);
  1639. this.post(renderContext)
  1640. }
  1641. },
  1642. drawImpl: function(renderContext) {
  1643. if (this.family === 0) this.drawGroup(renderContext);
  1644. else if (this.family === 1) this.drawPrimitive(renderContext);
  1645. else if (this.family === 3) this.drawGeometry(renderContext);
  1646. else if (this.family === 21) this.drawPath(renderContext)
  1647. },
  1648. drawPath: function(renderContext) {
  1649. var i, j;
  1650. if (this.vertices.length === 0) return;
  1651. renderContext.beginShape();
  1652. 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]);
  1653. 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]);
  1654. else {
  1655. var index = 0;
  1656. if (this.vertices[0].length === 2) for (i = 0, j = this.vertexCodes.length; i < j; i++) if (this.vertexCodes[i] === 0) {
  1657. renderContext.vertex(this.vertices[index][0], this.vertices[index][1], this.vertices[index]["moveTo"]);
  1658. renderContext.breakShape = false;
  1659. index++
  1660. } else if (this.vertexCodes[i] === 1) {
  1661. 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]);
  1662. index += 3
  1663. } else if (this.vertexCodes[i] === 2) {
  1664. renderContext.curveVertex(this.vertices[index][0], this.vertices[index][1]);
  1665. index++
  1666. } else {
  1667. if (this.vertexCodes[i] === 3) renderContext.breakShape = true
  1668. } else for (i = 0, j = this.vertexCodes.length; i < j; i++) if (this.vertexCodes[i] === 0) {
  1669. renderContext.vertex(this.vertices[index][0], this.vertices[index][1], this.vertices[index][2]);
  1670. if (this.vertices[index]["moveTo"] === true) vertArray[vertArray.length - 1]["moveTo"] = true;
  1671. else if (this.vertices[index]["moveTo"] === false) vertArray[vertArray.length - 1]["moveTo"] = false;
  1672. renderContext.breakShape = false
  1673. } else if (this.vertexCodes[i] === 1) {
  1674. 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]);
  1675. index += 3
  1676. } else if (this.vertexCodes[i] === 2) {
  1677. renderContext.curveVertex(this.vertices[index][0], this.vertices[index][1], this.vertices[index][2]);
  1678. index++
  1679. } else if (this.vertexCodes[i] === 3) renderContext.breakShape = true
  1680. }
  1681. renderContext.endShape(this.close ? 2 : 1)
  1682. },
  1683. drawGeometry: function(renderContext) {
  1684. var i, j;
  1685. renderContext.beginShape(this.kind);
  1686. if (this.style) for (i = 0, j = this.vertices.length; i < j; i++) renderContext.vertex(this.vertices[i]);
  1687. else for (i = 0, j = this.vertices.length; i < j; i++) {
  1688. var vert = this.vertices[i];
  1689. if (vert[2] === 0) renderContext.vertex(vert[0], vert[1]);
  1690. else renderContext.vertex(vert[0], vert[1], vert[2])
  1691. }
  1692. renderContext.endShape()
  1693. },
  1694. drawGroup: function(renderContext) {
  1695. for (var i = 0, j = this.children.length; i < j; i++) this.children[i].draw(renderContext)
  1696. },
  1697. drawPrimitive: function(renderContext) {
  1698. if (this.kind === 2) renderContext.point(this.params[0], this.params[1]);
  1699. else if (this.kind === 4) if (this.params.length === 4) renderContext.line(this.params[0], this.params[1], this.params[2], this.params[3]);
  1700. else renderContext.line(this.params[0], this.params[1], this.params[2], this.params[3], this.params[4], this.params[5]);
  1701. 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]);
  1702. 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]);
  1703. else if (this.kind === 30) if (this.image !== null) {
  1704. var imMode = imageModeConvert;
  1705. renderContext.imageMode(0);
  1706. renderContext.image(this.image, this.params[0], this.params[1], this.params[2], this.params[3]);
  1707. imageModeConvert = imMode
  1708. } else {
  1709. var rcMode = curRectMode;
  1710. renderContext.rectMode(0);
  1711. renderContext.rect(this.params[0], this.params[1], this.params[2], this.params[3]);
  1712. curRectMode = rcMode
  1713. } else if (this.kind === 31) {
  1714. var elMode = curEllipseMode;
  1715. renderContext.ellipseMode(0);
  1716. renderContext.ellipse(this.params[0], this.params[1], this.params[2], this.params[3]);
  1717. curEllipseMode = elMode
  1718. } else if (this.kind === 32) {
  1719. var eMode = curEllipseMode;
  1720. renderContext.ellipseMode(0);
  1721. renderContext.arc(this.params[0], this.params[1], this.params[2], this.params[3], this.params[4], this.params[5]);
  1722. curEllipseMode = eMode
  1723. } else if (this.kind === 41) if (this.params.length === 1) renderContext.box(this.params[0]);
  1724. else renderContext.box(this.params[0], this.params[1], this.params[2]);
  1725. else if (this.kind === 40) renderContext.sphere(this.params[0])
  1726. },
  1727. pre: function(renderContext) {
  1728. if (this.matrix) {
  1729. renderContext.pushMatrix();
  1730. renderContext.transform(this.matrix)
  1731. }
  1732. if (this.style) {
  1733. renderContext.pushStyle();
  1734. this.styles(renderContext)
  1735. }
  1736. },
  1737. post: function(renderContext) {
  1738. if (this.matrix) renderContext.popMatrix();
  1739. if (this.style) renderContext.popStyle()
  1740. },
  1741. styles: function(renderContext) {
  1742. if (this.stroke) {
  1743. renderContext.stroke(this.strokeColor);
  1744. renderContext.strokeWeight(this.strokeWeight);
  1745. renderContext.strokeCap(this.strokeCap);
  1746. renderContext.strokeJoin(this.strokeJoin)
  1747. } else renderContext.noStroke();
  1748. if (this.fill) renderContext.fill(this.fillColor);
  1749. else renderContext.noFill()
  1750. },
  1751. getChild: function(child) {
  1752. var i, j;
  1753. if (typeof child === "number") return this.children[child];
  1754. var found;
  1755. if (child === "" || this.name === child) return this;
  1756. if (this.nameTable.length > 0) {
  1757. for (i = 0, j = this.nameTable.length; i < j || found; i++) if (this.nameTable[i].getName === child) {
  1758. found = this.nameTable[i];
  1759. break
  1760. }
  1761. if (found) return found
  1762. }
  1763. for (i = 0, j = this.children.length; i < j; i++) {
  1764. found = this.children[i].getChild(child);
  1765. if (found) return found
  1766. }
  1767. return null
  1768. },
  1769. getChildCount: function() {
  1770. return this.children.length
  1771. },
  1772. addChild: function(child) {
  1773. this.children.push(child);
  1774. child.parent = this;
  1775. if (child.getName() !== null) this.addName(child.getName(), child)
  1776. },
  1777. addName: function(name, shape) {
  1778. if (this.parent !== null) this.parent.addName(name, shape);
  1779. else this.nameTable.push([name, shape])
  1780. },
  1781. translate: function() {
  1782. if (arguments.length === 2) {
  1783. this.checkMatrix(2);
  1784. this.matrix.translate(arguments[0], arguments[1])
  1785. } else {
  1786. this.checkMatrix(3);
  1787. this.matrix.translate(arguments[0], arguments[1], 0)
  1788. }
  1789. },
  1790. checkMatrix: function(dimensions) {
  1791. if (this.matrix === null) if (dimensions === 2) this.matrix = new p.PMatrix2D;
  1792. else this.matrix = new p.PMatrix3D;
  1793. else if (dimensions === 3 && this.matrix instanceof p.PMatrix2D) this.matrix = new p.PMatrix3D
  1794. },
  1795. rotateX: function(angle) {
  1796. this.rotate(angle, 1, 0, 0)
  1797. },
  1798. rotateY: function(angle) {
  1799. this.rotate(angle, 0, 1, 0)
  1800. },
  1801. rotateZ: function(angle) {
  1802. this.rotate(angle, 0, 0, 1)
  1803. },
  1804. rotate: function() {
  1805. if (arguments.length === 1) {
  1806. this.checkMatrix(2);
  1807. this.matrix.rotate(arguments[0])
  1808. } else {
  1809. this.checkMatrix(3);
  1810. this.matrix.rotate(arguments[0], arguments[1], arguments[2], arguments[3])
  1811. }
  1812. },
  1813. scale: function() {
  1814. if (arguments.length === 2) {
  1815. this.checkMatrix(2);
  1816. this.matrix.scale(arguments[0], arguments[1])
  1817. } else if (arguments.length === 3) {
  1818. this.checkMatrix(2);
  1819. this.matrix.scale(arguments[0], arguments[1], arguments[2])
  1820. } else {
  1821. this.checkMatrix(2);
  1822. this.matrix.scale(arguments[0])
  1823. }
  1824. },
  1825. resetMatrix: function() {
  1826. this.checkMatrix(2);
  1827. this.matrix.reset()
  1828. },
  1829. applyMatrix: function(matrix) {
  1830. 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);
  1831. else if (arguments.length === 6) {
  1832. this.checkMatrix(2);
  1833. 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)
  1834. } else if (arguments.length === 16) {
  1835. this.checkMatrix(3);
  1836. 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])
  1837. }
  1838. }
  1839. };
  1840. var PShapeSVG = p.PShapeSVG = function() {
  1841. p.PShape.call(this);
  1842. if (arguments.length === 1) {
  1843. this.element = arguments[0];
  1844. this.vertexCodes = [];
  1845. this.vertices = [];
  1846. this.opacity = 1;
  1847. this.stroke = false;
  1848. this.strokeColor = 4278190080;
  1849. this.strokeWeight = 1;
  1850. this.strokeCap = 'butt';
  1851. this.strokeJoin = 'miter';
  1852. this.strokeGradient = null;
  1853. this.strokeGradientPaint = null;
  1854. this.strokeName = null;
  1855. this.strokeOpacity = 1;
  1856. this.fill = true;
  1857. this.fillColor = 4278190080;
  1858. this.fillGradient = null;
  1859. this.fillGradientPaint = null;
  1860. this.fillName = null;
  1861. this.fillOpacity = 1;
  1862. if (this.element.getName() !== "svg") throw "root is not <svg>, it's <" + this.element.getName() + ">";
  1863. } else if (arguments.length === 2) if (typeof arguments[1] === "string") {
  1864. if (arguments[1].indexOf(".svg") > -1) {
  1865. this.element = new p.XMLElement(p, arguments[1]);
  1866. this.vertexCodes = [];
  1867. this.vertices = [];
  1868. this.opacity = 1;
  1869. this.stroke = false;
  1870. this.strokeColor = 4278190080;
  1871. this.strokeWeight = 1;
  1872. this.strokeCap = 'butt';
  1873. this.strokeJoin = 'miter';
  1874. this.strokeGradient = "";
  1875. this.strokeGradientPaint = "";
  1876. this.strokeName = "";
  1877. this.strokeOpacity = 1;
  1878. this.fill = true;
  1879. this.fillColor = 4278190080;
  1880. this.fillGradient = null;
  1881. this.fillGradientPaint = null;
  1882. this.fillOpacity = 1
  1883. }
  1884. } else if (arguments[0]) {
  1885. this.element = arguments[1];
  1886. this.vertexCodes = arguments[0].vertexCodes.slice();
  1887. this.vertices = arguments[0].vertices.slice();
  1888. this.stroke = arguments[0].stroke;
  1889. this.strokeColor = arguments[0].strokeColor;
  1890. this.strokeWeight = arguments[0].strokeWeight;
  1891. this.strokeCap = arguments[0].strokeCap;
  1892. this.strokeJoin = arguments[0].strokeJoin;
  1893. this.strokeGradient = arguments[0].strokeGradient;
  1894. this.strokeGradientPaint = arguments[0].strokeGradientPaint;
  1895. this.strokeName = arguments[0].strokeName;
  1896. this.fill = arguments[0].fill;
  1897. this.fillColor = arguments[0].fillColor;
  1898. this.fillGradient = arguments[0].fillGradient;
  1899. this.fillGradientPaint = arguments[0].fillGradientPaint;
  1900. this.fillName = arguments[0].fillName;
  1901. this.strokeOpacity = arguments[0].strokeOpacity;
  1902. this.fillOpacity = arguments[0].fillOpacity;
  1903. this.opacity = arguments[0].opacity
  1904. }
  1905. this.name = this.element.getStringAttribute("id");
  1906. var displayStr = this.element.getStringAttribute("display", "inline");
  1907. this.visible = displayStr !== "none";
  1908. var str = this.element.getAttribute("transform");
  1909. if (str) this.matrix = this.parseMatrix(str);
  1910. var viewBoxStr = this.element.getStringAttribute("viewBox");
  1911. if (viewBoxStr !== null) {
  1912. var viewBox = viewBoxStr.split(" ");
  1913. this.width = viewBox[2];
  1914. this.height = viewBox[3]
  1915. }
  1916. var unitWidth = this.element.getStringAttribute("width");
  1917. var unitHeight = this.element.getStringAttribute("height");
  1918. if (unitWidth !== null) {
  1919. this.width = this.parseUnitSize(unitWidth);
  1920. this.height = this.parseUnitSize(unitHeight)
  1921. } else if (this.width === 0 || this.height === 0) {
  1922. this.width = 1;
  1923. this.height = 1;
  1924. throw "The width and/or height is not " + "readable in the <svg> tag of this file.";
  1925. }
  1926. this.parseColors(this.element);
  1927. this.parseChildren(this.element)
  1928. };
  1929. PShapeSVG.prototype = new PShape;
  1930. PShapeSVG.prototype.parseMatrix = function() {
  1931. function getCoords(s) {
  1932. var m = [];
  1933. s.replace(/\((.*?)\)/, function() {
  1934. return function(all, params) {
  1935. m = params.replace(/,+/g, " ").split(/\s+/)
  1936. }
  1937. }());
  1938. return m
  1939. }
  1940. return function(str) {
  1941. this.checkMatrix(2);
  1942. var pieces = [];
  1943. str.replace(/\s*(\w+)\((.*?)\)/g, function(all) {
  1944. pieces.push(p.trim(all))
  1945. });
  1946. if (pieces.length === 0) return null;
  1947. for (var i = 0, j = pieces.length; i < j; i++) {
  1948. var m = getCoords(pieces[i]);
  1949. if (pieces[i].indexOf("matrix") !== -1) this.matrix.set(m[0], m[2], m[4], m[1], m[3], m[5]);
  1950. else if (pieces[i].indexOf("translate") !== -1) {
  1951. var tx = m[0];
  1952. var ty = m.length === 2 ? m[1] : 0;
  1953. this.matrix.translate(tx, ty)
  1954. } else if (pieces[i].indexOf("scale") !== -1) {
  1955. var sx = m[0];
  1956. var sy = m.length === 2 ? m[1] : m[0];
  1957. this.matrix.scale(sx, sy)
  1958. } else if (pieces[i].indexOf("rotate") !== -1) {
  1959. var angle = m[0];
  1960. if (m.length === 1) this.matrix.rotate(p.radians(angle));
  1961. else if (m.length === 3) {
  1962. this.matrix.translate(m[1], m[2]);
  1963. this.matrix.rotate(p.radians(m[0]));
  1964. this.matrix.translate(-m[1], -m[2])
  1965. }
  1966. } else if (pieces[i].indexOf("skewX") !== -1) this.matrix.skewX(parseFloat(m[0]));
  1967. else if (pieces[i].indexOf("skewY") !== -1) this.matrix.skewY(m[0]);
  1968. else if (pieces[i].indexOf("shearX") !== -1) this.matrix.shearX(m[0]);
  1969. else if (pieces[i].indexOf("shearY") !== -1) this.matrix.shearY(m[0])
  1970. }
  1971. return this.matrix
  1972. }
  1973. }();
  1974. PShapeSVG.prototype.parseChildren = function(element) {
  1975. var newelement = element.getChildren();
  1976. var children = new p.PShape;
  1977. for (var i = 0, j = newelement.length; i < j; i++) {
  1978. var kid = this.parseChild(newelement[i]);
  1979. if (kid) children.addChild(kid)
  1980. }
  1981. this.children.push(children)
  1982. };
  1983. PShapeSVG.prototype.getName = function() {
  1984. return this.name
  1985. };
  1986. PShapeSVG.prototype.parseChild = function(elem) {
  1987. var name = elem.getName();
  1988. var shape;
  1989. if (name === "g") shape = new PShapeSVG(this, elem);
  1990. else if (name === "defs") shape = new PShapeSVG(this, elem);
  1991. else if (name === "line") {
  1992. shape = new PShapeSVG(this, elem);
  1993. shape.parseLine()
  1994. } else if (name === "circle") {
  1995. shape = new PShapeSVG(this, elem);
  1996. shape.parseEllipse(true)
  1997. } else if (name === "ellipse") {
  1998. shape = new PShapeSVG(this, elem);
  1999. shape.parseEllipse(false)
  2000. } else if (name === "rect") {
  2001. shape = new PShapeSVG(this, elem);
  2002. shape.parseRect()
  2003. } else if (name === "polygon") {
  2004. shape = new PShapeSVG(this, elem);
  2005. shape.parsePoly(true)
  2006. } else if (name === "polyline") {
  2007. shape = new PShapeSVG(this, elem);
  2008. shape.parsePoly(false)
  2009. } else if (name === "path") {
  2010. shape = new PShapeSVG(this, elem);
  2011. shape.parsePath()
  2012. } else if (name === "radialGradient") unimplemented("PShapeSVG.prototype.parseChild, name = radialGradient");
  2013. else if (name === "linearGradient") unimplemented("PShapeSVG.prototype.parseChild, name = linearGradient");
  2014. else if (name === "text") unimplemented("PShapeSVG.prototype.parseChild, name = text");
  2015. else if (name === "filter") unimplemented("PShapeSVG.prototype.parseChild, name = filter");
  2016. else if (name === "mask") unimplemented("PShapeSVG.prototype.parseChild, name = mask");
  2017. else nop();
  2018. return shape
  2019. };
  2020. PShapeSVG.prototype.parsePath = function() {
  2021. this.family = 21;
  2022. this.kind = 0;
  2023. var pathDataChars = [];
  2024. var c;
  2025. var pathData = p.trim(this.element.getStringAttribute("d").replace(/[\s,]+/g, " "));
  2026. if (pathData === null) return;
  2027. pathData = p.__toCharArray(pathData);
  2028. var cx = 0,
  2029. cy = 0,
  2030. ctrlX = 0,
  2031. ctrlY = 0,
  2032. ctrlX1 = 0,
  2033. ctrlX2 = 0,
  2034. ctrlY1 = 0,
  2035. ctrlY2 = 0,
  2036. endX = 0,
  2037. endY = 0,
  2038. ppx = 0,
  2039. ppy = 0,
  2040. px = 0,
  2041. py = 0,
  2042. i = 0,
  2043. valOf = 0;
  2044. var str = "";
  2045. var tmpArray = [];
  2046. var flag = false;
  2047. var lastInstruction;
  2048. var command;
  2049. var j, k;
  2050. while (i < pathData.length) {
  2051. valOf = pathData[i].valueOf();
  2052. if (valOf >= 65 && valOf <= 90 || valOf >= 97 && valOf <= 122) {
  2053. j = i;
  2054. i++;
  2055. if (i < pathData.length) {
  2056. tmpArray = [];
  2057. valOf = pathData[i].valueOf();
  2058. while (! (valOf >= 65 && valOf <= 90 || valOf >= 97 && valOf <= 100 || valOf >= 102 && valOf <= 122) && flag === false) {
  2059. if (valOf === 32) {
  2060. if (str !== "") {
  2061. tmpArray.push(parseFloat(str));
  2062. str = ""
  2063. }
  2064. i++
  2065. } else if (valOf === 45) if (pathData[i - 1].valueOf() === 101) {
  2066. str += pathData[i].toString();
  2067. i++
  2068. } else {
  2069. if (str !== "") tmpArray.push(parseFloat(str));
  2070. str = pathData[i].toString();
  2071. i++
  2072. } else {
  2073. str += pathData[i].toString();
  2074. i++
  2075. }
  2076. if (i === pathData.length) flag = true;
  2077. else valOf = pathData[i].valueOf()
  2078. }
  2079. }
  2080. if (str !== "") {
  2081. tmpArray.push(parseFloat(str));
  2082. str = ""
  2083. }
  2084. command = pathData[j];
  2085. valOf = command.valueOf();
  2086. if (valOf === 77) {
  2087. if (tmpArray.length >= 2 && tmpArray.length % 2 === 0) {
  2088. cx = tmpArray[0];
  2089. cy = tmpArray[1];
  2090. this.parsePathMoveto(cx, cy);
  2091. if (tmpArray.length > 2) for (j = 2, k = tmpArray.length; j < k; j += 2) {
  2092. cx = tmpArray[j];
  2093. cy = tmpArray[j + 1];
  2094. this.parsePathLineto(cx, cy)
  2095. }
  2096. }
  2097. } else if (valOf === 109) {
  2098. if (tmpArray.length >= 2 && tmpArray.length % 2 === 0) {
  2099. cx += tmpArray[0];
  2100. cy += tmpArray[1];
  2101. this.parsePathMoveto(cx, cy);
  2102. if (tmpArray.length > 2) for (j = 2, k = tmpArray.length; j < k; j += 2) {
  2103. cx += tmpArray[j];
  2104. cy += tmpArray[j + 1];
  2105. this.parsePathLineto(cx, cy)
  2106. }
  2107. }
  2108. } else if (valOf === 76) {
  2109. if (tmpArray.length >= 2 && tmpArray.length % 2 === 0) for (j = 0, k = tmpArray.length; j < k; j += 2) {
  2110. cx = tmpArray[j];
  2111. cy = tmpArray[j + 1];
  2112. this.parsePathLineto(cx, cy)
  2113. }
  2114. } else if (valOf === 108) {
  2115. if (tmpArray.length >= 2 && tmpArray.length % 2 === 0) for (j = 0, k = tmpArray.length; j < k; j += 2) {
  2116. cx += tmpArray[j];
  2117. cy += tmpArray[j + 1];
  2118. this.parsePathLineto(cx, cy)
  2119. }
  2120. } else if (valOf === 72) for (j = 0, k = tmpArray.length; j < k; j++) {
  2121. cx = tmpArray[j];
  2122. this.parsePathLineto(cx, cy)
  2123. } else if (valOf === 104) for (j = 0, k = tmpArray.length; j < k; j++) {
  2124. cx += tmpArray[j];
  2125. this.parsePathLineto(cx, cy)
  2126. } else if (valOf === 86) for (j = 0, k = tmpArray.length; j < k; j++) {
  2127. cy = tmpArray[j];
  2128. this.parsePathLineto(cx, cy)
  2129. } else if (valOf === 118) for (j = 0, k = tmpArray.length; j < k; j++) {
  2130. cy += tmpArray[j];
  2131. this.parsePathLineto(cx, cy)
  2132. } else if (valOf === 67) {
  2133. if (tmpArray.length >= 6 && tmpArray.length % 6 === 0) for (j = 0, k = tmpArray.length; j < k; j += 6) {
  2134. ctrlX1 = tmpArray[j];
  2135. ctrlY1 = tmpArray[j + 1];
  2136. ctrlX2 = tmpArray[j + 2];
  2137. ctrlY2 = tmpArray[j + 3];
  2138. endX = tmpArray[j + 4];
  2139. endY = tmpArray[j + 5];
  2140. this.parsePathCurveto(ctrlX1, ctrlY1, ctrlX2, ctrlY2, endX, endY);
  2141. cx = endX;
  2142. cy = endY
  2143. }
  2144. } else if (valOf === 99) {
  2145. if (tmpArray.length >= 6 && tmpArray.length % 6 === 0) for (j = 0, k = tmpArray.length; j < k; j += 6) {
  2146. ctrlX1 = cx + tmpArray[j];
  2147. ctrlY1 = cy + tmpArray[j + 1];
  2148. ctrlX2 = cx + tmpArray[j + 2];
  2149. ctrlY2 = cy + tmpArray[j + 3];
  2150. endX = cx + tmpArray[j + 4];
  2151. endY = cy + tmpArray[j + 5];
  2152. this.parsePathCurveto(ctrlX1, ctrlY1, ctrlX2, ctrlY2, endX, endY);
  2153. cx = endX;
  2154. cy = endY
  2155. }
  2156. } else if (valOf === 83) {
  2157. if (tmpArray.length >= 4 && tmpArray.length % 4 === 0) for (j = 0, k = tmpArray.length; j < k; j += 4) {
  2158. if (lastInstruction.toLowerCase() === "c" || lastInstruction.toLowerCase() === "s") {
  2159. ppx = this.vertices[this.vertices.length - 2][0];
  2160. ppy = this.vertices[this.vertices.length - 2][1];
  2161. px = this.vertices[this.vertices.length - 1][0];
  2162. py = this.vertices[this.vertices.length - 1][1];
  2163. ctrlX1 = px + (px - ppx);
  2164. ctrlY1 = py + (py - ppy)
  2165. } else {
  2166. ctrlX1 = this.vertices[this.vertices.length - 1][0];
  2167. ctrlY1 = this.vertices[this.vertices.length - 1][1]
  2168. }
  2169. ctrlX2 = tmpArray[j];
  2170. ctrlY2 = tmpArray[j + 1];
  2171. endX = tmpArray[j + 2];
  2172. endY = tmpArray[j + 3];
  2173. this.parsePathCurveto(ctrlX1, ctrlY1, ctrlX2, ctrlY2, endX, endY);
  2174. cx = endX;
  2175. cy = endY
  2176. }
  2177. } else if (valOf === 115) {
  2178. if (tmpArray.length >= 4 && tmpArray.length % 4 === 0) for (j = 0, k = tmpArray.length; j < k; j += 4) {
  2179. if (lastInstruction.toLowerCase() === "c" || lastInstruction.toLowerCase() === "s") {
  2180. ppx = this.vertices[this.vertices.length - 2][0];
  2181. ppy = this.vertices[this.vertices.length - 2][1];
  2182. px = this.vertices[this.vertices.length - 1][0];
  2183. py = this.vertices[this.vertices.length - 1][1];
  2184. ctrlX1 = px + (px - ppx);
  2185. ctrlY1 = py + (py - ppy)
  2186. } else {
  2187. ctrlX1 = this.vertices[this.vertices.length - 1][0];
  2188. ctrlY1 = this.vertices[this.vertices.length - 1][1]
  2189. }
  2190. ctrlX2 = cx + tmpArray[j];
  2191. ctrlY2 = cy + tmpArray[j + 1];
  2192. endX = cx + tmpArray[j + 2];
  2193. endY = cy + tmpArray[j + 3];
  2194. this.parsePathCurveto(ctrlX1, ctrlY1, ctrlX2, ctrlY2, endX, endY);
  2195. cx = endX;
  2196. cy = endY
  2197. }
  2198. } else if (valOf === 81) {
  2199. if (tmpArray.length >= 4 && tmpArray.length % 4 === 0) for (j = 0, k = tmpArray.length; j < k; j += 4) {
  2200. ctrlX = tmpArray[j];
  2201. ctrlY = tmpArray[j + 1];
  2202. endX = tmpArray[j + 2];
  2203. endY = tmpArray[j + 3];
  2204. this.parsePathQuadto(cx, cy, ctrlX, ctrlY, endX, endY);
  2205. cx = endX;
  2206. cy = endY
  2207. }
  2208. } else if (valOf === 113) {
  2209. if (tmpArray.length >= 4 && tmpArray.length % 4 === 0) for (j = 0, k = tmpArray.length; j < k; j += 4) {
  2210. ctrlX = cx + tmpArray[j];
  2211. ctrlY = cy + tmpArray[j + 1];
  2212. endX = cx + tmpArray[j + 2];
  2213. endY = cy + tmpArray[j + 3];
  2214. this.parsePathQuadto(cx, cy, ctrlX, ctrlY, endX, endY);
  2215. cx = endX;
  2216. cy = endY
  2217. }
  2218. } else if (valOf === 84) {
  2219. if (tmpArray.length >= 2 && tmpArray.length % 2 === 0) for (j = 0, k = tmpArray.length; j < k; j += 2) {
  2220. if (lastInstruction.toLowerCase() === "q" || lastInstruction.toLowerCase() === "t") {
  2221. ppx = this.vertices[this.vertices.length - 2][0];
  2222. ppy = this.vertices[this.vertices.length - 2][1];
  2223. px = this.vertices[this.vertices.length - 1][0];
  2224. py = this.vertices[this.vertices.length - 1][1];
  2225. ctrlX = px + (px - ppx);
  2226. ctrlY = py + (py - ppy)
  2227. } else {
  2228. ctrlX = cx;
  2229. ctrlY = cy
  2230. }
  2231. endX = tmpArray[j];
  2232. endY = tmpArray[j + 1];
  2233. this.parsePathQuadto(cx, cy, ctrlX, ctrlY, endX, endY);
  2234. cx = endX;
  2235. cy = endY
  2236. }
  2237. } else if (valOf === 116) {
  2238. if (tmpArray.length >= 2 && tmpArray.length % 2 === 0) for (j = 0, k = tmpArray.length; j < k; j += 2) {
  2239. if (lastInstruction.toLowerCase() === "q" || lastInstruction.toLowerCase() === "t") {
  2240. ppx = this.vertices[this.vertices.length - 2][0];
  2241. ppy = this.vertices[this.vertices.length - 2][1];
  2242. px = this.vertices[this.vertices.length - 1][0];
  2243. py = this.vertices[this.vertices.length - 1][1];
  2244. ctrlX = px + (px - ppx);
  2245. ctrlY = py + (py - ppy)
  2246. } else {
  2247. ctrlX = cx;
  2248. ctrlY = cy
  2249. }
  2250. endX = cx + tmpArray[j];
  2251. endY = cy + tmpArray[j + 1];
  2252. this.parsePathQuadto(cx, cy, ctrlX, ctrlY, endX, endY);
  2253. cx = endX;
  2254. cy = endY
  2255. }
  2256. } else if (valOf === 90 || valOf === 122) this.close = true;
  2257. lastInstruction = command.toString()
  2258. } else i++
  2259. }
  2260. };
  2261. PShapeSVG.prototype.parsePathQuadto = function(x1, y1, cx, cy, x2, y2) {
  2262. if (this.vertices.length > 0) {
  2263. this.parsePathCode(1);
  2264. this.parsePathVertex(x1 + (cx - x1) * 2 / 3, y1 + (cy - y1) * 2 / 3);
  2265. this.parsePathVertex(x2 + (cx - x2) * 2 / 3, y2 + (cy - y2) * 2 / 3);
  2266. this.parsePathVertex(x2, y2)
  2267. } else throw "Path must start with M/m";
  2268. };
  2269. PShapeSVG.prototype.parsePathCurveto = function(x1, y1, x2, y2, x3, y3) {
  2270. if (this.vertices.length > 0) {
  2271. this.parsePathCode(1);
  2272. this.parsePathVertex(x1, y1);
  2273. this.parsePathVertex(x2, y2);
  2274. this.parsePathVertex(x3, y3)
  2275. } else throw "Path must start with M/m";
  2276. };
  2277. PShapeSVG.prototype.parsePathLineto = function(px, py) {
  2278. if (this.vertices.length > 0) {
  2279. this.parsePathCode(0);
  2280. this.parsePathVertex(px, py);
  2281. this.vertices[this.vertices.length - 1]["moveTo"] = false
  2282. } else throw "Path must start with M/m";
  2283. };
  2284. PShapeSVG.prototype.parsePathMoveto = function(px, py) {
  2285. if (this.vertices.length > 0) this.parsePathCode(3);
  2286. this.parsePathCode(0);
  2287. this.parsePathVertex(px, py);
  2288. this.vertices[this.vertices.length - 1]["moveTo"] = true
  2289. };
  2290. PShapeSVG.prototype.parsePathVertex = function(x, y) {
  2291. var verts = [];
  2292. verts[0] = x;
  2293. verts[1] = y;
  2294. this.vertices.push(verts)
  2295. };
  2296. PShapeSVG.prototype.parsePathCode = function(what) {
  2297. this.vertexCodes.push(what)
  2298. };
  2299. PShapeSVG.prototype.parsePoly = function(val) {
  2300. this.family = 21;
  2301. this.close = val;
  2302. var pointsAttr = p.trim(this.element.getStringAttribute("points").replace(/[,\s]+/g, " "));
  2303. if (pointsAttr !== null) {
  2304. var pointsBuffer = pointsAttr.split(" ");
  2305. if (pointsBuffer.length % 2 === 0) for (var i = 0, j = pointsBuffer.length; i < j; i++) {
  2306. var verts = [];
  2307. verts[0] = pointsBuffer[i];
  2308. verts[1] = pointsBuffer[++i];
  2309. this.vertices.push(verts)
  2310. } else throw "Error parsing polygon points: odd number of coordinates provided";
  2311. }
  2312. };
  2313. PShapeSVG.prototype.parseRect = function() {
  2314. this.kind = 30;
  2315. this.family = 1;
  2316. this.params = [];
  2317. this.params[0] = this.element.getFloatAttribute("x");
  2318. this.params[1] = this.element.getFloatAttribute("y");
  2319. this.params[2] = this.element.getFloatAttribute("width");
  2320. this.params[3] = this.element.getFloatAttribute("height");
  2321. if (this.params[2] < 0 || this.params[3] < 0) throw "svg error: negative width or height found while parsing <rect>";
  2322. };
  2323. PShapeSVG.prototype.parseEllipse = function(val) {
  2324. this.kind = 31;
  2325. this.family = 1;
  2326. this.params = [];
  2327. this.params[0] = this.element.getFloatAttribute("cx") | 0;
  2328. this.params[1] = this.element.getFloatAttribute("cy") | 0;
  2329. var rx, ry;
  2330. if (val) {
  2331. rx = ry = this.element.getFloatAttribute("r");
  2332. if (rx < 0) throw "svg error: negative radius found while parsing <circle>";
  2333. } else {
  2334. rx = this.element.getFloatAttribute("rx");
  2335. ry = this.element.getFloatAttribute("ry");
  2336. if (rx < 0 || ry < 0) throw "svg error: negative x-axis radius or y-axis radius found while parsing <ellipse>";
  2337. }
  2338. this.params[0] -= rx;
  2339. this.params[1] -= ry;
  2340. this.params[2] = rx * 2;
  2341. this.params[3] = ry * 2
  2342. };
  2343. PShapeSVG.prototype.parseLine = function() {
  2344. this.kind = 4;
  2345. this.family = 1;
  2346. this.params = [];
  2347. this.params[0] = this.element.getFloatAttribute("x1");
  2348. this.params[1] = this.element.getFloatAttribute("y1");
  2349. this.params[2] = this.element.getFloatAttribute("x2");
  2350. this.params[3] = this.element.getFloatAttribute("y2")
  2351. };
  2352. PShapeSVG.prototype.parseColors = function(element) {
  2353. if (element.hasAttribute("opacity")) this.setOpacity(element.getAttribute("opacity"));
  2354. if (element.hasAttribute("stroke")) this.setStroke(element.getAttribute("stroke"));
  2355. if (element.hasAttribute("stroke-width")) this.setStrokeWeight(element.getAttribute("stroke-width"));
  2356. if (element.hasAttribute("stroke-linejoin")) this.setStrokeJoin(element.getAttribute("stroke-linejoin"));
  2357. if (element.hasAttribute("stroke-linecap")) this.setStrokeCap(element.getStringAttribute("stroke-linecap"));
  2358. if (element.hasAttribute("fill")) this.setFill(element.getStringAttribute("fill"));
  2359. if (element.hasAttribute("style")) {
  2360. var styleText = element.getStringAttribute("style");
  2361. var styleTokens = styleText.toString().split(";");
  2362. for (var i = 0, j = styleTokens.length; i < j; i++) {
  2363. var tokens = p.trim(styleTokens[i].split(":"));
  2364. if (tokens[0] === "fill") this.setFill(tokens[1]);
  2365. else if (tokens[0] === "fill-opacity") this.setFillOpacity(tokens[1]);
  2366. else if (tokens[0] === "stroke") this.setStroke(tokens[1]);
  2367. else if (tokens[0] === "stroke-width") this.setStrokeWeight(tokens[1]);
  2368. else if (tokens[0] === "stroke-linecap") this.setStrokeCap(tokens[1]);
  2369. else if (tokens[0] === "stroke-linejoin") this.setStrokeJoin(tokens[1]);
  2370. else if (tokens[0] === "stroke-opacity") this.setStrokeOpacity(tokens[1]);
  2371. else if (tokens[0] === "opacity") this.setOpacity(tokens[1])
  2372. }
  2373. }
  2374. };
  2375. PShapeSVG.prototype.setFillOpacity = function(opacityText) {
  2376. this.fillOpacity = parseFloat(opacityText);
  2377. this.fillColor = this.fillOpacity * 255 << 24 | this.fillColor & 16777215
  2378. };
  2379. PShapeSVG.prototype.setFill = function(fillText) {
  2380. var opacityMask = this.fillColor & 4278190080;
  2381. if (fillText === "none") this.fill = false;
  2382. else if (fillText.indexOf("#") === 0) {
  2383. this.fill = true;
  2384. if (fillText.length === 4) fillText = fillText.replace(/#(.)(.)(.)/, "#$1$1$2$2$3$3");
  2385. this.fillColor = opacityMask | parseInt(fillText.substring(1), 16) & 16777215
  2386. } else if (fillText.indexOf("rgb") === 0) {
  2387. this.fill = true;
  2388. this.fillColor = opacityMask | this.parseRGB(fillText)
  2389. } else if (fillText.indexOf("url(#") === 0) this.fillName = fillText.substring(5, fillText.length - 1);
  2390. else if (colors[fillText]) {
  2391. this.fill = true;
  2392. this.fillColor = opacityMask | parseInt(colors[fillText].substring(1), 16) & 16777215
  2393. }
  2394. };
  2395. PShapeSVG.prototype.setOpacity = function(opacity) {
  2396. this.strokeColor = parseFloat(opacity) * 255 << 24 | this.strokeColor & 16777215;
  2397. this.fillColor = parseFloat(opacity) * 255 << 24 | this.fillColor & 16777215
  2398. };
  2399. PShapeSVG.prototype.setStroke = function(strokeText) {
  2400. var opacityMask = this.strokeColor & 4278190080;
  2401. if (strokeText === "none") this.stroke = false;
  2402. else if (strokeText.charAt(0) === "#") {
  2403. this.stroke = true;
  2404. if (strokeText.length === 4) strokeText = strokeText.replace(/#(.)(.)(.)/, "#$1$1$2$2$3$3");
  2405. this.strokeColor = opacityMask | parseInt(strokeText.substring(1), 16) & 16777215
  2406. } else if (strokeText.indexOf("rgb") === 0) {
  2407. this.stroke = true;
  2408. this.strokeColor = opacityMask | this.parseRGB(strokeText)
  2409. } else if (strokeText.indexOf("url(#") === 0) this.strokeName = strokeText.substring(5, strokeText.length - 1);
  2410. else if (colors[strokeText]) {
  2411. this.stroke = true;
  2412. this.strokeColor = opacityMask | parseInt(colors[strokeText].substring(1), 16) & 16777215
  2413. }
  2414. };
  2415. PShapeSVG.prototype.setStrokeWeight = function(weight) {
  2416. this.strokeWeight = this.parseUnitSize(weight)
  2417. };
  2418. PShapeSVG.prototype.setStrokeJoin = function(linejoin) {
  2419. if (linejoin === "miter") this.strokeJoin = 'miter';
  2420. else if (linejoin === "round") this.strokeJoin = 'round';
  2421. else if (linejoin === "bevel") this.strokeJoin = 'bevel'
  2422. };
  2423. PShapeSVG.prototype.setStrokeCap = function(linecap) {
  2424. if (linecap === "butt") this.strokeCap = 'butt';
  2425. else if (linecap === "round") this.strokeCap = 'round';
  2426. else if (linecap === "square") this.strokeCap = 'square'
  2427. };
  2428. PShapeSVG.prototype.setStrokeOpacity = function(opacityText) {
  2429. this.strokeOpacity = parseFloat(opacityText);
  2430. this.strokeColor = this.strokeOpacity * 255 << 24 | this.strokeColor & 16777215
  2431. };
  2432. PShapeSVG.prototype.parseRGB = function(color) {
  2433. var sub = color.substring(color.indexOf("(") + 1, color.indexOf(")"));
  2434. var values = sub.split(", ");
  2435. return values[0] << 16 | values[1] << 8 | values[2]
  2436. };
  2437. PShapeSVG.prototype.parseUnitSize = function(text) {
  2438. var len = text.length - 2;
  2439. if (len < 0) return text;
  2440. if (text.indexOf("pt") === len) return parseFloat(text.substring(0, len)) * 1.25;
  2441. if (text.indexOf("pc") === len) return parseFloat(text.substring(0, len)) * 15;
  2442. if (text.indexOf("mm") === len) return parseFloat(text.substring(0, len)) * 3.543307;
  2443. if (text.indexOf("cm") === len) return parseFloat(text.substring(0, len)) * 35.43307;
  2444. if (text.indexOf("in") === len) return parseFloat(text.substring(0, len)) * 90;
  2445. if (text.indexOf("px") === len) return parseFloat(text.substring(0, len));
  2446. return parseFloat(text)
  2447. };
  2448. p.shape = function(shape, x, y, width, height) {
  2449. if (arguments.length >= 1 && arguments[0] !== null) if (shape.isVisible()) {
  2450. p.pushMatrix();
  2451. if (curShapeMode === 3) if (arguments.length === 5) {
  2452. p.translate(x - width / 2, y - height / 2);
  2453. p.scale(width / shape.getWidth(), height / shape.getHeight())
  2454. } else if (arguments.length === 3) p.translate(x - shape.getWidth() / 2, -shape.getHeight() / 2);
  2455. else p.translate(-shape.getWidth() / 2, -shape.getHeight() / 2);
  2456. else if (curShapeMode === 0) if (arguments.length === 5) {
  2457. p.translate(x, y);
  2458. p.scale(width / shape.getWidth(), height / shape.getHeight())
  2459. } else {
  2460. if (arguments.length === 3) p.translate(x, y)
  2461. } else if (curShapeMode === 1) if (arguments.length === 5) {
  2462. width -= x;
  2463. height -= y;
  2464. p.translate(x, y);
  2465. p.scale(width / shape.getWidth(), height / shape.getHeight())
  2466. } else if (arguments.length === 3) p.translate(x, y);
  2467. shape.draw(p);
  2468. if (arguments.length === 1 && curShapeMode === 3 || arguments.length > 1) p.popMatrix()
  2469. }
  2470. };
  2471. p.shapeMode = function(mode) {
  2472. curShapeMode = mode
  2473. };
  2474. p.loadShape = function(filename) {
  2475. if (arguments.length === 1) if (filename.indexOf(".svg") > -1) return new PShapeSVG(null, filename);
  2476. return null
  2477. };
  2478. var XMLAttribute = function(fname, n, nameSpace, v, t) {
  2479. this.fullName = fname || "";
  2480. this.name = n || "";
  2481. this.namespace = nameSpace || "";
  2482. this.value = v;
  2483. this.type = t
  2484. };
  2485. XMLAttribute.prototype = {
  2486. getName: function() {
  2487. return this.name
  2488. },
  2489. getFullName: function() {
  2490. return this.fullName
  2491. },
  2492. getNamespace: function() {
  2493. return this.namespace
  2494. },
  2495. getValue: function() {
  2496. return this.value
  2497. },
  2498. getType: function() {
  2499. return this.type
  2500. },
  2501. setValue: function(newval) {
  2502. this.value = newval
  2503. }
  2504. };
  2505. var XMLElement = p.XMLElement = function(selector, uri, sysid, line) {
  2506. this.attributes = [];
  2507. this.children = [];
  2508. this.fullName = null;
  2509. this.name = null;
  2510. this.namespace = "";
  2511. this.content = null;
  2512. this.parent = null;
  2513. this.lineNr = "";
  2514. this.systemID = "";
  2515. this.type = "ELEMENT";
  2516. if (selector) if (typeof selector === "string") if (uri === undef && selector.indexOf("<") > -1) this.parse(selector);
  2517. else {
  2518. this.fullName = selector;
  2519. this.namespace = uri;
  2520. this.systemId = sysid;
  2521. this.lineNr = line
  2522. } else this.parse(uri)
  2523. };
  2524. XMLElement.prototype = {
  2525. parse: function(textstring) {
  2526. var xmlDoc;
  2527. try {
  2528. var extension = textstring.substring(textstring.length - 4);
  2529. if (extension === ".xml" || extension === ".svg") textstring = ajax(textstring);
  2530. xmlDoc = (new DOMParser).parseFromString(textstring, "text/xml");
  2531. var elements = xmlDoc.documentElement;
  2532. if (elements) this.parseChildrenRecursive(null, elements);
  2533. else throw "Error loading document";
  2534. return this
  2535. } catch(e) {
  2536. throw e;
  2537. }
  2538. },
  2539. parseChildrenRecursive: function(parent, elementpath) {
  2540. var xmlelement, xmlattribute, tmpattrib, l, m, child;
  2541. if (!parent) {
  2542. this.fullName = elementpath.localName;
  2543. this.name = elementpath.nodeName;
  2544. xmlelement = this
  2545. } else {
  2546. xmlelement = new XMLElement(elementpath.nodeName);
  2547. xmlelement.parent = parent
  2548. }
  2549. if (elementpath.nodeType === 3 && elementpath.textContent !== "") return this.createPCDataElement(elementpath.textContent);
  2550. if (elementpath.nodeType === 4) return this.createCDataElement(elementpath.textContent);
  2551. if (elementpath.attributes) for (l = 0, m = elementpath.attributes.length; l < m; l++) {
  2552. tmpattrib = elementpath.attributes[l];
  2553. xmlattribute = new XMLAttribute(tmpattrib.getname, tmpattrib.nodeName, tmpattrib.namespaceURI, tmpattrib.nodeValue, tmpattrib.nodeType);
  2554. xmlelement.attributes.push(xmlattribute)
  2555. }
  2556. if (elementpath.childNodes) for (l = 0, m = elementpath.childNodes.length; l < m; l++) {
  2557. var node = elementpath.childNodes[l];
  2558. child = xmlelement.parseChildrenRecursive(xmlelement, node);
  2559. if (child !== null) xmlelement.children.push(child)
  2560. }
  2561. return xmlelement
  2562. },
  2563. createElement: function(fullname, namespaceuri, sysid, line) {
  2564. if (sysid === undef) return new XMLElement(fullname, namespaceuri);
  2565. return new XMLElement(fullname, namespaceuri, sysid, line)
  2566. },
  2567. createPCDataElement: function(content, isCDATA) {
  2568. if (content.replace(/^\s+$/g, "") === "") return null;
  2569. var pcdata = new XMLElement;
  2570. pcdata.type = "TEXT";
  2571. pcdata.content = content;
  2572. return pcdata
  2573. },
  2574. createCDataElement: function(content) {
  2575. var cdata = this.createPCDataElement(content);
  2576. if (cdata === null) return null;
  2577. cdata.type = "CDATA";
  2578. var htmlentities = {
  2579. "<": "&lt;",
  2580. ">": "&gt;",
  2581. "'": "&apos;",
  2582. '"': "&quot;"
  2583. },
  2584. entity;
  2585. for (entity in htmlentities) if (!Object.hasOwnProperty(htmlentities, entity)) content = content.replace(new RegExp(entity, "g"), htmlentities[entity]);
  2586. cdata.cdata = content;
  2587. return cdata
  2588. },
  2589. hasAttribute: function() {
  2590. if (arguments.length === 1) return this.getAttribute(arguments[0]) !== null;
  2591. if (arguments.length === 2) return this.getAttribute(arguments[0], arguments[1]) !== null
  2592. },
  2593. equals: function(other) {
  2594. if (! (other instanceof XMLElement)) return false;
  2595. var i, j;
  2596. if (this.fullName !== other.fullName) return false;
  2597. if (this.attributes.length !== other.getAttributeCount()) return false;
  2598. if (this.attributes.length !== other.attributes.length) return false;
  2599. var attr_name, attr_ns, attr_value, attr_type, attr_other;
  2600. for (i = 0, j = this.attributes.length; i < j; i++) {
  2601. attr_name = this.attributes[i].getName();
  2602. attr_ns = this.attributes[i].getNamespace();
  2603. attr_other = other.findAttribute(attr_name, attr_ns);
  2604. if (attr_other === null) return false;
  2605. if (this.attributes[i].getValue() !== attr_other.getValue()) return false;
  2606. if (this.attributes[i].getType() !== attr_other.getType()) return false
  2607. }
  2608. if (this.children.length !== other.getChildCount()) return false;
  2609. if (this.children.length > 0) {
  2610. var child1, child2;
  2611. for (i = 0, j = this.children.length; i < j; i++) {
  2612. child1 = this.getChild(i);
  2613. child2 = other.getChild(i);
  2614. if (!child1.equals(child2)) return false
  2615. }
  2616. return true
  2617. }
  2618. return this.content === other.content
  2619. },
  2620. getContent: function() {
  2621. if (this.type === "TEXT" || this.type === "CDATA") return this.content;
  2622. var children = this.children;
  2623. if (children.length === 1 && (children[0].type === "TEXT" || children[0].type === "CDATA")) return children[0].content;
  2624. return null
  2625. },
  2626. getAttribute: function() {
  2627. var attribute;
  2628. if (arguments.length === 2) {
  2629. attribute = this.findAttribute(arguments[0]);
  2630. if (attribute) return attribute.getValue();
  2631. return arguments[1]
  2632. } else if (arguments.length === 1) {
  2633. attribute = this.findAttribute(arguments[0]);
  2634. if (attribute) return attribute.getValue();
  2635. return null
  2636. } else if (arguments.length === 3) {
  2637. attribute = this.findAttribute(arguments[0], arguments[1]);
  2638. if (attribute) return attribute.getValue();
  2639. return arguments[2]
  2640. }
  2641. },
  2642. getStringAttribute: function() {
  2643. if (arguments.length === 1) return this.getAttribute(arguments[0]);
  2644. if (arguments.length === 2) return this.getAttribute(arguments[0], arguments[1]);
  2645. return this.getAttribute(arguments[0], arguments[1], arguments[2])
  2646. },
  2647. getString: function(attributeName) {
  2648. return this.getStringAttribute(attributeName)
  2649. },
  2650. getFloatAttribute: function() {
  2651. if (arguments.length === 1) return parseFloat(this.getAttribute(arguments[0], 0));
  2652. if (arguments.length === 2) return this.getAttribute(arguments[0], arguments[1]);
  2653. return this.getAttribute(arguments[0], arguments[1], arguments[2])
  2654. },
  2655. getFloat: function(attributeName) {
  2656. return this.getFloatAttribute(attributeName)
  2657. },
  2658. getIntAttribute: function() {
  2659. if (arguments.length === 1) return this.getAttribute(arguments[0], 0);
  2660. if (arguments.length === 2) return this.getAttribute(arguments[0], arguments[1]);
  2661. return this.getAttribute(arguments[0], arguments[1], arguments[2])
  2662. },
  2663. getInt: function(attributeName) {
  2664. return this.getIntAttribute(attributeName)
  2665. },
  2666. hasChildren: function() {
  2667. return this.children.length > 0
  2668. },
  2669. addChild: function(child) {
  2670. if (child !== null) {
  2671. child.parent = this;
  2672. this.children.push(child)
  2673. }
  2674. },
  2675. insertChild: function(child, index) {
  2676. if (child) {
  2677. if (child.getLocalName() === null && !this.hasChildren()) {
  2678. var lastChild = this.children[this.children.length - 1];
  2679. if (lastChild.getLocalName() === null) {
  2680. lastChild.setContent(lastChild.getContent() + child.getContent());
  2681. return
  2682. }
  2683. }
  2684. child.parent = this;
  2685. this.children.splice(index, 0, child)
  2686. }
  2687. },
  2688. getChild: function(selector) {
  2689. if (typeof selector === "number") return this.children[selector];
  2690. if (selector.indexOf("/") !== -1) return this.getChildRecursive(selector.split("/"), 0);
  2691. var kid, kidName;
  2692. for (var i = 0, j = this.getChildCount(); i < j; i++) {
  2693. kid = this.getChild(i);
  2694. kidName = kid.getName();
  2695. if (kidName !== null && kidName === selector) return kid
  2696. }
  2697. return null
  2698. },
  2699. getChildren: function() {
  2700. if (arguments.length === 1) {
  2701. if (typeof arguments[0] === "number") return this.getChild(arguments[0]);
  2702. if (arguments[0].indexOf("/") !== -1) return this.getChildrenRecursive(arguments[0].split("/"), 0);
  2703. var matches = [];
  2704. var kid, kidName;
  2705. for (var i = 0, j = this.getChildCount(); i < j; i++) {
  2706. kid = this.getChild(i);
  2707. kidName = kid.getName();
  2708. if (kidName !== null && kidName === arguments[0]) matches.push(kid)
  2709. }
  2710. return matches
  2711. }
  2712. return this.children
  2713. },
  2714. getChildCount: function() {
  2715. return this.children.length
  2716. },
  2717. getChildRecursive: function(items, offset) {
  2718. if (offset === items.length) return this;
  2719. var kid, kidName, matchName = items[offset];
  2720. for (var i = 0, j = this.getChildCount(); i < j; i++) {
  2721. kid = this.getChild(i);
  2722. kidName = kid.getName();
  2723. if (kidName !== null && kidName === matchName) return kid.getChildRecursive(items, offset + 1)
  2724. }
  2725. return null
  2726. },
  2727. getChildrenRecursive: function(items, offset) {
  2728. if (offset === items.length - 1) return this.getChildren(items[offset]);
  2729. var matches = this.getChildren(items[offset]);
  2730. var kidMatches = [];
  2731. for (var i = 0; i < matches.length; i++) kidMatches = kidMatches.concat(matches[i].getChildrenRecursive(items, offset + 1));
  2732. return kidMatches
  2733. },
  2734. isLeaf: function() {
  2735. return !this.hasChildren()
  2736. },
  2737. listChildren: function() {
  2738. var arr = [];
  2739. for (var i = 0, j = this.children.length; i < j; i++) arr.push(this.getChild(i).getName());
  2740. return arr
  2741. },
  2742. removeAttribute: function(name, namespace) {
  2743. this.namespace = namespace || "";
  2744. for (var i = 0, j = this.attributes.length; i < j; i++) if (this.attributes[i].getName() === name && this.attributes[i].getNamespace() === this.namespace) {
  2745. this.attributes.splice(i, 1);
  2746. break
  2747. }
  2748. },
  2749. removeChild: function(child) {
  2750. if (child) for (var i = 0, j = this.children.length; i < j; i++) if (this.children[i].equals(child)) {
  2751. this.children.splice(i, 1);
  2752. break
  2753. }
  2754. },
  2755. removeChildAtIndex: function(index) {
  2756. if (this.children.length > index) this.children.splice(index, 1)
  2757. },
  2758. findAttribute: function(name, namespace) {
  2759. this.namespace = namespace || "";
  2760. 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];
  2761. return null
  2762. },
  2763. setAttribute: function() {
  2764. var attr;
  2765. if (arguments.length === 3) {
  2766. var index = arguments[0].indexOf(":");
  2767. var name = arguments[0].substring(index + 1);
  2768. attr = this.findAttribute(name, arguments[1]);
  2769. if (attr) attr.setValue(arguments[2]);
  2770. else {
  2771. attr = new XMLAttribute(arguments[0], name, arguments[1], arguments[2], "CDATA");
  2772. this.attributes.push(attr)
  2773. }
  2774. } else {
  2775. attr = this.findAttribute(arguments[0]);
  2776. if (attr) attr.setValue(arguments[1]);
  2777. else {
  2778. attr = new XMLAttribute(arguments[0], arguments[0], null, arguments[1], "CDATA");
  2779. this.attributes.push(attr)
  2780. }
  2781. }
  2782. },
  2783. setString: function(attribute, value) {
  2784. this.setAttribute(attribute, value)
  2785. },
  2786. setInt: function(attribute, value) {
  2787. this.setAttribute(attribute, value)
  2788. },
  2789. setFloat: function(attribute, value) {
  2790. this.setAttribute(attribute, value)
  2791. },
  2792. setContent: function(content) {
  2793. if (this.children.length > 0) Processing.debug("Tried to set content for XMLElement with children");
  2794. this.content = content
  2795. },
  2796. setName: function() {
  2797. if (arguments.length === 1) {
  2798. this.name = arguments[0];
  2799. this.fullName = arguments[0];
  2800. this.namespace = null
  2801. } else {
  2802. var index = arguments[0].indexOf(":");
  2803. if (arguments[1] === null || index < 0) this.name = arguments[0];
  2804. else this.name = arguments[0].substring(index + 1);
  2805. this.fullName = arguments[0];
  2806. this.namespace = arguments[1]
  2807. }
  2808. },
  2809. getName: function() {
  2810. return this.fullName
  2811. },
  2812. getLocalName: function() {
  2813. return this.name
  2814. },
  2815. getAttributeCount: function() {
  2816. return this.attributes.length
  2817. },
  2818. toString: function() {
  2819. if (this.type === "TEXT") return this.content;
  2820. if (this.type === "CDATA") return this.cdata;
  2821. var tagstring = this.fullName;
  2822. var xmlstring = "<" + tagstring;
  2823. var a, c;
  2824. for (a = 0; a < this.attributes.length; a++) {
  2825. var attr = this.attributes[a];
  2826. xmlstring += " " + attr.getName() + "=" + '"' + attr.getValue() + '"'
  2827. }
  2828. if (this.children.length === 0) if (this.content === "") xmlstring += "/>";
  2829. else xmlstring += ">" + this.content + "</" + tagstring + ">";
  2830. else {
  2831. xmlstring += ">";
  2832. for (c = 0; c < this.children.length; c++) xmlstring += this.children[c].toString();
  2833. xmlstring += "</" + tagstring + ">"
  2834. }
  2835. return xmlstring
  2836. }
  2837. };
  2838. XMLElement.parse = function(xmlstring) {
  2839. var element = new XMLElement;
  2840. element.parse(xmlstring);
  2841. return element
  2842. };
  2843. var XML = p.XML = p.XMLElement;
  2844. p.loadXML = function(uri) {
  2845. return new XML(p, uri)
  2846. };
  2847. var printMatrixHelper = function(elements) {
  2848. var big = 0;
  2849. for (var i = 0; i < elements.length; i++) if (i !== 0) big = Math.max(big, Math.abs(elements[i]));
  2850. else big = Math.abs(elements[i]);
  2851. var digits = (big + "").indexOf(".");
  2852. if (digits === 0) digits = 1;
  2853. else if (digits === -1) digits = (big + "").length;
  2854. return digits
  2855. };
  2856. var PMatrix2D = p.PMatrix2D = function() {
  2857. if (arguments.length === 0) this.reset();
  2858. else if (arguments.length === 1 && arguments[0] instanceof PMatrix2D) this.set(arguments[0].array());
  2859. else if (arguments.length === 6) this.set(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5])
  2860. };
  2861. PMatrix2D.prototype = {
  2862. set: function() {
  2863. if (arguments.length === 6) {
  2864. var a = arguments;
  2865. this.set([a[0], a[1], a[2], a[3], a[4], a[5]])
  2866. } else if (arguments.length === 1 && arguments[0] instanceof PMatrix2D) this.elements = arguments[0].array();
  2867. else if (arguments.length === 1 && arguments[0] instanceof Array) this.elements = arguments[0].slice()
  2868. },
  2869. get: function() {
  2870. var outgoing = new PMatrix2D;
  2871. outgoing.set(this.elements);
  2872. return outgoing
  2873. },
  2874. reset: function() {
  2875. this.set([1, 0, 0, 0, 1, 0])
  2876. },
  2877. array: function array() {
  2878. return this.elements.slice()
  2879. },
  2880. translate: function(tx, ty) {
  2881. this.elements[2] = tx * this.elements[0] + ty * this.elements[1] + this.elements[2];
  2882. this.elements[5] = tx * this.elements[3] + ty * this.elements[4] + this.elements[5]
  2883. },
  2884. invTranslate: function(tx, ty) {
  2885. this.translate(-tx, -ty)
  2886. },
  2887. transpose: function() {},
  2888. mult: function(source, target) {
  2889. var x, y;
  2890. if (source instanceof
  2891. PVector) {
  2892. x = source.x;
  2893. y = source.y;
  2894. if (!target) target = new PVector
  2895. } else if (source instanceof Array) {
  2896. x = source[0];
  2897. y = source[1];
  2898. if (!target) target = []
  2899. }
  2900. if (target instanceof Array) {
  2901. target[0] = this.elements[0] * x + this.elements[1] * y + this.elements[2];
  2902. target[1] = this.elements[3] * x + this.elements[4] * y + this.elements[5]
  2903. } else if (target instanceof PVector) {
  2904. target.x = this.elements[0] * x + this.elements[1] * y + this.elements[2];
  2905. target.y = this.elements[3] * x + this.elements[4] * y + this.elements[5];
  2906. target.z = 0
  2907. }
  2908. return target
  2909. },
  2910. multX: function(x, y) {
  2911. return x * this.elements[0] + y * this.elements[1] + this.elements[2]
  2912. },
  2913. multY: function(x, y) {
  2914. return x * this.elements[3] + y * this.elements[4] + this.elements[5]
  2915. },
  2916. skewX: function(angle) {
  2917. this.apply(1, 0, 1, angle, 0, 0)
  2918. },
  2919. skewY: function(angle) {
  2920. this.apply(1, 0, 1, 0, angle, 0)
  2921. },
  2922. shearX: function(angle) {
  2923. this.apply(1, 0, 1, Math.tan(angle), 0, 0)
  2924. },
  2925. shearY: function(angle) {
  2926. this.apply(1, 0, 1, 0, Math.tan(angle), 0)
  2927. },
  2928. determinant: function() {
  2929. return this.elements[0] * this.elements[4] - this.elements[1] * this.elements[3]
  2930. },
  2931. invert: function() {
  2932. var d = this.determinant();
  2933. if (Math.abs(d) > -2147483648) {
  2934. var old00 = this.elements[0];
  2935. var old01 = this.elements[1];
  2936. var old02 = this.elements[2];
  2937. var old10 = this.elements[3];
  2938. var old11 = this.elements[4];
  2939. var old12 = this.elements[5];
  2940. this.elements[0] = old11 / d;
  2941. this.elements[3] = -old10 / d;
  2942. this.elements[1] = -old01 / d;
  2943. this.elements[4] = old00 / d;
  2944. this.elements[2] = (old01 * old12 - old11 * old02) / d;
  2945. this.elements[5] = (old10 * old02 - old00 * old12) / d;
  2946. return true
  2947. }
  2948. return false
  2949. },
  2950. scale: function(sx, sy) {
  2951. if (sx && !sy) sy = sx;
  2952. if (sx && sy) {
  2953. this.elements[0] *= sx;
  2954. this.elements[1] *= sy;
  2955. this.elements[3] *= sx;
  2956. this.elements[4] *= sy
  2957. }
  2958. },
  2959. invScale: function(sx, sy) {
  2960. if (sx && !sy) sy = sx;
  2961. this.scale(1 / sx, 1 / sy)
  2962. },
  2963. apply: function() {
  2964. var source;
  2965. if (arguments.length === 1 && arguments[0] instanceof PMatrix2D) source = arguments[0].array();
  2966. else if (arguments.length === 6) source = Array.prototype.slice.call(arguments);
  2967. else if (arguments.length === 1 && arguments[0] instanceof Array) source = arguments[0];
  2968. var result = [0, 0, this.elements[2], 0, 0, this.elements[5]];
  2969. var e = 0;
  2970. 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];
  2971. this.elements = result.slice()
  2972. },
  2973. preApply: function() {
  2974. var source;
  2975. if (arguments.length === 1 && arguments[0] instanceof PMatrix2D) source = arguments[0].array();
  2976. else if (arguments.length === 6) source = Array.prototype.slice.call(arguments);
  2977. else if (arguments.length === 1 && arguments[0] instanceof Array) source = arguments[0];
  2978. var result = [0, 0, source[2], 0, 0, source[5]];
  2979. result[2] = source[2] + this.elements[2] * source[0] + this.elements[5] * source[1];
  2980. result[5] = source[5] + this.elements[2] * source[3] + this.elements[5] * source[4];
  2981. result[0] = this.elements[0] * source[0] + this.elements[3] * source[1];
  2982. result[3] = this.elements[0] * source[3] + this.elements[3] * source[4];
  2983. result[1] = this.elements[1] * source[0] + this.elements[4] * source[1];
  2984. result[4] = this.elements[1] * source[3] + this.elements[4] * source[4];
  2985. this.elements = result.slice()
  2986. },
  2987. rotate: function(angle) {
  2988. var c = Math.cos(angle);
  2989. var s = Math.sin(angle);
  2990. var temp1 = this.elements[0];
  2991. var temp2 = this.elements[1];
  2992. this.elements[0] = c * temp1 + s * temp2;
  2993. this.elements[1] = -s * temp1 + c * temp2;
  2994. temp1 = this.elements[3];
  2995. temp2 = this.elements[4];
  2996. this.elements[3] = c * temp1 + s * temp2;
  2997. this.elements[4] = -s * temp1 + c * temp2
  2998. },
  2999. rotateZ: function(angle) {
  3000. this.rotate(angle)
  3001. },
  3002. invRotateZ: function(angle) {
  3003. this.rotateZ(angle - Math.PI)
  3004. },
  3005. print: function() {
  3006. var digits = printMatrixHelper(this.elements);
  3007. 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";
  3008. p.println(output)
  3009. }
  3010. };
  3011. var PMatrix3D = p.PMatrix3D = function() {
  3012. this.reset()
  3013. };
  3014. PMatrix3D.prototype = {
  3015. set: function() {
  3016. if (arguments.length === 16) this.elements = Array.prototype.slice.call(arguments);
  3017. else if (arguments.length === 1 && arguments[0] instanceof PMatrix3D) this.elements = arguments[0].array();
  3018. else if (arguments.length === 1 && arguments[0] instanceof Array) this.elements = arguments[0].slice()
  3019. },
  3020. get: function() {
  3021. var outgoing = new PMatrix3D;
  3022. outgoing.set(this.elements);
  3023. return outgoing
  3024. },
  3025. reset: function() {
  3026. this.elements = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]
  3027. },
  3028. array: function array() {
  3029. return this.elements.slice()
  3030. },
  3031. translate: function(tx, ty, tz) {
  3032. if (tz === undef) tz = 0;
  3033. this.elements[3] += tx * this.elements[0] + ty * this.elements[1] + tz * this.elements[2];
  3034. this.elements[7] += tx * this.elements[4] + ty * this.elements[5] + tz * this.elements[6];
  3035. this.elements[11] += tx * this.elements[8] + ty * this.elements[9] + tz * this.elements[10];
  3036. this.elements[15] += tx * this.elements[12] + ty * this.elements[13] + tz * this.elements[14]
  3037. },
  3038. transpose: function() {
  3039. var temp = this.elements[4];
  3040. this.elements[4] = this.elements[1];
  3041. this.elements[1] = temp;
  3042. temp = this.elements[8];
  3043. this.elements[8] = this.elements[2];
  3044. this.elements[2] = temp;
  3045. temp = this.elements[6];
  3046. this.elements[6] = this.elements[9];
  3047. this.elements[9] = temp;
  3048. temp = this.elements[3];
  3049. this.elements[3] = this.elements[12];
  3050. this.elements[12] = temp;
  3051. temp = this.elements[7];
  3052. this.elements[7] = this.elements[13];
  3053. this.elements[13] = temp;
  3054. temp = this.elements[11];
  3055. this.elements[11] = this.elements[14];
  3056. this.elements[14] = temp
  3057. },
  3058. mult: function(source, target) {
  3059. var x, y, z, w;
  3060. if (source instanceof
  3061. PVector) {
  3062. x = source.x;
  3063. y = source.y;
  3064. z = source.z;
  3065. w = 1;
  3066. if (!target) target = new PVector
  3067. } else if (source instanceof Array) {
  3068. x = source[0];
  3069. y = source[1];
  3070. z = source[2];
  3071. w = source[3] || 1;
  3072. if (!target || target.length !== 3 && target.length !== 4) target = [0, 0, 0]
  3073. }
  3074. if (target instanceof Array) if (target.length === 3) {
  3075. target[0] = this.elements[0] * x + this.elements[1] * y + this.elements[2] * z + this.elements[3];
  3076. target[1] = this.elements[4] * x + this.elements[5] * y + this.elements[6] * z + this.elements[7];
  3077. target[2] = this.elements[8] * x + this.elements[9] * y + this.elements[10] * z + this.elements[11]
  3078. } else if (target.length === 4) {
  3079. target[0] = this.elements[0] * x + this.elements[1] * y + this.elements[2] * z + this.elements[3] * w;
  3080. target[1] = this.elements[4] * x + this.elements[5] * y + this.elements[6] * z + this.elements[7] * w;
  3081. target[2] = this.elements[8] * x + this.elements[9] * y + this.elements[10] * z + this.elements[11] * w;
  3082. target[3] = this.elements[12] * x + this.elements[13] * y + this.elements[14] * z + this.elements[15] * w
  3083. }
  3084. if (target instanceof PVector) {
  3085. target.x = this.elements[0] * x + this.elements[1] * y + this.elements[2] * z + this.elements[3];
  3086. target.y = this.elements[4] * x + this.elements[5] * y + this.elements[6] * z + this.elements[7];
  3087. target.z = this.elements[8] * x + this.elements[9] * y + this.elements[10] * z + this.elements[11]
  3088. }
  3089. return target
  3090. },
  3091. preApply: function() {
  3092. var source;
  3093. if (arguments.length === 1 && arguments[0] instanceof PMatrix3D) source = arguments[0].array();
  3094. else if (arguments.length === 16) source = Array.prototype.slice.call(arguments);
  3095. else if (arguments.length === 1 && arguments[0] instanceof Array) source = arguments[0];
  3096. var result = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
  3097. var e = 0;
  3098. 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];
  3099. this.elements = result.slice()
  3100. },
  3101. apply: function() {
  3102. var source;
  3103. if (arguments.length === 1 && arguments[0] instanceof PMatrix3D) source = arguments[0].array();
  3104. else if (arguments.length === 16) source = Array.prototype.slice.call(arguments);
  3105. else if (arguments.length === 1 && arguments[0] instanceof Array) source = arguments[0];
  3106. var result = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
  3107. var e = 0;
  3108. 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];
  3109. this.elements = result.slice()
  3110. },
  3111. rotate: function(angle, v0, v1, v2) {
  3112. if (!v1) this.rotateZ(angle);
  3113. else {
  3114. var c = p.cos(angle);
  3115. var s = p.sin(angle);
  3116. var t = 1 - c;
  3117. 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)
  3118. }
  3119. },
  3120. invApply: function() {
  3121. if (inverseCopy === undef) inverseCopy = new PMatrix3D;
  3122. var a = arguments;
  3123. 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]);
  3124. if (!inverseCopy.invert()) return false;
  3125. this.preApply(inverseCopy);
  3126. return true
  3127. },
  3128. rotateX: function(angle) {
  3129. var c = p.cos(angle);
  3130. var s = p.sin(angle);
  3131. this.apply([1, 0, 0, 0, 0, c, -s, 0, 0, s, c, 0, 0, 0, 0, 1])
  3132. },
  3133. rotateY: function(angle) {
  3134. var c = p.cos(angle);
  3135. var s = p.sin(angle);
  3136. this.apply([c,
  3137. 0, s, 0, 0, 1, 0, 0, -s, 0, c, 0, 0, 0, 0, 1])
  3138. },
  3139. rotateZ: function(angle) {
  3140. var c = Math.cos(angle);
  3141. var s = Math.sin(angle);
  3142. this.apply([c, -s, 0, 0, s, c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1])
  3143. },
  3144. scale: function(sx, sy, sz) {
  3145. if (sx && !sy && !sz) sy = sz = sx;
  3146. else if (sx && sy && !sz) sz = 1;
  3147. if (sx && sy && sz) {
  3148. this.elements[0] *= sx;
  3149. this.elements[1] *= sy;
  3150. this.elements[2] *= sz;
  3151. this.elements[4] *= sx;
  3152. this.elements[5] *= sy;
  3153. this.elements[6] *= sz;
  3154. this.elements[8] *= sx;
  3155. this.elements[9] *= sy;
  3156. this.elements[10] *= sz;
  3157. this.elements[12] *= sx;
  3158. this.elements[13] *= sy;
  3159. this.elements[14] *= sz
  3160. }
  3161. },
  3162. skewX: function(angle) {
  3163. var t = Math.tan(angle);
  3164. this.apply(1, t, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)
  3165. },
  3166. skewY: function(angle) {
  3167. var t = Math.tan(angle);
  3168. this.apply(1, 0, 0, 0, t, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)
  3169. },
  3170. shearX: function(angle) {
  3171. var t = Math.tan(angle);
  3172. this.apply(1, t, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)
  3173. },
  3174. shearY: function(angle) {
  3175. var t = Math.tan(angle);
  3176. this.apply(1, 0, 0, 0, t, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)
  3177. },
  3178. multX: function(x, y, z, w) {
  3179. if (!z) return this.elements[0] * x + this.elements[1] * y + this.elements[3];
  3180. if (!w) return this.elements[0] * x + this.elements[1] * y + this.elements[2] * z + this.elements[3];
  3181. return this.elements[0] * x + this.elements[1] * y + this.elements[2] * z + this.elements[3] * w
  3182. },
  3183. multY: function(x, y, z, w) {
  3184. if (!z) return this.elements[4] * x + this.elements[5] * y + this.elements[7];
  3185. if (!w) return this.elements[4] * x + this.elements[5] * y + this.elements[6] * z + this.elements[7];
  3186. return this.elements[4] * x + this.elements[5] * y + this.elements[6] * z + this.elements[7] * w
  3187. },
  3188. multZ: function(x, y, z, w) {
  3189. if (!w) return this.elements[8] * x + this.elements[9] * y + this.elements[10] * z + this.elements[11];
  3190. return this.elements[8] * x + this.elements[9] * y + this.elements[10] * z + this.elements[11] * w
  3191. },
  3192. multW: function(x, y, z, w) {
  3193. if (!w) return this.elements[12] * x + this.elements[13] * y + this.elements[14] * z + this.elements[15];
  3194. return this.elements[12] * x + this.elements[13] * y + this.elements[14] * z + this.elements[15] * w
  3195. },
  3196. invert: function() {
  3197. var fA0 = this.elements[0] * this.elements[5] - this.elements[1] * this.elements[4];
  3198. var fA1 = this.elements[0] * this.elements[6] - this.elements[2] * this.elements[4];
  3199. var fA2 = this.elements[0] * this.elements[7] - this.elements[3] * this.elements[4];
  3200. var fA3 = this.elements[1] * this.elements[6] - this.elements[2] * this.elements[5];
  3201. var fA4 = this.elements[1] * this.elements[7] - this.elements[3] * this.elements[5];
  3202. var fA5 = this.elements[2] * this.elements[7] - this.elements[3] * this.elements[6];
  3203. var fB0 = this.elements[8] * this.elements[13] - this.elements[9] * this.elements[12];
  3204. var fB1 = this.elements[8] * this.elements[14] - this.elements[10] * this.elements[12];
  3205. var fB2 = this.elements[8] * this.elements[15] - this.elements[11] * this.elements[12];
  3206. var fB3 = this.elements[9] * this.elements[14] - this.elements[10] * this.elements[13];
  3207. var fB4 = this.elements[9] * this.elements[15] - this.elements[11] * this.elements[13];
  3208. var fB5 = this.elements[10] * this.elements[15] - this.elements[11] * this.elements[14];
  3209. var fDet = fA0 * fB5 - fA1 * fB4 + fA2 * fB3 + fA3 * fB2 - fA4 * fB1 + fA5 * fB0;
  3210. if (Math.abs(fDet) <= 1.0E-9) return false;
  3211. var kInv = [];
  3212. kInv[0] = +this.elements[5] * fB5 - this.elements[6] * fB4 + this.elements[7] * fB3;
  3213. kInv[4] = -this.elements[4] * fB5 + this.elements[6] * fB2 - this.elements[7] * fB1;
  3214. kInv[8] = +this.elements[4] * fB4 - this.elements[5] * fB2 + this.elements[7] * fB0;
  3215. kInv[12] = -this.elements[4] * fB3 + this.elements[5] * fB1 - this.elements[6] * fB0;
  3216. kInv[1] = -this.elements[1] * fB5 + this.elements[2] * fB4 - this.elements[3] * fB3;
  3217. kInv[5] = +this.elements[0] * fB5 - this.elements[2] * fB2 + this.elements[3] * fB1;
  3218. kInv[9] = -this.elements[0] * fB4 + this.elements[1] * fB2 - this.elements[3] * fB0;
  3219. kInv[13] = +this.elements[0] * fB3 - this.elements[1] * fB1 + this.elements[2] * fB0;
  3220. kInv[2] = +this.elements[13] * fA5 - this.elements[14] * fA4 + this.elements[15] * fA3;
  3221. kInv[6] = -this.elements[12] * fA5 + this.elements[14] * fA2 - this.elements[15] * fA1;
  3222. kInv[10] = +this.elements[12] * fA4 - this.elements[13] * fA2 + this.elements[15] * fA0;
  3223. kInv[14] = -this.elements[12] * fA3 + this.elements[13] * fA1 - this.elements[14] * fA0;
  3224. kInv[3] = -this.elements[9] * fA5 + this.elements[10] * fA4 - this.elements[11] * fA3;
  3225. kInv[7] = +this.elements[8] * fA5 - this.elements[10] * fA2 + this.elements[11] * fA1;
  3226. kInv[11] = -this.elements[8] * fA4 + this.elements[9] * fA2 - this.elements[11] * fA0;
  3227. kInv[15] = +this.elements[8] * fA3 - this.elements[9] * fA1 + this.elements[10] * fA0;
  3228. var fInvDet = 1 / fDet;
  3229. kInv[0] *= fInvDet;
  3230. kInv[1] *= fInvDet;
  3231. kInv[2] *= fInvDet;
  3232. kInv[3] *= fInvDet;
  3233. kInv[4] *= fInvDet;
  3234. kInv[5] *= fInvDet;
  3235. kInv[6] *= fInvDet;
  3236. kInv[7] *= fInvDet;
  3237. kInv[8] *= fInvDet;
  3238. kInv[9] *= fInvDet;
  3239. kInv[10] *= fInvDet;
  3240. kInv[11] *= fInvDet;
  3241. kInv[12] *= fInvDet;
  3242. kInv[13] *= fInvDet;
  3243. kInv[14] *= fInvDet;
  3244. kInv[15] *= fInvDet;
  3245. this.elements = kInv.slice();
  3246. return true
  3247. },
  3248. toString: function() {
  3249. var str = "";
  3250. for (var i = 0; i < 15; i++) str += this.elements[i] + ", ";
  3251. str += this.elements[15];
  3252. return str
  3253. },
  3254. print: function() {
  3255. var digits = printMatrixHelper(this.elements);
  3256. 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";
  3257. p.println(output)
  3258. },
  3259. invTranslate: function(tx, ty, tz) {
  3260. this.preApply(1, 0, 0, -tx, 0, 1, 0, -ty, 0, 0, 1, -tz, 0, 0, 0, 1)
  3261. },
  3262. invRotateX: function(angle) {
  3263. var c = Math.cos(-angle);
  3264. var s = Math.sin(-angle);
  3265. this.preApply([1, 0, 0, 0, 0, c, -s, 0, 0, s, c, 0, 0, 0, 0, 1])
  3266. },
  3267. invRotateY: function(angle) {
  3268. var c = Math.cos(-angle);
  3269. var s = Math.sin(-angle);
  3270. this.preApply([c, 0, s, 0, 0, 1, 0, 0, -s, 0, c, 0, 0, 0, 0, 1])
  3271. },
  3272. invRotateZ: function(angle) {
  3273. var c = Math.cos(-angle);
  3274. var s = Math.sin(-angle);
  3275. this.preApply([c, -s, 0, 0, s, c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1])
  3276. },
  3277. invScale: function(x, y, z) {
  3278. this.preApply([1 / x, 0, 0, 0, 0, 1 / y, 0, 0, 0, 0, 1 / z, 0, 0, 0, 0, 1])
  3279. }
  3280. };
  3281. var PMatrixStack = p.PMatrixStack = function() {
  3282. this.matrixStack = []
  3283. };
  3284. PMatrixStack.prototype.load = function() {
  3285. var tmpMatrix = drawing.$newPMatrix();
  3286. if (arguments.length === 1) tmpMatrix.set(arguments[0]);
  3287. else tmpMatrix.set(arguments);
  3288. this.matrixStack.push(tmpMatrix)
  3289. };
  3290. Drawing2D.prototype.$newPMatrix = function() {
  3291. return new PMatrix2D
  3292. };
  3293. Drawing3D.prototype.$newPMatrix = function() {
  3294. return new PMatrix3D
  3295. };
  3296. PMatrixStack.prototype.push = function() {
  3297. this.matrixStack.push(this.peek())
  3298. };
  3299. PMatrixStack.prototype.pop = function() {
  3300. return this.matrixStack.pop()
  3301. };
  3302. PMatrixStack.prototype.peek = function() {
  3303. var tmpMatrix = drawing.$newPMatrix();
  3304. tmpMatrix.set(this.matrixStack[this.matrixStack.length - 1]);
  3305. return tmpMatrix
  3306. };
  3307. PMatrixStack.prototype.mult = function(matrix) {
  3308. this.matrixStack[this.matrixStack.length - 1].apply(matrix)
  3309. };
  3310. p.split = function(str, delim) {
  3311. return str.split(delim)
  3312. };
  3313. p.splitTokens = function(str, tokens) {
  3314. if (tokens === undef) return str.split(/\s+/g);
  3315. var chars = tokens.split(/()/g),
  3316. buffer = "",
  3317. len = str.length,
  3318. i, c, tokenized = [];
  3319. for (i = 0; i < len; i++) {
  3320. c = str[i];
  3321. if (chars.indexOf(c) > -1) {
  3322. if (buffer !== "") tokenized.push(buffer);
  3323. buffer = ""
  3324. } else buffer += c
  3325. }
  3326. if (buffer !== "") tokenized.push(buffer);
  3327. return tokenized
  3328. };
  3329. p.append = function(array, element) {
  3330. array[array.length] = element;
  3331. return array
  3332. };
  3333. p.concat = function(array1, array2) {
  3334. return array1.concat(array2)
  3335. };
  3336. p.sort = function(array, numElem) {
  3337. var ret = [];
  3338. if (array.length > 0) {
  3339. var elemsToCopy = numElem > 0 ? numElem : array.length;
  3340. for (var i = 0; i < elemsToCopy; i++) ret.push(array[i]);
  3341. if (typeof array[0] === "string") ret.sort();
  3342. else ret.sort(function(a, b) {
  3343. return a - b
  3344. });
  3345. if (numElem > 0) for (var j = ret.length; j < array.length; j++) ret.push(array[j])
  3346. }
  3347. return ret
  3348. };
  3349. p.splice = function(array, value, index) {
  3350. if (value.length === 0) return array;
  3351. if (value instanceof Array) for (var i = 0, j = index; i < value.length; j++, i++) array.splice(j, 0, value[i]);
  3352. else array.splice(index, 0, value);
  3353. return array
  3354. };
  3355. p.subset = function(array, offset, length) {
  3356. var end = length !== undef ? offset + length : array.length;
  3357. return array.slice(offset, end)
  3358. };
  3359. p.join = function(array, seperator) {
  3360. return array.join(seperator)
  3361. };
  3362. p.shorten = function(ary) {
  3363. var newary = [];
  3364. var len = ary.length;
  3365. for (var i = 0; i < len; i++) newary[i] = ary[i];
  3366. newary.pop();
  3367. return newary
  3368. };
  3369. p.expand = function(ary, targetSize) {
  3370. var temp = ary.slice(0),
  3371. newSize = targetSize || ary.length * 2;
  3372. temp.length = newSize;
  3373. return temp
  3374. };
  3375. p.arrayCopy = function() {
  3376. var src, srcPos = 0,
  3377. dest, destPos = 0,
  3378. length;
  3379. if (arguments.length === 2) {
  3380. src = arguments[0];
  3381. dest = arguments[1];
  3382. length = src.length
  3383. } else if (arguments.length === 3) {
  3384. src = arguments[0];
  3385. dest = arguments[1];
  3386. length = arguments[2]
  3387. } else if (arguments.length === 5) {
  3388. src = arguments[0];
  3389. srcPos = arguments[1];
  3390. dest = arguments[2];
  3391. destPos = arguments[3];
  3392. length = arguments[4]
  3393. }
  3394. for (var i = srcPos, j = destPos; i < length + srcPos; i++, j++) if (dest[j] !== undef) dest[j] = src[i];
  3395. else throw "array index out of bounds exception";
  3396. };
  3397. p.reverse = function(array) {
  3398. return array.reverse()
  3399. };
  3400. p.mix = function(a, b, f) {
  3401. return a + ((b - a) * f >> 8)
  3402. };
  3403. p.peg = function(n) {
  3404. return n < 0 ? 0 : n > 255 ? 255 : n
  3405. };
  3406. p.modes = function() {
  3407. var ALPHA_MASK = 4278190080,
  3408. RED_MASK = 16711680,
  3409. GREEN_MASK = 65280,
  3410. BLUE_MASK = 255,
  3411. min = Math.min,
  3412. max = Math.max;
  3413. function applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb) {
  3414. var a = min(((c1 & 4278190080) >>> 24) + f, 255) << 24;
  3415. var r = ar + ((cr - ar) * f >> 8);
  3416. r = (r < 0 ? 0 : r > 255 ? 255 : r) << 16;
  3417. var g = ag + ((cg - ag) * f >> 8);
  3418. g = (g < 0 ? 0 : g > 255 ? 255 : g) << 8;
  3419. var b = ab + ((cb - ab) * f >> 8);
  3420. b = b < 0 ? 0 : b > 255 ? 255 : b;
  3421. return a | r | g | b
  3422. }
  3423. return {
  3424. replace: function(c1, c2) {
  3425. return c2
  3426. },
  3427. blend: function(c1, c2) {
  3428. var f = (c2 & ALPHA_MASK) >>> 24,
  3429. ar = c1 & RED_MASK,
  3430. ag = c1 & GREEN_MASK,
  3431. ab = c1 & BLUE_MASK,
  3432. br = c2 & RED_MASK,
  3433. bg = c2 & GREEN_MASK,
  3434. bb = c2 & BLUE_MASK;
  3435. 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
  3436. },
  3437. add: function(c1, c2) {
  3438. var f = (c2 & ALPHA_MASK) >>> 24;
  3439. 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)
  3440. },
  3441. subtract: function(c1, c2) {
  3442. var f = (c2 & ALPHA_MASK) >>> 24;
  3443. 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)
  3444. },
  3445. lightest: function(c1, c2) {
  3446. var f = (c2 & ALPHA_MASK) >>> 24;
  3447. 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)
  3448. },
  3449. darkest: function(c1, c2) {
  3450. var f = (c2 & ALPHA_MASK) >>> 24,
  3451. ar = c1 & RED_MASK,
  3452. ag = c1 & GREEN_MASK,
  3453. ab = c1 & BLUE_MASK,
  3454. br = min(c1 & RED_MASK, ((c2 & RED_MASK) >> 8) * f),
  3455. bg = min(c1 & GREEN_MASK, ((c2 & GREEN_MASK) >> 8) * f),
  3456. bb = min(c1 & BLUE_MASK, (c2 & BLUE_MASK) * f >> 8);
  3457. 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
  3458. },
  3459. difference: function(c1, c2) {
  3460. var f = (c2 & ALPHA_MASK) >>> 24,
  3461. ar = (c1 & RED_MASK) >> 16,
  3462. ag = (c1 & GREEN_MASK) >> 8,
  3463. ab = c1 & BLUE_MASK,
  3464. br = (c2 & RED_MASK) >> 16,
  3465. bg = (c2 & GREEN_MASK) >> 8,
  3466. bb = c2 & BLUE_MASK,
  3467. cr = ar > br ? ar - br : br - ar,
  3468. cg = ag > bg ? ag - bg : bg - ag,
  3469. cb = ab > bb ? ab - bb : bb - ab;
  3470. return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb)
  3471. },
  3472. exclusion: function(c1, c2) {
  3473. var f = (c2 & ALPHA_MASK) >>> 24,
  3474. ar = (c1 & RED_MASK) >> 16,
  3475. ag = (c1 & GREEN_MASK) >> 8,
  3476. ab = c1 & BLUE_MASK,
  3477. br = (c2 & RED_MASK) >> 16,
  3478. bg = (c2 & GREEN_MASK) >> 8,
  3479. bb = c2 & BLUE_MASK,
  3480. cr = ar + br - (ar * br >> 7),
  3481. cg = ag + bg - (ag * bg >> 7),
  3482. cb = ab + bb - (ab * bb >> 7);
  3483. return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb)
  3484. },
  3485. multiply: function(c1, c2) {
  3486. var f = (c2 & ALPHA_MASK) >>> 24,
  3487. ar = (c1 & RED_MASK) >> 16,
  3488. ag = (c1 & GREEN_MASK) >> 8,
  3489. ab = c1 & BLUE_MASK,
  3490. br = (c2 & RED_MASK) >> 16,
  3491. bg = (c2 & GREEN_MASK) >> 8,
  3492. bb = c2 & BLUE_MASK,
  3493. cr = ar * br >> 8,
  3494. cg = ag * bg >> 8,
  3495. cb = ab * bb >> 8;
  3496. return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb)
  3497. },
  3498. screen: function(c1, c2) {
  3499. var f = (c2 & ALPHA_MASK) >>> 24,
  3500. ar = (c1 & RED_MASK) >> 16,
  3501. ag = (c1 & GREEN_MASK) >> 8,
  3502. ab = c1 & BLUE_MASK,
  3503. br = (c2 & RED_MASK) >> 16,
  3504. bg = (c2 & GREEN_MASK) >> 8,
  3505. bb = c2 & BLUE_MASK,
  3506. cr = 255 - ((255 - ar) * (255 - br) >> 8),
  3507. cg = 255 - ((255 - ag) * (255 - bg) >> 8),
  3508. cb = 255 - ((255 - ab) * (255 - bb) >> 8);
  3509. return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb)
  3510. },
  3511. hard_light: function(c1, c2) {
  3512. var f = (c2 & ALPHA_MASK) >>> 24,
  3513. ar = (c1 & RED_MASK) >> 16,
  3514. ag = (c1 & GREEN_MASK) >> 8,
  3515. ab = c1 & BLUE_MASK,
  3516. br = (c2 & RED_MASK) >> 16,
  3517. bg = (c2 & GREEN_MASK) >> 8,
  3518. bb = c2 & BLUE_MASK,
  3519. cr = br < 128 ? ar * br >> 7 : 255 - ((255 - ar) * (255 - br) >> 7),
  3520. cg = bg < 128 ? ag * bg >> 7 : 255 - ((255 - ag) * (255 - bg) >> 7),
  3521. cb = bb < 128 ? ab * bb >> 7 : 255 - ((255 - ab) * (255 - bb) >> 7);
  3522. return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb)
  3523. },
  3524. soft_light: function(c1, c2) {
  3525. var f = (c2 & ALPHA_MASK) >>> 24,
  3526. ar = (c1 & RED_MASK) >> 16,
  3527. ag = (c1 & GREEN_MASK) >> 8,
  3528. ab = c1 & BLUE_MASK,
  3529. br = (c2 & RED_MASK) >> 16,
  3530. bg = (c2 & GREEN_MASK) >> 8,
  3531. bb = c2 & BLUE_MASK,
  3532. cr = (ar * br >> 7) + (ar * ar >> 8) - (ar * ar * br >> 15),
  3533. cg = (ag * bg >> 7) + (ag * ag >> 8) - (ag * ag * bg >> 15),
  3534. cb = (ab * bb >> 7) + (ab * ab >> 8) - (ab * ab * bb >> 15);
  3535. return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb)
  3536. },
  3537. overlay: function(c1, c2) {
  3538. var f = (c2 & ALPHA_MASK) >>> 24,
  3539. ar = (c1 & RED_MASK) >> 16,
  3540. ag = (c1 & GREEN_MASK) >> 8,
  3541. ab = c1 & BLUE_MASK,
  3542. br = (c2 & RED_MASK) >> 16,
  3543. bg = (c2 & GREEN_MASK) >> 8,
  3544. bb = c2 & BLUE_MASK,
  3545. cr = ar < 128 ? ar * br >> 7 : 255 - ((255 - ar) * (255 - br) >> 7),
  3546. cg = ag < 128 ? ag * bg >> 7 : 255 - ((255 - ag) * (255 - bg) >> 7),
  3547. cb = ab < 128 ? ab * bb >> 7 : 255 - ((255 - ab) * (255 - bb) >> 7);
  3548. return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb)
  3549. },
  3550. dodge: function(c1, c2) {
  3551. var f = (c2 & ALPHA_MASK) >>> 24,
  3552. ar = (c1 & RED_MASK) >> 16,
  3553. ag = (c1 & GREEN_MASK) >> 8,
  3554. ab = c1 & BLUE_MASK,
  3555. br = (c2 & RED_MASK) >> 16,
  3556. bg = (c2 & GREEN_MASK) >> 8,
  3557. bb = c2 & BLUE_MASK;
  3558. var cr = 255;
  3559. if (br !== 255) {
  3560. cr = (ar << 8) / (255 - br);
  3561. cr = cr < 0 ? 0 : cr > 255 ? 255 : cr
  3562. }
  3563. var cg = 255;
  3564. if (bg !== 255) {
  3565. cg = (ag << 8) / (255 - bg);
  3566. cg = cg < 0 ? 0 : cg > 255 ? 255 : cg
  3567. }
  3568. var cb = 255;
  3569. if (bb !== 255) {
  3570. cb = (ab << 8) / (255 - bb);
  3571. cb = cb < 0 ? 0 : cb > 255 ? 255 : cb
  3572. }
  3573. return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb)
  3574. },
  3575. burn: function(c1, c2) {
  3576. var f = (c2 & ALPHA_MASK) >>> 24,
  3577. ar = (c1 & RED_MASK) >> 16,
  3578. ag = (c1 & GREEN_MASK) >> 8,
  3579. ab = c1 & BLUE_MASK,
  3580. br = (c2 & RED_MASK) >> 16,
  3581. bg = (c2 & GREEN_MASK) >> 8,
  3582. bb = c2 & BLUE_MASK;
  3583. var cr = 0;
  3584. if (br !== 0) {
  3585. cr = (255 - ar << 8) / br;
  3586. cr = 255 - (cr < 0 ? 0 : cr > 255 ? 255 : cr)
  3587. }
  3588. var cg = 0;
  3589. if (bg !== 0) {
  3590. cg = (255 - ag << 8) / bg;
  3591. cg = 255 - (cg < 0 ? 0 : cg > 255 ? 255 : cg)
  3592. }
  3593. var cb = 0;
  3594. if (bb !== 0) {
  3595. cb = (255 - ab << 8) / bb;
  3596. cb = 255 - (cb < 0 ? 0 : cb > 255 ? 255 : cb)
  3597. }
  3598. return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb)
  3599. }
  3600. }
  3601. }();
  3602. function color$4(aValue1, aValue2, aValue3, aValue4) {
  3603. var r, g, b, a;
  3604. if (curColorMode === 3) {
  3605. var rgb = p.color.toRGB(aValue1, aValue2, aValue3);
  3606. r = rgb[0];
  3607. g = rgb[1];
  3608. b = rgb[2]
  3609. } else {
  3610. r = Math.round(255 * (aValue1 / colorModeX));
  3611. g = Math.round(255 * (aValue2 / colorModeY));
  3612. b = Math.round(255 * (aValue3 / colorModeZ))
  3613. }
  3614. a = Math.round(255 * (aValue4 / colorModeA));
  3615. r = r < 0 ? 0 : r;
  3616. g = g < 0 ? 0 : g;
  3617. b = b < 0 ? 0 : b;
  3618. a = a < 0 ? 0 : a;
  3619. r = r > 255 ? 255 : r;
  3620. g = g > 255 ? 255 : g;
  3621. b = b > 255 ? 255 : b;
  3622. a = a > 255 ? 255 : a;
  3623. return a << 24 & 4278190080 | r << 16 & 16711680 | g << 8 & 65280 | b & 255
  3624. }
  3625. function color$2(aValue1, aValue2) {
  3626. var a;
  3627. if (aValue1 & 4278190080) {
  3628. a = Math.round(255 * (aValue2 / colorModeA));
  3629. a = a > 255 ? 255 : a;
  3630. a = a < 0 ? 0 : a;
  3631. return aValue1 - (aValue1 & 4278190080) + (a << 24 & 4278190080)
  3632. }
  3633. if (curColorMode === 1) return color$4(aValue1, aValue1, aValue1, aValue2);
  3634. if (curColorMode === 3) return color$4(0, 0, aValue1 / colorModeX * colorModeZ, aValue2)
  3635. }
  3636. function color$1(aValue1) {
  3637. if (aValue1 <= colorModeX && aValue1 >= 0) {
  3638. if (curColorMode === 1) return color$4(aValue1, aValue1, aValue1, colorModeA);
  3639. if (curColorMode === 3) return color$4(0, 0, aValue1 / colorModeX * colorModeZ, colorModeA)
  3640. }
  3641. if (aValue1) {
  3642. if (aValue1 > 2147483647) aValue1 -= 4294967296;
  3643. return aValue1
  3644. }
  3645. }
  3646. p.color = function(aValue1, aValue2, aValue3, aValue4) {
  3647. if (aValue1 !== undef && aValue2 !== undef && aValue3 !== undef && aValue4 !== undef) return color$4(aValue1, aValue2, aValue3, aValue4);
  3648. if (aValue1 !== undef && aValue2 !== undef && aValue3 !== undef) return color$4(aValue1, aValue2, aValue3, colorModeA);
  3649. if (aValue1 !== undef && aValue2 !== undef) return color$2(aValue1, aValue2);
  3650. if (typeof aValue1 === "number") return color$1(aValue1);
  3651. return color$4(colorModeX, colorModeY, colorModeZ, colorModeA)
  3652. };
  3653. p.color.toString = function(colorInt) {
  3654. return "rgba(" + ((colorInt >> 16) & 255) + "," + ((colorInt >> 8) & 255) + "," + (colorInt & 255) + "," + ((colorInt >> 24) & 255) / 255 + ")"
  3655. };
  3656. p.color.toInt = function(r, g, b, a) {
  3657. return a << 24 & 4278190080 | r << 16 & 16711680 | g << 8 & 65280 | b & 255
  3658. };
  3659. p.color.toArray = function(colorInt) {
  3660. return [(colorInt >> 16) & 255, (colorInt >> 8) & 255, colorInt & 255, (colorInt >> 24) & 255]
  3661. };
  3662. p.color.toGLArray = function(colorInt) {
  3663. return [((colorInt & 16711680) >>> 16) / 255, ((colorInt >> 8) & 255) / 255, (colorInt & 255) / 255, ((colorInt >> 24) & 255) / 255]
  3664. };
  3665. p.color.toRGB = function(h, s, b) {
  3666. h = h > colorModeX ? colorModeX : h;
  3667. s = s > colorModeY ? colorModeY : s;
  3668. b = b > colorModeZ ? colorModeZ : b;
  3669. h = h / colorModeX * 360;
  3670. s = s / colorModeY * 100;
  3671. b = b / colorModeZ * 100;
  3672. var br = Math.round(b / 100 * 255);
  3673. if (s === 0) return [br, br, br];
  3674. var hue = h % 360;
  3675. var f = hue % 60;
  3676. var p = Math.round(b * (100 - s) / 1E4 * 255);
  3677. var q = Math.round(b * (6E3 - s * f) / 6E5 * 255);
  3678. var t = Math.round(b * (6E3 - s * (60 - f)) / 6E5 * 255);
  3679. switch (Math.floor(hue / 60)) {
  3680. case 0:
  3681. return [br, t, p];
  3682. case 1:
  3683. return [q, br, p];
  3684. case 2:
  3685. return [p, br, t];
  3686. case 3:
  3687. return [p, q, br];
  3688. case 4:
  3689. return [t, p, br];
  3690. case 5:
  3691. return [br, p, q]
  3692. }
  3693. };
  3694. function colorToHSB(colorInt) {
  3695. var red, green, blue;
  3696. red = ((colorInt >> 16) & 255) / 255;
  3697. green = ((colorInt >> 8) & 255) / 255;
  3698. blue = (colorInt & 255) / 255;
  3699. var max = p.max(p.max(red, green), blue),
  3700. min = p.min(p.min(red, green), blue),
  3701. hue, saturation;
  3702. if (min === max) return [0, 0, max * colorModeZ];
  3703. saturation = (max - min) / max;
  3704. if (red === max) hue = (green - blue) / (max - min);
  3705. else if (green === max) hue = 2 + (blue - red) / (max - min);
  3706. else hue = 4 + (red - green) / (max - min);
  3707. hue /= 6;
  3708. if (hue < 0) hue += 1;
  3709. else if (hue > 1) hue -= 1;
  3710. return [hue * colorModeX, saturation * colorModeY, max * colorModeZ]
  3711. }
  3712. p.brightness = function(colInt) {
  3713. return colorToHSB(colInt)[2]
  3714. };
  3715. p.saturation = function(colInt) {
  3716. return colorToHSB(colInt)[1]
  3717. };
  3718. p.hue = function(colInt) {
  3719. return colorToHSB(colInt)[0]
  3720. };
  3721. p.red = function(aColor) {
  3722. return ((aColor >> 16) & 255) / 255 * colorModeX
  3723. };
  3724. p.green = function(aColor) {
  3725. return ((aColor & 65280) >>> 8) / 255 * colorModeY
  3726. };
  3727. p.blue = function(aColor) {
  3728. return (aColor & 255) / 255 * colorModeZ
  3729. };
  3730. p.alpha = function(aColor) {
  3731. return ((aColor >> 24) & 255) / 255 * colorModeA
  3732. };
  3733. p.lerpColor = function(c1, c2, amt) {
  3734. var r, g, b, a, r1, g1, b1, a1, r2, g2, b2, a2;
  3735. var hsb1, hsb2, rgb, h, s;
  3736. var colorBits1 = p.color(c1);
  3737. var colorBits2 = p.color(c2);
  3738. if (curColorMode === 3) {
  3739. hsb1 = colorToHSB(colorBits1);
  3740. a1 = ((colorBits1 >> 24) & 255) / colorModeA;
  3741. hsb2 = colorToHSB(colorBits2);
  3742. a2 = ((colorBits2 & 4278190080) >>> 24) / colorModeA;
  3743. h = p.lerp(hsb1[0], hsb2[0], amt);
  3744. s = p.lerp(hsb1[1], hsb2[1], amt);
  3745. b = p.lerp(hsb1[2], hsb2[2], amt);
  3746. rgb = p.color.toRGB(h, s, b);
  3747. a = p.lerp(a1, a2, amt) * colorModeA;
  3748. return a << 24 & 4278190080 | (rgb[0] & 255) << 16 | (rgb[1] & 255) << 8 | rgb[2] & 255
  3749. }
  3750. r1 = (colorBits1 >> 16) & 255;
  3751. g1 = (colorBits1 >> 8) & 255;
  3752. b1 = colorBits1 & 255;
  3753. a1 = ((colorBits1 >> 24) & 255) / colorModeA;
  3754. r2 = (colorBits2 & 16711680) >>> 16;
  3755. g2 = (colorBits2 >> 8) & 255;
  3756. b2 = colorBits2 & 255;
  3757. a2 = ((colorBits2 >> 24) & 255) / colorModeA;
  3758. r = p.lerp(r1, r2, amt) | 0;
  3759. g = p.lerp(g1, g2, amt) | 0;
  3760. b = p.lerp(b1, b2, amt) | 0;
  3761. a = p.lerp(a1, a2, amt) * colorModeA;
  3762. return a << 24 & 4278190080 | r << 16 & 16711680 | g << 8 & 65280 | b & 255
  3763. };
  3764. p.colorMode = function() {
  3765. curColorMode = arguments[0];
  3766. if (arguments.length > 1) {
  3767. colorModeX = arguments[1];
  3768. colorModeY = arguments[2] || arguments[1];
  3769. colorModeZ = arguments[3] || arguments[1];
  3770. colorModeA = arguments[4] || arguments[1]
  3771. }
  3772. };
  3773. p.blendColor = function(c1, c2, mode) {
  3774. if (mode === 0) return p.modes.replace(c1, c2);
  3775. else if (mode === 1) return p.modes.blend(c1, c2);
  3776. else if (mode === 2) return p.modes.add(c1, c2);
  3777. else if (mode === 4) return p.modes.subtract(c1, c2);
  3778. else if (mode === 8) return p.modes.lightest(c1, c2);
  3779. else if (mode === 16) return p.modes.darkest(c1, c2);
  3780. else if (mode === 32) return p.modes.difference(c1, c2);
  3781. else if (mode === 64) return p.modes.exclusion(c1, c2);
  3782. else if (mode === 128) return p.modes.multiply(c1, c2);
  3783. else if (mode === 256) return p.modes.screen(c1, c2);
  3784. else if (mode === 1024) return p.modes.hard_light(c1, c2);
  3785. else if (mode === 2048) return p.modes.soft_light(c1, c2);
  3786. else if (mode === 512) return p.modes.overlay(c1, c2);
  3787. else if (mode === 4096) return p.modes.dodge(c1, c2);
  3788. else if (mode === 8192) return p.modes.burn(c1, c2)
  3789. };
  3790. function saveContext() {
  3791. curContext.save()
  3792. }
  3793. function restoreContext() {
  3794. curContext.restore();
  3795. isStrokeDirty = true;
  3796. isFillDirty = true
  3797. }
  3798. p.printMatrix = function() {
  3799. modelView.print()
  3800. };
  3801. Drawing2D.prototype.translate = function(x, y) {
  3802. modelView.translate(x, y);
  3803. modelViewInv.invTranslate(x, y);
  3804. curContext.translate(x, y)
  3805. };
  3806. Drawing3D.prototype.translate = function(x, y, z) {
  3807. modelView.translate(x, y, z);
  3808. modelViewInv.invTranslate(x, y, z)
  3809. };
  3810. Drawing2D.prototype.scale = function(x, y) {
  3811. modelView.scale(x, y);
  3812. modelViewInv.invScale(x, y);
  3813. curContext.scale(x, y || x)
  3814. };
  3815. Drawing3D.prototype.scale = function(x, y, z) {
  3816. modelView.scale(x, y, z);
  3817. modelViewInv.invScale(x, y, z)
  3818. };
  3819. Drawing2D.prototype.transform = function(pmatrix) {
  3820. var e = pmatrix.array();
  3821. curContext.transform(e[0], e[3], e[1], e[4], e[2], e[5])
  3822. };
  3823. Drawing3D.prototype.transformm = function(pmatrix3d) {
  3824. throw "p.transform is currently not supported in 3D mode";
  3825. };
  3826. Drawing2D.prototype.pushMatrix = function() {
  3827. userMatrixStack.load(modelView);
  3828. userReverseMatrixStack.load(modelViewInv);
  3829. saveContext()
  3830. };
  3831. Drawing3D.prototype.pushMatrix = function() {
  3832. userMatrixStack.load(modelView);
  3833. userReverseMatrixStack.load(modelViewInv)
  3834. };
  3835. Drawing2D.prototype.popMatrix = function() {
  3836. modelView.set(userMatrixStack.pop());
  3837. modelViewInv.set(userReverseMatrixStack.pop());
  3838. restoreContext()
  3839. };
  3840. Drawing3D.prototype.popMatrix = function() {
  3841. modelView.set(userMatrixStack.pop());
  3842. modelViewInv.set(userReverseMatrixStack.pop())
  3843. };
  3844. Drawing2D.prototype.resetMatrix = function() {
  3845. modelView.reset();
  3846. modelViewInv.reset();
  3847. curContext.setTransform(1, 0, 0, 1, 0, 0)
  3848. };
  3849. Drawing3D.prototype.resetMatrix = function() {
  3850. modelView.reset();
  3851. modelViewInv.reset()
  3852. };
  3853. DrawingShared.prototype.applyMatrix = function() {
  3854. var a = arguments;
  3855. 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]);
  3856. 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])
  3857. };
  3858. Drawing2D.prototype.applyMatrix = function() {
  3859. var a = arguments;
  3860. for (var cnt = a.length; cnt < 16; cnt++) a[cnt] = 0;
  3861. a[10] = a[15] = 1;
  3862. DrawingShared.prototype.applyMatrix.apply(this, a)
  3863. };
  3864. p.rotateX = function(angleInRadians) {
  3865. modelView.rotateX(angleInRadians);
  3866. modelViewInv.invRotateX(angleInRadians)
  3867. };
  3868. Drawing2D.prototype.rotateZ = function() {
  3869. throw "rotateZ() is not supported in 2D mode. Use rotate(float) instead.";
  3870. };
  3871. Drawing3D.prototype.rotateZ = function(angleInRadians) {
  3872. modelView.rotateZ(angleInRadians);
  3873. modelViewInv.invRotateZ(angleInRadians)
  3874. };
  3875. p.rotateY = function(angleInRadians) {
  3876. modelView.rotateY(angleInRadians);
  3877. modelViewInv.invRotateY(angleInRadians)
  3878. };
  3879. Drawing2D.prototype.rotate = function(angleInRadians) {
  3880. modelView.rotateZ(angleInRadians);
  3881. modelViewInv.invRotateZ(angleInRadians);
  3882. curContext.rotate(angleInRadians)
  3883. };
  3884. Drawing3D.prototype.rotate = function(angleInRadians) {
  3885. p.rotateZ(angleInRadians)
  3886. };
  3887. Drawing2D.prototype.shearX = function(angleInRadians) {
  3888. modelView.shearX(angleInRadians);
  3889. curContext.transform(1, 0, angleInRadians, 1, 0, 0)
  3890. };
  3891. Drawing3D.prototype.shearX = function(angleInRadians) {
  3892. modelView.shearX(angleInRadians)
  3893. };
  3894. Drawing2D.prototype.shearY = function(angleInRadians) {
  3895. modelView.shearY(angleInRadians);
  3896. curContext.transform(1, angleInRadians, 0, 1, 0, 0)
  3897. };
  3898. Drawing3D.prototype.shearY = function(angleInRadians) {
  3899. modelView.shearY(angleInRadians)
  3900. };
  3901. p.pushStyle = function() {
  3902. saveContext();
  3903. p.pushMatrix();
  3904. var newState = {
  3905. "doFill": doFill,
  3906. "currentFillColor": currentFillColor,
  3907. "doStroke": doStroke,
  3908. "currentStrokeColor": currentStrokeColor,
  3909. "curTint": curTint,
  3910. "curRectMode": curRectMode,
  3911. "curColorMode": curColorMode,
  3912. "colorModeX": colorModeX,
  3913. "colorModeZ": colorModeZ,
  3914. "colorModeY": colorModeY,
  3915. "colorModeA": colorModeA,
  3916. "curTextFont": curTextFont,
  3917. "horizontalTextAlignment": horizontalTextAlignment,
  3918. "verticalTextAlignment": verticalTextAlignment,
  3919. "textMode": textMode,
  3920. "curFontName": curFontName,
  3921. "curTextSize": curTextSize,
  3922. "curTextAscent": curTextAscent,
  3923. "curTextDescent": curTextDescent,
  3924. "curTextLeading": curTextLeading
  3925. };
  3926. styleArray.push(newState)
  3927. };
  3928. p.popStyle = function() {
  3929. var oldState = styleArray.pop();
  3930. if (oldState) {
  3931. restoreContext();
  3932. p.popMatrix();
  3933. doFill = oldState.doFill;
  3934. currentFillColor = oldState.currentFillColor;
  3935. doStroke = oldState.doStroke;
  3936. currentStrokeColor = oldState.currentStrokeColor;
  3937. curTint = oldState.curTint;
  3938. curRectMode = oldState.curRectMode;
  3939. curColorMode = oldState.curColorMode;
  3940. colorModeX = oldState.colorModeX;
  3941. colorModeZ = oldState.colorModeZ;
  3942. colorModeY = oldState.colorModeY;
  3943. colorModeA = oldState.colorModeA;
  3944. curTextFont = oldState.curTextFont;
  3945. curFontName = oldState.curFontName;
  3946. curTextSize = oldState.curTextSize;
  3947. horizontalTextAlignment = oldState.horizontalTextAlignment;
  3948. verticalTextAlignment = oldState.verticalTextAlignment;
  3949. textMode = oldState.textMode;
  3950. curTextAscent = oldState.curTextAscent;
  3951. curTextDescent = oldState.curTextDescent;
  3952. curTextLeading = oldState.curTextLeading
  3953. } else throw "Too many popStyle() without enough pushStyle()";
  3954. };
  3955. p.year = function() {
  3956. return (new Date).getFullYear()
  3957. };
  3958. p.month = function() {
  3959. return (new Date).getMonth() + 1
  3960. };
  3961. p.day = function() {
  3962. return (new Date).getDate()
  3963. };
  3964. p.hour = function() {
  3965. return (new Date).getHours()
  3966. };
  3967. p.minute = function() {
  3968. return (new Date).getMinutes()
  3969. };
  3970. p.second = function() {
  3971. return (new Date).getSeconds()
  3972. };
  3973. p.millis = function() {
  3974. return Date.now() - start
  3975. };
  3976. function redrawHelper() {
  3977. var sec = (Date.now() - timeSinceLastFPS) / 1E3;
  3978. framesSinceLastFPS++;
  3979. var fps = framesSinceLastFPS / sec;
  3980. if (sec > 0.5) {
  3981. timeSinceLastFPS = Date.now();
  3982. framesSinceLastFPS = 0;
  3983. p.__frameRate = fps
  3984. }
  3985. p.frameCount++
  3986. }
  3987. Drawing2D.prototype.redraw = function() {
  3988. redrawHelper();
  3989. curContext.lineWidth = lineWidth;
  3990. var pmouseXLastEvent = p.pmouseX,
  3991. pmouseYLastEvent = p.pmouseY;
  3992. p.pmouseX = pmouseXLastFrame;
  3993. p.pmouseY = pmouseYLastFrame;
  3994. saveContext();
  3995. p.draw();
  3996. restoreContext();
  3997. pmouseXLastFrame = p.mouseX;
  3998. pmouseYLastFrame = p.mouseY;
  3999. p.pmouseX = pmouseXLastEvent;
  4000. p.pmouseY = pmouseYLastEvent
  4001. };
  4002. Drawing3D.prototype.redraw = function() {
  4003. redrawHelper();
  4004. var pmouseXLastEvent = p.pmouseX,
  4005. pmouseYLastEvent = p.pmouseY;
  4006. p.pmouseX = pmouseXLastFrame;
  4007. p.pmouseY = pmouseYLastFrame;
  4008. curContext.clear(curContext.DEPTH_BUFFER_BIT);
  4009. curContextCache = {
  4010. attributes: {},
  4011. locations: {}
  4012. };
  4013. p.noLights();
  4014. p.lightFalloff(1, 0, 0);
  4015. p.shininess(1);
  4016. p.ambient(255, 255, 255);
  4017. p.specular(0, 0, 0);
  4018. p.emissive(0, 0, 0);
  4019. p.camera();
  4020. p.draw();
  4021. pmouseXLastFrame = p.mouseX;
  4022. pmouseYLastFrame = p.mouseY;
  4023. p.pmouseX = pmouseXLastEvent;
  4024. p.pmouseY = pmouseYLastEvent
  4025. };
  4026. p.noLoop = function() {
  4027. doLoop = false;
  4028. loopStarted = false;
  4029. clearInterval(looping);
  4030. curSketch.onPause()
  4031. };
  4032. p.loop = function() {
  4033. if (loopStarted) return;
  4034. timeSinceLastFPS = Date.now();
  4035. framesSinceLastFPS = 0;
  4036. looping = window.setInterval(function() {
  4037. try {
  4038. curSketch.onFrameStart();
  4039. p.redraw();
  4040. curSketch.onFrameEnd()
  4041. } catch(e_loop) {
  4042. window.clearInterval(looping);
  4043. throw e_loop;
  4044. }
  4045. },
  4046. curMsPerFrame);
  4047. doLoop = true;
  4048. loopStarted = true;
  4049. curSketch.onLoop()
  4050. };
  4051. p.frameRate = function(aRate) {
  4052. curFrameRate = aRate;
  4053. curMsPerFrame = 1E3 / curFrameRate;
  4054. if (doLoop) {
  4055. p.noLoop();
  4056. p.loop()
  4057. }
  4058. };
  4059. var eventHandlers = [];
  4060. function attachEventHandler(elem, type, fn) {
  4061. if (elem.addEventListener) elem.addEventListener(type, fn, false);
  4062. else elem.attachEvent("on" + type, fn);
  4063. eventHandlers.push({
  4064. elem: elem,
  4065. type: type,
  4066. fn: fn
  4067. })
  4068. }
  4069. function detachEventHandler(eventHandler) {
  4070. var elem = eventHandler.elem,
  4071. type = eventHandler.type,
  4072. fn = eventHandler.fn;
  4073. if (elem.removeEventListener) elem.removeEventListener(type, fn, false);
  4074. else if (elem.detachEvent) elem.detachEvent("on" + type, fn)
  4075. }
  4076. p.exit = function() {
  4077. window.clearInterval(looping);
  4078. removeInstance(p.externals.canvas.id);
  4079. delete curElement.onmousedown;
  4080. for (var lib in Processing.lib) if (Processing.lib.hasOwnProperty(lib)) if (Processing.lib[lib].hasOwnProperty("detach")) Processing.lib[lib].detach(p);
  4081. var i = eventHandlers.length;
  4082. while (i--) detachEventHandler(eventHandlers[i]);
  4083. curSketch.onExit()
  4084. };
  4085. p.cursor = function() {
  4086. if (arguments.length > 1 || arguments.length === 1 && arguments[0] instanceof p.PImage) {
  4087. var image = arguments[0],
  4088. x, y;
  4089. if (arguments.length >= 3) {
  4090. x = arguments[1];
  4091. y = arguments[2];
  4092. 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";
  4093. } else {
  4094. x = image.width >>> 1;
  4095. y = image.height >>> 1
  4096. }
  4097. var imageDataURL = image.toDataURL();
  4098. var style = 'url("' + imageDataURL + '") ' + x + " " + y + ", default";
  4099. curCursor = curElement.style.cursor = style
  4100. } else if (arguments.length === 1) {
  4101. var mode = arguments[0];
  4102. curCursor = curElement.style.cursor = mode
  4103. } else curCursor = curElement.style.cursor = oldCursor
  4104. };
  4105. p.noCursor = function() {
  4106. curCursor = curElement.style.cursor = PConstants.NOCURSOR
  4107. };
  4108. p.link = function(href, target) {
  4109. if (target !== undef) window.open(href, target);
  4110. else window.location = href
  4111. };
  4112. p.beginDraw = nop;
  4113. p.endDraw = nop;
  4114. Drawing2D.prototype.toImageData = function(x, y, w, h) {
  4115. x = x !== undef ? x : 0;
  4116. y = y !== undef ? y : 0;
  4117. w = w !== undef ? w : p.width;
  4118. h = h !== undef ? h : p.height;
  4119. return curContext.getImageData(x, y, w, h)
  4120. };
  4121. Drawing3D.prototype.toImageData = function(x, y, w, h) {
  4122. x = x !== undef ? x : 0;
  4123. y = y !== undef ? y : 0;
  4124. w = w !== undef ? w : p.width;
  4125. h = h !== undef ? h : p.height;
  4126. var c = document.createElement("canvas"),
  4127. ctx = c.getContext("2d"),
  4128. obj = ctx.createImageData(w, h),
  4129. uBuff = new Uint8Array(w * h * 4);
  4130. curContext.readPixels(x, y, w, h, curContext.RGBA, curContext.UNSIGNED_BYTE, uBuff);
  4131. 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)];
  4132. return obj
  4133. };
  4134. p.status = function(text) {
  4135. window.status = text
  4136. };
  4137. p.binary = function(num, numBits) {
  4138. var bit;
  4139. if (numBits > 0) bit = numBits;
  4140. else if (num instanceof Char) {
  4141. bit = 16;
  4142. num |= 0
  4143. } else {
  4144. bit = 32;
  4145. while (bit > 1 && !(num >>> bit - 1 & 1)) bit--
  4146. }
  4147. var result = "";
  4148. while (bit > 0) result += num >>> --bit & 1 ? "1" : "0";
  4149. return result
  4150. };
  4151. p.unbinary = function(binaryString) {
  4152. var i = binaryString.length - 1,
  4153. mask = 1,
  4154. result = 0;
  4155. while (i >= 0) {
  4156. var ch = binaryString[i--];
  4157. if (ch !== "0" && ch !== "1") throw "the value passed into unbinary was not an 8 bit binary number";
  4158. if (ch === "1") result += mask;
  4159. mask <<= 1
  4160. }
  4161. return result
  4162. };
  4163. function nfCoreScalar(value, plus, minus, leftDigits, rightDigits, group) {
  4164. var sign = value < 0 ? minus : plus;
  4165. var autoDetectDecimals = rightDigits === 0;
  4166. var rightDigitsOfDefault = rightDigits === undef || rightDigits < 0 ? 0 : rightDigits;
  4167. var absValue = Math.abs(value);
  4168. if (autoDetectDecimals) {
  4169. rightDigitsOfDefault = 1;
  4170. absValue *= 10;
  4171. while (Math.abs(Math.round(absValue) - absValue) > 1.0E-6 && rightDigitsOfDefault < 7) {
  4172. ++rightDigitsOfDefault;
  4173. absValue *= 10
  4174. }
  4175. } else if (rightDigitsOfDefault !== 0) absValue *= Math.pow(10, rightDigitsOfDefault);
  4176. var number, doubled = absValue * 2;
  4177. if (Math.floor(absValue) === absValue) number = absValue;
  4178. else if (Math.floor(doubled) === doubled) {
  4179. var floored = Math.floor(absValue);
  4180. number = floored + floored % 2
  4181. } else number = Math.round(absValue);
  4182. var buffer = "";
  4183. var totalDigits = leftDigits + rightDigitsOfDefault;
  4184. while (totalDigits > 0 || number > 0) {
  4185. totalDigits--;
  4186. buffer = "" + number % 10 + buffer;
  4187. number = Math.floor(number / 10)
  4188. }
  4189. if (group !== undef) {
  4190. var i = buffer.length - 3 - rightDigitsOfDefault;
  4191. while (i > 0) {
  4192. buffer = buffer.substring(0, i) + group + buffer.substring(i);
  4193. i -= 3
  4194. }
  4195. }
  4196. if (rightDigitsOfDefault > 0) return sign + buffer.substring(0, buffer.length - rightDigitsOfDefault) + "." + buffer.substring(buffer.length - rightDigitsOfDefault, buffer.length);
  4197. return sign + buffer
  4198. }
  4199. function nfCore(value, plus, minus, leftDigits, rightDigits, group) {
  4200. if (value instanceof Array) {
  4201. var arr = [];
  4202. for (var i = 0, len = value.length; i < len; i++) arr.push(nfCoreScalar(value[i], plus, minus, leftDigits, rightDigits, group));
  4203. return arr
  4204. }
  4205. return nfCoreScalar(value, plus, minus, leftDigits, rightDigits, group)
  4206. }
  4207. p.nf = function(value, leftDigits, rightDigits) {
  4208. return nfCore(value, "", "-", leftDigits, rightDigits)
  4209. };
  4210. p.nfs = function(value, leftDigits, rightDigits) {
  4211. return nfCore(value, " ", "-", leftDigits, rightDigits)
  4212. };
  4213. p.nfp = function(value, leftDigits, rightDigits) {
  4214. return nfCore(value, "+", "-", leftDigits, rightDigits)
  4215. };
  4216. p.nfc = function(value, leftDigits, rightDigits) {
  4217. return nfCore(value, "", "-", leftDigits, rightDigits, ",")
  4218. };
  4219. var decimalToHex = function(d, padding) {
  4220. padding = padding === undef || padding === null ? padding = 8 : padding;
  4221. if (d < 0) d = 4294967295 + d + 1;
  4222. var hex = Number(d).toString(16).toUpperCase();
  4223. while (hex.length < padding) hex = "0" + hex;
  4224. if (hex.length >= padding) hex = hex.substring(hex.length - padding, hex.length);
  4225. return hex
  4226. };
  4227. p.hex = function(value, len) {
  4228. if (arguments.length === 1) if (value instanceof Char) len = 4;
  4229. else len = 8;
  4230. return decimalToHex(value, len)
  4231. };
  4232. function unhexScalar(hex) {
  4233. var value = parseInt("0x" + hex, 16);
  4234. if (value > 2147483647) value -= 4294967296;
  4235. return value
  4236. }
  4237. p.unhex = function(hex) {
  4238. if (hex instanceof Array) {
  4239. var arr = [];
  4240. for (var i = 0; i < hex.length; i++) arr.push(unhexScalar(hex[i]));
  4241. return arr
  4242. }
  4243. return unhexScalar(hex)
  4244. };
  4245. p.loadStrings = function(filename) {
  4246. if (localStorage[filename]) return localStorage[filename].split("\n");
  4247. var filecontent = ajax(filename);
  4248. if (typeof filecontent !== "string" || filecontent === "") return [];
  4249. filecontent = filecontent.replace(/(\r\n?)/g, "\n").replace(/\n$/, "");
  4250. return filecontent.split("\n")
  4251. };
  4252. p.saveStrings = function(filename, strings) {
  4253. localStorage[filename] = strings.join("\n")
  4254. };
  4255. p.loadBytes = function(url) {
  4256. var string = ajax(url);
  4257. var ret = [];
  4258. for (var i = 0; i < string.length; i++) ret.push(string.charCodeAt(i));
  4259. return ret
  4260. };
  4261. function removeFirstArgument(args) {
  4262. return Array.prototype.slice.call(args, 1)
  4263. }
  4264. p.matchAll = function(aString, aRegExp) {
  4265. var results = [],
  4266. latest;
  4267. var regexp = new RegExp(aRegExp, "g");
  4268. while ((latest = regexp.exec(aString)) !== null) {
  4269. results.push(latest);
  4270. if (latest[0].length === 0)++regexp.lastIndex
  4271. }
  4272. return results.length > 0 ? results : null
  4273. };
  4274. p.__contains = function(subject, subStr) {
  4275. if (typeof subject !== "string") return subject.contains.apply(subject, removeFirstArgument(arguments));
  4276. return subject !== null && subStr !== null && typeof subStr === "string" && subject.indexOf(subStr) > -1
  4277. };
  4278. p.__replaceAll = function(subject, regex, replacement) {
  4279. if (typeof subject !== "string") return subject.replaceAll.apply(subject, removeFirstArgument(arguments));
  4280. return subject.replace(new RegExp(regex, "g"), replacement)
  4281. };
  4282. p.__replaceFirst = function(subject, regex, replacement) {
  4283. if (typeof subject !== "string") return subject.replaceFirst.apply(subject, removeFirstArgument(arguments));
  4284. return subject.replace(new RegExp(regex, ""), replacement)
  4285. };
  4286. p.__replace = function(subject, what, replacement) {
  4287. if (typeof subject !== "string") return subject.replace.apply(subject, removeFirstArgument(arguments));
  4288. if (what instanceof RegExp) return subject.replace(what, replacement);
  4289. if (typeof what !== "string") what = what.toString();
  4290. if (what === "") return subject;
  4291. var i = subject.indexOf(what);
  4292. if (i < 0) return subject;
  4293. var j = 0,
  4294. result = "";
  4295. do {
  4296. result += subject.substring(j, i) + replacement;
  4297. j = i + what.length
  4298. } while ((i = subject.indexOf(what, j)) >= 0);
  4299. return result + subject.substring(j)
  4300. };
  4301. p.__equals = function(subject, other) {
  4302. if (subject.equals instanceof
  4303. Function) return subject.equals.apply(subject, removeFirstArgument(arguments));
  4304. return subject.valueOf() === other.valueOf()
  4305. };
  4306. p.__equalsIgnoreCase = function(subject, other) {
  4307. if (typeof subject !== "string") return subject.equalsIgnoreCase.apply(subject, removeFirstArgument(arguments));
  4308. return subject.toLowerCase() === other.toLowerCase()
  4309. };
  4310. p.__toCharArray = function(subject) {
  4311. if (typeof subject !== "string") return subject.toCharArray.apply(subject, removeFirstArgument(arguments));
  4312. var chars = [];
  4313. for (var i = 0, len = subject.length; i < len; ++i) chars[i] = new Char(subject.charAt(i));
  4314. return chars
  4315. };
  4316. p.__split = function(subject, regex, limit) {
  4317. if (typeof subject !== "string") return subject.split.apply(subject, removeFirstArgument(arguments));
  4318. var pattern = new RegExp(regex);
  4319. if (limit === undef || limit < 1) return subject.split(pattern);
  4320. var result = [],
  4321. currSubject = subject,
  4322. pos;
  4323. while ((pos = currSubject.search(pattern)) !== -1 && result.length < limit - 1) {
  4324. var match = pattern.exec(currSubject).toString();
  4325. result.push(currSubject.substring(0, pos));
  4326. currSubject = currSubject.substring(pos + match.length)
  4327. }
  4328. if (pos !== -1 || currSubject !== "") result.push(currSubject);
  4329. return result
  4330. };
  4331. p.__codePointAt = function(subject, idx) {
  4332. var code = subject.charCodeAt(idx),
  4333. hi, low;
  4334. if (55296 <= code && code <= 56319) {
  4335. hi = code;
  4336. low = subject.charCodeAt(idx + 1);
  4337. return (hi - 55296) * 1024 + (low - 56320) + 65536
  4338. }
  4339. return code
  4340. };
  4341. p.match = function(str, regexp) {
  4342. return str.match(regexp)
  4343. };
  4344. p.__matches = function(str, regexp) {
  4345. return (new RegExp(regexp)).test(str)
  4346. };
  4347. p.__startsWith = function(subject, prefix, toffset) {
  4348. if (typeof subject !== "string") return subject.startsWith.apply(subject, removeFirstArgument(arguments));
  4349. toffset = toffset || 0;
  4350. if (toffset < 0 || toffset > subject.length) return false;
  4351. return prefix === "" || prefix === subject ? true : subject.indexOf(prefix) === toffset
  4352. };
  4353. p.__endsWith = function(subject, suffix) {
  4354. if (typeof subject !== "string") return subject.endsWith.apply(subject, removeFirstArgument(arguments));
  4355. var suffixLen = suffix ? suffix.length : 0;
  4356. return suffix === "" || suffix === subject ? true : subject.indexOf(suffix) === subject.length - suffixLen
  4357. };
  4358. p.__hashCode = function(subject) {
  4359. if (subject.hashCode instanceof
  4360. Function) return subject.hashCode.apply(subject, removeFirstArgument(arguments));
  4361. return virtHashCode(subject)
  4362. };
  4363. p.__printStackTrace = function(subject) {
  4364. p.println("Exception: " + subject.toString())
  4365. };
  4366. var logBuffer = [];
  4367. p.println = function(message) {
  4368. var bufferLen = logBuffer.length;
  4369. if (bufferLen) {
  4370. Processing.logger.log(logBuffer.join(""));
  4371. logBuffer.length = 0
  4372. }
  4373. if (arguments.length === 0 && bufferLen === 0) Processing.logger.log("");
  4374. else if (arguments.length !== 0) Processing.logger.log(message)
  4375. };
  4376. p.print = function(message) {
  4377. logBuffer.push(message)
  4378. };
  4379. p.str = function(val) {
  4380. if (val instanceof Array) {
  4381. var arr = [];
  4382. for (var i = 0; i < val.length; i++) arr.push(val[i].toString() + "");
  4383. return arr
  4384. }
  4385. return val.toString() + ""
  4386. };
  4387. p.trim = function(str) {
  4388. if (str instanceof Array) {
  4389. var arr = [];
  4390. for (var i = 0; i < str.length; i++) arr.push(str[i].replace(/^\s*/, "").replace(/\s*$/, "").replace(/\r*$/, ""));
  4391. return arr
  4392. }
  4393. return str.replace(/^\s*/, "").replace(/\s*$/, "").replace(/\r*$/, "")
  4394. };
  4395. function booleanScalar(val) {
  4396. if (typeof val === "number") return val !== 0;
  4397. if (typeof val === "boolean") return val;
  4398. if (typeof val === "string") return val.toLowerCase() === "true";
  4399. if (val instanceof Char) return val.code === 49 || val.code === 84 || val.code === 116
  4400. }
  4401. p.parseBoolean = function(val) {
  4402. if (val instanceof Array) {
  4403. var ret = [];
  4404. for (var i = 0; i < val.length; i++) ret.push(booleanScalar(val[i]));
  4405. return ret
  4406. }
  4407. return booleanScalar(val)
  4408. };
  4409. p.parseByte = function(what) {
  4410. if (what instanceof Array) {
  4411. var bytes = [];
  4412. for (var i = 0; i < what.length; i++) bytes.push(0 - (what[i] & 128) | what[i] & 127);
  4413. return bytes
  4414. }
  4415. return 0 - (what & 128) | what & 127
  4416. };
  4417. p.parseChar = function(key) {
  4418. if (typeof key === "number") return new Char(String.fromCharCode(key & 65535));
  4419. if (key instanceof Array) {
  4420. var ret = [];
  4421. for (var i = 0; i < key.length; i++) ret.push(new Char(String.fromCharCode(key[i] & 65535)));
  4422. return ret
  4423. }
  4424. throw "char() may receive only one argument of type int, byte, int[], or byte[].";
  4425. };
  4426. function floatScalar(val) {
  4427. if (typeof val === "number") return val;
  4428. if (typeof val === "boolean") return val ? 1 : 0;
  4429. if (typeof val === "string") return parseFloat(val);
  4430. if (val instanceof Char) return val.code
  4431. }
  4432. p.parseFloat = function(val) {
  4433. if (val instanceof
  4434. Array) {
  4435. var ret = [];
  4436. for (var i = 0; i < val.length; i++) ret.push(floatScalar(val[i]));
  4437. return ret
  4438. }
  4439. return floatScalar(val)
  4440. };
  4441. function intScalar(val, radix) {
  4442. if (typeof val === "number") return val & 4294967295;
  4443. if (typeof val === "boolean") return val ? 1 : 0;
  4444. if (typeof val === "string") {
  4445. var number = parseInt(val, radix || 10);
  4446. return number & 4294967295
  4447. }
  4448. if (val instanceof Char) return val.code
  4449. }
  4450. p.parseInt = function(val, radix) {
  4451. if (val instanceof Array) {
  4452. var ret = [];
  4453. for (var i = 0; i < val.length; i++) if (typeof val[i] === "string" && !/^\s*[+\-]?\d+\s*$/.test(val[i])) ret.push(0);
  4454. else ret.push(intScalar(val[i], radix));
  4455. return ret
  4456. }
  4457. return intScalar(val, radix)
  4458. };
  4459. p.__int_cast = function(val) {
  4460. return 0 | val
  4461. };
  4462. p.__instanceof = function(obj, type) {
  4463. if (typeof type !== "function") throw "Function is expected as type argument for instanceof operator";
  4464. if (typeof obj === "string") return type === Object || type === String;
  4465. if (obj instanceof type) return true;
  4466. if (typeof obj !== "object" || obj === null) return false;
  4467. var objType = obj.constructor;
  4468. if (type.$isInterface) {
  4469. var interfaces = [];
  4470. while (objType) {
  4471. if (objType.$interfaces) interfaces = interfaces.concat(objType.$interfaces);
  4472. objType = objType.$base
  4473. }
  4474. while (interfaces.length > 0) {
  4475. var i = interfaces.shift();
  4476. if (i === type) return true;
  4477. if (i.$interfaces) interfaces = interfaces.concat(i.$interfaces)
  4478. }
  4479. return false
  4480. }
  4481. while (objType.hasOwnProperty("$base")) {
  4482. objType = objType.$base;
  4483. if (objType === type) return true
  4484. }
  4485. return false
  4486. };
  4487. p.abs = Math.abs;
  4488. p.ceil = Math.ceil;
  4489. p.constrain = function(aNumber, aMin, aMax) {
  4490. return aNumber > aMax ? aMax : aNumber < aMin ? aMin : aNumber
  4491. };
  4492. p.dist = function() {
  4493. var dx, dy, dz;
  4494. if (arguments.length === 4) {
  4495. dx = arguments[0] - arguments[2];
  4496. dy = arguments[1] - arguments[3];
  4497. return Math.sqrt(dx * dx + dy * dy)
  4498. }
  4499. if (arguments.length === 6) {
  4500. dx = arguments[0] - arguments[3];
  4501. dy = arguments[1] - arguments[4];
  4502. dz = arguments[2] - arguments[5];
  4503. return Math.sqrt(dx * dx + dy * dy + dz * dz)
  4504. }
  4505. };
  4506. p.exp = Math.exp;
  4507. p.floor = Math.floor;
  4508. p.lerp = function(value1, value2, amt) {
  4509. return (value2 - value1) * amt + value1
  4510. };
  4511. p.log = Math.log;
  4512. p.mag = function(a, b, c) {
  4513. if (c) return Math.sqrt(a * a + b * b + c * c);
  4514. return Math.sqrt(a * a + b * b)
  4515. };
  4516. p.map = function(value, istart, istop, ostart, ostop) {
  4517. return ostart + (ostop - ostart) * ((value - istart) / (istop - istart))
  4518. };
  4519. p.max = function() {
  4520. if (arguments.length === 2) return arguments[0] < arguments[1] ? arguments[1] : arguments[0];
  4521. var numbers = arguments.length === 1 ? arguments[0] : arguments;
  4522. if (! ("length" in numbers && numbers.length > 0)) throw "Non-empty array is expected";
  4523. var max = numbers[0],
  4524. count = numbers.length;
  4525. for (var i = 1; i < count; ++i) if (max < numbers[i]) max = numbers[i];
  4526. return max
  4527. };
  4528. p.min = function() {
  4529. if (arguments.length === 2) return arguments[0] < arguments[1] ? arguments[0] : arguments[1];
  4530. var numbers = arguments.length === 1 ? arguments[0] : arguments;
  4531. if (! ("length" in numbers && numbers.length > 0)) throw "Non-empty array is expected";
  4532. var min = numbers[0],
  4533. count = numbers.length;
  4534. for (var i = 1; i < count; ++i) if (min > numbers[i]) min = numbers[i];
  4535. return min
  4536. };
  4537. p.norm = function(aNumber, low, high) {
  4538. return (aNumber - low) / (high - low)
  4539. };
  4540. p.pow = Math.pow;
  4541. p.round = Math.round;
  4542. p.sq = function(aNumber) {
  4543. return aNumber * aNumber
  4544. };
  4545. p.sqrt = Math.sqrt;
  4546. p.acos = Math.acos;
  4547. p.asin = Math.asin;
  4548. p.atan = Math.atan;
  4549. p.atan2 = Math.atan2;
  4550. p.cos = Math.cos;
  4551. p.degrees = function(aAngle) {
  4552. return aAngle * 180 / Math.PI
  4553. };
  4554. p.radians = function(aAngle) {
  4555. return aAngle / 180 * Math.PI
  4556. };
  4557. p.sin = Math.sin;
  4558. p.tan = Math.tan;
  4559. var currentRandom = Math.random;
  4560. p.random = function() {
  4561. if (arguments.length === 0) return currentRandom();
  4562. if (arguments.length === 1) return currentRandom() * arguments[0];
  4563. var aMin = arguments[0],
  4564. aMax = arguments[1];
  4565. return currentRandom() * (aMax - aMin) + aMin
  4566. };
  4567. function Marsaglia(i1, i2) {
  4568. var z = i1 || 362436069,
  4569. w = i2 || 521288629;
  4570. var nextInt = function() {
  4571. z = 36969 * (z & 65535) + (z >>> 16) & 4294967295;
  4572. w = 18E3 * (w & 65535) + (w >>> 16) & 4294967295;
  4573. return ((z & 65535) << 16 | w & 65535) & 4294967295
  4574. };
  4575. this.nextDouble = function() {
  4576. var i = nextInt() / 4294967296;
  4577. return i < 0 ? 1 + i : i
  4578. };
  4579. this.nextInt = nextInt
  4580. }
  4581. Marsaglia.createRandomized = function() {
  4582. var now = new Date;
  4583. return new Marsaglia(now / 6E4 & 4294967295, now & 4294967295)
  4584. };
  4585. p.randomSeed = function(seed) {
  4586. currentRandom = (new Marsaglia(seed)).nextDouble
  4587. };
  4588. p.Random = function(seed) {
  4589. var haveNextNextGaussian = false,
  4590. nextNextGaussian, random;
  4591. this.nextGaussian = function() {
  4592. if (haveNextNextGaussian) {
  4593. haveNextNextGaussian = false;
  4594. return nextNextGaussian
  4595. }
  4596. var v1, v2, s;
  4597. do {
  4598. v1 = 2 * random() - 1;
  4599. v2 = 2 * random() - 1;
  4600. s = v1 * v1 + v2 * v2
  4601. } while (s >= 1 || s === 0);
  4602. var multiplier = Math.sqrt(-2 * Math.log(s) / s);
  4603. nextNextGaussian = v2 * multiplier;
  4604. haveNextNextGaussian = true;
  4605. return v1 * multiplier
  4606. };
  4607. random = seed === undef ? Math.random : (new Marsaglia(seed)).nextDouble
  4608. };
  4609. function PerlinNoise(seed) {
  4610. var rnd = seed !== undef ? new Marsaglia(seed) : Marsaglia.createRandomized();
  4611. var i, j;
  4612. var perm = new Uint8Array(512);
  4613. for (i = 0; i < 256; ++i) perm[i] = i;
  4614. for (i = 0; i < 256; ++i) {
  4615. var t = perm[j = rnd.nextInt() & 255];
  4616. perm[j] = perm[i];
  4617. perm[i] = t
  4618. }
  4619. for (i = 0; i < 256; ++i) perm[i + 256] = perm[i];
  4620. function grad3d(i, x, y, z) {
  4621. var h = i & 15;
  4622. var u = h < 8 ? x : y,
  4623. v = h < 4 ? y : h === 12 || h === 14 ? x : z;
  4624. return ((h & 1) === 0 ? u : -u) + ((h & 2) === 0 ? v : -v)
  4625. }
  4626. function grad2d(i, x, y) {
  4627. var v = (i & 1) === 0 ? x : y;
  4628. return (i & 2) === 0 ? -v : v
  4629. }
  4630. function grad1d(i, x) {
  4631. return (i & 1) === 0 ? -x : x
  4632. }
  4633. function lerp(t, a, b) {
  4634. return a + t * (b - a)
  4635. }
  4636. this.noise3d = function(x, y, z) {
  4637. var X = Math.floor(x) & 255,
  4638. Y = Math.floor(y) & 255,
  4639. Z = Math.floor(z) & 255;
  4640. x -= Math.floor(x);
  4641. y -= Math.floor(y);
  4642. z -= Math.floor(z);
  4643. var fx = (3 - 2 * x) * x * x,
  4644. fy = (3 - 2 * y) * y * y,
  4645. fz = (3 - 2 * z) * z * z;
  4646. var p0 = perm[X] + Y,
  4647. p00 = perm[p0] + Z,
  4648. p01 = perm[p0 + 1] + Z,
  4649. p1 = perm[X + 1] + Y,
  4650. p10 = perm[p1] + Z,
  4651. p11 = perm[p1 + 1] + Z;
  4652. 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))))
  4653. };
  4654. this.noise2d = function(x, y) {
  4655. var X = Math.floor(x) & 255,
  4656. Y = Math.floor(y) & 255;
  4657. x -= Math.floor(x);
  4658. y -= Math.floor(y);
  4659. var fx = (3 - 2 * x) * x * x,
  4660. fy = (3 - 2 * y) * y * y;
  4661. var p0 = perm[X] + Y,
  4662. p1 = perm[X + 1] + Y;
  4663. 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)))
  4664. };
  4665. this.noise1d = function(x) {
  4666. var X = Math.floor(x) & 255;
  4667. x -= Math.floor(x);
  4668. var fx = (3 - 2 * x) * x * x;
  4669. return lerp(fx, grad1d(perm[X], x), grad1d(perm[X + 1], x - 1))
  4670. }
  4671. }
  4672. var noiseProfile = {
  4673. generator: undef,
  4674. octaves: 4,
  4675. fallout: 0.5,
  4676. seed: undef
  4677. };
  4678. p.noise = function(x, y, z) {
  4679. if (noiseProfile.generator === undef) noiseProfile.generator = new PerlinNoise(noiseProfile.seed);
  4680. var generator = noiseProfile.generator;
  4681. var effect = 1,
  4682. k = 1,
  4683. sum = 0;
  4684. for (var i = 0; i < noiseProfile.octaves; ++i) {
  4685. effect *= noiseProfile.fallout;
  4686. switch (arguments.length) {
  4687. case 1:
  4688. sum += effect * (1 + generator.noise1d(k * x)) / 2;
  4689. break;
  4690. case 2:
  4691. sum += effect * (1 + generator.noise2d(k * x, k * y)) / 2;
  4692. break;
  4693. case 3:
  4694. sum += effect * (1 + generator.noise3d(k * x, k * y, k * z)) / 2;
  4695. break
  4696. }
  4697. k *= 2
  4698. }
  4699. return sum
  4700. };
  4701. p.noiseDetail = function(octaves, fallout) {
  4702. noiseProfile.octaves = octaves;
  4703. if (fallout !== undef) noiseProfile.fallout = fallout
  4704. };
  4705. p.noiseSeed = function(seed) {
  4706. noiseProfile.seed = seed;
  4707. noiseProfile.generator = undef
  4708. };
  4709. DrawingShared.prototype.size = function(aWidth, aHeight, aMode) {
  4710. if (doStroke) p.stroke(0);
  4711. if (doFill) p.fill(255);
  4712. var savedProperties = {
  4713. fillStyle: curContext.fillStyle,
  4714. strokeStyle: curContext.strokeStyle,
  4715. lineCap: curContext.lineCap,
  4716. lineJoin: curContext.lineJoin
  4717. };
  4718. if (curElement.style.length > 0) {
  4719. curElement.style.removeProperty("width");
  4720. curElement.style.removeProperty("height")
  4721. }
  4722. curElement.width = p.width = aWidth || 100;
  4723. curElement.height = p.height = aHeight || 100;
  4724. for (var prop in savedProperties) if (savedProperties.hasOwnProperty(prop)) curContext[prop] = savedProperties[prop];
  4725. p.textFont(curTextFont);
  4726. p.background();
  4727. maxPixelsCached = Math.max(1E3, aWidth * aHeight * 0.05);
  4728. p.externals.context = curContext;
  4729. for (var i = 0; i < 720; i++) {
  4730. sinLUT[i] = p.sin(i * (Math.PI / 180) * 0.5);
  4731. cosLUT[i] = p.cos(i * (Math.PI / 180) * 0.5)
  4732. }
  4733. };
  4734. Drawing2D.prototype.size = function(aWidth, aHeight, aMode) {
  4735. if (curContext === undef) {
  4736. curContext = curElement.getContext("2d");
  4737. userMatrixStack = new PMatrixStack;
  4738. userReverseMatrixStack = new PMatrixStack;
  4739. modelView = new PMatrix2D;
  4740. modelViewInv = new PMatrix2D
  4741. }
  4742. DrawingShared.prototype.size.apply(this, arguments)
  4743. };
  4744. Drawing3D.prototype.size = function() {
  4745. var size3DCalled = false;
  4746. return function size(aWidth, aHeight, aMode) {
  4747. if (size3DCalled) throw "Multiple calls to size() for 3D renders are not allowed.";
  4748. size3DCalled = true;
  4749. function getGLContext(canvas) {
  4750. var ctxNames = ["experimental-webgl", "webgl", "webkit-3d"],
  4751. gl;
  4752. for (var i = 0, l = ctxNames.length; i < l; i++) {
  4753. gl = canvas.getContext(ctxNames[i], {
  4754. antialias: false,
  4755. preserveDrawingBuffer: true
  4756. });
  4757. if (gl) break
  4758. }
  4759. return gl
  4760. }
  4761. try {
  4762. curElement.width = p.width = aWidth || 100;
  4763. curElement.height = p.height = aHeight || 100;
  4764. curContext = getGLContext(curElement);
  4765. canTex = curContext.createTexture();
  4766. textTex = curContext.createTexture()
  4767. } catch(e_size) {
  4768. Processing.debug(e_size)
  4769. }
  4770. if (!curContext) throw "WebGL context is not supported on this browser.";
  4771. curContext.viewport(0, 0, curElement.width, curElement.height);
  4772. curContext.enable(curContext.DEPTH_TEST);
  4773. curContext.enable(curContext.BLEND);
  4774. curContext.blendFunc(curContext.SRC_ALPHA, curContext.ONE_MINUS_SRC_ALPHA);
  4775. programObject2D = createProgramObject(curContext, vertexShaderSrc2D, fragmentShaderSrc2D);
  4776. programObjectUnlitShape = createProgramObject(curContext, vertexShaderSrcUnlitShape, fragmentShaderSrcUnlitShape);
  4777. p.strokeWeight(1);
  4778. programObject3D = createProgramObject(curContext, vertexShaderSrc3D, fragmentShaderSrc3D);
  4779. curContext.useProgram(programObject3D);
  4780. uniformi("usingTexture3d", programObject3D, "usingTexture", usingTexture);
  4781. p.lightFalloff(1, 0, 0);
  4782. p.shininess(1);
  4783. p.ambient(255, 255, 255);
  4784. p.specular(0, 0, 0);
  4785. p.emissive(0, 0, 0);
  4786. boxBuffer = curContext.createBuffer();
  4787. curContext.bindBuffer(curContext.ARRAY_BUFFER, boxBuffer);
  4788. curContext.bufferData(curContext.ARRAY_BUFFER, boxVerts, curContext.STATIC_DRAW);
  4789. boxNormBuffer = curContext.createBuffer();
  4790. curContext.bindBuffer(curContext.ARRAY_BUFFER, boxNormBuffer);
  4791. curContext.bufferData(curContext.ARRAY_BUFFER, boxNorms, curContext.STATIC_DRAW);
  4792. boxOutlineBuffer = curContext.createBuffer();
  4793. curContext.bindBuffer(curContext.ARRAY_BUFFER, boxOutlineBuffer);
  4794. curContext.bufferData(curContext.ARRAY_BUFFER, boxOutlineVerts, curContext.STATIC_DRAW);
  4795. rectBuffer = curContext.createBuffer();
  4796. curContext.bindBuffer(curContext.ARRAY_BUFFER, rectBuffer);
  4797. curContext.bufferData(curContext.ARRAY_BUFFER, rectVerts, curContext.STATIC_DRAW);
  4798. rectNormBuffer = curContext.createBuffer();
  4799. curContext.bindBuffer(curContext.ARRAY_BUFFER, rectNormBuffer);
  4800. curContext.bufferData(curContext.ARRAY_BUFFER, rectNorms, curContext.STATIC_DRAW);
  4801. sphereBuffer = curContext.createBuffer();
  4802. lineBuffer = curContext.createBuffer();
  4803. fillBuffer = curContext.createBuffer();
  4804. fillColorBuffer = curContext.createBuffer();
  4805. strokeColorBuffer = curContext.createBuffer();
  4806. shapeTexVBO = curContext.createBuffer();
  4807. pointBuffer = curContext.createBuffer();
  4808. curContext.bindBuffer(curContext.ARRAY_BUFFER, pointBuffer);
  4809. curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array([0, 0, 0]), curContext.STATIC_DRAW);
  4810. textBuffer = curContext.createBuffer();
  4811. curContext.bindBuffer(curContext.ARRAY_BUFFER, textBuffer);
  4812. curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array([1, 1, 0, -1, 1, 0, -1, -1, 0, 1, -1, 0]), curContext.STATIC_DRAW);
  4813. textureBuffer = curContext.createBuffer();
  4814. curContext.bindBuffer(curContext.ARRAY_BUFFER, textureBuffer);
  4815. curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array([0, 0, 1, 0, 1, 1, 0, 1]), curContext.STATIC_DRAW);
  4816. indexBuffer = curContext.createBuffer();
  4817. curContext.bindBuffer(curContext.ELEMENT_ARRAY_BUFFER, indexBuffer);
  4818. curContext.bufferData(curContext.ELEMENT_ARRAY_BUFFER, new Uint16Array([0, 1, 2, 2, 3, 0]), curContext.STATIC_DRAW);
  4819. cam = new PMatrix3D;
  4820. cameraInv = new PMatrix3D;
  4821. modelView = new PMatrix3D;
  4822. modelViewInv = new PMatrix3D;
  4823. projection = new PMatrix3D;
  4824. p.camera();
  4825. p.perspective();
  4826. userMatrixStack = new PMatrixStack;
  4827. userReverseMatrixStack = new PMatrixStack;
  4828. curveBasisMatrix = new PMatrix3D;
  4829. curveToBezierMatrix = new PMatrix3D;
  4830. curveDrawMatrix = new PMatrix3D;
  4831. bezierDrawMatrix = new PMatrix3D;
  4832. bezierBasisInverse = new PMatrix3D;
  4833. bezierBasisMatrix = new PMatrix3D;
  4834. bezierBasisMatrix.set(-1, 3, -3, 1, 3, -6, 3, 0, -3, 3, 0, 0, 1, 0, 0, 0);
  4835. DrawingShared.prototype.size.apply(this, arguments)
  4836. }
  4837. }();
  4838. Drawing2D.prototype.ambientLight = DrawingShared.prototype.a3DOnlyFunction;
  4839. Drawing3D.prototype.ambientLight = function(r, g, b, x, y, z) {
  4840. if (lightCount === 8) throw "can only create " + 8 + " lights";
  4841. var pos = new PVector(x, y, z);
  4842. var view = new PMatrix3D;
  4843. view.scale(1, -1, 1);
  4844. view.apply(modelView.array());
  4845. view.mult(pos, pos);
  4846. var col = color$4(r, g, b, 0);
  4847. var normalizedCol = [((col >> 16) & 255) / 255, ((col >> 8) & 255) / 255, (col & 255) / 255];
  4848. curContext.useProgram(programObject3D);
  4849. uniformf("uLights.color.3d." + lightCount, programObject3D, "uLights" + lightCount + ".color", normalizedCol);
  4850. uniformf("uLights.position.3d." + lightCount, programObject3D, "uLights" + lightCount + ".position", pos.array());
  4851. uniformi("uLights.type.3d." + lightCount, programObject3D, "uLights" + lightCount + ".type", 0);
  4852. uniformi("uLightCount3d", programObject3D, "uLightCount", ++lightCount)
  4853. };
  4854. Drawing2D.prototype.directionalLight = DrawingShared.prototype.a3DOnlyFunction;
  4855. Drawing3D.prototype.directionalLight = function(r, g, b, nx, ny, nz) {
  4856. if (lightCount === 8) throw "can only create " + 8 + " lights";
  4857. curContext.useProgram(programObject3D);
  4858. var mvm = new PMatrix3D;
  4859. mvm.scale(1, -1, 1);
  4860. mvm.apply(modelView.array());
  4861. mvm = mvm.array();
  4862. 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];
  4863. var col = color$4(r, g, b, 0);
  4864. var normalizedCol = [((col >> 16) & 255) / 255, ((col >> 8) & 255) / 255, (col & 255) / 255];
  4865. uniformf("uLights.color.3d." + lightCount, programObject3D, "uLights" + lightCount + ".color", normalizedCol);
  4866. uniformf("uLights.position.3d." + lightCount, programObject3D, "uLights" + lightCount + ".position", dir);
  4867. uniformi("uLights.type.3d." + lightCount, programObject3D, "uLights" + lightCount + ".type", 1);
  4868. uniformi("uLightCount3d", programObject3D, "uLightCount", ++lightCount)
  4869. };
  4870. Drawing2D.prototype.lightFalloff = DrawingShared.prototype.a3DOnlyFunction;
  4871. Drawing3D.prototype.lightFalloff = function(constant, linear, quadratic) {
  4872. curContext.useProgram(programObject3D);
  4873. uniformf("uFalloff3d", programObject3D, "uFalloff", [constant, linear, quadratic])
  4874. };
  4875. Drawing2D.prototype.lightSpecular = DrawingShared.prototype.a3DOnlyFunction;
  4876. Drawing3D.prototype.lightSpecular = function(r, g, b) {
  4877. var col = color$4(r, g, b, 0);
  4878. var normalizedCol = [((col >> 16) & 255) / 255, ((col >> 8) & 255) / 255, (col & 255) / 255];
  4879. curContext.useProgram(programObject3D);
  4880. uniformf("uSpecular3d", programObject3D, "uSpecular", normalizedCol)
  4881. };
  4882. p.lights = function() {
  4883. p.ambientLight(128, 128, 128);
  4884. p.directionalLight(128, 128, 128, 0, 0, -1);
  4885. p.lightFalloff(1, 0, 0);
  4886. p.lightSpecular(0, 0, 0)
  4887. };
  4888. Drawing2D.prototype.pointLight = DrawingShared.prototype.a3DOnlyFunction;
  4889. Drawing3D.prototype.pointLight = function(r, g, b, x, y, z) {
  4890. if (lightCount === 8) throw "can only create " + 8 + " lights";
  4891. var pos = new PVector(x, y, z);
  4892. var view = new PMatrix3D;
  4893. view.scale(1, -1, 1);
  4894. view.apply(modelView.array());
  4895. view.mult(pos, pos);
  4896. var col = color$4(r, g, b, 0);
  4897. var normalizedCol = [((col >> 16) & 255) / 255, ((col >> 8) & 255) / 255, (col & 255) / 255];
  4898. curContext.useProgram(programObject3D);
  4899. uniformf("uLights.color.3d." + lightCount, programObject3D, "uLights" + lightCount + ".color", normalizedCol);
  4900. uniformf("uLights.position.3d." + lightCount, programObject3D, "uLights" + lightCount + ".position", pos.array());
  4901. uniformi("uLights.type.3d." + lightCount, programObject3D, "uLights" + lightCount + ".type", 2);
  4902. uniformi("uLightCount3d", programObject3D, "uLightCount", ++lightCount)
  4903. };
  4904. Drawing2D.prototype.noLights = DrawingShared.prototype.a3DOnlyFunction;
  4905. Drawing3D.prototype.noLights = function() {
  4906. lightCount = 0;
  4907. curContext.useProgram(programObject3D);
  4908. uniformi("uLightCount3d", programObject3D, "uLightCount", lightCount)
  4909. };
  4910. Drawing2D.prototype.spotLight = DrawingShared.prototype.a3DOnlyFunction;
  4911. Drawing3D.prototype.spotLight = function(r, g, b, x, y, z, nx, ny, nz, angle, concentration) {
  4912. if (lightCount === 8) throw "can only create " + 8 + " lights";
  4913. curContext.useProgram(programObject3D);
  4914. var pos = new PVector(x, y, z);
  4915. var mvm = new PMatrix3D;
  4916. mvm.scale(1, -1, 1);
  4917. mvm.apply(modelView.array());
  4918. mvm.mult(pos, pos);
  4919. mvm = mvm.array();
  4920. var dir = [mvm[0] * nx + mvm[4] * ny + mvm[8] * nz, mvm[1] *
  4921. nx + mvm[5] * ny + mvm[9] * nz, mvm[2] * nx + mvm[6] * ny + mvm[10] * nz];
  4922. var col = color$4(r, g, b, 0);
  4923. var normalizedCol = [((col >> 16) & 255) / 255, ((col >> 8) & 255) / 255, (col & 255) / 255];
  4924. uniformf("uLights.color.3d." + lightCount, programObject3D, "uLights" + lightCount + ".color", normalizedCol);
  4925. uniformf("uLights.position.3d." + lightCount, programObject3D, "uLights" + lightCount + ".position", pos.array());
  4926. uniformf("uLights.direction.3d." + lightCount, programObject3D, "uLights" + lightCount + ".direction", dir);
  4927. uniformf("uLights.concentration.3d." + lightCount, programObject3D, "uLights" + lightCount + ".concentration", concentration);
  4928. uniformf("uLights.angle.3d." + lightCount, programObject3D, "uLights" + lightCount + ".angle", angle);
  4929. uniformi("uLights.type.3d." + lightCount, programObject3D, "uLights" + lightCount + ".type", 3);
  4930. uniformi("uLightCount3d", programObject3D, "uLightCount", ++lightCount)
  4931. };
  4932. Drawing2D.prototype.beginCamera = function() {
  4933. throw "beginCamera() is not available in 2D mode";
  4934. };
  4935. Drawing3D.prototype.beginCamera = function() {
  4936. if (manipulatingCamera) throw "You cannot call beginCamera() again before calling endCamera()";
  4937. manipulatingCamera = true;
  4938. modelView = cameraInv;
  4939. modelViewInv = cam
  4940. };
  4941. Drawing2D.prototype.endCamera = function() {
  4942. throw "endCamera() is not available in 2D mode";
  4943. };
  4944. Drawing3D.prototype.endCamera = function() {
  4945. if (!manipulatingCamera) throw "You cannot call endCamera() before calling beginCamera()";
  4946. modelView.set(cam);
  4947. modelViewInv.set(cameraInv);
  4948. manipulatingCamera = false
  4949. };
  4950. p.camera = function(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ) {
  4951. if (eyeX === undef) {
  4952. cameraX = p.width / 2;
  4953. cameraY = p.height / 2;
  4954. cameraZ = cameraY / Math.tan(cameraFOV / 2);
  4955. eyeX = cameraX;
  4956. eyeY = cameraY;
  4957. eyeZ = cameraZ;
  4958. centerX = cameraX;
  4959. centerY = cameraY;
  4960. centerZ = 0;
  4961. upX = 0;
  4962. upY = 1;
  4963. upZ = 0
  4964. }
  4965. var z = new PVector(eyeX - centerX, eyeY - centerY, eyeZ - centerZ);
  4966. var y = new PVector(upX, upY, upZ);
  4967. z.normalize();
  4968. var x = PVector.cross(y, z);
  4969. y = PVector.cross(z, x);
  4970. x.normalize();
  4971. y.normalize();
  4972. var xX = x.x,
  4973. xY = x.y,
  4974. xZ = x.z;
  4975. var yX = y.x,
  4976. yY = y.y,
  4977. yZ = y.z;
  4978. var zX = z.x,
  4979. zY = z.y,
  4980. zZ = z.z;
  4981. cam.set(xX, xY, xZ, 0, yX, yY, yZ, 0, zX, zY, zZ, 0, 0, 0, 0, 1);
  4982. cam.translate(-eyeX, -eyeY, -eyeZ);
  4983. cameraInv.reset();
  4984. cameraInv.invApply(xX, xY, xZ, 0, yX, yY, yZ, 0, zX, zY, zZ, 0, 0, 0, 0, 1);
  4985. cameraInv.translate(eyeX, eyeY, eyeZ);
  4986. modelView.set(cam);
  4987. modelViewInv.set(cameraInv)
  4988. };
  4989. p.perspective = function(fov, aspect, near, far) {
  4990. if (arguments.length === 0) {
  4991. cameraY = curElement.height / 2;
  4992. cameraZ = cameraY / Math.tan(cameraFOV / 2);
  4993. cameraNear = cameraZ / 10;
  4994. cameraFar = cameraZ * 10;
  4995. cameraAspect = p.width / p.height;
  4996. fov = cameraFOV;
  4997. aspect = cameraAspect;
  4998. near = cameraNear;
  4999. far = cameraFar
  5000. }
  5001. var yMax, yMin, xMax, xMin;
  5002. yMax = near * Math.tan(fov / 2);
  5003. yMin = -yMax;
  5004. xMax = yMax * aspect;
  5005. xMin = yMin * aspect;
  5006. p.frustum(xMin, xMax, yMin, yMax, near, far)
  5007. };
  5008. Drawing2D.prototype.frustum = function() {
  5009. throw "Processing.js: frustum() is not supported in 2D mode";
  5010. };
  5011. Drawing3D.prototype.frustum = function(left, right, bottom, top, near, far) {
  5012. frustumMode = true;
  5013. projection = new PMatrix3D;
  5014. 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);
  5015. var proj = new PMatrix3D;
  5016. proj.set(projection);
  5017. proj.transpose();
  5018. curContext.useProgram(programObject2D);
  5019. uniformMatrix("projection2d", programObject2D, "uProjection", false, proj.array());
  5020. curContext.useProgram(programObject3D);
  5021. uniformMatrix("projection3d", programObject3D, "uProjection", false, proj.array());
  5022. curContext.useProgram(programObjectUnlitShape);
  5023. uniformMatrix("uProjectionUS", programObjectUnlitShape, "uProjection", false, proj.array())
  5024. };
  5025. p.ortho = function(left, right, bottom, top, near, far) {
  5026. if (arguments.length === 0) {
  5027. left = 0;
  5028. right = p.width;
  5029. bottom = 0;
  5030. top = p.height;
  5031. near = -10;
  5032. far = 10
  5033. }
  5034. var x = 2 / (right - left);
  5035. var y = 2 / (top - bottom);
  5036. var z = -2 / (far - near);
  5037. var tx = -(right + left) / (right - left);
  5038. var ty = -(top + bottom) / (top - bottom);
  5039. var tz = -(far + near) / (far - near);
  5040. projection = new PMatrix3D;
  5041. projection.set(x, 0, 0, tx, 0, y, 0, ty, 0, 0, z, tz, 0, 0, 0, 1);
  5042. var proj = new PMatrix3D;
  5043. proj.set(projection);
  5044. proj.transpose();
  5045. curContext.useProgram(programObject2D);
  5046. uniformMatrix("projection2d", programObject2D, "uProjection", false, proj.array());
  5047. curContext.useProgram(programObject3D);
  5048. uniformMatrix("projection3d", programObject3D, "uProjection", false, proj.array());
  5049. curContext.useProgram(programObjectUnlitShape);
  5050. uniformMatrix("uProjectionUS", programObjectUnlitShape, "uProjection", false, proj.array());
  5051. frustumMode = false
  5052. };
  5053. p.printProjection = function() {
  5054. projection.print()
  5055. };
  5056. p.printCamera = function() {
  5057. cam.print()
  5058. };
  5059. Drawing2D.prototype.box = DrawingShared.prototype.a3DOnlyFunction;
  5060. Drawing3D.prototype.box = function(w, h, d) {
  5061. if (!h || !d) h = d = w;
  5062. var model = new PMatrix3D;
  5063. model.scale(w, h, d);
  5064. var view = new PMatrix3D;
  5065. view.scale(1, -1, 1);
  5066. view.apply(modelView.array());
  5067. view.transpose();
  5068. if (doFill) {
  5069. curContext.useProgram(programObject3D);
  5070. uniformMatrix("model3d", programObject3D, "uModel", false, model.array());
  5071. uniformMatrix("view3d", programObject3D, "uView", false, view.array());
  5072. curContext.enable(curContext.POLYGON_OFFSET_FILL);
  5073. curContext.polygonOffset(1, 1);
  5074. uniformf("color3d", programObject3D, "uColor", fillStyle);
  5075. if (lightCount > 0) {
  5076. var v = new PMatrix3D;
  5077. v.set(view);
  5078. var m = new PMatrix3D;
  5079. m.set(model);
  5080. v.mult(m);
  5081. var normalMatrix = new PMatrix3D;
  5082. normalMatrix.set(v);
  5083. normalMatrix.invert();
  5084. normalMatrix.transpose();
  5085. uniformMatrix("uNormalTransform3d", programObject3D, "uNormalTransform", false, normalMatrix.array());
  5086. vertexAttribPointer("aNormal3d", programObject3D, "aNormal", 3, boxNormBuffer)
  5087. } else disableVertexAttribPointer("aNormal3d", programObject3D, "aNormal");
  5088. vertexAttribPointer("aVertex3d", programObject3D, "aVertex", 3, boxBuffer);
  5089. disableVertexAttribPointer("aColor3d", programObject3D, "aColor");
  5090. disableVertexAttribPointer("aTexture3d", programObject3D, "aTexture");
  5091. curContext.drawArrays(curContext.TRIANGLES, 0, boxVerts.length / 3);
  5092. curContext.disable(curContext.POLYGON_OFFSET_FILL)
  5093. }
  5094. if (lineWidth > 0 && doStroke) {
  5095. curContext.useProgram(programObject2D);
  5096. uniformMatrix("uModel2d", programObject2D, "uModel", false, model.array());
  5097. uniformMatrix("uView2d", programObject2D, "uView", false, view.array());
  5098. uniformf("uColor2d", programObject2D, "uColor", strokeStyle);
  5099. uniformi("uIsDrawingText2d", programObject2D, "uIsDrawingText", false);
  5100. vertexAttribPointer("vertex2d", programObject2D, "aVertex", 3, boxOutlineBuffer);
  5101. disableVertexAttribPointer("aTextureCoord2d", programObject2D, "aTextureCoord");
  5102. curContext.drawArrays(curContext.LINES, 0, boxOutlineVerts.length / 3)
  5103. }
  5104. };
  5105. var initSphere = function() {
  5106. var i;
  5107. sphereVerts = [];
  5108. for (i = 0; i < sphereDetailU; i++) {
  5109. sphereVerts.push(0);
  5110. sphereVerts.push(-1);
  5111. sphereVerts.push(0);
  5112. sphereVerts.push(sphereX[i]);
  5113. sphereVerts.push(sphereY[i]);
  5114. sphereVerts.push(sphereZ[i])
  5115. }
  5116. sphereVerts.push(0);
  5117. sphereVerts.push(-1);
  5118. sphereVerts.push(0);
  5119. sphereVerts.push(sphereX[0]);
  5120. sphereVerts.push(sphereY[0]);
  5121. sphereVerts.push(sphereZ[0]);
  5122. var v1, v11, v2;
  5123. var voff = 0;
  5124. for (i = 2; i < sphereDetailV; i++) {
  5125. v1 = v11 = voff;
  5126. voff += sphereDetailU;
  5127. v2 = voff;
  5128. for (var j = 0; j < sphereDetailU; j++) {
  5129. sphereVerts.push(sphereX[v1]);
  5130. sphereVerts.push(sphereY[v1]);
  5131. sphereVerts.push(sphereZ[v1++]);
  5132. sphereVerts.push(sphereX[v2]);
  5133. sphereVerts.push(sphereY[v2]);
  5134. sphereVerts.push(sphereZ[v2++])
  5135. }
  5136. v1 = v11;
  5137. v2 = voff;
  5138. sphereVerts.push(sphereX[v1]);
  5139. sphereVerts.push(sphereY[v1]);
  5140. sphereVerts.push(sphereZ[v1]);
  5141. sphereVerts.push(sphereX[v2]);
  5142. sphereVerts.push(sphereY[v2]);
  5143. sphereVerts.push(sphereZ[v2])
  5144. }
  5145. for (i = 0; i < sphereDetailU; i++) {
  5146. v2 = voff + i;
  5147. sphereVerts.push(sphereX[v2]);
  5148. sphereVerts.push(sphereY[v2]);
  5149. sphereVerts.push(sphereZ[v2]);
  5150. sphereVerts.push(0);
  5151. sphereVerts.push(1);
  5152. sphereVerts.push(0)
  5153. }
  5154. sphereVerts.push(sphereX[voff]);
  5155. sphereVerts.push(sphereY[voff]);
  5156. sphereVerts.push(sphereZ[voff]);
  5157. sphereVerts.push(0);
  5158. sphereVerts.push(1);
  5159. sphereVerts.push(0);
  5160. curContext.bindBuffer(curContext.ARRAY_BUFFER, sphereBuffer);
  5161. curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(sphereVerts), curContext.STATIC_DRAW)
  5162. };
  5163. p.sphereDetail = function(ures, vres) {
  5164. var i;
  5165. if (arguments.length === 1) ures = vres = arguments[0];
  5166. if (ures < 3) ures = 3;
  5167. if (vres < 2) vres = 2;
  5168. if (ures === sphereDetailU && vres === sphereDetailV) return;
  5169. var delta = 720 / ures;
  5170. var cx = new Float32Array(ures);
  5171. var cz = new Float32Array(ures);
  5172. for (i = 0; i < ures; i++) {
  5173. cx[i] = cosLUT[i * delta % 720 | 0];
  5174. cz[i] = sinLUT[i * delta % 720 | 0]
  5175. }
  5176. var vertCount = ures * (vres - 1) + 2;
  5177. var currVert = 0;
  5178. sphereX = new Float32Array(vertCount);
  5179. sphereY = new Float32Array(vertCount);
  5180. sphereZ = new Float32Array(vertCount);
  5181. var angle_step = 720 * 0.5 / vres;
  5182. var angle = angle_step;
  5183. for (i = 1; i < vres; i++) {
  5184. var curradius = sinLUT[angle % 720 | 0];
  5185. var currY = -cosLUT[angle % 720 | 0];
  5186. for (var j = 0; j < ures; j++) {
  5187. sphereX[currVert] = cx[j] * curradius;
  5188. sphereY[currVert] = currY;
  5189. sphereZ[currVert++] = cz[j] * curradius
  5190. }
  5191. angle += angle_step
  5192. }
  5193. sphereDetailU = ures;
  5194. sphereDetailV = vres;
  5195. initSphere()
  5196. };
  5197. Drawing2D.prototype.sphere = DrawingShared.prototype.a3DOnlyFunction;
  5198. Drawing3D.prototype.sphere = function() {
  5199. var sRad = arguments[0];
  5200. if (sphereDetailU < 3 || sphereDetailV < 2) p.sphereDetail(30);
  5201. var model = new PMatrix3D;
  5202. model.scale(sRad, sRad, sRad);
  5203. var view = new PMatrix3D;
  5204. view.scale(1, -1, 1);
  5205. view.apply(modelView.array());
  5206. view.transpose();
  5207. if (doFill) {
  5208. if (lightCount > 0) {
  5209. var v = new PMatrix3D;
  5210. v.set(view);
  5211. var m = new PMatrix3D;
  5212. m.set(model);
  5213. v.mult(m);
  5214. var normalMatrix = new PMatrix3D;
  5215. normalMatrix.set(v);
  5216. normalMatrix.invert();
  5217. normalMatrix.transpose();
  5218. uniformMatrix("uNormalTransform3d", programObject3D, "uNormalTransform", false, normalMatrix.array());
  5219. vertexAttribPointer("aNormal3d", programObject3D, "aNormal", 3, sphereBuffer)
  5220. } else disableVertexAttribPointer("aNormal3d", programObject3D, "aNormal");
  5221. curContext.useProgram(programObject3D);
  5222. disableVertexAttribPointer("aTexture3d", programObject3D, "aTexture");
  5223. uniformMatrix("uModel3d", programObject3D, "uModel", false, model.array());
  5224. uniformMatrix("uView3d", programObject3D, "uView", false, view.array());
  5225. vertexAttribPointer("aVertex3d", programObject3D, "aVertex", 3, sphereBuffer);
  5226. disableVertexAttribPointer("aColor3d", programObject3D, "aColor");
  5227. curContext.enable(curContext.POLYGON_OFFSET_FILL);
  5228. curContext.polygonOffset(1, 1);
  5229. uniformf("uColor3d", programObject3D, "uColor", fillStyle);
  5230. curContext.drawArrays(curContext.TRIANGLE_STRIP, 0, sphereVerts.length / 3);
  5231. curContext.disable(curContext.POLYGON_OFFSET_FILL)
  5232. }
  5233. if (lineWidth > 0 && doStroke) {
  5234. curContext.useProgram(programObject2D);
  5235. uniformMatrix("uModel2d", programObject2D, "uModel", false, model.array());
  5236. uniformMatrix("uView2d", programObject2D, "uView", false, view.array());
  5237. vertexAttribPointer("aVertex2d", programObject2D, "aVertex", 3, sphereBuffer);
  5238. disableVertexAttribPointer("aTextureCoord2d", programObject2D, "aTextureCoord");
  5239. uniformf("uColor2d", programObject2D, "uColor", strokeStyle);
  5240. uniformi("uIsDrawingText", programObject2D, "uIsDrawingText", false);
  5241. curContext.drawArrays(curContext.LINE_STRIP, 0, sphereVerts.length / 3)
  5242. }
  5243. };
  5244. p.modelX = function(x, y, z) {
  5245. var mv = modelView.array();
  5246. var ci = cameraInv.array();
  5247. var ax = mv[0] * x + mv[1] * y + mv[2] * z + mv[3];
  5248. var ay = mv[4] * x + mv[5] * y + mv[6] * z + mv[7];
  5249. var az = mv[8] * x + mv[9] * y + mv[10] * z + mv[11];
  5250. var aw = mv[12] * x + mv[13] * y + mv[14] * z + mv[15];
  5251. var ox = ci[0] * ax + ci[1] * ay + ci[2] * az + ci[3] * aw;
  5252. var ow = ci[12] * ax + ci[13] * ay + ci[14] * az + ci[15] * aw;
  5253. return ow !== 0 ? ox / ow : ox
  5254. };
  5255. p.modelY = function(x, y, z) {
  5256. var mv = modelView.array();
  5257. var ci = cameraInv.array();
  5258. var ax = mv[0] * x + mv[1] * y + mv[2] * z + mv[3];
  5259. var ay = mv[4] * x + mv[5] * y + mv[6] * z + mv[7];
  5260. var az = mv[8] * x + mv[9] * y + mv[10] * z + mv[11];
  5261. var aw = mv[12] * x + mv[13] * y + mv[14] * z + mv[15];
  5262. var oy = ci[4] * ax + ci[5] * ay + ci[6] * az + ci[7] * aw;
  5263. var ow = ci[12] * ax + ci[13] * ay + ci[14] * az + ci[15] * aw;
  5264. return ow !== 0 ? oy / ow : oy
  5265. };
  5266. p.modelZ = function(x, y, z) {
  5267. var mv = modelView.array();
  5268. var ci = cameraInv.array();
  5269. var ax = mv[0] * x + mv[1] * y + mv[2] * z + mv[3];
  5270. var ay = mv[4] * x + mv[5] * y + mv[6] * z + mv[7];
  5271. var az = mv[8] * x + mv[9] * y + mv[10] * z + mv[11];
  5272. var aw = mv[12] * x + mv[13] * y + mv[14] * z + mv[15];
  5273. var oz = ci[8] * ax + ci[9] * ay + ci[10] * az + ci[11] * aw;
  5274. var ow = ci[12] * ax + ci[13] * ay + ci[14] * az + ci[15] * aw;
  5275. return ow !== 0 ? oz / ow : oz
  5276. };
  5277. Drawing2D.prototype.ambient = DrawingShared.prototype.a3DOnlyFunction;
  5278. Drawing3D.prototype.ambient = function(v1, v2, v3) {
  5279. curContext.useProgram(programObject3D);
  5280. uniformi("uUsingMat3d", programObject3D, "uUsingMat", true);
  5281. var col = p.color(v1, v2, v3);
  5282. uniformf("uMaterialAmbient3d", programObject3D, "uMaterialAmbient", p.color.toGLArray(col).slice(0, 3))
  5283. };
  5284. Drawing2D.prototype.emissive = DrawingShared.prototype.a3DOnlyFunction;
  5285. Drawing3D.prototype.emissive = function(v1, v2, v3) {
  5286. curContext.useProgram(programObject3D);
  5287. uniformi("uUsingMat3d", programObject3D, "uUsingMat", true);
  5288. var col = p.color(v1, v2, v3);
  5289. uniformf("uMaterialEmissive3d", programObject3D, "uMaterialEmissive", p.color.toGLArray(col).slice(0, 3))
  5290. };
  5291. Drawing2D.prototype.shininess = DrawingShared.prototype.a3DOnlyFunction;
  5292. Drawing3D.prototype.shininess = function(shine) {
  5293. curContext.useProgram(programObject3D);
  5294. uniformi("uUsingMat3d", programObject3D, "uUsingMat", true);
  5295. uniformf("uShininess3d", programObject3D, "uShininess", shine)
  5296. };
  5297. Drawing2D.prototype.specular = DrawingShared.prototype.a3DOnlyFunction;
  5298. Drawing3D.prototype.specular = function(v1, v2, v3) {
  5299. curContext.useProgram(programObject3D);
  5300. uniformi("uUsingMat3d", programObject3D, "uUsingMat", true);
  5301. var col = p.color(v1, v2, v3);
  5302. uniformf("uMaterialSpecular3d", programObject3D, "uMaterialSpecular", p.color.toGLArray(col).slice(0, 3))
  5303. };
  5304. p.screenX = function(x, y, z) {
  5305. var mv = modelView.array();
  5306. if (mv.length === 16) {
  5307. var ax = mv[0] * x + mv[1] * y + mv[2] * z + mv[3];
  5308. var ay = mv[4] * x + mv[5] * y + mv[6] * z + mv[7];
  5309. var az = mv[8] * x + mv[9] * y + mv[10] * z + mv[11];
  5310. var aw = mv[12] * x + mv[13] * y + mv[14] * z + mv[15];
  5311. var pj = projection.array();
  5312. var ox = pj[0] * ax + pj[1] * ay + pj[2] * az + pj[3] * aw;
  5313. var ow = pj[12] * ax + pj[13] * ay + pj[14] * az + pj[15] * aw;
  5314. if (ow !== 0) ox /= ow;
  5315. return p.width * (1 + ox) / 2
  5316. }
  5317. return modelView.multX(x, y)
  5318. };
  5319. p.screenY = function screenY(x, y, z) {
  5320. var mv = modelView.array();
  5321. if (mv.length === 16) {
  5322. var ax = mv[0] * x + mv[1] * y + mv[2] * z + mv[3];
  5323. var ay = mv[4] * x + mv[5] * y + mv[6] * z + mv[7];
  5324. var az = mv[8] * x + mv[9] * y + mv[10] * z + mv[11];
  5325. var aw = mv[12] * x + mv[13] * y + mv[14] * z + mv[15];
  5326. var pj = projection.array();
  5327. var oy = pj[4] * ax + pj[5] * ay + pj[6] * az + pj[7] * aw;
  5328. var ow = pj[12] * ax + pj[13] * ay + pj[14] * az + pj[15] * aw;
  5329. if (ow !== 0) oy /= ow;
  5330. return p.height * (1 + oy) / 2
  5331. }
  5332. return modelView.multY(x, y)
  5333. };
  5334. p.screenZ = function screenZ(x, y, z) {
  5335. var mv = modelView.array();
  5336. if (mv.length !== 16) return 0;
  5337. var pj = projection.array();
  5338. var ax = mv[0] * x + mv[1] * y + mv[2] * z + mv[3];
  5339. var ay = mv[4] * x + mv[5] * y + mv[6] * z + mv[7];
  5340. var az = mv[8] * x + mv[9] * y + mv[10] * z + mv[11];
  5341. var aw = mv[12] * x + mv[13] * y + mv[14] * z + mv[15];
  5342. var oz = pj[8] * ax + pj[9] * ay + pj[10] * az + pj[11] * aw;
  5343. var ow = pj[12] * ax + pj[13] * ay + pj[14] * az + pj[15] * aw;
  5344. if (ow !== 0) oz /= ow;
  5345. return (oz + 1) / 2
  5346. };
  5347. DrawingShared.prototype.fill = function() {
  5348. var color = p.color(arguments[0], arguments[1], arguments[2], arguments[3]);
  5349. if (color === currentFillColor && doFill) return;
  5350. doFill = true;
  5351. currentFillColor = color
  5352. };
  5353. Drawing2D.prototype.fill = function() {
  5354. DrawingShared.prototype.fill.apply(this, arguments);
  5355. isFillDirty = true
  5356. };
  5357. Drawing3D.prototype.fill = function() {
  5358. DrawingShared.prototype.fill.apply(this, arguments);
  5359. fillStyle = p.color.toGLArray(currentFillColor)
  5360. };
  5361. function executeContextFill() {
  5362. if (doFill) {
  5363. if (isFillDirty) {
  5364. curContext.fillStyle = p.color.toString(currentFillColor);
  5365. isFillDirty = false
  5366. }
  5367. curContext.fill()
  5368. }
  5369. }
  5370. p.noFill = function() {
  5371. doFill = false
  5372. };
  5373. DrawingShared.prototype.stroke = function() {
  5374. var color = p.color(arguments[0], arguments[1], arguments[2], arguments[3]);
  5375. if (color === currentStrokeColor && doStroke) return;
  5376. doStroke = true;
  5377. currentStrokeColor = color
  5378. };
  5379. Drawing2D.prototype.stroke = function() {
  5380. DrawingShared.prototype.stroke.apply(this, arguments);
  5381. isStrokeDirty = true
  5382. };
  5383. Drawing3D.prototype.stroke = function() {
  5384. DrawingShared.prototype.stroke.apply(this, arguments);
  5385. strokeStyle = p.color.toGLArray(currentStrokeColor)
  5386. };
  5387. function executeContextStroke() {
  5388. if (doStroke) {
  5389. if (isStrokeDirty) {
  5390. curContext.strokeStyle = p.color.toString(currentStrokeColor);
  5391. isStrokeDirty = false
  5392. }
  5393. curContext.stroke()
  5394. }
  5395. }
  5396. p.noStroke = function() {
  5397. doStroke = false
  5398. };
  5399. DrawingShared.prototype.strokeWeight = function(w) {
  5400. lineWidth = w
  5401. };
  5402. Drawing2D.prototype.strokeWeight = function(w) {
  5403. DrawingShared.prototype.strokeWeight.apply(this, arguments);
  5404. curContext.lineWidth = w
  5405. };
  5406. Drawing3D.prototype.strokeWeight = function(w) {
  5407. DrawingShared.prototype.strokeWeight.apply(this, arguments);
  5408. curContext.useProgram(programObject2D);
  5409. uniformf("pointSize2d", programObject2D, "uPointSize", w);
  5410. curContext.useProgram(programObjectUnlitShape);
  5411. uniformf("pointSizeUnlitShape", programObjectUnlitShape, "uPointSize", w);
  5412. curContext.lineWidth(w)
  5413. };
  5414. p.strokeCap = function(value) {
  5415. drawing.$ensureContext().lineCap = value
  5416. };
  5417. p.strokeJoin = function(value) {
  5418. drawing.$ensureContext().lineJoin = value
  5419. };
  5420. Drawing2D.prototype.smooth = function() {
  5421. renderSmooth = true;
  5422. var style = curElement.style;
  5423. style.setProperty("image-rendering", "optimizeQuality", "important");
  5424. style.setProperty("-ms-interpolation-mode", "bicubic", "important");
  5425. if (curContext.hasOwnProperty("mozImageSmoothingEnabled")) curContext.mozImageSmoothingEnabled = true
  5426. };
  5427. Drawing3D.prototype.smooth = function() {
  5428. renderSmooth = true
  5429. };
  5430. Drawing2D.prototype.noSmooth = function() {
  5431. renderSmooth = false;
  5432. var style = curElement.style;
  5433. style.setProperty("image-rendering", "optimizeSpeed", "important");
  5434. style.setProperty("image-rendering", "-moz-crisp-edges", "important");
  5435. style.setProperty("image-rendering", "-webkit-optimize-contrast", "important");
  5436. style.setProperty("image-rendering", "optimize-contrast", "important");
  5437. style.setProperty("-ms-interpolation-mode", "nearest-neighbor", "important");
  5438. if (curContext.hasOwnProperty("mozImageSmoothingEnabled")) curContext.mozImageSmoothingEnabled = false
  5439. };
  5440. Drawing3D.prototype.noSmooth = function() {
  5441. renderSmooth = false
  5442. };
  5443. Drawing2D.prototype.point = function(x, y) {
  5444. if (!doStroke) return;
  5445. x = Math.round(x);
  5446. y = Math.round(y);
  5447. curContext.fillStyle = p.color.toString(currentStrokeColor);
  5448. isFillDirty = true;
  5449. if (lineWidth > 1) {
  5450. curContext.beginPath();
  5451. curContext.arc(x, y, lineWidth / 2, 0, 6.283185307179586, false);
  5452. curContext.fill()
  5453. } else curContext.fillRect(x, y, 1, 1)
  5454. };
  5455. Drawing3D.prototype.point = function(x, y, z) {
  5456. var model = new PMatrix3D;
  5457. model.translate(x, y, z || 0);
  5458. model.transpose();
  5459. var view = new PMatrix3D;
  5460. view.scale(1, -1, 1);
  5461. view.apply(modelView.array());
  5462. view.transpose();
  5463. curContext.useProgram(programObject2D);
  5464. uniformMatrix("uModel2d", programObject2D, "uModel", false, model.array());
  5465. uniformMatrix("uView2d", programObject2D, "uView", false, view.array());
  5466. if (lineWidth > 0 && doStroke) {
  5467. uniformf("uColor2d", programObject2D, "uColor", strokeStyle);
  5468. uniformi("uIsDrawingText2d", programObject2D, "uIsDrawingText", false);
  5469. uniformi("uSmooth2d", programObject2D, "uSmooth", renderSmooth);
  5470. vertexAttribPointer("aVertex2d", programObject2D, "aVertex", 3, pointBuffer);
  5471. disableVertexAttribPointer("aTextureCoord2d", programObject2D, "aTextureCoord");
  5472. curContext.drawArrays(curContext.POINTS, 0, 1)
  5473. }
  5474. };
  5475. p.beginShape = function(type) {
  5476. curShape = type;
  5477. curvePoints = [];
  5478. vertArray = []
  5479. };
  5480. Drawing2D.prototype.vertex = function(x, y, moveTo) {
  5481. var vert = [];
  5482. if (firstVert) firstVert = false;
  5483. vert["isVert"] = true;
  5484. vert[0] = x;
  5485. vert[1] = y;
  5486. vert[2] = 0;
  5487. vert[3] = 0;
  5488. vert[4] = 0;
  5489. vert[5] = currentFillColor;
  5490. vert[6] = currentStrokeColor;
  5491. vertArray.push(vert);
  5492. if (moveTo) vertArray[vertArray.length - 1]["moveTo"] = moveTo
  5493. };
  5494. Drawing3D.prototype.vertex = function(x, y, z, u, v) {
  5495. var vert = [];
  5496. if (firstVert) firstVert = false;
  5497. vert["isVert"] = true;
  5498. if (v === undef && usingTexture) {
  5499. v = u;
  5500. u = z;
  5501. z = 0
  5502. }
  5503. if (u !== undef && v !== undef) {
  5504. if (curTextureMode === 2) {
  5505. u /= curTexture.width;
  5506. v /= curTexture.height
  5507. }
  5508. u = u > 1 ? 1 : u;
  5509. u = u < 0 ? 0 : u;
  5510. v = v > 1 ? 1 : v;
  5511. v = v < 0 ? 0 : v
  5512. }
  5513. vert[0] = x;
  5514. vert[1] = y;
  5515. vert[2] = z || 0;
  5516. vert[3] = u || 0;
  5517. vert[4] = v || 0;
  5518. vert[5] = fillStyle[0];
  5519. vert[6] = fillStyle[1];
  5520. vert[7] = fillStyle[2];
  5521. vert[8] = fillStyle[3];
  5522. vert[9] = strokeStyle[0];
  5523. vert[10] = strokeStyle[1];
  5524. vert[11] = strokeStyle[2];
  5525. vert[12] = strokeStyle[3];
  5526. vert[13] = normalX;
  5527. vert[14] = normalY;
  5528. vert[15] = normalZ;
  5529. vertArray.push(vert)
  5530. };
  5531. var point3D = function(vArray, cArray) {
  5532. var view = new PMatrix3D;
  5533. view.scale(1, -1, 1);
  5534. view.apply(modelView.array());
  5535. view.transpose();
  5536. curContext.useProgram(programObjectUnlitShape);
  5537. uniformMatrix("uViewUS", programObjectUnlitShape, "uView", false, view.array());
  5538. uniformi("uSmoothUS", programObjectUnlitShape, "uSmooth", renderSmooth);
  5539. vertexAttribPointer("aVertexUS", programObjectUnlitShape, "aVertex", 3, pointBuffer);
  5540. curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(vArray), curContext.STREAM_DRAW);
  5541. vertexAttribPointer("aColorUS", programObjectUnlitShape, "aColor", 4, fillColorBuffer);
  5542. curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(cArray), curContext.STREAM_DRAW);
  5543. curContext.drawArrays(curContext.POINTS, 0, vArray.length / 3)
  5544. };
  5545. var line3D = function(vArray, mode, cArray) {
  5546. var ctxMode;
  5547. if (mode === "LINES") ctxMode = curContext.LINES;
  5548. else if (mode === "LINE_LOOP") ctxMode = curContext.LINE_LOOP;
  5549. else ctxMode = curContext.LINE_STRIP;
  5550. var view = new PMatrix3D;
  5551. view.scale(1, -1, 1);
  5552. view.apply(modelView.array());
  5553. view.transpose();
  5554. curContext.useProgram(programObjectUnlitShape);
  5555. uniformMatrix("uViewUS", programObjectUnlitShape, "uView", false, view.array());
  5556. vertexAttribPointer("aVertexUS", programObjectUnlitShape, "aVertex", 3, lineBuffer);
  5557. curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(vArray), curContext.STREAM_DRAW);
  5558. vertexAttribPointer("aColorUS", programObjectUnlitShape, "aColor", 4, strokeColorBuffer);
  5559. curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(cArray), curContext.STREAM_DRAW);
  5560. curContext.drawArrays(ctxMode, 0, vArray.length / 3)
  5561. };
  5562. var fill3D = function(vArray, mode, cArray, tArray) {
  5563. var ctxMode;
  5564. if (mode === "TRIANGLES") ctxMode = curContext.TRIANGLES;
  5565. else if (mode === "TRIANGLE_FAN") ctxMode = curContext.TRIANGLE_FAN;
  5566. else ctxMode = curContext.TRIANGLE_STRIP;
  5567. var view = new PMatrix3D;
  5568. view.scale(1, -1, 1);
  5569. view.apply(modelView.array());
  5570. view.transpose();
  5571. curContext.useProgram(programObject3D);
  5572. uniformMatrix("model3d", programObject3D, "uModel", false, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
  5573. uniformMatrix("view3d", programObject3D, "uView", false, view.array());
  5574. curContext.enable(curContext.POLYGON_OFFSET_FILL);
  5575. curContext.polygonOffset(1, 1);
  5576. uniformf("color3d", programObject3D, "uColor", [-1, 0, 0, 0]);
  5577. vertexAttribPointer("vertex3d", programObject3D, "aVertex", 3, fillBuffer);
  5578. curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(vArray), curContext.STREAM_DRAW);
  5579. if (usingTexture && curTint !== null) curTint3d(cArray);
  5580. vertexAttribPointer("aColor3d", programObject3D, "aColor", 4, fillColorBuffer);
  5581. curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(cArray), curContext.STREAM_DRAW);
  5582. disableVertexAttribPointer("aNormal3d", programObject3D, "aNormal");
  5583. if (usingTexture) {
  5584. uniformi("uUsingTexture3d", programObject3D, "uUsingTexture", usingTexture);
  5585. vertexAttribPointer("aTexture3d", programObject3D, "aTexture", 2, shapeTexVBO);
  5586. curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(tArray), curContext.STREAM_DRAW)
  5587. }
  5588. curContext.drawArrays(ctxMode, 0, vArray.length / 3);
  5589. curContext.disable(curContext.POLYGON_OFFSET_FILL)
  5590. };
  5591. function fillStrokeClose() {
  5592. executeContextFill();
  5593. executeContextStroke();
  5594. curContext.closePath()
  5595. }
  5596. Drawing2D.prototype.endShape = function(mode) {
  5597. if (vertArray.length === 0) return;
  5598. var closeShape = mode === 2;
  5599. if (closeShape) vertArray.push(vertArray[0]);
  5600. var lineVertArray = [];
  5601. var fillVertArray = [];
  5602. var colorVertArray = [];
  5603. var strokeVertArray = [];
  5604. var texVertArray = [];
  5605. var cachedVertArray;
  5606. firstVert = true;
  5607. var i, j, k;
  5608. var vertArrayLength = vertArray.length;
  5609. for (i = 0; i < vertArrayLength; i++) {
  5610. cachedVertArray = vertArray[i];
  5611. for (j = 0; j < 3; j++) fillVertArray.push(cachedVertArray[j])
  5612. }
  5613. for (i = 0; i < vertArrayLength; i++) {
  5614. cachedVertArray = vertArray[i];
  5615. for (j = 5; j < 9; j++) colorVertArray.push(cachedVertArray[j])
  5616. }
  5617. for (i = 0; i < vertArrayLength; i++) {
  5618. cachedVertArray = vertArray[i];
  5619. for (j = 9; j < 13; j++) strokeVertArray.push(cachedVertArray[j])
  5620. }
  5621. for (i = 0; i < vertArrayLength; i++) {
  5622. cachedVertArray = vertArray[i];
  5623. texVertArray.push(cachedVertArray[3]);
  5624. texVertArray.push(cachedVertArray[4])
  5625. }
  5626. if (isCurve && (curShape === 20 || curShape === undef)) {
  5627. if (vertArrayLength > 3) {
  5628. var b = [],
  5629. s = 1 - curTightness;
  5630. curContext.beginPath();
  5631. curContext.moveTo(vertArray[1][0], vertArray[1][1]);
  5632. for (i = 1; i + 2 < vertArrayLength; i++) {
  5633. cachedVertArray = vertArray[i];
  5634. b[0] = [cachedVertArray[0], cachedVertArray[1]];
  5635. 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];
  5636. 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];
  5637. b[3] = [vertArray[i + 1][0], vertArray[i + 1][1]];
  5638. curContext.bezierCurveTo(b[1][0], b[1][1], b[2][0], b[2][1], b[3][0], b[3][1])
  5639. }
  5640. fillStrokeClose()
  5641. }
  5642. } else if (isBezier && (curShape === 20 || curShape === undef)) {
  5643. curContext.beginPath();
  5644. for (i = 0; i < vertArrayLength; i++) {
  5645. cachedVertArray = vertArray[i];
  5646. if (vertArray[i]["isVert"]) if (vertArray[i]["moveTo"]) curContext.moveTo(cachedVertArray[0], cachedVertArray[1]);
  5647. else curContext.lineTo(cachedVertArray[0], cachedVertArray[1]);
  5648. else curContext.bezierCurveTo(vertArray[i][0], vertArray[i][1], vertArray[i][2], vertArray[i][3], vertArray[i][4], vertArray[i][5])
  5649. }
  5650. fillStrokeClose()
  5651. } else if (curShape === 2) for (i = 0; i < vertArrayLength; i++) {
  5652. cachedVertArray = vertArray[i];
  5653. if (doStroke) p.stroke(cachedVertArray[6]);
  5654. p.point(cachedVertArray[0], cachedVertArray[1])
  5655. } else if (curShape === 4) for (i = 0; i + 1 < vertArrayLength; i += 2) {
  5656. cachedVertArray = vertArray[i];
  5657. if (doStroke) p.stroke(vertArray[i + 1][6]);
  5658. p.line(cachedVertArray[0], cachedVertArray[1], vertArray[i + 1][0], vertArray[i + 1][1])
  5659. } else if (curShape === 9) for (i = 0; i + 2 < vertArrayLength; i += 3) {
  5660. cachedVertArray = vertArray[i];
  5661. curContext.beginPath();
  5662. curContext.moveTo(cachedVertArray[0], cachedVertArray[1]);
  5663. curContext.lineTo(vertArray[i + 1][0], vertArray[i + 1][1]);
  5664. curContext.lineTo(vertArray[i + 2][0], vertArray[i + 2][1]);
  5665. curContext.lineTo(cachedVertArray[0], cachedVertArray[1]);
  5666. if (doFill) {
  5667. p.fill(vertArray[i + 2][5]);
  5668. executeContextFill()
  5669. }
  5670. if (doStroke) {
  5671. p.stroke(vertArray[i + 2][6]);
  5672. executeContextStroke()
  5673. }
  5674. curContext.closePath()
  5675. } else if (curShape === 10) for (i = 0; i + 1 < vertArrayLength; i++) {
  5676. cachedVertArray = vertArray[i];
  5677. curContext.beginPath();
  5678. curContext.moveTo(vertArray[i + 1][0], vertArray[i + 1][1]);
  5679. curContext.lineTo(cachedVertArray[0], cachedVertArray[1]);
  5680. if (doStroke) p.stroke(vertArray[i + 1][6]);
  5681. if (doFill) p.fill(vertArray[i + 1][5]);
  5682. if (i + 2 < vertArrayLength) {
  5683. curContext.lineTo(vertArray[i + 2][0], vertArray[i + 2][1]);
  5684. if (doStroke) p.stroke(vertArray[i + 2][6]);
  5685. if (doFill) p.fill(vertArray[i + 2][5])
  5686. }
  5687. fillStrokeClose()
  5688. } else if (curShape === 11) {
  5689. if (vertArrayLength > 2) {
  5690. curContext.beginPath();
  5691. curContext.moveTo(vertArray[0][0], vertArray[0][1]);
  5692. curContext.lineTo(vertArray[1][0], vertArray[1][1]);
  5693. curContext.lineTo(vertArray[2][0], vertArray[2][1]);
  5694. if (doFill) {
  5695. p.fill(vertArray[2][5]);
  5696. executeContextFill()
  5697. }
  5698. if (doStroke) {
  5699. p.stroke(vertArray[2][6]);
  5700. executeContextStroke()
  5701. }
  5702. curContext.closePath();
  5703. for (i = 3; i < vertArrayLength; i++) {
  5704. cachedVertArray = vertArray[i];
  5705. curContext.beginPath();
  5706. curContext.moveTo(vertArray[0][0], vertArray[0][1]);
  5707. curContext.lineTo(vertArray[i - 1][0], vertArray[i - 1][1]);
  5708. curContext.lineTo(cachedVertArray[0], cachedVertArray[1]);
  5709. if (doFill) {
  5710. p.fill(cachedVertArray[5]);
  5711. executeContextFill()
  5712. }
  5713. if (doStroke) {
  5714. p.stroke(cachedVertArray[6]);
  5715. executeContextStroke()
  5716. }
  5717. curContext.closePath()
  5718. }
  5719. }
  5720. } else if (curShape === 16) for (i = 0; i + 3 < vertArrayLength; i += 4) {
  5721. cachedVertArray = vertArray[i];
  5722. curContext.beginPath();
  5723. curContext.moveTo(cachedVertArray[0], cachedVertArray[1]);
  5724. for (j = 1; j < 4; j++) curContext.lineTo(vertArray[i + j][0], vertArray[i + j][1]);
  5725. curContext.lineTo(cachedVertArray[0], cachedVertArray[1]);
  5726. if (doFill) {
  5727. p.fill(vertArray[i + 3][5]);
  5728. executeContextFill()
  5729. }
  5730. if (doStroke) {
  5731. p.stroke(vertArray[i + 3][6]);
  5732. executeContextStroke()
  5733. }
  5734. curContext.closePath()
  5735. } else if (curShape === 17) {
  5736. if (vertArrayLength > 3) for (i = 0; i + 1 < vertArrayLength; i += 2) {
  5737. cachedVertArray = vertArray[i];
  5738. curContext.beginPath();
  5739. if (i + 3 < vertArrayLength) {
  5740. curContext.moveTo(vertArray[i + 2][0], vertArray[i + 2][1]);
  5741. curContext.lineTo(cachedVertArray[0], cachedVertArray[1]);
  5742. curContext.lineTo(vertArray[i + 1][0], vertArray[i + 1][1]);
  5743. curContext.lineTo(vertArray[i + 3][0], vertArray[i + 3][1]);
  5744. if (doFill) p.fill(vertArray[i + 3][5]);
  5745. if (doStroke) p.stroke(vertArray[i + 3][6])
  5746. } else {
  5747. curContext.moveTo(cachedVertArray[0], cachedVertArray[1]);
  5748. curContext.lineTo(vertArray[i + 1][0], vertArray[i + 1][1])
  5749. }
  5750. fillStrokeClose()
  5751. }
  5752. } else {
  5753. curContext.beginPath();
  5754. curContext.moveTo(vertArray[0][0], vertArray[0][1]);
  5755. for (i = 1; i < vertArrayLength; i++) {
  5756. cachedVertArray = vertArray[i];
  5757. if (cachedVertArray["isVert"]) if (cachedVertArray["moveTo"]) curContext.moveTo(cachedVertArray[0], cachedVertArray[1]);
  5758. else curContext.lineTo(cachedVertArray[0], cachedVertArray[1])
  5759. }
  5760. fillStrokeClose()
  5761. }
  5762. isCurve = false;
  5763. isBezier = false;
  5764. curveVertArray = [];
  5765. curveVertCount = 0;
  5766. if (closeShape) vertArray.pop()
  5767. };
  5768. Drawing3D.prototype.endShape = function(mode) {
  5769. if (vertArray.length === 0) return;
  5770. var closeShape = mode === 2;
  5771. var lineVertArray = [];
  5772. var fillVertArray = [];
  5773. var colorVertArray = [];
  5774. var strokeVertArray = [];
  5775. var texVertArray = [];
  5776. var cachedVertArray;
  5777. firstVert = true;
  5778. var i, j, k;
  5779. var vertArrayLength = vertArray.length;
  5780. for (i = 0; i < vertArrayLength; i++) {
  5781. cachedVertArray = vertArray[i];
  5782. for (j = 0; j < 3; j++) fillVertArray.push(cachedVertArray[j])
  5783. }
  5784. for (i = 0; i < vertArrayLength; i++) {
  5785. cachedVertArray = vertArray[i];
  5786. for (j = 5; j < 9; j++) colorVertArray.push(cachedVertArray[j])
  5787. }
  5788. for (i = 0; i < vertArrayLength; i++) {
  5789. cachedVertArray = vertArray[i];
  5790. for (j = 9; j < 13; j++) strokeVertArray.push(cachedVertArray[j])
  5791. }
  5792. for (i = 0; i < vertArrayLength; i++) {
  5793. cachedVertArray = vertArray[i];
  5794. texVertArray.push(cachedVertArray[3]);
  5795. texVertArray.push(cachedVertArray[4])
  5796. }
  5797. if (closeShape) {
  5798. fillVertArray.push(vertArray[0][0]);
  5799. fillVertArray.push(vertArray[0][1]);
  5800. fillVertArray.push(vertArray[0][2]);
  5801. for (i = 5; i < 9; i++) colorVertArray.push(vertArray[0][i]);
  5802. for (i = 9; i < 13; i++) strokeVertArray.push(vertArray[0][i]);
  5803. texVertArray.push(vertArray[0][3]);
  5804. texVertArray.push(vertArray[0][4])
  5805. }
  5806. if (isCurve && (curShape === 20 || curShape === undef)) {
  5807. lineVertArray = fillVertArray;
  5808. if (doStroke) line3D(lineVertArray, null, strokeVertArray);
  5809. if (doFill) fill3D(fillVertArray, null, colorVertArray)
  5810. } else if (isBezier && (curShape === 20 || curShape === undef)) {
  5811. lineVertArray = fillVertArray;
  5812. lineVertArray.splice(lineVertArray.length - 3);
  5813. strokeVertArray.splice(strokeVertArray.length - 4);
  5814. if (doStroke) line3D(lineVertArray, null, strokeVertArray);
  5815. if (doFill) fill3D(fillVertArray, "TRIANGLES", colorVertArray)
  5816. } else {
  5817. if (curShape === 2) {
  5818. for (i = 0; i < vertArrayLength; i++) {
  5819. cachedVertArray = vertArray[i];
  5820. for (j = 0; j < 3; j++) lineVertArray.push(cachedVertArray[j])
  5821. }
  5822. point3D(lineVertArray, strokeVertArray)
  5823. } else if (curShape === 4) {
  5824. for (i = 0; i < vertArrayLength; i++) {
  5825. cachedVertArray = vertArray[i];
  5826. for (j = 0; j < 3; j++) lineVertArray.push(cachedVertArray[j])
  5827. }
  5828. for (i = 0; i < vertArrayLength; i++) {
  5829. cachedVertArray = vertArray[i];
  5830. for (j = 5; j < 9; j++) colorVertArray.push(cachedVertArray[j])
  5831. }
  5832. line3D(lineVertArray, "LINES", strokeVertArray)
  5833. } else if (curShape === 9) {
  5834. if (vertArrayLength > 2) for (i = 0; i + 2 < vertArrayLength; i += 3) {
  5835. fillVertArray = [];
  5836. texVertArray = [];
  5837. lineVertArray = [];
  5838. colorVertArray = [];
  5839. strokeVertArray = [];
  5840. for (j = 0; j < 3; j++) for (k = 0; k < 3; k++) {
  5841. lineVertArray.push(vertArray[i + j][k]);
  5842. fillVertArray.push(vertArray[i + j][k])
  5843. }
  5844. for (j = 0; j < 3; j++) for (k = 3; k < 5; k++) texVertArray.push(vertArray[i + j][k]);
  5845. for (j = 0; j < 3; j++) for (k = 5; k < 9; k++) {
  5846. colorVertArray.push(vertArray[i + j][k]);
  5847. strokeVertArray.push(vertArray[i + j][k + 4])
  5848. }
  5849. if (doStroke) line3D(lineVertArray, "LINE_LOOP", strokeVertArray);
  5850. if (doFill || usingTexture) fill3D(fillVertArray, "TRIANGLES", colorVertArray, texVertArray)
  5851. }
  5852. } else if (curShape === 10) {
  5853. if (vertArrayLength > 2) for (i = 0; i + 2 < vertArrayLength; i++) {
  5854. lineVertArray = [];
  5855. fillVertArray = [];
  5856. strokeVertArray = [];
  5857. colorVertArray = [];
  5858. texVertArray = [];
  5859. for (j = 0; j < 3; j++) for (k = 0; k < 3; k++) {
  5860. lineVertArray.push(vertArray[i + j][k]);
  5861. fillVertArray.push(vertArray[i + j][k])
  5862. }
  5863. for (j = 0; j < 3; j++) for (k = 3; k < 5; k++) texVertArray.push(vertArray[i + j][k]);
  5864. for (j = 0; j < 3; j++) for (k = 5; k < 9; k++) {
  5865. strokeVertArray.push(vertArray[i + j][k + 4]);
  5866. colorVertArray.push(vertArray[i + j][k])
  5867. }
  5868. if (doFill || usingTexture) fill3D(fillVertArray, "TRIANGLE_STRIP", colorVertArray, texVertArray);
  5869. if (doStroke) line3D(lineVertArray, "LINE_LOOP", strokeVertArray)
  5870. }
  5871. } else if (curShape === 11) {
  5872. if (vertArrayLength > 2) {
  5873. for (i = 0; i < 3; i++) {
  5874. cachedVertArray = vertArray[i];
  5875. for (j = 0; j < 3; j++) lineVertArray.push(cachedVertArray[j])
  5876. }
  5877. for (i = 0; i < 3; i++) {
  5878. cachedVertArray = vertArray[i];
  5879. for (j = 9; j < 13; j++) strokeVertArray.push(cachedVertArray[j])
  5880. }
  5881. if (doStroke) line3D(lineVertArray, "LINE_LOOP", strokeVertArray);
  5882. for (i = 2; i + 1 < vertArrayLength; i++) {
  5883. lineVertArray = [];
  5884. strokeVertArray = [];
  5885. lineVertArray.push(vertArray[0][0]);
  5886. lineVertArray.push(vertArray[0][1]);
  5887. lineVertArray.push(vertArray[0][2]);
  5888. strokeVertArray.push(vertArray[0][9]);
  5889. strokeVertArray.push(vertArray[0][10]);
  5890. strokeVertArray.push(vertArray[0][11]);
  5891. strokeVertArray.push(vertArray[0][12]);
  5892. for (j = 0; j < 2; j++) for (k = 0; k < 3; k++) lineVertArray.push(vertArray[i + j][k]);
  5893. for (j = 0; j < 2; j++) for (k = 9; k < 13; k++) strokeVertArray.push(vertArray[i + j][k]);
  5894. if (doStroke) line3D(lineVertArray, "LINE_STRIP", strokeVertArray)
  5895. }
  5896. if (doFill || usingTexture) fill3D(fillVertArray, "TRIANGLE_FAN", colorVertArray, texVertArray)
  5897. }
  5898. } else if (curShape === 16) for (i = 0; i + 3 < vertArrayLength; i += 4) {
  5899. lineVertArray = [];
  5900. for (j = 0; j < 4; j++) {
  5901. cachedVertArray = vertArray[i + j];
  5902. for (k = 0; k < 3; k++) lineVertArray.push(cachedVertArray[k])
  5903. }
  5904. if (doStroke) line3D(lineVertArray, "LINE_LOOP", strokeVertArray);
  5905. if (doFill) {
  5906. fillVertArray = [];
  5907. colorVertArray = [];
  5908. texVertArray = [];
  5909. for (j = 0; j < 3; j++) fillVertArray.push(vertArray[i][j]);
  5910. for (j = 5; j < 9; j++) colorVertArray.push(vertArray[i][j]);
  5911. for (j = 0; j < 3; j++) fillVertArray.push(vertArray[i + 1][j]);
  5912. for (j = 5; j < 9; j++) colorVertArray.push(vertArray[i + 1][j]);
  5913. for (j = 0; j < 3; j++) fillVertArray.push(vertArray[i + 3][j]);
  5914. for (j = 5; j < 9; j++) colorVertArray.push(vertArray[i + 3][j]);
  5915. for (j = 0; j < 3; j++) fillVertArray.push(vertArray[i + 2][j]);
  5916. for (j = 5; j < 9; j++) colorVertArray.push(vertArray[i + 2][j]);
  5917. if (usingTexture) {
  5918. texVertArray.push(vertArray[i + 0][3]);
  5919. texVertArray.push(vertArray[i + 0][4]);
  5920. texVertArray.push(vertArray[i + 1][3]);
  5921. texVertArray.push(vertArray[i + 1][4]);
  5922. texVertArray.push(vertArray[i + 3][3]);
  5923. texVertArray.push(vertArray[i + 3][4]);
  5924. texVertArray.push(vertArray[i + 2][3]);
  5925. texVertArray.push(vertArray[i + 2][4])
  5926. }
  5927. fill3D(fillVertArray, "TRIANGLE_STRIP", colorVertArray, texVertArray)
  5928. }
  5929. } else if (curShape === 17) {
  5930. var tempArray = [];
  5931. if (vertArrayLength > 3) {
  5932. for (i = 0; i < 2; i++) {
  5933. cachedVertArray = vertArray[i];
  5934. for (j = 0; j < 3; j++) lineVertArray.push(cachedVertArray[j])
  5935. }
  5936. for (i = 0; i < 2; i++) {
  5937. cachedVertArray = vertArray[i];
  5938. for (j = 9; j < 13; j++) strokeVertArray.push(cachedVertArray[j])
  5939. }
  5940. line3D(lineVertArray, "LINE_STRIP", strokeVertArray);
  5941. if (vertArrayLength > 4 && vertArrayLength % 2 > 0) {
  5942. tempArray = fillVertArray.splice(fillVertArray.length - 3);
  5943. vertArray.pop()
  5944. }
  5945. for (i = 0; i + 3 < vertArrayLength; i += 2) {
  5946. lineVertArray = [];
  5947. strokeVertArray = [];
  5948. for (j = 0; j < 3; j++) lineVertArray.push(vertArray[i + 1][j]);
  5949. for (j = 0; j < 3; j++) lineVertArray.push(vertArray[i + 3][j]);
  5950. for (j = 0; j < 3; j++) lineVertArray.push(vertArray[i + 2][j]);
  5951. for (j = 0; j < 3; j++) lineVertArray.push(vertArray[i + 0][j]);
  5952. for (j = 9; j < 13; j++) strokeVertArray.push(vertArray[i + 1][j]);
  5953. for (j = 9; j < 13; j++) strokeVertArray.push(vertArray[i + 3][j]);
  5954. for (j = 9; j < 13; j++) strokeVertArray.push(vertArray[i + 2][j]);
  5955. for (j = 9; j < 13; j++) strokeVertArray.push(vertArray[i + 0][j]);
  5956. if (doStroke) line3D(lineVertArray, "LINE_STRIP", strokeVertArray)
  5957. }
  5958. if (doFill || usingTexture) fill3D(fillVertArray, "TRIANGLE_LIST", colorVertArray, texVertArray)
  5959. }
  5960. } else if (vertArrayLength === 1) {
  5961. for (j = 0; j < 3; j++) lineVertArray.push(vertArray[0][j]);
  5962. for (j = 9; j < 13; j++) strokeVertArray.push(vertArray[0][j]);
  5963. point3D(lineVertArray, strokeVertArray)
  5964. } else {
  5965. for (i = 0; i < vertArrayLength; i++) {
  5966. cachedVertArray = vertArray[i];
  5967. for (j = 0; j < 3; j++) lineVertArray.push(cachedVertArray[j]);
  5968. for (j = 5; j < 9; j++) strokeVertArray.push(cachedVertArray[j])
  5969. }
  5970. if (doStroke && closeShape) line3D(lineVertArray, "LINE_LOOP", strokeVertArray);
  5971. else if (doStroke && !closeShape) line3D(lineVertArray, "LINE_STRIP", strokeVertArray);
  5972. if (doFill || usingTexture) fill3D(fillVertArray, "TRIANGLE_FAN", colorVertArray, texVertArray)
  5973. }
  5974. usingTexture = false;
  5975. curContext.useProgram(programObject3D);
  5976. uniformi("usingTexture3d", programObject3D, "uUsingTexture", usingTexture)
  5977. }
  5978. isCurve = false;
  5979. isBezier = false;
  5980. curveVertArray = [];
  5981. curveVertCount = 0
  5982. };
  5983. var splineForward = function(segments, matrix) {
  5984. var f = 1 / segments;
  5985. var ff = f * f;
  5986. var fff = ff * f;
  5987. matrix.set(0, 0, 0, 1, fff, ff, f, 0, 6 * fff, 2 * ff, 0, 0, 6 * fff, 0, 0, 0)
  5988. };
  5989. var curveInit = function() {
  5990. if (!curveDrawMatrix) {
  5991. curveBasisMatrix = new PMatrix3D;
  5992. curveDrawMatrix = new PMatrix3D;
  5993. curveInited = true
  5994. }
  5995. var s = curTightness;
  5996. 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);
  5997. splineForward(curveDet, curveDrawMatrix);
  5998. if (!bezierBasisInverse) curveToBezierMatrix = new PMatrix3D;
  5999. curveToBezierMatrix.set(curveBasisMatrix);
  6000. curveToBezierMatrix.preApply(bezierBasisInverse);
  6001. curveDrawMatrix.apply(curveBasisMatrix)
  6002. };
  6003. Drawing2D.prototype.bezierVertex = function() {
  6004. isBezier = true;
  6005. var vert = [];
  6006. if (firstVert) throw "vertex() must be used at least once before calling bezierVertex()";
  6007. for (var i = 0; i < arguments.length; i++) vert[i] = arguments[i];
  6008. vertArray.push(vert);
  6009. vertArray[vertArray.length - 1]["isVert"] = false
  6010. };
  6011. Drawing3D.prototype.bezierVertex = function() {
  6012. isBezier = true;
  6013. var vert = [];
  6014. if (firstVert) throw "vertex() must be used at least once before calling bezierVertex()";
  6015. if (arguments.length === 9) {
  6016. if (bezierDrawMatrix === undef) bezierDrawMatrix = new PMatrix3D;
  6017. var lastPoint = vertArray.length - 1;
  6018. splineForward(bezDetail, bezierDrawMatrix);
  6019. bezierDrawMatrix.apply(bezierBasisMatrix);
  6020. var draw = bezierDrawMatrix.array();
  6021. var x1 = vertArray[lastPoint][0],
  6022. y1 = vertArray[lastPoint][1],
  6023. z1 = vertArray[lastPoint][2];
  6024. var xplot1 = draw[4] * x1 + draw[5] * arguments[0] + draw[6] * arguments[3] + draw[7] * arguments[6];
  6025. var xplot2 = draw[8] * x1 + draw[9] * arguments[0] + draw[10] * arguments[3] + draw[11] * arguments[6];
  6026. var xplot3 = draw[12] * x1 + draw[13] * arguments[0] + draw[14] * arguments[3] + draw[15] * arguments[6];
  6027. var yplot1 = draw[4] * y1 + draw[5] * arguments[1] + draw[6] * arguments[4] + draw[7] * arguments[7];
  6028. var yplot2 = draw[8] * y1 + draw[9] * arguments[1] + draw[10] * arguments[4] + draw[11] * arguments[7];
  6029. var yplot3 = draw[12] * y1 + draw[13] * arguments[1] + draw[14] * arguments[4] + draw[15] * arguments[7];
  6030. var zplot1 = draw[4] * z1 + draw[5] * arguments[2] + draw[6] * arguments[5] + draw[7] * arguments[8];
  6031. var zplot2 = draw[8] * z1 + draw[9] * arguments[2] + draw[10] * arguments[5] + draw[11] * arguments[8];
  6032. var zplot3 = draw[12] * z1 + draw[13] * arguments[2] + draw[14] * arguments[5] + draw[15] * arguments[8];
  6033. for (var j = 0; j < bezDetail; j++) {
  6034. x1 += xplot1;
  6035. xplot1 += xplot2;
  6036. xplot2 += xplot3;
  6037. y1 += yplot1;
  6038. yplot1 += yplot2;
  6039. yplot2 += yplot3;
  6040. z1 += zplot1;
  6041. zplot1 += zplot2;
  6042. zplot2 += zplot3;
  6043. p.vertex(x1, y1, z1)
  6044. }
  6045. p.vertex(arguments[6], arguments[7], arguments[8])
  6046. }
  6047. };
  6048. p.texture = function(pimage) {
  6049. var curContext = drawing.$ensureContext();
  6050. if (pimage.__texture) curContext.bindTexture(curContext.TEXTURE_2D, pimage.__texture);
  6051. else if (pimage.localName === "canvas") {
  6052. curContext.bindTexture(curContext.TEXTURE_2D, canTex);
  6053. curContext.texImage2D(curContext.TEXTURE_2D, 0, curContext.RGBA, curContext.RGBA, curContext.UNSIGNED_BYTE, pimage);
  6054. curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_MAG_FILTER, curContext.LINEAR);
  6055. curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_MIN_FILTER, curContext.LINEAR);
  6056. curContext.generateMipmap(curContext.TEXTURE_2D);
  6057. curTexture.width = pimage.width;
  6058. curTexture.height = pimage.height
  6059. } else {
  6060. var texture = curContext.createTexture(),
  6061. cvs = document.createElement("canvas"),
  6062. cvsTextureCtx = cvs.getContext("2d"),
  6063. pot;
  6064. if (pimage.width & pimage.width - 1 === 0) cvs.width = pimage.width;
  6065. else {
  6066. pot = 1;
  6067. while (pot < pimage.width) pot *= 2;
  6068. cvs.width = pot
  6069. }
  6070. if (pimage.height & pimage.height - 1 === 0) cvs.height = pimage.height;
  6071. else {
  6072. pot = 1;
  6073. while (pot < pimage.height) pot *= 2;
  6074. cvs.height = pot
  6075. }
  6076. cvsTextureCtx.drawImage(pimage.sourceImg, 0, 0, pimage.width, pimage.height, 0, 0, cvs.width, cvs.height);
  6077. curContext.bindTexture(curContext.TEXTURE_2D, texture);
  6078. curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_MIN_FILTER, curContext.LINEAR_MIPMAP_LINEAR);
  6079. curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_MAG_FILTER, curContext.LINEAR);
  6080. curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_WRAP_T, curContext.CLAMP_TO_EDGE);
  6081. curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_WRAP_S, curContext.CLAMP_TO_EDGE);
  6082. curContext.texImage2D(curContext.TEXTURE_2D, 0, curContext.RGBA, curContext.RGBA, curContext.UNSIGNED_BYTE, cvs);
  6083. curContext.generateMipmap(curContext.TEXTURE_2D);
  6084. pimage.__texture = texture;
  6085. curTexture.width = pimage.width;
  6086. curTexture.height = pimage.height
  6087. }
  6088. usingTexture = true;
  6089. curContext.useProgram(programObject3D);
  6090. uniformi("usingTexture3d", programObject3D, "uUsingTexture", usingTexture)
  6091. };
  6092. p.textureMode = function(mode) {
  6093. curTextureMode = mode
  6094. };
  6095. var curveVertexSegment = function(x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4) {
  6096. var x0 = x2;
  6097. var y0 = y2;
  6098. var z0 = z2;
  6099. var draw = curveDrawMatrix.array();
  6100. var xplot1 = draw[4] * x1 + draw[5] * x2 + draw[6] * x3 + draw[7] * x4;
  6101. var xplot2 = draw[8] * x1 + draw[9] * x2 + draw[10] * x3 + draw[11] * x4;
  6102. var xplot3 = draw[12] * x1 + draw[13] * x2 + draw[14] * x3 + draw[15] * x4;
  6103. var yplot1 = draw[4] * y1 + draw[5] * y2 + draw[6] * y3 + draw[7] * y4;
  6104. var yplot2 = draw[8] * y1 + draw[9] * y2 + draw[10] * y3 + draw[11] * y4;
  6105. var yplot3 = draw[12] * y1 + draw[13] * y2 + draw[14] * y3 + draw[15] * y4;
  6106. var zplot1 = draw[4] * z1 + draw[5] * z2 + draw[6] * z3 + draw[7] * z4;
  6107. var zplot2 = draw[8] * z1 + draw[9] * z2 + draw[10] * z3 + draw[11] * z4;
  6108. var zplot3 = draw[12] * z1 + draw[13] * z2 + draw[14] * z3 + draw[15] * z4;
  6109. p.vertex(x0, y0, z0);
  6110. for (var j = 0; j < curveDet; j++) {
  6111. x0 += xplot1;
  6112. xplot1 += xplot2;
  6113. xplot2 += xplot3;
  6114. y0 += yplot1;
  6115. yplot1 += yplot2;
  6116. yplot2 += yplot3;
  6117. z0 += zplot1;
  6118. zplot1 += zplot2;
  6119. zplot2 += zplot3;
  6120. p.vertex(x0, y0, z0)
  6121. }
  6122. };
  6123. Drawing2D.prototype.curveVertex = function(x, y) {
  6124. isCurve = true;
  6125. p.vertex(x, y)
  6126. };
  6127. Drawing3D.prototype.curveVertex = function(x, y, z) {
  6128. isCurve = true;
  6129. if (!curveInited) curveInit();
  6130. var vert = [];
  6131. vert[0] = x;
  6132. vert[1] = y;
  6133. vert[2] = z;
  6134. curveVertArray.push(vert);
  6135. curveVertCount++;
  6136. 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])
  6137. };
  6138. Drawing2D.prototype.curve = function(x1, y1, x2, y2, x3, y3, x4, y4) {
  6139. p.beginShape();
  6140. p.curveVertex(x1, y1);
  6141. p.curveVertex(x2, y2);
  6142. p.curveVertex(x3, y3);
  6143. p.curveVertex(x4, y4);
  6144. p.endShape()
  6145. };
  6146. Drawing3D.prototype.curve = function(x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4) {
  6147. if (z4 !== undef) {
  6148. p.beginShape();
  6149. p.curveVertex(x1, y1, z1);
  6150. p.curveVertex(x2, y2, z2);
  6151. p.curveVertex(x3, y3, z3);
  6152. p.curveVertex(x4, y4, z4);
  6153. p.endShape();
  6154. return
  6155. }
  6156. p.beginShape();
  6157. p.curveVertex(x1, y1);
  6158. p.curveVertex(z1, x2);
  6159. p.curveVertex(y2, z2);
  6160. p.curveVertex(x3, y3);
  6161. p.endShape()
  6162. };
  6163. p.curveTightness = function(tightness) {
  6164. curTightness = tightness
  6165. };
  6166. p.curveDetail = function(detail) {
  6167. curveDet = detail;
  6168. curveInit()
  6169. };
  6170. p.rectMode = function(aRectMode) {
  6171. curRectMode = aRectMode
  6172. };
  6173. p.imageMode = function(mode) {
  6174. switch (mode) {
  6175. case 0:
  6176. imageModeConvert = imageModeCorner;
  6177. break;
  6178. case 1:
  6179. imageModeConvert = imageModeCorners;
  6180. break;
  6181. case 3:
  6182. imageModeConvert = imageModeCenter;
  6183. break;
  6184. default:
  6185. throw "Invalid imageMode";
  6186. }
  6187. };
  6188. p.ellipseMode = function(aEllipseMode) {
  6189. curEllipseMode = aEllipseMode
  6190. };
  6191. p.arc = function(x, y, width, height, start, stop) {
  6192. if (width <= 0 || stop < start) return;
  6193. if (curEllipseMode === 1) {
  6194. width = width - x;
  6195. height = height - y
  6196. } else if (curEllipseMode === 2) {
  6197. x = x - width;
  6198. y = y - height;
  6199. width = width * 2;
  6200. height = height * 2
  6201. } else if (curEllipseMode === 3) {
  6202. x = x - width / 2;
  6203. y = y - height / 2
  6204. }
  6205. while (start < 0) {
  6206. start += 6.283185307179586;
  6207. stop += 6.283185307179586
  6208. }
  6209. if (stop - start > 6.283185307179586) {
  6210. start = 0;
  6211. stop = 6.283185307179586
  6212. }
  6213. var hr = width / 2,
  6214. vr = height / 2,
  6215. centerX = x + hr,
  6216. centerY = y + vr,
  6217. startLUT = 0 | 0.5 + start * p.RAD_TO_DEG * 2,
  6218. stopLUT = 0 | 0.5 + stop * p.RAD_TO_DEG * 2,
  6219. i, j;
  6220. if (doFill) {
  6221. var savedStroke = doStroke;
  6222. doStroke = false;
  6223. p.beginShape();
  6224. p.vertex(centerX, centerY);
  6225. for (i = startLUT; i <= stopLUT; i++) {
  6226. j = i % 720;
  6227. p.vertex(centerX + cosLUT[j] * hr, centerY + sinLUT[j] * vr)
  6228. }
  6229. p.endShape(2);
  6230. doStroke = savedStroke
  6231. }
  6232. if (doStroke) {
  6233. var savedFill = doFill;
  6234. doFill = false;
  6235. p.beginShape();
  6236. for (i = startLUT; i <= stopLUT; i++) {
  6237. j = i % 720;
  6238. p.vertex(centerX + cosLUT[j] * hr, centerY + sinLUT[j] * vr)
  6239. }
  6240. p.endShape();
  6241. doFill = savedFill
  6242. }
  6243. };
  6244. Drawing2D.prototype.line = function(x1, y1, x2, y2) {
  6245. if (!doStroke) return;
  6246. x1 = Math.round(x1);
  6247. x2 = Math.round(x2);
  6248. y1 = Math.round(y1);
  6249. y2 = Math.round(y2);
  6250. if (x1 === x2 && y1 === y2) {
  6251. p.point(x1, y1);
  6252. return
  6253. }
  6254. var swap = undef,
  6255. lineCap = undef,
  6256. drawCrisp = true,
  6257. currentModelView = modelView.array(),
  6258. identityMatrix = [1, 0, 0, 0, 1, 0];
  6259. for (var i = 0; i < 6 && drawCrisp; i++) drawCrisp = currentModelView[i] === identityMatrix[i];
  6260. if (drawCrisp) {
  6261. if (x1 === x2) {
  6262. if (y1 > y2) {
  6263. swap = y1;
  6264. y1 = y2;
  6265. y2 = swap
  6266. }
  6267. y2++;
  6268. if (lineWidth % 2 === 1) curContext.translate(0.5, 0)
  6269. } else if (y1 === y2) {
  6270. if (x1 > x2) {
  6271. swap = x1;
  6272. x1 = x2;
  6273. x2 = swap
  6274. }
  6275. x2++;
  6276. if (lineWidth % 2 === 1) curContext.translate(0, 0.5)
  6277. }
  6278. if (lineWidth === 1) {
  6279. lineCap = curContext.lineCap;
  6280. curContext.lineCap = "butt"
  6281. }
  6282. }
  6283. curContext.beginPath();
  6284. curContext.moveTo(x1 || 0, y1 || 0);
  6285. curContext.lineTo(x2 || 0, y2 || 0);
  6286. executeContextStroke();
  6287. if (drawCrisp) {
  6288. if (x1 === x2 && lineWidth % 2 === 1) curContext.translate(-0.5, 0);
  6289. else if (y1 === y2 && lineWidth % 2 === 1) curContext.translate(0, -0.5);
  6290. if (lineWidth === 1) curContext.lineCap = lineCap
  6291. }
  6292. };
  6293. Drawing3D.prototype.line = function(x1, y1, z1, x2, y2, z2) {
  6294. if (y2 === undef || z2 === undef) {
  6295. z2 = 0;
  6296. y2 = x2;
  6297. x2 = z1;
  6298. z1 = 0
  6299. }
  6300. if (x1 === x2 && y1 === y2 && z1 === z2) {
  6301. p.point(x1, y1, z1);
  6302. return
  6303. }
  6304. var lineVerts = [x1, y1, z1, x2, y2, z2];
  6305. var view = new PMatrix3D;
  6306. view.scale(1, -1, 1);
  6307. view.apply(modelView.array());
  6308. view.transpose();
  6309. if (lineWidth > 0 && doStroke) {
  6310. curContext.useProgram(programObject2D);
  6311. uniformMatrix("uModel2d", programObject2D, "uModel", false, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
  6312. uniformMatrix("uView2d", programObject2D, "uView", false, view.array());
  6313. uniformf("uColor2d", programObject2D, "uColor", strokeStyle);
  6314. uniformi("uIsDrawingText", programObject2D, "uIsDrawingText", false);
  6315. vertexAttribPointer("aVertex2d", programObject2D, "aVertex", 3, lineBuffer);
  6316. disableVertexAttribPointer("aTextureCoord2d", programObject2D, "aTextureCoord");
  6317. curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(lineVerts), curContext.STREAM_DRAW);
  6318. curContext.drawArrays(curContext.LINES, 0, 2)
  6319. }
  6320. };
  6321. Drawing2D.prototype.bezier = function() {
  6322. if (arguments.length !== 8) throw "You must use 8 parameters for bezier() in 2D mode";
  6323. p.beginShape();
  6324. p.vertex(arguments[0], arguments[1]);
  6325. p.bezierVertex(arguments[2], arguments[3], arguments[4], arguments[5], arguments[6], arguments[7]);
  6326. p.endShape()
  6327. };
  6328. Drawing3D.prototype.bezier = function() {
  6329. if (arguments.length !== 12) throw "You must use 12 parameters for bezier() in 3D mode";
  6330. p.beginShape();
  6331. p.vertex(arguments[0], arguments[1], arguments[2]);
  6332. p.bezierVertex(arguments[3], arguments[4], arguments[5], arguments[6], arguments[7], arguments[8], arguments[9], arguments[10], arguments[11]);
  6333. p.endShape()
  6334. };
  6335. p.bezierDetail = function(detail) {
  6336. bezDetail = detail
  6337. };
  6338. p.bezierPoint = function(a, b, c, d, t) {
  6339. 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
  6340. };
  6341. p.bezierTangent = function(a, b, c, d, t) {
  6342. return 3 * t * t * (-a + 3 * b - 3 * c + d) + 6 * t * (a - 2 * b + c) + 3 * (-a + b)
  6343. };
  6344. p.curvePoint = function(a, b, c, d, t) {
  6345. 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)
  6346. };
  6347. p.curveTangent = function(a, b, c, d, t) {
  6348. return 0.5 * (-a + c + 2 * (2 * a - 5 * b + 4 * c - d) * t + 3 * (-a + 3 * b - 3 * c + d) * t * t)
  6349. };
  6350. p.triangle = function(x1, y1, x2, y2, x3, y3) {
  6351. p.beginShape(9);
  6352. p.vertex(x1, y1, 0);
  6353. p.vertex(x2, y2, 0);
  6354. p.vertex(x3, y3, 0);
  6355. p.endShape()
  6356. };
  6357. p.quad = function(x1, y1, x2, y2, x3, y3, x4, y4) {
  6358. p.beginShape(16);
  6359. p.vertex(x1, y1, 0);
  6360. p.vertex(x2, y2, 0);
  6361. p.vertex(x3, y3, 0);
  6362. p.vertex(x4, y4, 0);
  6363. p.endShape()
  6364. };
  6365. var roundedRect$2d = function(x, y, width, height, tl, tr, br, bl) {
  6366. if (bl === undef) {
  6367. tr = tl;
  6368. br = tl;
  6369. bl = tl
  6370. }
  6371. var halfWidth = width / 2,
  6372. halfHeight = height / 2;
  6373. if (tl > halfWidth || tl > halfHeight) tl = Math.min(halfWidth, halfHeight);
  6374. if (tr > halfWidth || tr > halfHeight) tr = Math.min(halfWidth, halfHeight);
  6375. if (br > halfWidth || br > halfHeight) br = Math.min(halfWidth, halfHeight);
  6376. if (bl > halfWidth || bl > halfHeight) bl = Math.min(halfWidth, halfHeight);
  6377. if (!doFill || doStroke) curContext.translate(0.5, 0.5);
  6378. curContext.beginPath();
  6379. curContext.moveTo(x + tl, y);
  6380. curContext.lineTo(x + width - tr, y);
  6381. curContext.quadraticCurveTo(x + width, y, x + width, y + tr);
  6382. curContext.lineTo(x + width, y + height - br);
  6383. curContext.quadraticCurveTo(x + width, y + height, x + width - br, y + height);
  6384. curContext.lineTo(x + bl, y + height);
  6385. curContext.quadraticCurveTo(x, y + height, x, y + height - bl);
  6386. curContext.lineTo(x, y + tl);
  6387. curContext.quadraticCurveTo(x, y, x + tl, y);
  6388. if (!doFill || doStroke) curContext.translate(-0.5, -0.5);
  6389. executeContextFill();
  6390. executeContextStroke()
  6391. };
  6392. Drawing2D.prototype.rect = function(x, y, width, height, tl, tr, br, bl) {
  6393. if (!width && !height) return;
  6394. if (curRectMode === 1) {
  6395. width -= x;
  6396. height -= y
  6397. } else if (curRectMode === 2) {
  6398. width *= 2;
  6399. height *= 2;
  6400. x -= width / 2;
  6401. y -= height / 2
  6402. } else if (curRectMode === 3) {
  6403. x -= width / 2;
  6404. y -= height / 2
  6405. }
  6406. x = Math.round(x);
  6407. y = Math.round(y);
  6408. width = Math.round(width);
  6409. height = Math.round(height);
  6410. if (tl !== undef) {
  6411. roundedRect$2d(x, y, width, height, tl, tr, br, bl);
  6412. return
  6413. }
  6414. if (doStroke && lineWidth % 2 === 1) curContext.translate(0.5, 0.5);
  6415. curContext.beginPath();
  6416. curContext.rect(x, y, width, height);
  6417. executeContextFill();
  6418. executeContextStroke();
  6419. if (doStroke && lineWidth % 2 === 1) curContext.translate(-0.5, -0.5)
  6420. };
  6421. Drawing3D.prototype.rect = function(x, y, width, height, tl, tr, br, bl) {
  6422. if (tl !== undef) throw "rect() with rounded corners is not supported in 3D mode";
  6423. if (curRectMode === 1) {
  6424. width -= x;
  6425. height -= y
  6426. } else if (curRectMode === 2) {
  6427. width *= 2;
  6428. height *= 2;
  6429. x -= width / 2;
  6430. y -= height / 2
  6431. } else if (curRectMode === 3) {
  6432. x -= width / 2;
  6433. y -= height / 2
  6434. }
  6435. var model = new PMatrix3D;
  6436. model.translate(x, y, 0);
  6437. model.scale(width, height, 1);
  6438. model.transpose();
  6439. var view = new PMatrix3D;
  6440. view.scale(1, -1, 1);
  6441. view.apply(modelView.array());
  6442. view.transpose();
  6443. if (lineWidth > 0 && doStroke) {
  6444. curContext.useProgram(programObject2D);
  6445. uniformMatrix("uModel2d", programObject2D, "uModel", false, model.array());
  6446. uniformMatrix("uView2d", programObject2D, "uView", false, view.array());
  6447. uniformf("uColor2d", programObject2D, "uColor", strokeStyle);
  6448. uniformi("uIsDrawingText2d", programObject2D, "uIsDrawingText", false);
  6449. vertexAttribPointer("aVertex2d", programObject2D, "aVertex", 3, rectBuffer);
  6450. disableVertexAttribPointer("aTextureCoord2d", programObject2D, "aTextureCoord");
  6451. curContext.drawArrays(curContext.LINE_LOOP, 0, rectVerts.length / 3)
  6452. }
  6453. if (doFill) {
  6454. curContext.useProgram(programObject3D);
  6455. uniformMatrix("uModel3d", programObject3D, "uModel", false, model.array());
  6456. uniformMatrix("uView3d", programObject3D, "uView", false, view.array());
  6457. curContext.enable(curContext.POLYGON_OFFSET_FILL);
  6458. curContext.polygonOffset(1, 1);
  6459. uniformf("color3d", programObject3D, "uColor", fillStyle);
  6460. if (lightCount > 0) {
  6461. var v = new PMatrix3D;
  6462. v.set(view);
  6463. var m = new PMatrix3D;
  6464. m.set(model);
  6465. v.mult(m);
  6466. var normalMatrix = new PMatrix3D;
  6467. normalMatrix.set(v);
  6468. normalMatrix.invert();
  6469. normalMatrix.transpose();
  6470. uniformMatrix("uNormalTransform3d", programObject3D, "uNormalTransform", false, normalMatrix.array());
  6471. vertexAttribPointer("aNormal3d", programObject3D, "aNormal", 3, rectNormBuffer)
  6472. } else disableVertexAttribPointer("normal3d", programObject3D, "aNormal");
  6473. vertexAttribPointer("vertex3d", programObject3D, "aVertex", 3, rectBuffer);
  6474. curContext.drawArrays(curContext.TRIANGLE_FAN, 0, rectVerts.length / 3);
  6475. curContext.disable(curContext.POLYGON_OFFSET_FILL)
  6476. }
  6477. };
  6478. Drawing2D.prototype.ellipse = function(x, y, width, height) {
  6479. x = x || 0;
  6480. y = y || 0;
  6481. if (width <= 0 && height <= 0) return;
  6482. if (curEllipseMode === 2) {
  6483. width *= 2;
  6484. height *= 2
  6485. } else if (curEllipseMode === 1) {
  6486. width = width - x;
  6487. height = height - y;
  6488. x += width / 2;
  6489. y += height / 2
  6490. } else if (curEllipseMode === 0) {
  6491. x += width / 2;
  6492. y += height / 2
  6493. }
  6494. if (width === height) {
  6495. curContext.beginPath();
  6496. curContext.arc(x, y, width / 2, 0, 6.283185307179586, false);
  6497. executeContextFill();
  6498. executeContextStroke()
  6499. } else {
  6500. var w = width / 2,
  6501. h = height / 2,
  6502. C = 0.5522847498307933,
  6503. c_x = C * w,
  6504. c_y = C * h;
  6505. p.beginShape();
  6506. p.vertex(x + w, y);
  6507. p.bezierVertex(x + w, y - c_y, x + c_x, y - h, x, y - h);
  6508. p.bezierVertex(x - c_x, y - h, x - w, y - c_y, x - w, y);
  6509. p.bezierVertex(x - w, y + c_y, x - c_x, y + h, x, y + h);
  6510. p.bezierVertex(x + c_x, y + h, x + w, y + c_y, x + w, y);
  6511. p.endShape()
  6512. }
  6513. };
  6514. Drawing3D.prototype.ellipse = function(x, y, width, height) {
  6515. x = x || 0;
  6516. y = y || 0;
  6517. if (width <= 0 && height <= 0) return;
  6518. if (curEllipseMode === 2) {
  6519. width *= 2;
  6520. height *= 2
  6521. } else if (curEllipseMode === 1) {
  6522. width = width - x;
  6523. height = height - y;
  6524. x += width / 2;
  6525. y += height / 2
  6526. } else if (curEllipseMode === 0) {
  6527. x += width / 2;
  6528. y += height / 2
  6529. }
  6530. var w = width / 2,
  6531. h = height / 2,
  6532. C = 0.5522847498307933,
  6533. c_x = C * w,
  6534. c_y = C * h;
  6535. p.beginShape();
  6536. p.vertex(x + w, y);
  6537. p.bezierVertex(x + w, y - c_y, 0, x + c_x, y - h, 0, x, y - h, 0);
  6538. p.bezierVertex(x - c_x, y - h, 0, x - w, y - c_y, 0, x - w, y, 0);
  6539. p.bezierVertex(x - w, y + c_y, 0, x - c_x, y + h, 0, x, y + h, 0);
  6540. p.bezierVertex(x + c_x, y + h, 0, x + w, y + c_y, 0, x + w, y, 0);
  6541. p.endShape();
  6542. if (doFill) {
  6543. var xAv = 0,
  6544. yAv = 0,
  6545. i, j;
  6546. for (i = 0; i < vertArray.length; i++) {
  6547. xAv += vertArray[i][0];
  6548. yAv += vertArray[i][1]
  6549. }
  6550. xAv /= vertArray.length;
  6551. yAv /= vertArray.length;
  6552. var vert = [],
  6553. fillVertArray = [],
  6554. colorVertArray = [];
  6555. vert[0] = xAv;
  6556. vert[1] = yAv;
  6557. vert[2] = 0;
  6558. vert[3] = 0;
  6559. vert[4] = 0;
  6560. vert[5] = fillStyle[0];
  6561. vert[6] = fillStyle[1];
  6562. vert[7] = fillStyle[2];
  6563. vert[8] = fillStyle[3];
  6564. vert[9] = strokeStyle[0];
  6565. vert[10] = strokeStyle[1];
  6566. vert[11] = strokeStyle[2];
  6567. vert[12] = strokeStyle[3];
  6568. vert[13] = normalX;
  6569. vert[14] = normalY;
  6570. vert[15] = normalZ;
  6571. vertArray.unshift(vert);
  6572. for (i = 0; i < vertArray.length; i++) {
  6573. for (j = 0; j < 3; j++) fillVertArray.push(vertArray[i][j]);
  6574. for (j = 5; j < 9; j++) colorVertArray.push(vertArray[i][j])
  6575. }
  6576. fill3D(fillVertArray, "TRIANGLE_FAN", colorVertArray)
  6577. }
  6578. };
  6579. p.normal = function(nx, ny, nz) {
  6580. if (arguments.length !== 3 || !(typeof nx === "number" && typeof ny === "number" && typeof nz === "number")) throw "normal() requires three numeric arguments.";
  6581. normalX = nx;
  6582. normalY = ny;
  6583. normalZ = nz;
  6584. if (curShape !== 0) if (normalMode === 0) normalMode = 1;
  6585. else if (normalMode === 1) normalMode = 2
  6586. };
  6587. p.save = function(file, img) {
  6588. if (img !== undef) return window.open(img.toDataURL(), "_blank");
  6589. return window.open(p.externals.canvas.toDataURL(), "_blank")
  6590. };
  6591. var saveNumber = 0;
  6592. p.saveFrame = function(file) {
  6593. if (file === undef) file = "screen-####.png";
  6594. var frameFilename = file.replace(/#+/, function(all) {
  6595. var s = "" + saveNumber++;
  6596. while (s.length < all.length) s = "0" + s;
  6597. return s
  6598. });
  6599. p.save(frameFilename)
  6600. };
  6601. var utilityContext2d = document.createElement("canvas").getContext("2d");
  6602. var canvasDataCache = [undef, undef, undef];
  6603. function getCanvasData(obj, w, h) {
  6604. var canvasData = canvasDataCache.shift();
  6605. if (canvasData === undef) {
  6606. canvasData = {};
  6607. canvasData.canvas = document.createElement("canvas");
  6608. canvasData.context = canvasData.canvas.getContext("2d")
  6609. }
  6610. canvasDataCache.push(canvasData);
  6611. var canvas = canvasData.canvas,
  6612. context = canvasData.context,
  6613. width = w || obj.width,
  6614. height = h || obj.height;
  6615. canvas.width = width;
  6616. canvas.height = height;
  6617. if (!obj) context.clearRect(0, 0, width, height);
  6618. else if ("data" in obj) context.putImageData(obj, 0, 0);
  6619. else {
  6620. context.clearRect(0, 0, width, height);
  6621. context.drawImage(obj, 0, 0, width, height)
  6622. }
  6623. return canvasData
  6624. }
  6625. function buildPixelsObject(pImage) {
  6626. return {
  6627. getLength: function(aImg) {
  6628. return function() {
  6629. if (aImg.isRemote) throw "Image is loaded remotely. Cannot get length.";
  6630. else return aImg.imageData.data.length ? aImg.imageData.data.length / 4 : 0
  6631. }
  6632. }(pImage),
  6633. getPixel: function(aImg) {
  6634. return function(i) {
  6635. var offset = i * 4,
  6636. data = aImg.imageData.data;
  6637. if (aImg.isRemote) throw "Image is loaded remotely. Cannot get pixels.";
  6638. return (data[offset + 3] & 255) << 24 | (data[offset] & 255) << 16 | (data[offset + 1] & 255) << 8 | data[offset + 2] & 255
  6639. }
  6640. }(pImage),
  6641. setPixel: function(aImg) {
  6642. return function(i, c) {
  6643. var offset = i * 4,
  6644. data = aImg.imageData.data;
  6645. if (aImg.isRemote) throw "Image is loaded remotely. Cannot set pixel.";
  6646. data[offset + 0] = (c >> 16) & 255;
  6647. data[offset + 1] = (c >> 8) & 255;
  6648. data[offset + 2] = c & 255;
  6649. data[offset + 3] = (c >> 24) & 255;
  6650. aImg.__isDirty = true
  6651. }
  6652. }(pImage),
  6653. toArray: function(aImg) {
  6654. return function() {
  6655. var arr = [],
  6656. data = aImg.imageData.data,
  6657. length = aImg.width * aImg.height;
  6658. if (aImg.isRemote) throw "Image is loaded remotely. Cannot get pixels.";
  6659. 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);
  6660. return arr
  6661. }
  6662. }(pImage),
  6663. set: function(aImg) {
  6664. return function(arr) {
  6665. var offset, data, c;
  6666. if (this.isRemote) throw "Image is loaded remotely. Cannot set pixels.";
  6667. data = aImg.imageData.data;
  6668. for (var i = 0, aL = arr.length; i < aL; i++) {
  6669. c = arr[i];
  6670. offset = i * 4;
  6671. data[offset + 0] = (c >> 16) & 255;
  6672. data[offset + 1] = (c >> 8) & 255;
  6673. data[offset + 2] = c & 255;
  6674. data[offset + 3] = (c >> 24) & 255
  6675. }
  6676. aImg.__isDirty = true
  6677. }
  6678. }(pImage)
  6679. }
  6680. }
  6681. var PImage = function(aWidth, aHeight, aFormat) {
  6682. this.__isDirty = false;
  6683. if (aWidth instanceof HTMLImageElement) this.fromHTMLImageData(aWidth);
  6684. else if (aHeight || aFormat) {
  6685. this.width = aWidth || 1;
  6686. this.height = aHeight || 1;
  6687. var canvas = this.sourceImg = document.createElement("canvas");
  6688. canvas.width = this.width;
  6689. canvas.height = this.height;
  6690. var imageData = this.imageData = canvas.getContext("2d").createImageData(this.width, this.height);
  6691. this.format = aFormat === 2 || aFormat === 4 ? aFormat : 1;
  6692. if (this.format === 1) for (var i = 3, data = this.imageData.data, len = data.length; i < len; i += 4) data[i] = 255;
  6693. this.__isDirty = true;
  6694. this.updatePixels()
  6695. } else {
  6696. this.width = 0;
  6697. this.height = 0;
  6698. this.imageData = utilityContext2d.createImageData(1, 1);
  6699. this.format = 2
  6700. }
  6701. this.pixels = buildPixelsObject(this)
  6702. };
  6703. PImage.prototype = {
  6704. __isPImage: true,
  6705. updatePixels: function() {
  6706. var canvas = this.sourceImg;
  6707. if (canvas && canvas instanceof HTMLCanvasElement && this.__isDirty) canvas.getContext("2d").putImageData(this.imageData, 0, 0);
  6708. this.__isDirty = false
  6709. },
  6710. fromHTMLImageData: function(htmlImg) {
  6711. var canvasData = getCanvasData(htmlImg);
  6712. try {
  6713. var imageData = canvasData.context.getImageData(0, 0, htmlImg.width, htmlImg.height);
  6714. this.fromImageData(imageData)
  6715. } catch(e) {
  6716. if (htmlImg.width && htmlImg.height) {
  6717. this.isRemote = true;
  6718. this.width = htmlImg.width;
  6719. this.height = htmlImg.height
  6720. }
  6721. }
  6722. this.sourceImg = htmlImg
  6723. },
  6724. "get": function(x, y, w, h) {
  6725. if (!arguments.length) return p.get(this);
  6726. if (arguments.length === 2) return p.get(x, y, this);
  6727. if (arguments.length === 4) return p.get(x, y, w, h, this)
  6728. },
  6729. "set": function(x, y, c) {
  6730. p.set(x, y, c, this);
  6731. this.__isDirty = true
  6732. },
  6733. blend: function(srcImg, x, y, width, height, dx, dy, dwidth, dheight, MODE) {
  6734. if (arguments.length === 9) p.blend(this, srcImg, x, y, width, height, dx, dy, dwidth, dheight, this);
  6735. else if (arguments.length === 10) p.blend(srcImg, x, y, width, height, dx, dy, dwidth, dheight, MODE, this);
  6736. delete this.sourceImg
  6737. },
  6738. copy: function(srcImg, sx, sy, swidth, sheight, dx, dy, dwidth, dheight) {
  6739. if (arguments.length === 8) p.blend(this, srcImg, sx, sy, swidth, sheight, dx, dy, dwidth, 0, this);
  6740. else if (arguments.length === 9) p.blend(srcImg, sx, sy, swidth, sheight, dx, dy, dwidth, dheight, 0, this);
  6741. delete this.sourceImg
  6742. },
  6743. filter: function(mode, param) {
  6744. if (arguments.length === 2) p.filter(mode, param, this);
  6745. else if (arguments.length === 1) p.filter(mode, null, this);
  6746. delete this.sourceImg
  6747. },
  6748. save: function(file) {
  6749. p.save(file, this)
  6750. },
  6751. resize: function(w, h) {
  6752. if (this.isRemote) throw "Image is loaded remotely. Cannot resize.";
  6753. if (this.width !== 0 || this.height !== 0) {
  6754. if (w === 0 && h !== 0) w = Math.floor(this.width / this.height * h);
  6755. else if (h === 0 && w !== 0) h = Math.floor(this.height / this.width * w);
  6756. var canvas = getCanvasData(this.imageData).canvas;
  6757. var imageData = getCanvasData(canvas, w, h).context.getImageData(0, 0, w, h);
  6758. this.fromImageData(imageData)
  6759. }
  6760. },
  6761. mask: function(mask) {
  6762. var obj = this.toImageData(),
  6763. i, size;
  6764. if (mask instanceof PImage || mask.__isPImage) if (mask.width === this.width && mask.height === this.height) {
  6765. mask = mask.toImageData();
  6766. for (i = 2, size = this.width * this.height * 4; i < size; i += 4) obj.data[i + 1] = mask.data[i]
  6767. } else throw "mask must have the same dimensions as PImage.";
  6768. else if (mask instanceof
  6769. Array) if (this.width * this.height === mask.length) for (i = 0, size = mask.length; i < size; ++i) obj.data[i * 4 + 3] = mask[i];
  6770. else throw "mask array must be the same length as PImage pixels array.";
  6771. this.fromImageData(obj)
  6772. },
  6773. loadPixels: nop,
  6774. toImageData: function() {
  6775. if (this.isRemote) return this.sourceImg;
  6776. if (!this.__isDirty) return this.imageData;
  6777. var canvasData = getCanvasData(this.sourceImg);
  6778. return canvasData.context.getImageData(0, 0, this.width, this.height)
  6779. },
  6780. toDataURL: function() {
  6781. if (this.isRemote) throw "Image is loaded remotely. Cannot create dataURI.";
  6782. var canvasData = getCanvasData(this.imageData);
  6783. return canvasData.canvas.toDataURL()
  6784. },
  6785. fromImageData: function(canvasImg) {
  6786. var w = canvasImg.width,
  6787. h = canvasImg.height,
  6788. canvas = document.createElement("canvas"),
  6789. ctx = canvas.getContext("2d");
  6790. this.width = canvas.width = w;
  6791. this.height = canvas.height = h;
  6792. ctx.putImageData(canvasImg, 0, 0);
  6793. this.format = 2;
  6794. this.imageData = canvasImg;
  6795. this.sourceImg = canvas
  6796. }
  6797. };
  6798. p.PImage = PImage;
  6799. p.createImage = function(w, h, mode) {
  6800. return new PImage(w, h, mode)
  6801. };
  6802. p.loadImage = function(file, type, callback) {
  6803. if (type) file = file + "." + type;
  6804. var pimg;
  6805. if (curSketch.imageCache.images[file]) {
  6806. pimg = new PImage(curSketch.imageCache.images[file]);
  6807. pimg.loaded = true;
  6808. return pimg
  6809. }
  6810. pimg = new PImage;
  6811. var img = document.createElement("img");
  6812. pimg.sourceImg = img;
  6813. img.onload = function(aImage, aPImage, aCallback) {
  6814. var image = aImage;
  6815. var pimg = aPImage;
  6816. var callback = aCallback;
  6817. return function() {
  6818. pimg.fromHTMLImageData(image);
  6819. pimg.loaded = true;
  6820. if (callback) callback()
  6821. }
  6822. }(img, pimg, callback);
  6823. img.src = file;
  6824. return pimg
  6825. };
  6826. p.requestImage = p.loadImage;
  6827. function get$2(x, y) {
  6828. var data;
  6829. if (x >= p.width || x < 0 || y < 0 || y >= p.height) return 0;
  6830. if (isContextReplaced) {
  6831. var offset = ((0 | x) + p.width * (0 | y)) * 4;
  6832. data = p.imageData.data;
  6833. return (data[offset + 3] & 255) << 24 | (data[offset] & 255) << 16 | (data[offset + 1] & 255) << 8 | data[offset + 2] & 255
  6834. }
  6835. data = p.toImageData(0 | x, 0 | y, 1, 1).data;
  6836. return (data[3] & 255) << 24 | (data[0] & 255) << 16 | (data[1] & 255) << 8 | data[2] & 255
  6837. }
  6838. function get$3(x, y, img) {
  6839. if (img.isRemote) throw "Image is loaded remotely. Cannot get x,y.";
  6840. var offset = y * img.width * 4 + x * 4,
  6841. data = img.imageData.data;
  6842. return (data[offset + 3] & 255) << 24 | (data[offset] & 255) << 16 | (data[offset + 1] & 255) << 8 | data[offset + 2] & 255
  6843. }
  6844. function get$4(x, y, w, h) {
  6845. var c = new PImage(w, h, 2);
  6846. c.fromImageData(p.toImageData(x, y, w, h));
  6847. return c
  6848. }
  6849. function get$5(x, y, w, h, img) {
  6850. if (img.isRemote) throw "Image is loaded remotely. Cannot get x,y,w,h.";
  6851. var c = new PImage(w, h, 2),
  6852. cData = c.imageData.data,
  6853. imgWidth = img.width,
  6854. imgHeight = img.height,
  6855. imgData = img.imageData.data;
  6856. var startRow = Math.max(0, -y),
  6857. startColumn = Math.max(0, -x),
  6858. stopRow = Math.min(h, imgHeight - y),
  6859. stopColumn = Math.min(w, imgWidth - x);
  6860. for (var i = startRow; i < stopRow; ++i) {
  6861. var sourceOffset = ((y + i) * imgWidth + (x + startColumn)) * 4;
  6862. var targetOffset = (i * w + startColumn) * 4;
  6863. for (var j = startColumn; j < stopColumn; ++j) {
  6864. cData[targetOffset++] = imgData[sourceOffset++];
  6865. cData[targetOffset++] = imgData[sourceOffset++];
  6866. cData[targetOffset++] = imgData[sourceOffset++];
  6867. cData[targetOffset++] = imgData[sourceOffset++]
  6868. }
  6869. }
  6870. c.__isDirty = true;
  6871. return c
  6872. }
  6873. p.get = function(x, y, w, h, img) {
  6874. if (img !== undefined) return get$5(x, y, w, h, img);
  6875. if (h !== undefined) return get$4(x, y, w, h);
  6876. if (w !== undefined) return get$3(x, y, w);
  6877. if (y !== undefined) return get$2(x, y);
  6878. if (x !== undefined) return get$5(0, 0, x.width, x.height, x);
  6879. return get$4(0, 0, p.width, p.height)
  6880. };
  6881. p.createGraphics = function(w, h, render) {
  6882. var pg = new Processing;
  6883. pg.size(w, h, render);
  6884. pg.background(0, 0);
  6885. return pg
  6886. };
  6887. function resetContext() {
  6888. if (isContextReplaced) {
  6889. curContext = originalContext;
  6890. isContextReplaced = false;
  6891. p.updatePixels()
  6892. }
  6893. }
  6894. function SetPixelContextWrapper() {
  6895. function wrapFunction(newContext, name) {
  6896. function wrapper() {
  6897. resetContext();
  6898. curContext[name].apply(curContext, arguments)
  6899. }
  6900. newContext[name] = wrapper
  6901. }
  6902. function wrapProperty(newContext, name) {
  6903. function getter() {
  6904. resetContext();
  6905. return curContext[name]
  6906. }
  6907. function setter(value) {
  6908. resetContext();
  6909. curContext[name] = value
  6910. }
  6911. p.defineProperty(newContext, name, {
  6912. get: getter,
  6913. set: setter
  6914. })
  6915. }
  6916. for (var n in curContext) if (typeof curContext[n] === "function") wrapFunction(this, n);
  6917. else wrapProperty(this, n)
  6918. }
  6919. function replaceContext() {
  6920. if (isContextReplaced) return;
  6921. p.loadPixels();
  6922. if (proxyContext === null) {
  6923. originalContext = curContext;
  6924. proxyContext = new SetPixelContextWrapper
  6925. }
  6926. isContextReplaced = true;
  6927. curContext = proxyContext;
  6928. setPixelsCached = 0
  6929. }
  6930. function set$3(x, y, c) {
  6931. if (x < p.width && x >= 0 && y >= 0 && y < p.height) {
  6932. replaceContext();
  6933. p.pixels.setPixel((0 | x) + p.width * (0 | y), c);
  6934. if (++setPixelsCached > maxPixelsCached) resetContext()
  6935. }
  6936. }
  6937. function set$4(x, y, obj, img) {
  6938. if (img.isRemote) throw "Image is loaded remotely. Cannot set x,y.";
  6939. var c = p.color.toArray(obj);
  6940. var offset = y * img.width * 4 + x * 4;
  6941. var data = img.imageData.data;
  6942. data[offset] = c[0];
  6943. data[offset + 1] = c[1];
  6944. data[offset + 2] = c[2];
  6945. data[offset + 3] = c[3]
  6946. }
  6947. p.set = function(x, y, obj, img) {
  6948. var color, oldFill;
  6949. if (arguments.length === 3) if (typeof obj === "number") set$3(x, y, obj);
  6950. else {
  6951. if (obj instanceof PImage || obj.__isPImage) p.image(obj, x, y)
  6952. } else if (arguments.length === 4) set$4(x, y, obj, img)
  6953. };
  6954. p.imageData = {};
  6955. p.pixels = {
  6956. getLength: function() {
  6957. return p.imageData.data.length ? p.imageData.data.length / 4 : 0
  6958. },
  6959. getPixel: function(i) {
  6960. var offset = i * 4,
  6961. data = p.imageData.data;
  6962. return data[offset + 3] << 24 & 4278190080 | data[offset + 0] << 16 & 16711680 | data[offset + 1] << 8 & 65280 | data[offset + 2] & 255
  6963. },
  6964. setPixel: function(i, c) {
  6965. var offset = i * 4,
  6966. data = p.imageData.data;
  6967. data[offset + 0] = (c & 16711680) >>> 16;
  6968. data[offset + 1] = (c & 65280) >>> 8;
  6969. data[offset + 2] = c & 255;
  6970. data[offset + 3] = (c & 4278190080) >>> 24
  6971. },
  6972. toArray: function() {
  6973. var arr = [],
  6974. length = p.imageData.width * p.imageData.height,
  6975. data = p.imageData.data;
  6976. 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);
  6977. return arr
  6978. },
  6979. set: function(arr) {
  6980. for (var i = 0, aL = arr.length; i < aL; i++) this.setPixel(i, arr[i])
  6981. }
  6982. };
  6983. p.loadPixels = function() {
  6984. p.imageData = drawing.$ensureContext().getImageData(0, 0, p.width, p.height)
  6985. };
  6986. p.updatePixels = function() {
  6987. if (p.imageData) drawing.$ensureContext().putImageData(p.imageData, 0, 0)
  6988. };
  6989. p.hint = function(which) {
  6990. var curContext = drawing.$ensureContext();
  6991. if (which === 4) {
  6992. curContext.disable(curContext.DEPTH_TEST);
  6993. curContext.depthMask(false);
  6994. curContext.clear(curContext.DEPTH_BUFFER_BIT)
  6995. } else if (which === -4) {
  6996. curContext.enable(curContext.DEPTH_TEST);
  6997. curContext.depthMask(true)
  6998. } else if (which === -1 || which === 2) renderSmooth = true;
  6999. else if (which === 1) renderSmooth = false
  7000. };
  7001. var backgroundHelper = function(arg1, arg2, arg3, arg4) {
  7002. var obj;
  7003. if (arg1 instanceof PImage || arg1.__isPImage) {
  7004. obj = arg1;
  7005. if (!obj.loaded) throw "Error using image in background(): PImage not loaded.";
  7006. if (obj.width !== p.width || obj.height !== p.height) throw "Background image must be the same dimensions as the canvas.";
  7007. } else obj = p.color(arg1, arg2, arg3, arg4);
  7008. backgroundObj = obj
  7009. };
  7010. Drawing2D.prototype.background = function(arg1, arg2, arg3, arg4) {
  7011. if (arg1 !== undef) backgroundHelper(arg1, arg2, arg3, arg4);
  7012. if (backgroundObj instanceof PImage || backgroundObj.__isPImage) {
  7013. saveContext();
  7014. curContext.setTransform(1, 0, 0, 1, 0, 0);
  7015. p.image(backgroundObj, 0, 0);
  7016. restoreContext()
  7017. } else {
  7018. saveContext();
  7019. curContext.setTransform(1, 0, 0, 1, 0, 0);
  7020. if (p.alpha(backgroundObj) !== colorModeA) curContext.clearRect(0, 0, p.width, p.height);
  7021. curContext.fillStyle = p.color.toString(backgroundObj);
  7022. curContext.fillRect(0, 0, p.width, p.height);
  7023. isFillDirty = true;
  7024. restoreContext()
  7025. }
  7026. };
  7027. Drawing3D.prototype.background = function(arg1, arg2, arg3, arg4) {
  7028. if (arguments.length > 0) backgroundHelper(arg1, arg2, arg3, arg4);
  7029. var c = p.color.toGLArray(backgroundObj);
  7030. curContext.clearColor(c[0], c[1], c[2], c[3]);
  7031. curContext.clear(curContext.COLOR_BUFFER_BIT | curContext.DEPTH_BUFFER_BIT)
  7032. };
  7033. Drawing2D.prototype.image = function(img, x, y, w, h) {
  7034. x = Math.round(x);
  7035. y = Math.round(y);
  7036. if (img.width > 0) {
  7037. var wid = w || img.width;
  7038. var hgt = h || img.height;
  7039. var bounds = imageModeConvert(x || 0, y || 0, w || img.width, h || img.height, arguments.length < 4);
  7040. var fastImage = !!img.sourceImg && curTint === null;
  7041. if (fastImage) {
  7042. var htmlElement = img.sourceImg;
  7043. if (img.__isDirty) img.updatePixels();
  7044. curContext.drawImage(htmlElement, 0, 0, htmlElement.width, htmlElement.height, bounds.x, bounds.y, bounds.w, bounds.h)
  7045. } else {
  7046. var obj = img.toImageData();
  7047. if (curTint !== null) {
  7048. curTint(obj);
  7049. img.__isDirty = true
  7050. }
  7051. curContext.drawImage(getCanvasData(obj).canvas, 0, 0, img.width, img.height, bounds.x, bounds.y, bounds.w, bounds.h)
  7052. }
  7053. }
  7054. };
  7055. Drawing3D.prototype.image = function(img, x, y, w, h) {
  7056. if (img.width > 0) {
  7057. x = Math.round(x);
  7058. y = Math.round(y);
  7059. w = w || img.width;
  7060. h = h || img.height;
  7061. p.beginShape(p.QUADS);
  7062. p.texture(img);
  7063. p.vertex(x, y, 0, 0, 0);
  7064. p.vertex(x, y + h, 0, 0, h);
  7065. p.vertex(x + w, y + h, 0, w, h);
  7066. p.vertex(x + w, y, 0, w, 0);
  7067. p.endShape()
  7068. }
  7069. };
  7070. p.tint = function(a1, a2, a3, a4) {
  7071. var tintColor = p.color(a1, a2, a3, a4);
  7072. var r = p.red(tintColor) / colorModeX;
  7073. var g = p.green(tintColor) / colorModeY;
  7074. var b = p.blue(tintColor) / colorModeZ;
  7075. var a = p.alpha(tintColor) / colorModeA;
  7076. curTint = function(obj) {
  7077. var data = obj.data,
  7078. length = 4 * obj.width * obj.height;
  7079. for (var i = 0; i < length;) {
  7080. data[i++] *= r;
  7081. data[i++] *= g;
  7082. data[i++] *= b;
  7083. data[i++] *= a
  7084. }
  7085. };
  7086. curTint3d = function(data) {
  7087. for (var i = 0; i < data.length;) {
  7088. data[i++] = r;
  7089. data[i++] = g;
  7090. data[i++] = b;
  7091. data[i++] = a
  7092. }
  7093. }
  7094. };
  7095. p.noTint = function() {
  7096. curTint = null;
  7097. curTint3d = null
  7098. };
  7099. p.copy = function(src, sx, sy, sw, sh, dx, dy, dw, dh) {
  7100. if (dh === undef) {
  7101. dh = dw;
  7102. dw = dy;
  7103. dy = dx;
  7104. dx = sh;
  7105. sh = sw;
  7106. sw = sy;
  7107. sy = sx;
  7108. sx = src;
  7109. src = p
  7110. }
  7111. p.blend(src, sx, sy, sw, sh, dx, dy, dw, dh, 0)
  7112. };
  7113. p.blend = function(src, sx, sy, sw, sh, dx, dy, dw, dh, mode, pimgdest) {
  7114. if (src.isRemote) throw "Image is loaded remotely. Cannot blend image.";
  7115. if (mode === undef) {
  7116. mode = dh;
  7117. dh = dw;
  7118. dw = dy;
  7119. dy = dx;
  7120. dx = sh;
  7121. sh = sw;
  7122. sw = sy;
  7123. sy = sx;
  7124. sx = src;
  7125. src = p
  7126. }
  7127. var sx2 = sx + sw,
  7128. sy2 = sy + sh,
  7129. dx2 = dx + dw,
  7130. dy2 = dy + dh,
  7131. dest = pimgdest || p;
  7132. if (pimgdest === undef || mode === undef) p.loadPixels();
  7133. src.loadPixels();
  7134. 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);
  7135. else p.blit_resize(src, sx, sy, sx2, sy2, dest.imageData.data, dest.width, dest.height, dx, dy, dx2, dy2, mode);
  7136. if (pimgdest === undef) p.updatePixels()
  7137. };
  7138. var buildBlurKernel = function(r) {
  7139. var radius = p.floor(r * 3.5),
  7140. i, radiusi;
  7141. radius = radius < 1 ? 1 : radius < 248 ? radius : 248;
  7142. if (p.shared.blurRadius !== radius) {
  7143. p.shared.blurRadius = radius;
  7144. p.shared.blurKernelSize = 1 + (p.shared.blurRadius << 1);
  7145. p.shared.blurKernel = new Float32Array(p.shared.blurKernelSize);
  7146. var sharedBlurKernal = p.shared.blurKernel;
  7147. var sharedBlurKernelSize = p.shared.blurKernelSize;
  7148. var sharedBlurRadius = p.shared.blurRadius;
  7149. for (i = 0; i < sharedBlurKernelSize; i++) sharedBlurKernal[i] = 0;
  7150. var radiusiSquared = (radius - 1) * (radius - 1);
  7151. for (i = 1; i < radius; i++) sharedBlurKernal[radius + i] = sharedBlurKernal[radiusi] = radiusiSquared;
  7152. sharedBlurKernal[radius] = radius * radius
  7153. }
  7154. };
  7155. var blurARGB = function(r, aImg) {
  7156. var sum, cr, cg, cb, ca, c, m;
  7157. var read, ri, ym, ymi, bk0;
  7158. var wh = aImg.pixels.getLength();
  7159. var r2 = new Float32Array(wh);
  7160. var g2 = new Float32Array(wh);
  7161. var b2 = new Float32Array(wh);
  7162. var a2 = new Float32Array(wh);
  7163. var yi = 0;
  7164. var x, y, i, offset;
  7165. buildBlurKernel(r);
  7166. var aImgHeight = aImg.height;
  7167. var aImgWidth = aImg.width;
  7168. var sharedBlurKernelSize = p.shared.blurKernelSize;
  7169. var sharedBlurRadius = p.shared.blurRadius;
  7170. var sharedBlurKernal = p.shared.blurKernel;
  7171. var pix = aImg.imageData.data;
  7172. for (y = 0; y < aImgHeight; y++) {
  7173. for (x = 0; x < aImgWidth; x++) {
  7174. cb = cg = cr = ca = sum = 0;
  7175. read = x - sharedBlurRadius;
  7176. if (read < 0) {
  7177. bk0 = -read;
  7178. read = 0
  7179. } else {
  7180. if (read >= aImgWidth) break;
  7181. bk0 = 0
  7182. }
  7183. for (i = bk0; i < sharedBlurKernelSize; i++) {
  7184. if (read >= aImgWidth) break;
  7185. offset = (read + yi) * 4;
  7186. m = sharedBlurKernal[i];
  7187. ca += m * pix[offset + 3];
  7188. cr += m * pix[offset];
  7189. cg += m * pix[offset + 1];
  7190. cb += m * pix[offset + 2];
  7191. sum += m;
  7192. read++
  7193. }
  7194. ri = yi + x;
  7195. a2[ri] = ca / sum;
  7196. r2[ri] = cr / sum;
  7197. g2[ri] = cg / sum;
  7198. b2[ri] = cb / sum
  7199. }
  7200. yi += aImgWidth
  7201. }
  7202. yi = 0;
  7203. ym = -sharedBlurRadius;
  7204. ymi = ym * aImgWidth;
  7205. for (y = 0; y < aImgHeight; y++) {
  7206. for (x = 0; x < aImgWidth; x++) {
  7207. cb = cg = cr = ca = sum = 0;
  7208. if (ym < 0) {
  7209. bk0 = ri = -ym;
  7210. read = x
  7211. } else {
  7212. if (ym >= aImgHeight) break;
  7213. bk0 = 0;
  7214. ri = ym;
  7215. read = x + ymi
  7216. }
  7217. for (i = bk0; i < sharedBlurKernelSize; i++) {
  7218. if (ri >= aImgHeight) break;
  7219. m = sharedBlurKernal[i];
  7220. ca += m * a2[read];
  7221. cr += m * r2[read];
  7222. cg += m * g2[read];
  7223. cb += m * b2[read];
  7224. sum += m;
  7225. ri++;
  7226. read += aImgWidth
  7227. }
  7228. offset = (x + yi) * 4;
  7229. pix[offset] = cr / sum;
  7230. pix[offset + 1] = cg / sum;
  7231. pix[offset + 2] = cb / sum;
  7232. pix[offset + 3] = ca / sum
  7233. }
  7234. yi += aImgWidth;
  7235. ymi += aImgWidth;
  7236. ym++
  7237. }
  7238. };
  7239. var dilate = function(isInverted, aImg) {
  7240. var currIdx = 0;
  7241. var maxIdx = aImg.pixels.getLength();
  7242. var out = new Int32Array(maxIdx);
  7243. var currRowIdx, maxRowIdx, colOrig, colOut, currLum;
  7244. var idxRight, idxLeft, idxUp, idxDown, colRight, colLeft, colUp, colDown, lumRight, lumLeft, lumUp, lumDown;
  7245. if (!isInverted) while (currIdx < maxIdx) {
  7246. currRowIdx = currIdx;
  7247. maxRowIdx = currIdx + aImg.width;
  7248. while (currIdx < maxRowIdx) {
  7249. colOrig = colOut = aImg.pixels.getPixel(currIdx);
  7250. idxLeft = currIdx - 1;
  7251. idxRight = currIdx + 1;
  7252. idxUp = currIdx - aImg.width;
  7253. idxDown = currIdx + aImg.width;
  7254. if (idxLeft < currRowIdx) idxLeft = currIdx;
  7255. if (idxRight >= maxRowIdx) idxRight = currIdx;
  7256. if (idxUp < 0) idxUp = 0;
  7257. if (idxDown >= maxIdx) idxDown = currIdx;
  7258. colUp = aImg.pixels.getPixel(idxUp);
  7259. colLeft = aImg.pixels.getPixel(idxLeft);
  7260. colDown = aImg.pixels.getPixel(idxDown);
  7261. colRight = aImg.pixels.getPixel(idxRight);
  7262. currLum = 77 * (colOrig >> 16 & 255) + 151 * (colOrig >> 8 & 255) + 28 * (colOrig & 255);
  7263. lumLeft = 77 * (colLeft >> 16 & 255) + 151 * (colLeft >> 8 & 255) + 28 * (colLeft & 255);
  7264. lumRight = 77 * (colRight >> 16 & 255) + 151 * (colRight >> 8 & 255) + 28 * (colRight & 255);
  7265. lumUp = 77 * (colUp >> 16 & 255) + 151 * (colUp >> 8 & 255) + 28 * (colUp & 255);
  7266. lumDown = 77 * (colDown >> 16 & 255) + 151 * (colDown >> 8 & 255) + 28 * (colDown & 255);
  7267. if (lumLeft > currLum) {
  7268. colOut = colLeft;
  7269. currLum = lumLeft
  7270. }
  7271. if (lumRight > currLum) {
  7272. colOut = colRight;
  7273. currLum = lumRight
  7274. }
  7275. if (lumUp > currLum) {
  7276. colOut = colUp;
  7277. currLum = lumUp
  7278. }
  7279. if (lumDown > currLum) {
  7280. colOut = colDown;
  7281. currLum = lumDown
  7282. }
  7283. out[currIdx++] = colOut
  7284. }
  7285. } else while (currIdx < maxIdx) {
  7286. currRowIdx = currIdx;
  7287. maxRowIdx = currIdx + aImg.width;
  7288. while (currIdx < maxRowIdx) {
  7289. colOrig = colOut = aImg.pixels.getPixel(currIdx);
  7290. idxLeft = currIdx - 1;
  7291. idxRight = currIdx + 1;
  7292. idxUp = currIdx - aImg.width;
  7293. idxDown = currIdx + aImg.width;
  7294. if (idxLeft < currRowIdx) idxLeft = currIdx;
  7295. if (idxRight >= maxRowIdx) idxRight = currIdx;
  7296. if (idxUp < 0) idxUp = 0;
  7297. if (idxDown >= maxIdx) idxDown = currIdx;
  7298. colUp = aImg.pixels.getPixel(idxUp);
  7299. colLeft = aImg.pixels.getPixel(idxLeft);
  7300. colDown = aImg.pixels.getPixel(idxDown);
  7301. colRight = aImg.pixels.getPixel(idxRight);
  7302. currLum = 77 * (colOrig >> 16 & 255) + 151 * (colOrig >> 8 & 255) + 28 * (colOrig & 255);
  7303. lumLeft = 77 * (colLeft >> 16 & 255) + 151 * (colLeft >> 8 & 255) + 28 * (colLeft & 255);
  7304. lumRight = 77 * (colRight >> 16 & 255) + 151 * (colRight >> 8 & 255) + 28 * (colRight & 255);
  7305. lumUp = 77 * (colUp >> 16 & 255) + 151 * (colUp >> 8 & 255) + 28 * (colUp & 255);
  7306. lumDown = 77 * (colDown >> 16 & 255) + 151 * (colDown >> 8 & 255) + 28 * (colDown & 255);
  7307. if (lumLeft < currLum) {
  7308. colOut = colLeft;
  7309. currLum = lumLeft
  7310. }
  7311. if (lumRight < currLum) {
  7312. colOut = colRight;
  7313. currLum = lumRight
  7314. }
  7315. if (lumUp < currLum) {
  7316. colOut = colUp;
  7317. currLum = lumUp
  7318. }
  7319. if (lumDown < currLum) {
  7320. colOut = colDown;
  7321. currLum = lumDown
  7322. }
  7323. out[currIdx++] = colOut
  7324. }
  7325. }
  7326. aImg.pixels.set(out)
  7327. };
  7328. p.filter = function(kind, param, aImg) {
  7329. var img, col, lum, i;
  7330. if (arguments.length === 3) {
  7331. aImg.loadPixels();
  7332. img = aImg
  7333. } else {
  7334. p.loadPixels();
  7335. img = p
  7336. }
  7337. if (param === undef) param = null;
  7338. if (img.isRemote) throw "Image is loaded remotely. Cannot filter image.";
  7339. var imglen = img.pixels.getLength();
  7340. switch (kind) {
  7341. case 11:
  7342. var radius = param || 1;
  7343. blurARGB(radius, img);
  7344. break;
  7345. case 12:
  7346. if (img.format === 4) {
  7347. for (i = 0; i < imglen; i++) {
  7348. col = 255 - img.pixels.getPixel(i);
  7349. img.pixels.setPixel(i, 4278190080 | col << 16 | col << 8 | col)
  7350. }
  7351. img.format = 1
  7352. } else for (i = 0; i < imglen; i++) {
  7353. col = img.pixels.getPixel(i);
  7354. lum = 77 * (col >> 16 & 255) + 151 * (col >> 8 & 255) + 28 * (col & 255) >> 8;
  7355. img.pixels.setPixel(i, col & 4278190080 | lum << 16 | lum << 8 | lum)
  7356. }
  7357. break;
  7358. case 13:
  7359. for (i = 0; i < imglen; i++) img.pixels.setPixel(i, img.pixels.getPixel(i) ^ 16777215);
  7360. break;
  7361. case 15:
  7362. if (param === null) throw "Use filter(POSTERIZE, int levels) instead of filter(POSTERIZE)";
  7363. var levels = p.floor(param);
  7364. if (levels < 2 || levels > 255) throw "Levels must be between 2 and 255 for filter(POSTERIZE, levels)";
  7365. var levels1 = levels - 1;
  7366. for (i = 0; i < imglen; i++) {
  7367. var rlevel = img.pixels.getPixel(i) >> 16 & 255;
  7368. var glevel = img.pixels.getPixel(i) >> 8 & 255;
  7369. var blevel = img.pixels.getPixel(i) & 255;
  7370. rlevel = (rlevel * levels >> 8) * 255 / levels1;
  7371. glevel = (glevel * levels >> 8) * 255 / levels1;
  7372. blevel = (blevel * levels >> 8) * 255 / levels1;
  7373. img.pixels.setPixel(i, 4278190080 & img.pixels.getPixel(i) | rlevel << 16 | glevel << 8 | blevel)
  7374. }
  7375. break;
  7376. case 14:
  7377. for (i = 0; i < imglen; i++) img.pixels.setPixel(i, img.pixels.getPixel(i) | 4278190080);
  7378. img.format = 1;
  7379. break;
  7380. case 16:
  7381. if (param === null) param = 0.5;
  7382. if (param < 0 || param > 1) throw "Level must be between 0 and 1 for filter(THRESHOLD, level)";
  7383. var thresh = p.floor(param * 255);
  7384. for (i = 0; i < imglen; i++) {
  7385. var max = p.max((img.pixels.getPixel(i) & 16711680) >> 16, p.max((img.pixels.getPixel(i) & 65280) >> 8, img.pixels.getPixel(i) & 255));
  7386. img.pixels.setPixel(i, img.pixels.getPixel(i) & 4278190080 | (max < thresh ? 0 : 16777215))
  7387. }
  7388. break;
  7389. case 17:
  7390. dilate(true, img);
  7391. break;
  7392. case 18:
  7393. dilate(false, img);
  7394. break
  7395. }
  7396. img.updatePixels()
  7397. };
  7398. p.shared = {
  7399. fracU: 0,
  7400. ifU: 0,
  7401. fracV: 0,
  7402. ifV: 0,
  7403. u1: 0,
  7404. u2: 0,
  7405. v1: 0,
  7406. v2: 0,
  7407. sX: 0,
  7408. sY: 0,
  7409. iw: 0,
  7410. iw1: 0,
  7411. ih1: 0,
  7412. ul: 0,
  7413. ll: 0,
  7414. ur: 0,
  7415. lr: 0,
  7416. cUL: 0,
  7417. cLL: 0,
  7418. cUR: 0,
  7419. cLR: 0,
  7420. srcXOffset: 0,
  7421. srcYOffset: 0,
  7422. r: 0,
  7423. g: 0,
  7424. b: 0,
  7425. a: 0,
  7426. srcBuffer: null,
  7427. blurRadius: 0,
  7428. blurKernelSize: 0,
  7429. blurKernel: null
  7430. };
  7431. p.intersect = function(sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2) {
  7432. var sw = sx2 - sx1 + 1;
  7433. var sh = sy2 - sy1 + 1;
  7434. var dw = dx2 - dx1 + 1;
  7435. var dh = dy2 - dy1 + 1;
  7436. if (dx1 < sx1) {
  7437. dw += dx1 - sx1;
  7438. if (dw > sw) dw = sw
  7439. } else {
  7440. var w = sw + sx1 - dx1;
  7441. if (dw > w) dw = w
  7442. }
  7443. if (dy1 < sy1) {
  7444. dh += dy1 - sy1;
  7445. if (dh > sh) dh = sh
  7446. } else {
  7447. var h = sh + sy1 - dy1;
  7448. if (dh > h) dh = h
  7449. }
  7450. return ! (dw <= 0 || dh <= 0)
  7451. };
  7452. var blendFuncs = {};
  7453. blendFuncs[1] = p.modes.blend;
  7454. blendFuncs[2] = p.modes.add;
  7455. blendFuncs[4] = p.modes.subtract;
  7456. blendFuncs[8] = p.modes.lightest;
  7457. blendFuncs[16] = p.modes.darkest;
  7458. blendFuncs[0] = p.modes.replace;
  7459. blendFuncs[32] = p.modes.difference;
  7460. blendFuncs[64] = p.modes.exclusion;
  7461. blendFuncs[128] = p.modes.multiply;
  7462. blendFuncs[256] = p.modes.screen;
  7463. blendFuncs[512] = p.modes.overlay;
  7464. blendFuncs[1024] = p.modes.hard_light;
  7465. blendFuncs[2048] = p.modes.soft_light;
  7466. blendFuncs[4096] = p.modes.dodge;
  7467. blendFuncs[8192] = p.modes.burn;
  7468. p.blit_resize = function(img, srcX1, srcY1, srcX2, srcY2, destPixels, screenW, screenH, destX1, destY1, destX2, destY2, mode) {
  7469. var x, y;
  7470. if (srcX1 < 0) srcX1 = 0;
  7471. if (srcY1 < 0) srcY1 = 0;
  7472. if (srcX2 >= img.width) srcX2 = img.width - 1;
  7473. if (srcY2 >= img.height) srcY2 = img.height - 1;
  7474. var srcW = srcX2 - srcX1;
  7475. var srcH = srcY2 - srcY1;
  7476. var destW = destX2 - destX1;
  7477. var destH = destY2 - destY1;
  7478. if (destW <= 0 || destH <= 0 || srcW <= 0 || srcH <= 0 || destX1 >= screenW || destY1 >= screenH || srcX1 >= img.width || srcY1 >= img.height) return;
  7479. var dx = Math.floor(srcW / destW * 32768);
  7480. var dy = Math.floor(srcH / destH * 32768);
  7481. var pshared = p.shared;
  7482. pshared.srcXOffset = Math.floor(destX1 < 0 ? -destX1 * dx : srcX1 * 32768);
  7483. pshared.srcYOffset = Math.floor(destY1 < 0 ? -destY1 * dy : srcY1 * 32768);
  7484. if (destX1 < 0) {
  7485. destW += destX1;
  7486. destX1 = 0
  7487. }
  7488. if (destY1 < 0) {
  7489. destH += destY1;
  7490. destY1 = 0
  7491. }
  7492. destW = Math.min(destW, screenW - destX1);
  7493. destH = Math.min(destH, screenH - destY1);
  7494. var destOffset = destY1 * screenW + destX1;
  7495. var destColor;
  7496. pshared.srcBuffer = img.imageData.data;
  7497. pshared.iw = img.width;
  7498. pshared.iw1 = img.width - 1;
  7499. pshared.ih1 = img.height - 1;
  7500. var filterBilinear = p.filter_bilinear,
  7501. filterNewScanline = p.filter_new_scanline,
  7502. blendFunc = blendFuncs[mode],
  7503. blendedColor, idx, cULoffset, cURoffset, cLLoffset, cLRoffset, ALPHA_MASK = 4278190080,
  7504. RED_MASK = 16711680,
  7505. GREEN_MASK = 65280,
  7506. BLUE_MASK = 255,
  7507. PREC_MAXVAL = 32767,
  7508. PRECISIONB = 15,
  7509. PREC_RED_SHIFT = 1,
  7510. PREC_ALPHA_SHIFT = 9,
  7511. srcBuffer = pshared.srcBuffer,
  7512. min = Math.min;
  7513. for (y = 0; y < destH; y++) {
  7514. pshared.sX = pshared.srcXOffset;
  7515. pshared.fracV = pshared.srcYOffset & PREC_MAXVAL;
  7516. pshared.ifV = PREC_MAXVAL - pshared.fracV;
  7517. pshared.v1 = (pshared.srcYOffset >> PRECISIONB) * pshared.iw;
  7518. pshared.v2 = min((pshared.srcYOffset >> PRECISIONB) + 1, pshared.ih1) * pshared.iw;
  7519. for (x = 0; x < destW; x++) {
  7520. idx = (destOffset + x) * 4;
  7521. destColor = destPixels[idx + 3] << 24 & ALPHA_MASK | destPixels[idx] << 16 & RED_MASK | destPixels[idx + 1] << 8 & GREEN_MASK | destPixels[idx + 2] & BLUE_MASK;
  7522. pshared.fracU = pshared.sX & PREC_MAXVAL;
  7523. pshared.ifU = PREC_MAXVAL - pshared.fracU;
  7524. pshared.ul = pshared.ifU * pshared.ifV >> PRECISIONB;
  7525. pshared.ll = pshared.ifU * pshared.fracV >> PRECISIONB;
  7526. pshared.ur = pshared.fracU * pshared.ifV >> PRECISIONB;
  7527. pshared.lr = pshared.fracU * pshared.fracV >> PRECISIONB;
  7528. pshared.u1 = pshared.sX >> PRECISIONB;
  7529. pshared.u2 = min(pshared.u1 + 1, pshared.iw1);
  7530. cULoffset = (pshared.v1 + pshared.u1) * 4;
  7531. cURoffset = (pshared.v1 + pshared.u2) * 4;
  7532. cLLoffset = (pshared.v2 + pshared.u1) * 4;
  7533. cLRoffset = (pshared.v2 + pshared.u2) * 4;
  7534. pshared.cUL = srcBuffer[cULoffset + 3] << 24 & ALPHA_MASK | srcBuffer[cULoffset] << 16 & RED_MASK | srcBuffer[cULoffset + 1] << 8 & GREEN_MASK | srcBuffer[cULoffset + 2] & BLUE_MASK;
  7535. pshared.cUR = srcBuffer[cURoffset + 3] << 24 & ALPHA_MASK | srcBuffer[cURoffset] << 16 & RED_MASK | srcBuffer[cURoffset + 1] << 8 & GREEN_MASK | srcBuffer[cURoffset + 2] & BLUE_MASK;
  7536. pshared.cLL = srcBuffer[cLLoffset + 3] << 24 & ALPHA_MASK | srcBuffer[cLLoffset] << 16 & RED_MASK | srcBuffer[cLLoffset + 1] << 8 & GREEN_MASK | srcBuffer[cLLoffset + 2] & BLUE_MASK;
  7537. pshared.cLR = srcBuffer[cLRoffset + 3] << 24 & ALPHA_MASK | srcBuffer[cLRoffset] << 16 & RED_MASK | srcBuffer[cLRoffset + 1] << 8 & GREEN_MASK | srcBuffer[cLRoffset + 2] & BLUE_MASK;
  7538. 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;
  7539. 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;
  7540. 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;
  7541. 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;
  7542. blendedColor = blendFunc(destColor, pshared.a | pshared.r | pshared.g | pshared.b);
  7543. destPixels[idx] = (blendedColor & RED_MASK) >>> 16;
  7544. destPixels[idx + 1] = (blendedColor & GREEN_MASK) >>> 8;
  7545. destPixels[idx + 2] = blendedColor & BLUE_MASK;
  7546. destPixels[idx + 3] = (blendedColor & ALPHA_MASK) >>> 24;
  7547. pshared.sX += dx
  7548. }
  7549. destOffset += screenW;
  7550. pshared.srcYOffset += dy
  7551. }
  7552. };
  7553. p.loadFont = function(name, size) {
  7554. if (name === undef) throw "font name required in loadFont.";
  7555. if (name.indexOf(".svg") === -1) {
  7556. if (size === undef) size = curTextFont.size;
  7557. return PFont.get(name, size)
  7558. }
  7559. var font = p.loadGlyphs(name);
  7560. return {
  7561. name: name,
  7562. css: "12px sans-serif",
  7563. glyph: true,
  7564. units_per_em: font.units_per_em,
  7565. horiz_adv_x: 1 / font.units_per_em * font.horiz_adv_x,
  7566. ascent: font.ascent,
  7567. descent: font.descent,
  7568. width: function(str) {
  7569. var width = 0;
  7570. var len = str.length;
  7571. for (var i = 0; i < len; i++) try {
  7572. width += parseFloat(p.glyphLook(p.glyphTable[name], str[i]).horiz_adv_x)
  7573. } catch(e) {
  7574. Processing.debug(e)
  7575. }
  7576. return width / p.glyphTable[name].units_per_em
  7577. }
  7578. }
  7579. };
  7580. p.createFont = function(name, size) {
  7581. return p.loadFont(name, size)
  7582. };
  7583. p.textFont = function(pfont, size) {
  7584. if (size !== undef) {
  7585. if (!pfont.glyph) pfont = PFont.get(pfont.name, size);
  7586. curTextSize = size
  7587. }
  7588. curTextFont = pfont;
  7589. curFontName = curTextFont.name;
  7590. curTextAscent = curTextFont.ascent;
  7591. curTextDescent = curTextFont.descent;
  7592. curTextLeading = curTextFont.leading;
  7593. var curContext = drawing.$ensureContext();
  7594. curContext.font = curTextFont.css
  7595. };
  7596. p.textSize = function(size) {
  7597. curTextFont = PFont.get(curFontName, size);
  7598. curTextSize = size;
  7599. curTextAscent = curTextFont.ascent;
  7600. curTextDescent = curTextFont.descent;
  7601. curTextLeading = curTextFont.leading;
  7602. var curContext = drawing.$ensureContext();
  7603. curContext.font = curTextFont.css
  7604. };
  7605. p.textAscent = function() {
  7606. return curTextAscent
  7607. };
  7608. p.textDescent = function() {
  7609. return curTextDescent
  7610. };
  7611. p.textLeading = function(leading) {
  7612. curTextLeading = leading
  7613. };
  7614. p.textAlign = function(xalign, yalign) {
  7615. horizontalTextAlignment = xalign;
  7616. verticalTextAlignment = yalign || 0
  7617. };
  7618. function toP5String(obj) {
  7619. if (obj instanceof String) return obj;
  7620. if (typeof obj === "number") {
  7621. if (obj === (0 | obj)) return obj.toString();
  7622. return p.nf(obj, 0, 3)
  7623. }
  7624. if (obj === null || obj === undef) return "";
  7625. return obj.toString()
  7626. }
  7627. Drawing2D.prototype.textWidth = function(str) {
  7628. var lines = toP5String(str).split(/\r?\n/g),
  7629. width = 0;
  7630. var i, linesCount = lines.length;
  7631. curContext.font = curTextFont.css;
  7632. for (i = 0; i < linesCount; ++i) width = Math.max(width, curTextFont.measureTextWidth(lines[i]));
  7633. return width | 0
  7634. };
  7635. Drawing3D.prototype.textWidth = function(str) {
  7636. var lines = toP5String(str).split(/\r?\n/g),
  7637. width = 0;
  7638. var i, linesCount = lines.length;
  7639. if (textcanvas === undef) textcanvas = document.createElement("canvas");
  7640. var textContext = textcanvas.getContext("2d");
  7641. textContext.font = curTextFont.css;
  7642. for (i = 0; i < linesCount; ++i) width = Math.max(width, textContext.measureText(lines[i]).width);
  7643. return width | 0
  7644. };
  7645. p.glyphLook = function(font, chr) {
  7646. try {
  7647. switch (chr) {
  7648. case "1":
  7649. return font.one;
  7650. case "2":
  7651. return font.two;
  7652. case "3":
  7653. return font.three;
  7654. case "4":
  7655. return font.four;
  7656. case "5":
  7657. return font.five;
  7658. case "6":
  7659. return font.six;
  7660. case "7":
  7661. return font.seven;
  7662. case "8":
  7663. return font.eight;
  7664. case "9":
  7665. return font.nine;
  7666. case "0":
  7667. return font.zero;
  7668. case " ":
  7669. return font.space;
  7670. case "$":
  7671. return font.dollar;
  7672. case "!":
  7673. return font.exclam;
  7674. case '"':
  7675. return font.quotedbl;
  7676. case "#":
  7677. return font.numbersign;
  7678. case "%":
  7679. return font.percent;
  7680. case "&":
  7681. return font.ampersand;
  7682. case "'":
  7683. return font.quotesingle;
  7684. case "(":
  7685. return font.parenleft;
  7686. case ")":
  7687. return font.parenright;
  7688. case "*":
  7689. return font.asterisk;
  7690. case "+":
  7691. return font.plus;
  7692. case ",":
  7693. return font.comma;
  7694. case "-":
  7695. return font.hyphen;
  7696. case ".":
  7697. return font.period;
  7698. case "/":
  7699. return font.slash;
  7700. case "_":
  7701. return font.underscore;
  7702. case ":":
  7703. return font.colon;
  7704. case ";":
  7705. return font.semicolon;
  7706. case "<":
  7707. return font.less;
  7708. case "=":
  7709. return font.equal;
  7710. case ">":
  7711. return font.greater;
  7712. case "?":
  7713. return font.question;
  7714. case "@":
  7715. return font.at;
  7716. case "[":
  7717. return font.bracketleft;
  7718. case "\\":
  7719. return font.backslash;
  7720. case "]":
  7721. return font.bracketright;
  7722. case "^":
  7723. return font.asciicircum;
  7724. case "`":
  7725. return font.grave;
  7726. case "{":
  7727. return font.braceleft;
  7728. case "|":
  7729. return font.bar;
  7730. case "}":
  7731. return font.braceright;
  7732. case "~":
  7733. return font.asciitilde;
  7734. default:
  7735. return font[chr]
  7736. }
  7737. } catch(e) {
  7738. Processing.debug(e)
  7739. }
  7740. };
  7741. Drawing2D.prototype.text$line = function(str, x, y, z, align) {
  7742. var textWidth = 0,
  7743. xOffset = 0;
  7744. if (!curTextFont.glyph) {
  7745. if (str && "fillText" in curContext) {
  7746. if (isFillDirty) {
  7747. curContext.fillStyle = p.color.toString(currentFillColor);
  7748. isFillDirty = false
  7749. }
  7750. if (align === 39 || align === 3) {
  7751. textWidth = curTextFont.measureTextWidth(str);
  7752. if (align === 39) xOffset = -textWidth;
  7753. else xOffset = -textWidth / 2
  7754. }
  7755. curContext.fillText(str, x + xOffset, y)
  7756. }
  7757. } else {
  7758. var font = p.glyphTable[curFontName];
  7759. saveContext();
  7760. curContext.translate(x, y + curTextSize);
  7761. if (align === 39 || align === 3) {
  7762. textWidth = font.width(str);
  7763. if (align === 39) xOffset = -textWidth;
  7764. else xOffset = -textWidth / 2
  7765. }
  7766. var upem = font.units_per_em,
  7767. newScale = 1 / upem * curTextSize;
  7768. curContext.scale(newScale, newScale);
  7769. for (var i = 0, len = str.length; i < len; i++) try {
  7770. p.glyphLook(font, str[i]).draw()
  7771. } catch(e) {
  7772. Processing.debug(e)
  7773. }
  7774. restoreContext()
  7775. }
  7776. };
  7777. Drawing3D.prototype.text$line = function(str, x, y, z, align) {
  7778. if (textcanvas === undef) textcanvas = document.createElement("canvas");
  7779. var oldContext = curContext;
  7780. curContext = textcanvas.getContext("2d");
  7781. curContext.font = curTextFont.css;
  7782. var textWidth = curTextFont.measureTextWidth(str);
  7783. textcanvas.width = textWidth;
  7784. textcanvas.height = curTextSize;
  7785. curContext = textcanvas.getContext("2d");
  7786. curContext.font = curTextFont.css;
  7787. curContext.textBaseline = "top";
  7788. Drawing2D.prototype.text$line(str, 0, 0, 0, 37);
  7789. var aspect = textcanvas.width / textcanvas.height;
  7790. curContext = oldContext;
  7791. curContext.bindTexture(curContext.TEXTURE_2D, textTex);
  7792. curContext.texImage2D(curContext.TEXTURE_2D, 0, curContext.RGBA, curContext.RGBA, curContext.UNSIGNED_BYTE, textcanvas);
  7793. curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_MAG_FILTER, curContext.LINEAR);
  7794. curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_MIN_FILTER, curContext.LINEAR);
  7795. curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_WRAP_T, curContext.CLAMP_TO_EDGE);
  7796. curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_WRAP_S, curContext.CLAMP_TO_EDGE);
  7797. var xOffset = 0;
  7798. if (align === 39) xOffset = -textWidth;
  7799. else if (align === 3) xOffset = -textWidth / 2;
  7800. var model = new PMatrix3D;
  7801. var scalefactor = curTextSize * 0.5;
  7802. model.translate(x + xOffset - scalefactor / 2, y - scalefactor, z);
  7803. model.scale(-aspect * scalefactor, -scalefactor, scalefactor);
  7804. model.translate(-1, -1, -1);
  7805. model.transpose();
  7806. var view = new PMatrix3D;
  7807. view.scale(1, -1, 1);
  7808. view.apply(modelView.array());
  7809. view.transpose();
  7810. curContext.useProgram(programObject2D);
  7811. vertexAttribPointer("aVertex2d", programObject2D, "aVertex", 3, textBuffer);
  7812. vertexAttribPointer("aTextureCoord2d", programObject2D, "aTextureCoord", 2, textureBuffer);
  7813. uniformi("uSampler2d", programObject2D, "uSampler", [0]);
  7814. uniformi("uIsDrawingText2d", programObject2D, "uIsDrawingText", true);
  7815. uniformMatrix("uModel2d", programObject2D, "uModel", false, model.array());
  7816. uniformMatrix("uView2d", programObject2D, "uView", false, view.array());
  7817. uniformf("uColor2d", programObject2D, "uColor", fillStyle);
  7818. curContext.bindBuffer(curContext.ELEMENT_ARRAY_BUFFER, indexBuffer);
  7819. curContext.drawElements(curContext.TRIANGLES, 6, curContext.UNSIGNED_SHORT, 0)
  7820. };
  7821. function text$4(str, x, y, z) {
  7822. var lines, linesCount;
  7823. if (str.indexOf("\n") < 0) {
  7824. lines = [str];
  7825. linesCount = 1
  7826. } else {
  7827. lines = str.split(/\r?\n/g);
  7828. linesCount = lines.length
  7829. }
  7830. var yOffset = 0;
  7831. if (verticalTextAlignment === 101) yOffset = curTextAscent + curTextDescent;
  7832. else if (verticalTextAlignment === 3) yOffset = curTextAscent / 2 - (linesCount - 1) * curTextLeading / 2;
  7833. else if (verticalTextAlignment === 102) yOffset = -(curTextDescent + (linesCount - 1) * curTextLeading);
  7834. for (var i = 0; i < linesCount; ++i) {
  7835. var line = lines[i];
  7836. drawing.text$line(line, x, y + yOffset, z, horizontalTextAlignment);
  7837. yOffset += curTextLeading
  7838. }
  7839. }
  7840. function text$6(str, x, y, width, height, z) {
  7841. if (str.length === 0 || width === 0 || height === 0) return;
  7842. if (curTextSize > height) return;
  7843. var spaceMark = -1;
  7844. var start = 0;
  7845. var lineWidth = 0;
  7846. var drawCommands = [];
  7847. for (var charPos = 0, len = str.length; charPos < len; charPos++) {
  7848. var currentChar = str[charPos];
  7849. var spaceChar = currentChar === " ";
  7850. var letterWidth = curTextFont.measureTextWidth(currentChar);
  7851. if (currentChar !== "\n" && lineWidth + letterWidth <= width) {
  7852. if (spaceChar) spaceMark = charPos;
  7853. lineWidth += letterWidth
  7854. } else {
  7855. if (spaceMark + 1 === start) if (charPos > 0) spaceMark = charPos;
  7856. else return;
  7857. if (currentChar === "\n") {
  7858. drawCommands.push({
  7859. text: str.substring(start, charPos),
  7860. width: lineWidth
  7861. });
  7862. start = charPos + 1
  7863. } else {
  7864. drawCommands.push({
  7865. text: str.substring(start, spaceMark + 1),
  7866. width: lineWidth
  7867. });
  7868. start = spaceMark + 1
  7869. }
  7870. lineWidth = 0;
  7871. charPos = start - 1
  7872. }
  7873. }
  7874. if (start < len) drawCommands.push({
  7875. text: str.substring(start),
  7876. width: lineWidth
  7877. });
  7878. var xOffset = 1,
  7879. yOffset = curTextAscent;
  7880. if (horizontalTextAlignment === 3) xOffset = width / 2;
  7881. else if (horizontalTextAlignment === 39) xOffset = width;
  7882. var linesCount = drawCommands.length,
  7883. visibleLines = Math.min(linesCount, Math.floor(height / curTextLeading));
  7884. if (verticalTextAlignment === 101) yOffset = curTextAscent + curTextDescent;
  7885. else if (verticalTextAlignment === 3) yOffset = height / 2 - curTextLeading * (visibleLines / 2 - 1);
  7886. else if (verticalTextAlignment === 102) yOffset = curTextDescent + curTextLeading;
  7887. var command, drawCommand, leading;
  7888. for (command = 0; command < linesCount; command++) {
  7889. leading = command * curTextLeading;
  7890. if (yOffset + leading > height - curTextDescent) break;
  7891. drawCommand = drawCommands[command];
  7892. drawing.text$line(drawCommand.text, x + xOffset, y + yOffset + leading, z, horizontalTextAlignment)
  7893. }
  7894. }
  7895. p.text = function() {
  7896. if (textMode === 5) return;
  7897. if (arguments.length === 3) text$4(toP5String(arguments[0]), arguments[1], arguments[2], 0);
  7898. else if (arguments.length === 4) text$4(toP5String(arguments[0]), arguments[1], arguments[2], arguments[3]);
  7899. else if (arguments.length === 5) text$6(toP5String(arguments[0]), arguments[1], arguments[2], arguments[3], arguments[4], 0);
  7900. else if (arguments.length === 6) text$6(toP5String(arguments[0]), arguments[1], arguments[2], arguments[3], arguments[4], arguments[5])
  7901. };
  7902. p.textMode = function(mode) {
  7903. textMode = mode
  7904. };
  7905. p.loadGlyphs = function(url) {
  7906. var x, y, cx, cy, nx, ny, d, a, lastCom, lenC, horiz_adv_x, getXY = "[0-9\\-]+",
  7907. path;
  7908. var regex = function(needle, hay) {
  7909. var i = 0,
  7910. results = [],
  7911. latest, regexp = new RegExp(needle, "g");
  7912. latest = results[i] = regexp.exec(hay);
  7913. while (latest) {
  7914. i++;
  7915. latest = results[i] = regexp.exec(hay)
  7916. }
  7917. return results
  7918. };
  7919. var buildPath = function(d) {
  7920. var c = regex("[A-Za-z][0-9\\- ]+|Z", d);
  7921. var beforePathDraw = function() {
  7922. saveContext();
  7923. return drawing.$ensureContext()
  7924. };
  7925. var afterPathDraw = function() {
  7926. executeContextFill();
  7927. executeContextStroke();
  7928. restoreContext()
  7929. };
  7930. path = "return {draw:function(){var curContext=beforePathDraw();curContext.beginPath();";
  7931. x = 0;
  7932. y = 0;
  7933. cx = 0;
  7934. cy = 0;
  7935. nx = 0;
  7936. ny = 0;
  7937. d = 0;
  7938. a = 0;
  7939. lastCom = "";
  7940. lenC = c.length - 1;
  7941. for (var j = 0; j < lenC; j++) {
  7942. var com = c[j][0],
  7943. xy = regex(getXY, com);
  7944. switch (com[0]) {
  7945. case "M":
  7946. x = parseFloat(xy[0][0]);
  7947. y = parseFloat(xy[1][0]);
  7948. path += "curContext.moveTo(" + x + "," + -y + ");";
  7949. break;
  7950. case "L":
  7951. x = parseFloat(xy[0][0]);
  7952. y = parseFloat(xy[1][0]);
  7953. path += "curContext.lineTo(" + x + "," + -y + ");";
  7954. break;
  7955. case "H":
  7956. x = parseFloat(xy[0][0]);
  7957. path += "curContext.lineTo(" + x + "," + -y + ");";
  7958. break;
  7959. case "V":
  7960. y = parseFloat(xy[0][0]);
  7961. path += "curContext.lineTo(" + x + "," + -y + ");";
  7962. break;
  7963. case "T":
  7964. nx = parseFloat(xy[0][0]);
  7965. ny = parseFloat(xy[1][0]);
  7966. if (lastCom === "Q" || lastCom === "T") {
  7967. d = Math.sqrt(Math.pow(x - cx, 2) + Math.pow(cy - y, 2));
  7968. a = Math.PI + Math.atan2(cx - x, cy - y);
  7969. cx = x + Math.sin(a) * d;
  7970. cy = y + Math.cos(a) * d
  7971. } else {
  7972. cx = x;
  7973. cy = y
  7974. }
  7975. path += "curContext.quadraticCurveTo(" + cx + "," + -cy + "," + nx + "," + -ny + ");";
  7976. x = nx;
  7977. y = ny;
  7978. break;
  7979. case "Q":
  7980. cx = parseFloat(xy[0][0]);
  7981. cy = parseFloat(xy[1][0]);
  7982. nx = parseFloat(xy[2][0]);
  7983. ny = parseFloat(xy[3][0]);
  7984. path += "curContext.quadraticCurveTo(" + cx + "," + -cy + "," + nx + "," + -ny + ");";
  7985. x = nx;
  7986. y = ny;
  7987. break;
  7988. case "Z":
  7989. path += "curContext.closePath();";
  7990. break
  7991. }
  7992. lastCom = com[0]
  7993. }
  7994. path += "afterPathDraw();";
  7995. path += "curContext.translate(" + horiz_adv_x + ",0);";
  7996. path += "}}";
  7997. return (new Function("beforePathDraw", "afterPathDraw", path))(beforePathDraw, afterPathDraw)
  7998. };
  7999. var parseSVGFont = function(svg) {
  8000. var font = svg.getElementsByTagName("font");
  8001. p.glyphTable[url].horiz_adv_x = font[0].getAttribute("horiz-adv-x");
  8002. var font_face = svg.getElementsByTagName("font-face")[0];
  8003. p.glyphTable[url].units_per_em = parseFloat(font_face.getAttribute("units-per-em"));
  8004. p.glyphTable[url].ascent = parseFloat(font_face.getAttribute("ascent"));
  8005. p.glyphTable[url].descent = parseFloat(font_face.getAttribute("descent"));
  8006. var glyph = svg.getElementsByTagName("glyph"),
  8007. len = glyph.length;
  8008. for (var i = 0; i < len; i++) {
  8009. var unicode = glyph[i].getAttribute("unicode");
  8010. var name = glyph[i].getAttribute("glyph-name");
  8011. horiz_adv_x = glyph[i].getAttribute("horiz-adv-x");
  8012. if (horiz_adv_x === null) horiz_adv_x = p.glyphTable[url].horiz_adv_x;
  8013. d = glyph[i].getAttribute("d");
  8014. if (d !== undef) {
  8015. path = buildPath(d);
  8016. p.glyphTable[url][name] = {
  8017. name: name,
  8018. unicode: unicode,
  8019. horiz_adv_x: horiz_adv_x,
  8020. draw: path.draw
  8021. }
  8022. }
  8023. }
  8024. };
  8025. var loadXML = function() {
  8026. var xmlDoc;
  8027. try {
  8028. xmlDoc = document.implementation.createDocument("", "", null)
  8029. } catch(e_fx_op) {
  8030. Processing.debug(e_fx_op.message);
  8031. return
  8032. }
  8033. try {
  8034. xmlDoc.async = false;
  8035. xmlDoc.load(url);
  8036. parseSVGFont(xmlDoc.getElementsByTagName("svg")[0])
  8037. } catch(e_sf_ch) {
  8038. Processing.debug(e_sf_ch);
  8039. try {
  8040. var xmlhttp = new window.XMLHttpRequest;
  8041. xmlhttp.open("GET", url, false);
  8042. xmlhttp.send(null);
  8043. parseSVGFont(xmlhttp.responseXML.documentElement)
  8044. } catch(e) {
  8045. Processing.debug(e_sf_ch)
  8046. }
  8047. }
  8048. };
  8049. p.glyphTable[url] = {};
  8050. loadXML(url);
  8051. return p.glyphTable[url]
  8052. };
  8053. p.param = function(name) {
  8054. var attributeName = "data-processing-" + name;
  8055. if (curElement.hasAttribute(attributeName)) return curElement.getAttribute(attributeName);
  8056. for (var i = 0, len = curElement.childNodes.length; i < len; ++i) {
  8057. var item = curElement.childNodes.item(i);
  8058. if (item.nodeType !== 1 || item.tagName.toLowerCase() !== "param") continue;
  8059. if (item.getAttribute("name") === name) return item.getAttribute("value")
  8060. }
  8061. if (curSketch.params.hasOwnProperty(name)) return curSketch.params[name];
  8062. return null
  8063. };
  8064. function wireDimensionalFunctions(mode) {
  8065. if (mode === "3D") drawing = new Drawing3D;
  8066. else if (mode === "2D") drawing = new Drawing2D;
  8067. else drawing = new DrawingPre;
  8068. for (var i in DrawingPre.prototype) if (DrawingPre.prototype.hasOwnProperty(i) && i.indexOf("$") < 0) p[i] = drawing[i];
  8069. drawing.$init()
  8070. }
  8071. function createDrawingPreFunction(name) {
  8072. return function() {
  8073. wireDimensionalFunctions("2D");
  8074. return drawing[name].apply(this, arguments)
  8075. }
  8076. }
  8077. DrawingPre.prototype.translate = createDrawingPreFunction("translate");
  8078. DrawingPre.prototype.transform = createDrawingPreFunction("transform");
  8079. DrawingPre.prototype.scale = createDrawingPreFunction("scale");
  8080. DrawingPre.prototype.pushMatrix = createDrawingPreFunction("pushMatrix");
  8081. DrawingPre.prototype.popMatrix = createDrawingPreFunction("popMatrix");
  8082. DrawingPre.prototype.resetMatrix = createDrawingPreFunction("resetMatrix");
  8083. DrawingPre.prototype.applyMatrix = createDrawingPreFunction("applyMatrix");
  8084. DrawingPre.prototype.rotate = createDrawingPreFunction("rotate");
  8085. DrawingPre.prototype.rotateZ = createDrawingPreFunction("rotateZ");
  8086. DrawingPre.prototype.shearX = createDrawingPreFunction("shearX");
  8087. DrawingPre.prototype.shearY = createDrawingPreFunction("shearY");
  8088. DrawingPre.prototype.redraw = createDrawingPreFunction("redraw");
  8089. DrawingPre.prototype.toImageData = createDrawingPreFunction("toImageData");
  8090. DrawingPre.prototype.ambientLight = createDrawingPreFunction("ambientLight");
  8091. DrawingPre.prototype.directionalLight = createDrawingPreFunction("directionalLight");
  8092. DrawingPre.prototype.lightFalloff = createDrawingPreFunction("lightFalloff");
  8093. DrawingPre.prototype.lightSpecular = createDrawingPreFunction("lightSpecular");
  8094. DrawingPre.prototype.pointLight = createDrawingPreFunction("pointLight");
  8095. DrawingPre.prototype.noLights = createDrawingPreFunction("noLights");
  8096. DrawingPre.prototype.spotLight = createDrawingPreFunction("spotLight");
  8097. DrawingPre.prototype.beginCamera = createDrawingPreFunction("beginCamera");
  8098. DrawingPre.prototype.endCamera = createDrawingPreFunction("endCamera");
  8099. DrawingPre.prototype.frustum = createDrawingPreFunction("frustum");
  8100. DrawingPre.prototype.box = createDrawingPreFunction("box");
  8101. DrawingPre.prototype.sphere = createDrawingPreFunction("sphere");
  8102. DrawingPre.prototype.ambient = createDrawingPreFunction("ambient");
  8103. DrawingPre.prototype.emissive = createDrawingPreFunction("emissive");
  8104. DrawingPre.prototype.shininess = createDrawingPreFunction("shininess");
  8105. DrawingPre.prototype.specular = createDrawingPreFunction("specular");
  8106. DrawingPre.prototype.fill = createDrawingPreFunction("fill");
  8107. DrawingPre.prototype.stroke = createDrawingPreFunction("stroke");
  8108. DrawingPre.prototype.strokeWeight = createDrawingPreFunction("strokeWeight");
  8109. DrawingPre.prototype.smooth = createDrawingPreFunction("smooth");
  8110. DrawingPre.prototype.noSmooth = createDrawingPreFunction("noSmooth");
  8111. DrawingPre.prototype.point = createDrawingPreFunction("point");
  8112. DrawingPre.prototype.vertex = createDrawingPreFunction("vertex");
  8113. DrawingPre.prototype.endShape = createDrawingPreFunction("endShape");
  8114. DrawingPre.prototype.bezierVertex = createDrawingPreFunction("bezierVertex");
  8115. DrawingPre.prototype.curveVertex = createDrawingPreFunction("curveVertex");
  8116. DrawingPre.prototype.curve = createDrawingPreFunction("curve");
  8117. DrawingPre.prototype.line = createDrawingPreFunction("line");
  8118. DrawingPre.prototype.bezier = createDrawingPreFunction("bezier");
  8119. DrawingPre.prototype.rect = createDrawingPreFunction("rect");
  8120. DrawingPre.prototype.ellipse = createDrawingPreFunction("ellipse");
  8121. DrawingPre.prototype.background = createDrawingPreFunction("background");
  8122. DrawingPre.prototype.image = createDrawingPreFunction("image");
  8123. DrawingPre.prototype.textWidth = createDrawingPreFunction("textWidth");
  8124. DrawingPre.prototype.text$line = createDrawingPreFunction("text$line");
  8125. DrawingPre.prototype.$ensureContext = createDrawingPreFunction("$ensureContext");
  8126. DrawingPre.prototype.$newPMatrix = createDrawingPreFunction("$newPMatrix");
  8127. DrawingPre.prototype.size = function(aWidth, aHeight, aMode) {
  8128. wireDimensionalFunctions(aMode === 2 ? "3D" : "2D");
  8129. p.size(aWidth, aHeight, aMode)
  8130. };
  8131. DrawingPre.prototype.$init = nop;
  8132. Drawing2D.prototype.$init = function() {
  8133. p.size(p.width, p.height);
  8134. curContext.lineCap = "round";
  8135. p.noSmooth();
  8136. p.disableContextMenu()
  8137. };
  8138. Drawing3D.prototype.$init = function() {
  8139. p.use3DContext = true;
  8140. p.disableContextMenu()
  8141. };
  8142. DrawingShared.prototype.$ensureContext = function() {
  8143. return curContext
  8144. };
  8145. function calculateOffset(curElement, event) {
  8146. var element = curElement,
  8147. offsetX = 0,
  8148. offsetY = 0;
  8149. p.pmouseX = p.mouseX;
  8150. p.pmouseY = p.mouseY;
  8151. if (element.offsetParent) {
  8152. do {
  8153. offsetX += element.offsetLeft;
  8154. offsetY += element.offsetTop
  8155. } while ( !! (element = element.offsetParent))
  8156. }
  8157. element = curElement;
  8158. do {
  8159. offsetX -= element.scrollLeft || 0;
  8160. offsetY -= element.scrollTop || 0
  8161. } while ( !! (element = element.parentNode));
  8162. offsetX += stylePaddingLeft;
  8163. offsetY += stylePaddingTop;
  8164. offsetX += styleBorderLeft;
  8165. offsetY += styleBorderTop;
  8166. offsetX += window.pageXOffset;
  8167. offsetY += window.pageYOffset;
  8168. return {
  8169. "X": offsetX,
  8170. "Y": offsetY
  8171. }
  8172. }
  8173. function updateMousePosition(curElement, event) {
  8174. var offset = calculateOffset(curElement, event);
  8175. p.mouseX = event.pageX - offset.X;
  8176. p.mouseY = event.pageY - offset.Y
  8177. }
  8178. function addTouchEventOffset(t) {
  8179. var offset = calculateOffset(t.changedTouches[0].target, t.changedTouches[0]),
  8180. i;
  8181. for (i = 0; i < t.touches.length; i++) {
  8182. var touch = t.touches[i];
  8183. touch.offsetX = touch.pageX - offset.X;
  8184. touch.offsetY = touch.pageY - offset.Y
  8185. }
  8186. for (i = 0; i < t.targetTouches.length; i++) {
  8187. var targetTouch = t.targetTouches[i];
  8188. targetTouch.offsetX = targetTouch.pageX - offset.X;
  8189. targetTouch.offsetY = targetTouch.pageY - offset.Y
  8190. }
  8191. for (i = 0; i < t.changedTouches.length; i++) {
  8192. var changedTouch = t.changedTouches[i];
  8193. changedTouch.offsetX = changedTouch.pageX - offset.X;
  8194. changedTouch.offsetY = changedTouch.pageY - offset.Y
  8195. }
  8196. return t
  8197. }
  8198. attachEventHandler(curElement, "touchstart", function(t) {
  8199. curElement.setAttribute("style", "-webkit-user-select: none");
  8200. curElement.setAttribute("onclick", "void(0)");
  8201. curElement.setAttribute("style", "-webkit-tap-highlight-color:rgba(0,0,0,0)");
  8202. for (var i = 0, ehl = eventHandlers.length; i < ehl; i++) {
  8203. var type = eventHandlers[i].type;
  8204. if (type === "mouseout" || type === "mousemove" || type === "mousedown" || type === "mouseup" || type === "DOMMouseScroll" || type === "mousewheel" || type === "touchstart") detachEventHandler(eventHandlers[i])
  8205. }
  8206. if (p.touchStart !== undef || p.touchMove !== undef || p.touchEnd !== undef || p.touchCancel !== undef) {
  8207. attachEventHandler(curElement, "touchstart", function(t) {
  8208. if (p.touchStart !== undef) {
  8209. t = addTouchEventOffset(t);
  8210. p.touchStart(t)
  8211. }
  8212. });
  8213. attachEventHandler(curElement, "touchmove", function(t) {
  8214. if (p.touchMove !== undef) {
  8215. t.preventDefault();
  8216. t = addTouchEventOffset(t);
  8217. p.touchMove(t)
  8218. }
  8219. });
  8220. attachEventHandler(curElement, "touchend", function(t) {
  8221. if (p.touchEnd !== undef) {
  8222. t = addTouchEventOffset(t);
  8223. p.touchEnd(t)
  8224. }
  8225. });
  8226. attachEventHandler(curElement, "touchcancel", function(t) {
  8227. if (p.touchCancel !== undef) {
  8228. t = addTouchEventOffset(t);
  8229. p.touchCancel(t)
  8230. }
  8231. })
  8232. } else {
  8233. attachEventHandler(curElement, "touchstart", function(e) {
  8234. updateMousePosition(curElement, e.touches[0]);
  8235. p.__mousePressed = true;
  8236. p.mouseDragging = false;
  8237. p.mouseButton = 37;
  8238. if (typeof p.mousePressed === "function") p.mousePressed()
  8239. });
  8240. attachEventHandler(curElement, "touchmove", function(e) {
  8241. e.preventDefault();
  8242. updateMousePosition(curElement, e.touches[0]);
  8243. if (typeof p.mouseMoved === "function" && !p.__mousePressed) p.mouseMoved();
  8244. if (typeof p.mouseDragged === "function" && p.__mousePressed) {
  8245. p.mouseDragged();
  8246. p.mouseDragging = true
  8247. }
  8248. });
  8249. attachEventHandler(curElement, "touchend", function(e) {
  8250. p.__mousePressed = false;
  8251. if (typeof p.mouseClicked === "function" && !p.mouseDragging) p.mouseClicked();
  8252. if (typeof p.mouseReleased === "function") p.mouseReleased()
  8253. })
  8254. }
  8255. curElement.dispatchEvent(t)
  8256. });
  8257. (function() {
  8258. var enabled = true,
  8259. contextMenu = function(e) {
  8260. e.preventDefault();
  8261. e.stopPropagation()
  8262. };
  8263. p.disableContextMenu = function() {
  8264. if (!enabled) return;
  8265. attachEventHandler(curElement, "contextmenu", contextMenu);
  8266. enabled = false
  8267. };
  8268. p.enableContextMenu = function() {
  8269. if (enabled) return;
  8270. detachEventHandler({
  8271. elem: curElement,
  8272. type: "contextmenu",
  8273. fn: contextMenu
  8274. });
  8275. enabled = true
  8276. }
  8277. })();
  8278. attachEventHandler(curElement, "mousemove", function(e) {
  8279. updateMousePosition(curElement, e);
  8280. if (typeof p.mouseMoved === "function" && !p.__mousePressed) p.mouseMoved();
  8281. if (typeof p.mouseDragged === "function" && p.__mousePressed) {
  8282. p.mouseDragged();
  8283. p.mouseDragging = true
  8284. }
  8285. });
  8286. attachEventHandler(curElement, "mouseout", function(e) {
  8287. if (typeof p.mouseOut === "function") p.mouseOut()
  8288. });
  8289. attachEventHandler(curElement, "mouseover", function(e) {
  8290. updateMousePosition(curElement, e);
  8291. if (typeof p.mouseOver === "function") p.mouseOver()
  8292. });
  8293. curElement.onmousedown = function() {
  8294. curElement.focus();
  8295. return false
  8296. };
  8297. attachEventHandler(curElement, "mousedown", function(e) {
  8298. p.__mousePressed = true;
  8299. p.mouseDragging = false;
  8300. switch (e.which) {
  8301. case 1:
  8302. p.mouseButton = 37;
  8303. break;
  8304. case 2:
  8305. p.mouseButton = 3;
  8306. break;
  8307. case 3:
  8308. p.mouseButton = 39;
  8309. break
  8310. }
  8311. if (typeof p.mousePressed === "function") p.mousePressed()
  8312. });
  8313. attachEventHandler(curElement, "mouseup", function(e) {
  8314. p.__mousePressed = false;
  8315. if (typeof p.mouseClicked === "function" && !p.mouseDragging) p.mouseClicked();
  8316. if (typeof p.mouseReleased === "function") p.mouseReleased()
  8317. });
  8318. var mouseWheelHandler = function(e) {
  8319. var delta = 0;
  8320. if (e.wheelDelta) {
  8321. delta = e.wheelDelta / 120;
  8322. if (window.opera) delta = -delta
  8323. } else if (e.detail) delta = -e.detail / 3;
  8324. p.mouseScroll = delta;
  8325. if (delta && typeof p.mouseScrolled === "function") p.mouseScrolled()
  8326. };
  8327. attachEventHandler(document, "DOMMouseScroll", mouseWheelHandler);
  8328. attachEventHandler(document, "mousewheel", mouseWheelHandler);
  8329. if (!curElement.getAttribute("tabindex")) curElement.setAttribute("tabindex", 0);
  8330. function getKeyCode(e) {
  8331. var code = e.which || e.keyCode;
  8332. switch (code) {
  8333. case 13:
  8334. return 10;
  8335. case 91:
  8336. case 93:
  8337. case 224:
  8338. return 157;
  8339. case 57392:
  8340. return 17;
  8341. case 46:
  8342. return 127;
  8343. case 45:
  8344. return 155
  8345. }
  8346. return code
  8347. }
  8348. function getKeyChar(e) {
  8349. var c = e.which || e.keyCode;
  8350. var anyShiftPressed = e.shiftKey || e.ctrlKey || e.altKey || e.metaKey;
  8351. switch (c) {
  8352. case 13:
  8353. c = anyShiftPressed ? 13 : 10;
  8354. break;
  8355. case 8:
  8356. c = anyShiftPressed ? 127 : 8;
  8357. break
  8358. }
  8359. return new Char(c)
  8360. }
  8361. function suppressKeyEvent(e) {
  8362. if (typeof e.preventDefault === "function") e.preventDefault();
  8363. else if (typeof e.stopPropagation === "function") e.stopPropagation();
  8364. return false
  8365. }
  8366. function updateKeyPressed() {
  8367. var ch;
  8368. for (ch in pressedKeysMap) if (pressedKeysMap.hasOwnProperty(ch)) {
  8369. p.__keyPressed = true;
  8370. return
  8371. }
  8372. p.__keyPressed = false
  8373. }
  8374. function resetKeyPressed() {
  8375. p.__keyPressed = false;
  8376. pressedKeysMap = [];
  8377. lastPressedKeyCode = null
  8378. }
  8379. function simulateKeyTyped(code, c) {
  8380. pressedKeysMap[code] = c;
  8381. lastPressedKeyCode = null;
  8382. p.key = c;
  8383. p.keyCode = code;
  8384. p.keyPressed();
  8385. p.keyCode = 0;
  8386. p.keyTyped();
  8387. updateKeyPressed()
  8388. }
  8389. function handleKeydown(e) {
  8390. var code = getKeyCode(e);
  8391. if (code === 127) {
  8392. simulateKeyTyped(code, new Char(127));
  8393. return
  8394. }
  8395. if (codedKeys.indexOf(code) < 0) {
  8396. lastPressedKeyCode = code;
  8397. return
  8398. }
  8399. var c = new Char(65535);
  8400. p.key = c;
  8401. p.keyCode = code;
  8402. pressedKeysMap[code] = c;
  8403. p.keyPressed();
  8404. lastPressedKeyCode = null;
  8405. updateKeyPressed();
  8406. return suppressKeyEvent(e)
  8407. }
  8408. function handleKeypress(e) {
  8409. if (lastPressedKeyCode === null) return;
  8410. var code = lastPressedKeyCode,
  8411. c = getKeyChar(e);
  8412. simulateKeyTyped(code, c);
  8413. return suppressKeyEvent(e)
  8414. }
  8415. function handleKeyup(e) {
  8416. var code = getKeyCode(e),
  8417. c = pressedKeysMap[code];
  8418. if (c === undef) return;
  8419. p.key = c;
  8420. p.keyCode = code;
  8421. p.keyReleased();
  8422. delete pressedKeysMap[code];
  8423. updateKeyPressed()
  8424. }
  8425. if (!pgraphicsMode) {
  8426. if (aCode instanceof Processing.Sketch) curSketch = aCode;
  8427. else if (typeof aCode === "function") curSketch = new Processing.Sketch(aCode);
  8428. else if (!aCode) curSketch = new Processing.Sketch(function() {});
  8429. else curSketch = Processing.compile(aCode);
  8430. p.externals.sketch = curSketch;
  8431. wireDimensionalFunctions();
  8432. curElement.onfocus = function() {
  8433. p.focused = true
  8434. };
  8435. curElement.onblur = function() {
  8436. p.focused = false;
  8437. if (!curSketch.options.globalKeyEvents) resetKeyPressed()
  8438. };
  8439. if (curSketch.options.pauseOnBlur) {
  8440. attachEventHandler(window, "focus", function() {
  8441. if (doLoop) p.loop()
  8442. });
  8443. attachEventHandler(window, "blur", function() {
  8444. if (doLoop && loopStarted) {
  8445. p.noLoop();
  8446. doLoop = true
  8447. }
  8448. resetKeyPressed()
  8449. })
  8450. }
  8451. var keyTrigger = curSketch.options.globalKeyEvents ? window : curElement;
  8452. attachEventHandler(keyTrigger, "keydown", handleKeydown);
  8453. attachEventHandler(keyTrigger, "keypress", handleKeypress);
  8454. attachEventHandler(keyTrigger, "keyup", handleKeyup);
  8455. for (var i in Processing.lib) if (Processing.lib.hasOwnProperty(i)) if (Processing.lib[i].hasOwnProperty("attach")) Processing.lib[i].attach(p);
  8456. else if (Processing.lib[i] instanceof Function) Processing.lib[i].call(this);
  8457. var retryInterval = 100;
  8458. var executeSketch = function(processing) {
  8459. if (! (curSketch.imageCache.pending || PFont.preloading.pending(retryInterval))) {
  8460. if (window.opera) {
  8461. var link, element, operaCache = curSketch.imageCache.operaCache;
  8462. for (link in operaCache) if (operaCache.hasOwnProperty(link)) {
  8463. element = operaCache[link];
  8464. if (element !== null) document.body.removeChild(element);
  8465. delete operaCache[link]
  8466. }
  8467. }
  8468. curSketch.attach(processing, defaultScope);
  8469. curSketch.onLoad(processing);
  8470. if (processing.setup) {
  8471. processing.setup();
  8472. processing.resetMatrix();
  8473. curSketch.onSetup()
  8474. }
  8475. resetContext();
  8476. if (processing.draw) if (!doLoop) processing.redraw();
  8477. else processing.loop()
  8478. } else window.setTimeout(function() {
  8479. executeSketch(processing)
  8480. },
  8481. retryInterval)
  8482. };
  8483. addInstance(this);
  8484. executeSketch(p)
  8485. } else {
  8486. curSketch = new Processing.Sketch;
  8487. wireDimensionalFunctions();
  8488. p.size = function(w, h, render) {
  8489. if (render && render === 2) wireDimensionalFunctions("3D");
  8490. else wireDimensionalFunctions("2D");
  8491. p.size(w, h, render)
  8492. }
  8493. }
  8494. };
  8495. Processing.debug = debug;
  8496. Processing.prototype = defaultScope;
  8497. function getGlobalMembers() {
  8498. var names = ["abs", "acos", "alpha", "ambient", "ambientLight", "append",
  8499. "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",
  8500. "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",
  8501. "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",
  8502. "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",
  8503. "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",
  8504. "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"];
  8505. var members = {};
  8506. var i, l;
  8507. for (i = 0, l = names.length; i < l; ++i) members[names[i]] = null;
  8508. for (var lib in Processing.lib) if (Processing.lib.hasOwnProperty(lib)) if (Processing.lib[lib].exports) {
  8509. var exportedNames = Processing.lib[lib].exports;
  8510. for (i = 0, l = exportedNames.length; i < l; ++i) members[exportedNames[i]] = null
  8511. }
  8512. return members
  8513. }
  8514. function parseProcessing(code) {
  8515. var globalMembers = getGlobalMembers();
  8516. function splitToAtoms(code) {
  8517. var atoms = [];
  8518. var items = code.split(/([\{\[\(\)\]\}])/);
  8519. var result = items[0];
  8520. var stack = [];
  8521. for (var i = 1; i < items.length; i += 2) {
  8522. var item = items[i];
  8523. if (item === "[" || item === "{" || item === "(") {
  8524. stack.push(result);
  8525. result = item
  8526. } else if (item === "]" || item === "}" || item === ")") {
  8527. var kind = item === "}" ? "A" : item === ")" ? "B" : "C";
  8528. var index = atoms.length;
  8529. atoms.push(result + item);
  8530. result = stack.pop() + '"' + kind + (index + 1) + '"'
  8531. }
  8532. result += items[i + 1]
  8533. }
  8534. atoms.unshift(result);
  8535. return atoms
  8536. }
  8537. function injectStrings(code, strings) {
  8538. return code.replace(/'(\d+)'/g, function(all, index) {
  8539. var val = strings[index];
  8540. if (val.charAt(0) === "/") return val;
  8541. return /^'((?:[^'\\\n])|(?:\\.[0-9A-Fa-f]*))'$/.test(val) ? "(new $p.Character(" + val + "))" : val
  8542. })
  8543. }
  8544. function trimSpaces(string) {
  8545. var m1 = /^\s*/.exec(string),
  8546. result;
  8547. if (m1[0].length === string.length) result = {
  8548. left: m1[0],
  8549. middle: "",
  8550. right: ""
  8551. };
  8552. else {
  8553. var m2 = /\s*$/.exec(string);
  8554. result = {
  8555. left: m1[0],
  8556. middle: string.substring(m1[0].length, m2.index),
  8557. right: m2[0]
  8558. }
  8559. }
  8560. result.untrim = function(t) {
  8561. return this.left + t + this.right
  8562. };
  8563. return result
  8564. }
  8565. function trim(string) {
  8566. return string.replace(/^\s+/, "").replace(/\s+$/, "")
  8567. }
  8568. function appendToLookupTable(table, array) {
  8569. for (var i = 0, l = array.length; i < l; ++i) table[array[i]] = null;
  8570. return table
  8571. }
  8572. function isLookupTableEmpty(table) {
  8573. for (var i in table) if (table.hasOwnProperty(i)) return false;
  8574. return true
  8575. }
  8576. function getAtomIndex(templ) {
  8577. return templ.substring(2, templ.length - 1)
  8578. }
  8579. var codeWoExtraCr = code.replace(/\r\n?|\n\r/g, "\n");
  8580. var strings = [];
  8581. var codeWoStrings = codeWoExtraCr.replace(/("(?:[^"\\\n]|\\.)*")|('(?:[^'\\\n]|\\.)*')|(([\[\(=|&!\^:?]\s*)(\/(?![*\/])(?:[^\/\\\n]|\\.)*\/[gim]*)\b)|(\/\/[^\n]*\n)|(\/\*(?:(?!\*\/)(?:.|\n))*\*\/)/g, function(all, quoted, aposed, regexCtx, prefix, regex, singleComment, comment) {
  8582. var index;
  8583. if (quoted || aposed) {
  8584. index = strings.length;
  8585. strings.push(all);
  8586. return "'" + index + "'"
  8587. }
  8588. if (regexCtx) {
  8589. index = strings.length;
  8590. strings.push(regex);
  8591. return prefix + "'" + index + "'"
  8592. }
  8593. return comment !== "" ? " " : "\n"
  8594. });
  8595. codeWoStrings = codeWoStrings.replace(/__x([0-9A-F]{4})/g, function(all, hexCode) {
  8596. return "__x005F_x" + hexCode
  8597. });
  8598. codeWoStrings = codeWoStrings.replace(/\$/g, "__x0024");
  8599. var genericsWereRemoved;
  8600. var codeWoGenerics = codeWoStrings;
  8601. var replaceFunc = function(all, before, types, after) {
  8602. if ( !! before || !!after) return all;
  8603. genericsWereRemoved = true;
  8604. return ""
  8605. };
  8606. do {
  8607. genericsWereRemoved = false;
  8608. 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)
  8609. } while (genericsWereRemoved);
  8610. var atoms = splitToAtoms(codeWoGenerics);
  8611. var replaceContext;
  8612. var declaredClasses = {},
  8613. currentClassId, classIdSeed = 0;
  8614. function addAtom(text, type) {
  8615. var lastIndex = atoms.length;
  8616. atoms.push(text);
  8617. return '"' + type + lastIndex + '"'
  8618. }
  8619. function generateClassId() {
  8620. return "class" + ++classIdSeed
  8621. }
  8622. function appendClass(class_, classId, scopeId) {
  8623. class_.classId = classId;
  8624. class_.scopeId = scopeId;
  8625. declaredClasses[classId] = class_
  8626. }
  8627. var transformClassBody, transformInterfaceBody, transformStatementsBlock, transformStatements, transformMain, transformExpression;
  8628. 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;
  8629. 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;
  8630. 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*)*([=,]|$)/;
  8631. 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;
  8632. 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*/;
  8633. var functionsRegex = /\bfunction(?:\s+([A-Za-z_$][\w$]*))?\s*("B\d+")\s*("A\d+")/g;
  8634. function extractClassesAndMethods(code) {
  8635. var s = code;
  8636. s = s.replace(classesRegex, function(all) {
  8637. return addAtom(all, "E")
  8638. });
  8639. s = s.replace(methodsRegex, function(all) {
  8640. return addAtom(all, "D")
  8641. });
  8642. s = s.replace(functionsRegex, function(all) {
  8643. return addAtom(all, "H")
  8644. });
  8645. return s
  8646. }
  8647. function extractConstructors(code, className) {
  8648. var result = code.replace(cstrsRegex, function(all, attr, name, params, throws_, body) {
  8649. if (name !== className) return all;
  8650. return addAtom(all, "G")
  8651. });
  8652. return result
  8653. }
  8654. function AstParam(name) {
  8655. this.name = name
  8656. }
  8657. AstParam.prototype.toString = function() {
  8658. return this.name
  8659. };
  8660. function AstParams(params, methodArgsParam) {
  8661. this.params = params;
  8662. this.methodArgsParam = methodArgsParam
  8663. }
  8664. AstParams.prototype.getNames = function() {
  8665. var names = [];
  8666. for (var i = 0, l = this.params.length; i < l; ++i) names.push(this.params[i].name);
  8667. return names
  8668. };
  8669. AstParams.prototype.prependMethodArgs = function(body) {
  8670. if (!this.methodArgsParam) return body;
  8671. return "{\nvar " + this.methodArgsParam.name + " = Array.prototype.slice.call(arguments, " + this.params.length + ");\n" + body.substring(1)
  8672. };
  8673. AstParams.prototype.toString = function() {
  8674. if (this.params.length === 0) return "()";
  8675. var result = "(";
  8676. for (var i = 0, l = this.params.length; i < l; ++i) result += this.params[i] + ", ";
  8677. return result.substring(0, result.length - 2) + ")"
  8678. };
  8679. function transformParams(params) {
  8680. var paramsWoPars = trim(params.substring(1, params.length - 1));
  8681. var result = [],
  8682. methodArgsParam = null;
  8683. if (paramsWoPars !== "") {
  8684. var paramList = paramsWoPars.split(",");
  8685. for (var i = 0; i < paramList.length; ++i) {
  8686. var param = /\b([A-Za-z_$][\w$]*\b)(\s*"[ABC][\d]*")*\s*$/.exec(paramList[i]);
  8687. if (i === paramList.length - 1 && paramList[i].indexOf("...") >= 0) {
  8688. methodArgsParam = new AstParam(param[1]);
  8689. break
  8690. }
  8691. result.push(new AstParam(param[1]))
  8692. }
  8693. }
  8694. return new AstParams(result, methodArgsParam)
  8695. }
  8696. function preExpressionTransform(expr) {
  8697. var s = expr;
  8698. 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) {
  8699. return init
  8700. });
  8701. 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) {
  8702. return addAtom(all, "F")
  8703. });
  8704. s = s.replace(functionsRegex, function(all) {
  8705. return addAtom(all, "H")
  8706. });
  8707. 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) {
  8708. var args = index.replace(/"C(\d+)"/g, function(all, j) {
  8709. return atoms[j]
  8710. }).replace(/\[\s*\]/g, "[null]").replace(/\s*\]\s*\[\s*/g, ", ");
  8711. var arrayInitializer = "{" + args.substring(1, args.length - 1) + "}";
  8712. var createArrayArgs = "('" + type + "', " + addAtom(arrayInitializer, "A") + ")";
  8713. return "$p.createJavaArray" + addAtom(createArrayArgs, "B")
  8714. });
  8715. s = s.replace(/(\.\s*length)\s*"B\d+"/g, "$1");
  8716. s = s.replace(/#([0-9A-Fa-f]{6})\b/g, function(all, digits) {
  8717. return "0xFF" + digits
  8718. });
  8719. s = s.replace(/"B(\d+)"(\s*(?:[\w$']|"B))/g, function(all, index, next) {
  8720. var atom = atoms[index];
  8721. if (!/^\(\s*[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*\s*(?:"C\d+"\s*)*\)$/.test(atom)) return all;
  8722. if (/^\(\s*int\s*\)$/.test(atom)) return "(int)" + next;
  8723. var indexParts = atom.split(/"C(\d+)"/g);
  8724. if (indexParts.length > 1) if (!/^\[\s*\]$/.test(atoms[indexParts[1]])) return all;
  8725. return "" + next
  8726. });
  8727. s = s.replace(/\(int\)([^,\]\)\}\?\:\*\+\-\/\^\|\%\&\~<\>\=]+)/g, function(all, arg) {
  8728. var trimmed = trimSpaces(arg);
  8729. return trimmed.untrim("__int_cast(" + trimmed.middle + ")")
  8730. });
  8731. s = s.replace(/\bsuper(\s*"B\d+")/g, "$$superCstr$1").replace(/\bsuper(\s*\.)/g, "$$super$1");
  8732. s = s.replace(/\b0+((\d*)(?:\.[\d*])?(?:[eE][\-\+]?\d+)?[fF]?)\b/, function(all, numberWo0, intPart) {
  8733. if (numberWo0 === intPart) return all;
  8734. return intPart === "" ? "0" + numberWo0 : numberWo0
  8735. });
  8736. s = s.replace(/\b(\.?\d+\.?)[fF]\b/g, "$1");
  8737. s = s.replace(/([^\s])%([^=\s])/g, "$1 % $2");
  8738. s = s.replace(/\b(frameRate|keyPressed|mousePressed)\b(?!\s*"B)/g, "__$1");
  8739. s = s.replace(/\b(boolean|byte|char|float|int)\s*"B/g, function(all, name) {
  8740. return "parse" + name.substring(0, 1).toUpperCase() + name.substring(1) + '"B'
  8741. });
  8742. s = s.replace(/\bpixels\b\s*(("C(\d+)")|\.length)?(\s*=(?!=)([^,\]\)\}]+))?/g, function(all, indexOrLength, index, atomIndex, equalsPart, rightSide) {
  8743. if (index) {
  8744. var atom = atoms[atomIndex];
  8745. if (equalsPart) return "pixels.setPixel" + addAtom("(" + atom.substring(1, atom.length - 1) + "," + rightSide + ")", "B");
  8746. return "pixels.getPixel" + addAtom("(" + atom.substring(1, atom.length - 1) + ")", "B")
  8747. }
  8748. if (indexOrLength) return "pixels.getLength" + addAtom("()", "B");
  8749. if (equalsPart) return "pixels.set" + addAtom("(" + rightSide + ")", "B");
  8750. return "pixels.toArray" + addAtom("()", "B")
  8751. });
  8752. var repeatJavaReplacement;
  8753. function replacePrototypeMethods(all, subject, method, atomIndex) {
  8754. var atom = atoms[atomIndex];
  8755. repeatJavaReplacement = true;
  8756. var trimmed = trimSpaces(atom.substring(1, atom.length - 1));
  8757. return "__" + method + (trimmed.middle === "" ? addAtom("(" + subject.replace(/\.\s*$/, "") + ")", "B") : addAtom("(" + subject.replace(/\.\s*$/, "") + "," + trimmed.middle + ")", "B"))
  8758. }
  8759. do {
  8760. repeatJavaReplacement = false;
  8761. 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)
  8762. } while (repeatJavaReplacement);
  8763. function replaceInstanceof(all, subject, type) {
  8764. repeatJavaReplacement = true;
  8765. return "__instanceof" + addAtom("(" + subject + ", " + type + ")", "B")
  8766. }
  8767. do {
  8768. repeatJavaReplacement = false;
  8769. 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)
  8770. } while (repeatJavaReplacement);
  8771. s = s.replace(/\bthis(\s*"B\d+")/g, "$$constr$1");
  8772. return s
  8773. }
  8774. function AstInlineClass(baseInterfaceName, body) {
  8775. this.baseInterfaceName = baseInterfaceName;
  8776. this.body = body;
  8777. body.owner = this
  8778. }
  8779. AstInlineClass.prototype.toString = function() {
  8780. return "new (" + this.body + ")"
  8781. };
  8782. function transformInlineClass(class_) {
  8783. var m = (new RegExp(/\bnew\s*([A-Za-z_$][\w$]*\s*(?:\.\s*[A-Za-z_$][\w$]*)*)\s*"B\d+"\s*"A(\d+)"/)).exec(class_);
  8784. var oldClassId = currentClassId,
  8785. newClassId = generateClassId();
  8786. currentClassId = newClassId;
  8787. var uniqueClassName = m[1] + "$" + newClassId;
  8788. var inlineClass = new AstInlineClass(uniqueClassName, transformClassBody(atoms[m[2]], uniqueClassName, "", "implements " + m[1]));
  8789. appendClass(inlineClass, newClassId, oldClassId);
  8790. currentClassId = oldClassId;
  8791. return inlineClass
  8792. }
  8793. function AstFunction(name, params, body) {
  8794. this.name = name;
  8795. this.params = params;
  8796. this.body = body
  8797. }
  8798. AstFunction.prototype.toString = function() {
  8799. var oldContext = replaceContext;
  8800. var names = appendToLookupTable({
  8801. "this": null
  8802. },
  8803. this.params.getNames());
  8804. replaceContext = function(subject) {
  8805. return names.hasOwnProperty(subject.name) ? subject.name : oldContext(subject)
  8806. };
  8807. var result = "function";
  8808. if (this.name) result += " " + this.name;
  8809. var body = this.params.prependMethodArgs(this.body.toString());
  8810. result += this.params + " " + body;
  8811. replaceContext = oldContext;
  8812. return result
  8813. };
  8814. function transformFunction(class_) {
  8815. var m = (new RegExp(/\b([A-Za-z_$][\w$]*)\s*"B(\d+)"\s*"A(\d+)"/)).exec(class_);
  8816. return new AstFunction(m[1] !== "function" ? m[1] : null, transformParams(atoms[m[2]]), transformStatementsBlock(atoms[m[3]]))
  8817. }
  8818. function AstInlineObject(members) {
  8819. this.members = members
  8820. }
  8821. AstInlineObject.prototype.toString = function() {
  8822. var oldContext = replaceContext;
  8823. replaceContext = function(subject) {
  8824. return subject.name === "this" ? "this" : oldContext(subject)
  8825. };
  8826. var result = "";
  8827. for (var i = 0, l = this.members.length; i < l; ++i) {
  8828. if (this.members[i].label) result += this.members[i].label + ": ";
  8829. result += this.members[i].value.toString() + ", "
  8830. }
  8831. replaceContext = oldContext;
  8832. return result.substring(0, result.length - 2)
  8833. };
  8834. function transformInlineObject(obj) {
  8835. var members = obj.split(",");
  8836. for (var i = 0; i < members.length; ++i) {
  8837. var label = members[i].indexOf(":");
  8838. if (label < 0) members[i] = {
  8839. value: transformExpression(members[i])
  8840. };
  8841. else members[i] = {
  8842. label: trim(members[i].substring(0, label)),
  8843. value: transformExpression(trim(members[i].substring(label + 1)))
  8844. }
  8845. }
  8846. return new AstInlineObject(members)
  8847. }
  8848. function expandExpression(expr) {
  8849. if (expr.charAt(0) === "(" || expr.charAt(0) === "[") return expr.charAt(0) + expandExpression(expr.substring(1, expr.length - 1)) + expr.charAt(expr.length - 1);
  8850. if (expr.charAt(0) === "{") {
  8851. if (/^\{\s*(?:[A-Za-z_$][\w$]*|'\d+')\s*:/.test(expr)) return "{" + addAtom(expr.substring(1, expr.length - 1), "I") + "}";
  8852. return "[" + expandExpression(expr.substring(1, expr.length - 1)) + "]"
  8853. }
  8854. var trimmed = trimSpaces(expr);
  8855. var result = preExpressionTransform(trimmed.middle);
  8856. result = result.replace(/"[ABC](\d+)"/g, function(all, index) {
  8857. return expandExpression(atoms[index])
  8858. });
  8859. return trimmed.untrim(result)
  8860. }
  8861. function replaceContextInVars(expr) {
  8862. return expr.replace(/(\.\s*)?((?:\b[A-Za-z_]|\$)[\w$]*)(\s*\.\s*([A-Za-z_$][\w$]*)(\s*\()?)?/g, function(all, memberAccessSign, identifier, suffix, subMember, callSign) {
  8863. if (memberAccessSign) return all;
  8864. var subject = {
  8865. name: identifier,
  8866. member: subMember,
  8867. callSign: !!callSign
  8868. };
  8869. return replaceContext(subject) + (suffix === undef ? "" : suffix)
  8870. })
  8871. }
  8872. function AstExpression(expr, transforms) {
  8873. this.expr = expr;
  8874. this.transforms = transforms
  8875. }
  8876. AstExpression.prototype.toString = function() {
  8877. var transforms = this.transforms;
  8878. var expr = replaceContextInVars(this.expr);
  8879. return expr.replace(/"!(\d+)"/g, function(all, index) {
  8880. return transforms[index].toString()
  8881. })
  8882. };
  8883. transformExpression = function(expr) {
  8884. var transforms = [];
  8885. var s = expandExpression(expr);
  8886. s = s.replace(/"H(\d+)"/g, function(all, index) {
  8887. transforms.push(transformFunction(atoms[index]));
  8888. return '"!' + (transforms.length - 1) + '"'
  8889. });
  8890. s = s.replace(/"F(\d+)"/g, function(all, index) {
  8891. transforms.push(transformInlineClass(atoms[index]));
  8892. return '"!' + (transforms.length - 1) + '"'
  8893. });
  8894. s = s.replace(/"I(\d+)"/g, function(all, index) {
  8895. transforms.push(transformInlineObject(atoms[index]));
  8896. return '"!' + (transforms.length - 1) + '"'
  8897. });
  8898. return new AstExpression(s, transforms)
  8899. };
  8900. function AstVarDefinition(name, value, isDefault) {
  8901. this.name = name;
  8902. this.value = value;
  8903. this.isDefault = isDefault
  8904. }
  8905. AstVarDefinition.prototype.toString = function() {
  8906. return this.name + " = " + this.value
  8907. };
  8908. function transformVarDefinition(def, defaultTypeValue) {
  8909. var eqIndex = def.indexOf("=");
  8910. var name, value, isDefault;
  8911. if (eqIndex < 0) {
  8912. name = def;
  8913. value = defaultTypeValue;
  8914. isDefault = true
  8915. } else {
  8916. name = def.substring(0, eqIndex);
  8917. value = transformExpression(def.substring(eqIndex + 1));
  8918. isDefault = false
  8919. }
  8920. return new AstVarDefinition(trim(name.replace(/(\s*"C\d+")+/g, "")), value, isDefault)
  8921. }
  8922. function getDefaultValueForType(type) {
  8923. if (type === "int" || type === "float") return "0";
  8924. if (type === "boolean") return "false";
  8925. if (type === "color") return "0x00000000";
  8926. return "null"
  8927. }
  8928. function AstVar(definitions, varType) {
  8929. this.definitions = definitions;
  8930. this.varType = varType
  8931. }
  8932. AstVar.prototype.getNames = function() {
  8933. var names = [];
  8934. for (var i = 0, l = this.definitions.length; i < l; ++i) names.push(this.definitions[i].name);
  8935. return names
  8936. };
  8937. AstVar.prototype.toString = function() {
  8938. return "var " + this.definitions.join(",")
  8939. };
  8940. function AstStatement(expression) {
  8941. this.expression = expression
  8942. }
  8943. AstStatement.prototype.toString = function() {
  8944. return this.expression.toString()
  8945. };
  8946. function transformStatement(statement) {
  8947. if (fieldTest.test(statement)) {
  8948. var attrAndType = attrAndTypeRegex.exec(statement);
  8949. var definitions = statement.substring(attrAndType[0].length).split(",");
  8950. var defaultTypeValue = getDefaultValueForType(attrAndType[2]);
  8951. for (var i = 0; i < definitions.length; ++i) definitions[i] = transformVarDefinition(definitions[i], defaultTypeValue);
  8952. return new AstVar(definitions, attrAndType[2])
  8953. }
  8954. return new AstStatement(transformExpression(statement))
  8955. }
  8956. function AstForExpression(initStatement, condition, step) {
  8957. this.initStatement = initStatement;
  8958. this.condition = condition;
  8959. this.step = step
  8960. }
  8961. AstForExpression.prototype.toString = function() {
  8962. return "(" + this.initStatement + "; " + this.condition + "; " + this.step + ")"
  8963. };
  8964. function AstForInExpression(initStatement, container) {
  8965. this.initStatement = initStatement;
  8966. this.container = container
  8967. }
  8968. AstForInExpression.prototype.toString = function() {
  8969. var init = this.initStatement.toString();
  8970. if (init.indexOf("=") >= 0) init = init.substring(0, init.indexOf("="));
  8971. return "(" + init + " in " + this.container + ")"
  8972. };
  8973. function AstForEachExpression(initStatement, container) {
  8974. this.initStatement = initStatement;
  8975. this.container = container
  8976. }
  8977. AstForEachExpression.iteratorId = 0;
  8978. AstForEachExpression.prototype.toString = function() {
  8979. var init = this.initStatement.toString();
  8980. var iterator = "$it" + AstForEachExpression.iteratorId++;
  8981. var variableName = init.replace(/^\s*var\s*/, "").split("=")[0];
  8982. var initIteratorAndVariable = "var " + iterator + " = new $p.ObjectIterator(" + this.container + "), " + variableName + " = void(0)";
  8983. var nextIterationCondition = iterator + ".hasNext() && ((" + variableName + " = " + iterator + ".next()) || true)";
  8984. return "(" + initIteratorAndVariable + "; " + nextIterationCondition + ";)"
  8985. };
  8986. function transformForExpression(expr) {
  8987. var content;
  8988. if (/\bin\b/.test(expr)) {
  8989. content = expr.substring(1, expr.length - 1).split(/\bin\b/g);
  8990. return new AstForInExpression(transformStatement(trim(content[0])), transformExpression(content[1]))
  8991. }
  8992. if (expr.indexOf(":") >= 0 && expr.indexOf(";") < 0) {
  8993. content = expr.substring(1, expr.length - 1).split(":");
  8994. return new AstForEachExpression(transformStatement(trim(content[0])), transformExpression(content[1]))
  8995. }
  8996. content = expr.substring(1, expr.length - 1).split(";");
  8997. return new AstForExpression(transformStatement(trim(content[0])), transformExpression(content[1]), transformExpression(content[2]))
  8998. }
  8999. function sortByWeight(array) {
  9000. array.sort(function(a, b) {
  9001. return b.weight - a.weight
  9002. })
  9003. }
  9004. function AstInnerInterface(name, body, isStatic) {
  9005. this.name = name;
  9006. this.body = body;
  9007. this.isStatic = isStatic;
  9008. body.owner = this
  9009. }
  9010. AstInnerInterface.prototype.toString = function() {
  9011. return "" + this.body
  9012. };
  9013. function AstInnerClass(name, body, isStatic) {
  9014. this.name = name;
  9015. this.body = body;
  9016. this.isStatic = isStatic;
  9017. body.owner = this
  9018. }
  9019. AstInnerClass.prototype.toString = function() {
  9020. return "" + this.body
  9021. };
  9022. function transformInnerClass(class_) {
  9023. var m = classesRegex.exec(class_);
  9024. classesRegex.lastIndex = 0;
  9025. var isStatic = m[1].indexOf("static") >= 0;
  9026. var body = atoms[getAtomIndex(m[6])],
  9027. innerClass;
  9028. var oldClassId = currentClassId,
  9029. newClassId = generateClassId();
  9030. currentClassId = newClassId;
  9031. if (m[2] === "interface") innerClass = new AstInnerInterface(m[3], transformInterfaceBody(body, m[3], m[4]), isStatic);
  9032. else innerClass = new AstInnerClass(m[3], transformClassBody(body, m[3], m[4], m[5]), isStatic);
  9033. appendClass(innerClass, newClassId, oldClassId);
  9034. currentClassId = oldClassId;
  9035. return innerClass
  9036. }
  9037. function AstClassMethod(name, params, body, isStatic) {
  9038. this.name = name;
  9039. this.params = params;
  9040. this.body = body;
  9041. this.isStatic = isStatic
  9042. }
  9043. AstClassMethod.prototype.toString = function() {
  9044. var paramNames = appendToLookupTable({},
  9045. this.params.getNames());
  9046. var oldContext = replaceContext;
  9047. replaceContext = function(subject) {
  9048. return paramNames.hasOwnProperty(subject.name) ? subject.name : oldContext(subject)
  9049. };
  9050. var body = this.params.prependMethodArgs(this.body.toString());
  9051. var result = "function " + this.methodId + this.params + " " + body + "\n";
  9052. replaceContext = oldContext;
  9053. return result
  9054. };
  9055. function transformClassMethod(method) {
  9056. var m = methodsRegex.exec(method);
  9057. methodsRegex.lastIndex = 0;
  9058. var isStatic = m[1].indexOf("static") >= 0;
  9059. var body = m[6] !== ";" ? atoms[getAtomIndex(m[6])] : "{}";
  9060. return new AstClassMethod(m[3], transformParams(atoms[getAtomIndex(m[4])]), transformStatementsBlock(body), isStatic)
  9061. }
  9062. function AstClassField(definitions, fieldType, isStatic) {
  9063. this.definitions = definitions;
  9064. this.fieldType = fieldType;
  9065. this.isStatic = isStatic
  9066. }
  9067. AstClassField.prototype.getNames = function() {
  9068. var names = [];
  9069. for (var i = 0, l = this.definitions.length; i < l; ++i) names.push(this.definitions[i].name);
  9070. return names
  9071. };
  9072. AstClassField.prototype.toString = function() {
  9073. var thisPrefix = replaceContext({
  9074. name: "[this]"
  9075. });
  9076. if (this.isStatic) {
  9077. var className = this.owner.name;
  9078. var staticDeclarations = [];
  9079. for (var i = 0, l = this.definitions.length; i < l; ++i) {
  9080. var definition = this.definitions[i];
  9081. var name = definition.name,
  9082. staticName = className + "." + name;
  9083. 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";
  9084. staticDeclarations.push(declaration)
  9085. }
  9086. return staticDeclarations.join("")
  9087. }
  9088. return thisPrefix + "." + this.definitions.join("; " + thisPrefix + ".")
  9089. };
  9090. function transformClassField(statement) {
  9091. var attrAndType = attrAndTypeRegex.exec(statement);
  9092. var isStatic = attrAndType[1].indexOf("static") >= 0;
  9093. var definitions = statement.substring(attrAndType[0].length).split(/,\s*/g);
  9094. var defaultTypeValue = getDefaultValueForType(attrAndType[2]);
  9095. for (var i = 0; i < definitions.length; ++i) definitions[i] = transformVarDefinition(definitions[i], defaultTypeValue);
  9096. return new AstClassField(definitions, attrAndType[2], isStatic)
  9097. }
  9098. function AstConstructor(params, body) {
  9099. this.params = params;
  9100. this.body = body
  9101. }
  9102. AstConstructor.prototype.toString = function() {
  9103. var paramNames = appendToLookupTable({},
  9104. this.params.getNames());
  9105. var oldContext = replaceContext;
  9106. replaceContext = function(subject) {
  9107. return paramNames.hasOwnProperty(subject.name) ? subject.name : oldContext(subject)
  9108. };
  9109. var prefix = "function $constr_" + this.params.params.length + this.params.toString();
  9110. var body = this.params.prependMethodArgs(this.body.toString());
  9111. if (!/\$(superCstr|constr)\b/.test(body)) body = "{\n$superCstr();\n" + body.substring(1);
  9112. replaceContext = oldContext;
  9113. return prefix + body + "\n"
  9114. };
  9115. function transformConstructor(cstr) {
  9116. var m = (new RegExp(/"B(\d+)"\s*"A(\d+)"/)).exec(cstr);
  9117. var params = transformParams(atoms[m[1]]);
  9118. return new AstConstructor(params, transformStatementsBlock(atoms[m[2]]))
  9119. }
  9120. function AstInterfaceBody(name, interfacesNames, methodsNames, fields, innerClasses, misc) {
  9121. var i, l;
  9122. this.name = name;
  9123. this.interfacesNames = interfacesNames;
  9124. this.methodsNames = methodsNames;
  9125. this.fields = fields;
  9126. this.innerClasses = innerClasses;
  9127. this.misc = misc;
  9128. for (i = 0, l = fields.length; i < l; ++i) fields[i].owner = this
  9129. }
  9130. AstInterfaceBody.prototype.getMembers = function(classFields, classMethods, classInners) {
  9131. if (this.owner.base) this.owner.base.body.getMembers(classFields, classMethods, classInners);
  9132. var i, j, l, m;
  9133. for (i = 0, l = this.fields.length; i < l; ++i) {
  9134. var fieldNames = this.fields[i].getNames();
  9135. for (j = 0, m = fieldNames.length; j < m; ++j) classFields[fieldNames[j]] = this.fields[i]
  9136. }
  9137. for (i = 0, l = this.methodsNames.length; i < l; ++i) {
  9138. var methodName = this.methodsNames[i];
  9139. classMethods[methodName] = true
  9140. }
  9141. for (i = 0, l = this.innerClasses.length; i < l; ++i) {
  9142. var innerClass = this.innerClasses[i];
  9143. classInners[innerClass.name] = innerClass
  9144. }
  9145. };
  9146. AstInterfaceBody.prototype.toString = function() {
  9147. function getScopeLevel(p) {
  9148. var i = 0;
  9149. while (p) {
  9150. ++i;
  9151. p = p.scope
  9152. }
  9153. return i
  9154. }
  9155. var scopeLevel = getScopeLevel(this.owner);
  9156. var className = this.name;
  9157. var staticDefinitions = "";
  9158. var metadata = "";
  9159. var thisClassFields = {},
  9160. thisClassMethods = {},
  9161. thisClassInners = {};
  9162. this.getMembers(thisClassFields, thisClassMethods, thisClassInners);
  9163. var i, l, j, m;
  9164. if (this.owner.interfaces) {
  9165. var resolvedInterfaces = [],
  9166. resolvedInterface;
  9167. for (i = 0, l = this.interfacesNames.length; i < l; ++i) {
  9168. if (!this.owner.interfaces[i]) continue;
  9169. resolvedInterface = replaceContext({
  9170. name: this.interfacesNames[i]
  9171. });
  9172. resolvedInterfaces.push(resolvedInterface);
  9173. staticDefinitions += "$p.extendInterfaceMembers(" + className + ", " + resolvedInterface + ");\n"
  9174. }
  9175. metadata += className + ".$interfaces = [" + resolvedInterfaces.join(", ") + "];\n"
  9176. }
  9177. metadata += className + ".$isInterface = true;\n";
  9178. metadata += className + ".$methods = ['" + this.methodsNames.join("', '") + "'];\n";
  9179. sortByWeight(this.innerClasses);
  9180. for (i = 0, l = this.innerClasses.length; i < l; ++i) {
  9181. var innerClass = this.innerClasses[i];
  9182. if (innerClass.isStatic) staticDefinitions += className + "." + innerClass.name + " = " + innerClass + ";\n"
  9183. }
  9184. for (i = 0, l = this.fields.length; i < l; ++i) {
  9185. var field = this.fields[i];
  9186. if (field.isStatic) staticDefinitions += className + "." + field.definitions.join(";\n" + className + ".") + ";\n"
  9187. }
  9188. return "(function() {\n" + "function " + className + "() { throw 'Unable to create the interface'; }\n" + staticDefinitions + metadata + "return " + className + ";\n" + "})()"
  9189. };
  9190. transformInterfaceBody = function(body, name, baseInterfaces) {
  9191. var declarations = body.substring(1, body.length - 1);
  9192. declarations = extractClassesAndMethods(declarations);
  9193. declarations = extractConstructors(declarations, name);
  9194. var methodsNames = [],
  9195. classes = [];
  9196. declarations = declarations.replace(/"([DE])(\d+)"/g, function(all, type, index) {
  9197. if (type === "D") methodsNames.push(index);
  9198. else if (type === "E") classes.push(index);
  9199. return ""
  9200. });
  9201. var fields = declarations.split(/;(?:\s*;)*/g);
  9202. var baseInterfaceNames;
  9203. var i, l;
  9204. if (baseInterfaces !== undef) baseInterfaceNames = baseInterfaces.replace(/^\s*extends\s+(.+?)\s*$/g, "$1").split(/\s*,\s*/g);
  9205. for (i = 0, l = methodsNames.length; i < l; ++i) {
  9206. var method = transformClassMethod(atoms[methodsNames[i]]);
  9207. methodsNames[i] = method.name
  9208. }
  9209. for (i = 0, l = fields.length - 1; i < l; ++i) {
  9210. var field = trimSpaces(fields[i]);
  9211. fields[i] = transformClassField(field.middle)
  9212. }
  9213. var tail = fields.pop();
  9214. for (i = 0, l = classes.length; i < l; ++i) classes[i] = transformInnerClass(atoms[classes[i]]);
  9215. return new AstInterfaceBody(name, baseInterfaceNames, methodsNames, fields, classes, {
  9216. tail: tail
  9217. })
  9218. };
  9219. function AstClassBody(name, baseClassName, interfacesNames, functions, methods, fields, cstrs, innerClasses, misc) {
  9220. var i, l;
  9221. this.name = name;
  9222. this.baseClassName = baseClassName;
  9223. this.interfacesNames = interfacesNames;
  9224. this.functions = functions;
  9225. this.methods = methods;
  9226. this.fields = fields;
  9227. this.cstrs = cstrs;
  9228. this.innerClasses = innerClasses;
  9229. this.misc = misc;
  9230. for (i = 0, l = fields.length; i < l; ++i) fields[i].owner = this
  9231. }
  9232. AstClassBody.prototype.getMembers = function(classFields, classMethods, classInners) {
  9233. if (this.owner.base) this.owner.base.body.getMembers(classFields, classMethods, classInners);
  9234. var i, j, l, m;
  9235. for (i = 0, l = this.fields.length; i < l; ++i) {
  9236. var fieldNames = this.fields[i].getNames();
  9237. for (j = 0, m = fieldNames.length; j < m; ++j) classFields[fieldNames[j]] = this.fields[i]
  9238. }
  9239. for (i = 0, l = this.methods.length; i < l; ++i) {
  9240. var method = this.methods[i];
  9241. classMethods[method.name] = method
  9242. }
  9243. for (i = 0, l = this.innerClasses.length; i < l; ++i) {
  9244. var innerClass = this.innerClasses[i];
  9245. classInners[innerClass.name] = innerClass
  9246. }
  9247. };
  9248. AstClassBody.prototype.toString = function() {
  9249. function getScopeLevel(p) {
  9250. var i = 0;
  9251. while (p) {
  9252. ++i;
  9253. p = p.scope
  9254. }
  9255. return i
  9256. }
  9257. var scopeLevel = getScopeLevel(this.owner);
  9258. var selfId = "$this_" + scopeLevel;
  9259. var className = this.name;
  9260. var result = "var " + selfId + " = this;\n";
  9261. var staticDefinitions = "";
  9262. var metadata = "";
  9263. var thisClassFields = {},
  9264. thisClassMethods = {},
  9265. thisClassInners = {};
  9266. this.getMembers(thisClassFields, thisClassMethods, thisClassInners);
  9267. var oldContext = replaceContext;
  9268. replaceContext = function(subject) {
  9269. var name = subject.name;
  9270. if (name === "this") return subject.callSign || !subject.member ? selfId + ".$self" : selfId;
  9271. if (thisClassFields.hasOwnProperty(name)) return thisClassFields[name].isStatic ? className + "." + name : selfId + "." + name;
  9272. if (thisClassInners.hasOwnProperty(name)) return selfId + "." + name;
  9273. if (thisClassMethods.hasOwnProperty(name)) return thisClassMethods[name].isStatic ? className + "." + name : selfId + ".$self." + name;
  9274. return oldContext(subject)
  9275. };
  9276. var resolvedBaseClassName;
  9277. if (this.baseClassName) {
  9278. resolvedBaseClassName = oldContext({
  9279. name: this.baseClassName
  9280. });
  9281. result += "var $super = { $upcast: " + selfId + " };\n";
  9282. result += "function $superCstr(){" + resolvedBaseClassName + ".apply($super,arguments);if(!('$self' in $super)) $p.extendClassChain($super)}\n";
  9283. metadata += className + ".$base = " + resolvedBaseClassName + ";\n"
  9284. } else result += "function $superCstr(){$p.extendClassChain(" + selfId + ")}\n";
  9285. if (this.owner.base) staticDefinitions += "$p.extendStaticMembers(" + className + ", " + resolvedBaseClassName + ");\n";
  9286. var i, l, j, m;
  9287. if (this.owner.interfaces) {
  9288. var resolvedInterfaces = [],
  9289. resolvedInterface;
  9290. for (i = 0, l = this.interfacesNames.length; i < l; ++i) {
  9291. if (!this.owner.interfaces[i]) continue;
  9292. resolvedInterface = oldContext({
  9293. name: this.interfacesNames[i]
  9294. });
  9295. resolvedInterfaces.push(resolvedInterface);
  9296. staticDefinitions += "$p.extendInterfaceMembers(" + className + ", " + resolvedInterface + ");\n"
  9297. }
  9298. metadata += className + ".$interfaces = [" + resolvedInterfaces.join(", ") + "];\n"
  9299. }
  9300. if (this.functions.length > 0) result += this.functions.join("\n") + "\n";
  9301. sortByWeight(this.innerClasses);
  9302. for (i = 0, l = this.innerClasses.length; i < l; ++i) {
  9303. var innerClass = this.innerClasses[i];
  9304. if (innerClass.isStatic) {
  9305. staticDefinitions += className + "." + innerClass.name + " = " + innerClass + ";\n";
  9306. result += selfId + "." + innerClass.name + " = " + className + "." + innerClass.name + ";\n"
  9307. } else result += selfId + "." + innerClass.name + " = " + innerClass + ";\n"
  9308. }
  9309. for (i = 0, l = this.fields.length; i < l; ++i) {
  9310. var field = this.fields[i];
  9311. if (field.isStatic) {
  9312. staticDefinitions += className + "." + field.definitions.join(";\n" + className + ".") + ";\n";
  9313. for (j = 0, m = field.definitions.length; j < m; ++j) {
  9314. var fieldName = field.definitions[j].name,
  9315. staticName = className + "." + fieldName;
  9316. result += "$p.defineProperty(" + selfId + ", '" + fieldName + "', {" + "get: function(){return " + staticName + "}, " + "set: function(val){" + staticName + " = val}});\n"
  9317. }
  9318. } else result += selfId + "." + field.definitions.join(";\n" + selfId + ".") + ";\n"
  9319. }
  9320. var methodOverloads = {};
  9321. for (i = 0, l = this.methods.length; i < l; ++i) {
  9322. var method = this.methods[i];
  9323. var overload = methodOverloads[method.name];
  9324. var methodId = method.name + "$" + method.params.params.length;
  9325. var hasMethodArgs = !!method.params.methodArgsParam;
  9326. if (overload) {
  9327. ++overload;
  9328. methodId += "_" + overload
  9329. } else overload = 1;
  9330. method.methodId = methodId;
  9331. methodOverloads[method.name] = overload;
  9332. if (method.isStatic) {
  9333. staticDefinitions += method;
  9334. staticDefinitions += "$p.addMethod(" + className + ", '" + method.name + "', " + methodId + ", " + hasMethodArgs + ");\n";
  9335. result += "$p.addMethod(" + selfId + ", '" + method.name + "', " + methodId + ", " + hasMethodArgs + ");\n"
  9336. } else {
  9337. result += method;
  9338. result += "$p.addMethod(" + selfId + ", '" + method.name + "', " + methodId + ", " + hasMethodArgs + ");\n"
  9339. }
  9340. }
  9341. result += trim(this.misc.tail);
  9342. if (this.cstrs.length > 0) result += this.cstrs.join("\n") + "\n";
  9343. result += "function $constr() {\n";
  9344. var cstrsIfs = [];
  9345. for (i = 0, l = this.cstrs.length; i < l; ++i) {
  9346. var paramsLength = this.cstrs[i].params.params.length;
  9347. var methodArgsPresent = !!this.cstrs[i].params.methodArgsParam;
  9348. cstrsIfs.push("if(arguments.length " + (methodArgsPresent ? ">=" : "===") + " " + paramsLength + ") { " + "$constr_" + paramsLength + ".apply(" + selfId + ", arguments); }")
  9349. }
  9350. if (cstrsIfs.length > 0) result += cstrsIfs.join(" else ") + " else ";
  9351. result += "$superCstr();\n}\n";
  9352. result += "$constr.apply(null, arguments);\n";
  9353. replaceContext = oldContext;
  9354. return "(function() {\n" + "function " + className + "() {\n" + result + "}\n" + staticDefinitions + metadata + "return " + className + ";\n" + "})()"
  9355. };
  9356. transformClassBody = function(body, name, baseName, interfaces) {
  9357. var declarations = body.substring(1, body.length - 1);
  9358. declarations = extractClassesAndMethods(declarations);
  9359. declarations = extractConstructors(declarations, name);
  9360. var methods = [],
  9361. classes = [],
  9362. cstrs = [],
  9363. functions = [];
  9364. declarations = declarations.replace(/"([DEGH])(\d+)"/g, function(all, type, index) {
  9365. if (type === "D") methods.push(index);
  9366. else if (type === "E") classes.push(index);
  9367. else if (type === "H") functions.push(index);
  9368. else cstrs.push(index);
  9369. return ""
  9370. });
  9371. var fields = declarations.replace(/^(?:\s*;)+/, "").split(/;(?:\s*;)*/g);
  9372. var baseClassName, interfacesNames;
  9373. var i;
  9374. if (baseName !== undef) baseClassName = baseName.replace(/^\s*extends\s+([A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*)\s*$/g, "$1");
  9375. if (interfaces !== undef) interfacesNames = interfaces.replace(/^\s*implements\s+(.+?)\s*$/g, "$1").split(/\s*,\s*/g);
  9376. for (i = 0; i < functions.length; ++i) functions[i] = transformFunction(atoms[functions[i]]);
  9377. for (i = 0; i < methods.length; ++i) methods[i] = transformClassMethod(atoms[methods[i]]);
  9378. for (i = 0; i < fields.length - 1; ++i) {
  9379. var field = trimSpaces(fields[i]);
  9380. fields[i] = transformClassField(field.middle)
  9381. }
  9382. var tail = fields.pop();
  9383. for (i = 0; i < cstrs.length; ++i) cstrs[i] = transformConstructor(atoms[cstrs[i]]);
  9384. for (i = 0; i < classes.length; ++i) classes[i] = transformInnerClass(atoms[classes[i]]);
  9385. return new AstClassBody(name, baseClassName, interfacesNames, functions, methods, fields, cstrs, classes, {
  9386. tail: tail
  9387. })
  9388. };
  9389. function AstInterface(name, body) {
  9390. this.name = name;
  9391. this.body = body;
  9392. body.owner = this
  9393. }
  9394. AstInterface.prototype.toString = function() {
  9395. return "var " + this.name + " = " + this.body + ";\n" + "$p." + this.name + " = " + this.name + ";\n"
  9396. };
  9397. function AstClass(name, body) {
  9398. this.name = name;
  9399. this.body = body;
  9400. body.owner = this
  9401. }
  9402. AstClass.prototype.toString = function() {
  9403. return "var " + this.name + " = " + this.body + ";\n" + "$p." + this.name + " = " + this.name + ";\n"
  9404. };
  9405. function transformGlobalClass(class_) {
  9406. var m = classesRegex.exec(class_);
  9407. classesRegex.lastIndex = 0;
  9408. var body = atoms[getAtomIndex(m[6])];
  9409. var oldClassId = currentClassId,
  9410. newClassId = generateClassId();
  9411. currentClassId = newClassId;
  9412. var globalClass;
  9413. if (m[2] === "interface") globalClass = new AstInterface(m[3], transformInterfaceBody(body, m[3], m[4]));
  9414. else globalClass = new AstClass(m[3], transformClassBody(body, m[3], m[4], m[5]));
  9415. appendClass(globalClass, newClassId, oldClassId);
  9416. currentClassId = oldClassId;
  9417. return globalClass
  9418. }
  9419. function AstMethod(name, params, body) {
  9420. this.name = name;
  9421. this.params = params;
  9422. this.body = body
  9423. }
  9424. AstMethod.prototype.toString = function() {
  9425. var paramNames = appendToLookupTable({},
  9426. this.params.getNames());
  9427. var oldContext = replaceContext;
  9428. replaceContext = function(subject) {
  9429. return paramNames.hasOwnProperty(subject.name) ? subject.name : oldContext(subject)
  9430. };
  9431. var body = this.params.prependMethodArgs(this.body.toString());
  9432. var result = "function " + this.name + this.params + " " + body + "\n" + "$p." + this.name + " = " + this.name + ";";
  9433. replaceContext = oldContext;
  9434. return result
  9435. };
  9436. function transformGlobalMethod(method) {
  9437. var m = methodsRegex.exec(method);
  9438. var result = methodsRegex.lastIndex = 0;
  9439. return new AstMethod(m[3], transformParams(atoms[getAtomIndex(m[4])]), transformStatementsBlock(atoms[getAtomIndex(m[6])]))
  9440. }
  9441. function preStatementsTransform(statements) {
  9442. var s = statements;
  9443. s = s.replace(/\b(catch\s*"B\d+"\s*"A\d+")(\s*catch\s*"B\d+"\s*"A\d+")+/g, "$1");
  9444. return s
  9445. }
  9446. function AstForStatement(argument, misc) {
  9447. this.argument = argument;
  9448. this.misc = misc
  9449. }
  9450. AstForStatement.prototype.toString = function() {
  9451. return this.misc.prefix + this.argument.toString()
  9452. };
  9453. function AstCatchStatement(argument, misc) {
  9454. this.argument = argument;
  9455. this.misc = misc
  9456. }
  9457. AstCatchStatement.prototype.toString = function() {
  9458. return this.misc.prefix + this.argument.toString()
  9459. };
  9460. function AstPrefixStatement(name, argument, misc) {
  9461. this.name = name;
  9462. this.argument = argument;
  9463. this.misc = misc
  9464. }
  9465. AstPrefixStatement.prototype.toString = function() {
  9466. var result = this.misc.prefix;
  9467. if (this.argument !== undef) result += this.argument.toString();
  9468. return result
  9469. };
  9470. function AstSwitchCase(expr) {
  9471. this.expr = expr
  9472. }
  9473. AstSwitchCase.prototype.toString = function() {
  9474. return "case " + this.expr + ":"
  9475. };
  9476. function AstLabel(label) {
  9477. this.label = label
  9478. }
  9479. AstLabel.prototype.toString = function() {
  9480. return this.label
  9481. };
  9482. transformStatements = function(statements, transformMethod, transformClass) {
  9483. 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);
  9484. var res = [];
  9485. statements = preStatementsTransform(statements);
  9486. var lastIndex = 0,
  9487. m, space;
  9488. while ((m = nextStatement.exec(statements)) !== null) {
  9489. if (m[1] !== undef) {
  9490. var i = statements.lastIndexOf('"B', nextStatement.lastIndex);
  9491. var statementsPrefix = statements.substring(lastIndex, i);
  9492. if (m[1] === "for") res.push(new AstForStatement(transformForExpression(atoms[m[2]]), {
  9493. prefix: statementsPrefix
  9494. }));
  9495. else if (m[1] === "catch") res.push(new AstCatchStatement(transformParams(atoms[m[2]]), {
  9496. prefix: statementsPrefix
  9497. }));
  9498. else res.push(new AstPrefixStatement(m[1], transformExpression(atoms[m[2]]), {
  9499. prefix: statementsPrefix
  9500. }))
  9501. } else if (m[3] !== undef) res.push(new AstPrefixStatement(m[3], undef, {
  9502. prefix: statements.substring(lastIndex, nextStatement.lastIndex)
  9503. }));
  9504. else if (m[4] !== undef) {
  9505. space = statements.substring(lastIndex, nextStatement.lastIndex - m[4].length);
  9506. if (trim(space).length !== 0) continue;
  9507. res.push(space);
  9508. var kind = m[4].charAt(1),
  9509. atomIndex = m[5];
  9510. if (kind === "D") res.push(transformMethod(atoms[atomIndex]));
  9511. else if (kind === "E") res.push(transformClass(atoms[atomIndex]));
  9512. else if (kind === "H") res.push(transformFunction(atoms[atomIndex]));
  9513. else res.push(transformStatementsBlock(atoms[atomIndex]))
  9514. } else if (m[6] !== undef) res.push(new AstSwitchCase(transformExpression(trim(m[7]))));
  9515. else if (m[8] !== undef) {
  9516. space = statements.substring(lastIndex, nextStatement.lastIndex - m[8].length);
  9517. if (trim(space).length !== 0) continue;
  9518. res.push(new AstLabel(statements.substring(lastIndex, nextStatement.lastIndex)))
  9519. } else {
  9520. var statement = trimSpaces(statements.substring(lastIndex, nextStatement.lastIndex - 1));
  9521. res.push(statement.left);
  9522. res.push(transformStatement(statement.middle));
  9523. res.push(statement.right + ";")
  9524. }
  9525. lastIndex = nextStatement.lastIndex
  9526. }
  9527. var statementsTail = trimSpaces(statements.substring(lastIndex));
  9528. res.push(statementsTail.left);
  9529. if (statementsTail.middle !== "") {
  9530. res.push(transformStatement(statementsTail.middle));
  9531. res.push(";" + statementsTail.right)
  9532. }
  9533. return res
  9534. };
  9535. function getLocalNames(statements) {
  9536. var localNames = [];
  9537. for (var i = 0, l = statements.length; i < l; ++i) {
  9538. var statement = statements[i];
  9539. if (statement instanceof AstVar) localNames = localNames.concat(statement.getNames());
  9540. else if (statement instanceof AstForStatement && statement.argument.initStatement instanceof AstVar) localNames = localNames.concat(statement.argument.initStatement.getNames());
  9541. else if (statement instanceof AstInnerInterface || statement instanceof AstInnerClass || statement instanceof AstInterface || statement instanceof AstClass || statement instanceof AstMethod || statement instanceof AstFunction) localNames.push(statement.name)
  9542. }
  9543. return appendToLookupTable({},
  9544. localNames)
  9545. }
  9546. function AstStatementsBlock(statements) {
  9547. this.statements = statements
  9548. }
  9549. AstStatementsBlock.prototype.toString = function() {
  9550. var localNames = getLocalNames(this.statements);
  9551. var oldContext = replaceContext;
  9552. if (!isLookupTableEmpty(localNames)) replaceContext = function(subject) {
  9553. return localNames.hasOwnProperty(subject.name) ? subject.name : oldContext(subject)
  9554. };
  9555. var result = "{\n" + this.statements.join("") + "\n}";
  9556. replaceContext = oldContext;
  9557. return result
  9558. };
  9559. transformStatementsBlock = function(block) {
  9560. var content = trimSpaces(block.substring(1, block.length - 1));
  9561. return new AstStatementsBlock(transformStatements(content.middle))
  9562. };
  9563. function AstRoot(statements) {
  9564. this.statements = statements
  9565. }
  9566. AstRoot.prototype.toString = function() {
  9567. var classes = [],
  9568. otherStatements = [],
  9569. statement;
  9570. for (var i = 0, len = this.statements.length; i < len; ++i) {
  9571. statement = this.statements[i];
  9572. if (statement instanceof AstClass || statement instanceof AstInterface) classes.push(statement);
  9573. else otherStatements.push(statement)
  9574. }
  9575. sortByWeight(classes);
  9576. var localNames = getLocalNames(this.statements);
  9577. replaceContext = function(subject) {
  9578. var name = subject.name;
  9579. if (localNames.hasOwnProperty(name)) return name;
  9580. if (globalMembers.hasOwnProperty(name) || PConstants.hasOwnProperty(name) || defaultScope.hasOwnProperty(name)) return "$p." + name;
  9581. return name
  9582. };
  9583. var result = "// this code was autogenerated from PJS\n" + "(function($p) {\n" + classes.join("") + "\n" + otherStatements.join("") + "\n})";
  9584. replaceContext = null;
  9585. return result
  9586. };
  9587. transformMain = function() {
  9588. var statements = extractClassesAndMethods(atoms[0]);
  9589. statements = statements.replace(/\bimport\s+[^;]+;/g, "");
  9590. return new AstRoot(transformStatements(statements, transformGlobalMethod, transformGlobalClass))
  9591. };
  9592. function generateMetadata(ast) {
  9593. var globalScope = {};
  9594. var id, class_;
  9595. for (id in declaredClasses) if (declaredClasses.hasOwnProperty(id)) {
  9596. class_ = declaredClasses[id];
  9597. var scopeId = class_.scopeId,
  9598. name = class_.name;
  9599. if (scopeId) {
  9600. var scope = declaredClasses[scopeId];
  9601. class_.scope = scope;
  9602. if (scope.inScope === undef) scope.inScope = {};
  9603. scope.inScope[name] = class_
  9604. } else globalScope[name] = class_
  9605. }
  9606. function findInScopes(class_, name) {
  9607. var parts = name.split(".");
  9608. var currentScope = class_.scope,
  9609. found;
  9610. while (currentScope) {
  9611. if (currentScope.hasOwnProperty(parts[0])) {
  9612. found = currentScope[parts[0]];
  9613. break
  9614. }
  9615. currentScope = currentScope.scope
  9616. }
  9617. if (found === undef) found = globalScope[parts[0]];
  9618. for (var i = 1, l = parts.length; i < l && found; ++i) found = found.inScope[parts[i]];
  9619. return found
  9620. }
  9621. for (id in declaredClasses) if (declaredClasses.hasOwnProperty(id)) {
  9622. class_ = declaredClasses[id];
  9623. var baseClassName = class_.body.baseClassName;
  9624. if (baseClassName) {
  9625. var parent = findInScopes(class_, baseClassName);
  9626. if (parent) {
  9627. class_.base = parent;
  9628. if (!parent.derived) parent.derived = [];
  9629. parent.derived.push(class_)
  9630. }
  9631. }
  9632. var interfacesNames = class_.body.interfacesNames,
  9633. interfaces = [],
  9634. i, l;
  9635. if (interfacesNames && interfacesNames.length > 0) {
  9636. for (i = 0, l = interfacesNames.length; i < l; ++i) {
  9637. var interface_ = findInScopes(class_, interfacesNames[i]);
  9638. interfaces.push(interface_);
  9639. if (!interface_) continue;
  9640. if (!interface_.derived) interface_.derived = [];
  9641. interface_.derived.push(class_)
  9642. }
  9643. if (interfaces.length > 0) class_.interfaces = interfaces
  9644. }
  9645. }
  9646. }
  9647. function setWeight(ast) {
  9648. var queue = [],
  9649. tocheck = {};
  9650. var id, scopeId, class_;
  9651. for (id in declaredClasses) if (declaredClasses.hasOwnProperty(id)) {
  9652. class_ = declaredClasses[id];
  9653. if (!class_.inScope && !class_.derived) {
  9654. queue.push(id);
  9655. class_.weight = 0
  9656. } else {
  9657. var dependsOn = [];
  9658. if (class_.inScope) for (scopeId in class_.inScope) if (class_.inScope.hasOwnProperty(scopeId)) dependsOn.push(class_.inScope[scopeId]);
  9659. if (class_.derived) dependsOn = dependsOn.concat(class_.derived);
  9660. tocheck[id] = dependsOn
  9661. }
  9662. }
  9663. function removeDependentAndCheck(targetId, from) {
  9664. var dependsOn = tocheck[targetId];
  9665. if (!dependsOn) return false;
  9666. var i = dependsOn.indexOf(from);
  9667. if (i < 0) return false;
  9668. dependsOn.splice(i, 1);
  9669. if (dependsOn.length > 0) return false;
  9670. delete tocheck[targetId];
  9671. return true
  9672. }
  9673. while (queue.length > 0) {
  9674. id = queue.shift();
  9675. class_ = declaredClasses[id];
  9676. if (class_.scopeId && removeDependentAndCheck(class_.scopeId, class_)) {
  9677. queue.push(class_.scopeId);
  9678. declaredClasses[class_.scopeId].weight = class_.weight + 1
  9679. }
  9680. if (class_.base && removeDependentAndCheck(class_.base.classId, class_)) {
  9681. queue.push(class_.base.classId);
  9682. class_.base.weight = class_.weight + 1
  9683. }
  9684. if (class_.interfaces) {
  9685. var i, l;
  9686. for (i = 0, l = class_.interfaces.length; i < l; ++i) {
  9687. if (!class_.interfaces[i] || !removeDependentAndCheck(class_.interfaces[i].classId, class_)) continue;
  9688. queue.push(class_.interfaces[i].classId);
  9689. class_.interfaces[i].weight = class_.weight + 1
  9690. }
  9691. }
  9692. }
  9693. }
  9694. var transformed = transformMain();
  9695. generateMetadata(transformed);
  9696. setWeight(transformed);
  9697. var redendered = transformed.toString();
  9698. redendered = redendered.replace(/\s*\n(?:[\t ]*\n)+/g, "\n\n");
  9699. redendered = redendered.replace(/__x([0-9A-F]{4})/g, function(all, hexCode) {
  9700. return String.fromCharCode(parseInt(hexCode, 16))
  9701. });
  9702. return injectStrings(redendered, strings)
  9703. }
  9704. function preprocessCode(aCode, sketch) {
  9705. var dm = (new RegExp(/\/\*\s*@pjs\s+((?:[^\*]|\*+[^\*\/])*)\*\//g)).exec(aCode);
  9706. if (dm && dm.length === 2) {
  9707. var jsonItems = [],
  9708. directives = dm.splice(1, 2)[0].replace(/\{([\s\S]*?)\}/g, function() {
  9709. return function(all, item) {
  9710. jsonItems.push(item);
  9711. return "{" + (jsonItems.length - 1) + "}"
  9712. }
  9713. }()).replace("\n", "").replace("\r", "").split(";");
  9714. var clean = function(s) {
  9715. return s.replace(/^\s*["']?/, "").replace(/["']?\s*$/, "")
  9716. };
  9717. for (var i = 0, dl = directives.length; i < dl; i++) {
  9718. var pair = directives[i].split("=");
  9719. if (pair && pair.length === 2) {
  9720. var key = clean(pair[0]),
  9721. value = clean(pair[1]),
  9722. list = [];
  9723. if (key === "preload") {
  9724. list = value.split(",");
  9725. for (var j = 0, jl = list.length; j < jl; j++) {
  9726. var imageName = clean(list[j]);
  9727. sketch.imageCache.add(imageName)
  9728. }
  9729. } else if (key === "font") {
  9730. list = value.split(",");
  9731. for (var x = 0, xl = list.length; x < xl; x++) {
  9732. var fontName = clean(list[x]),
  9733. index = /^\{(\d*?)\}$/.exec(fontName);
  9734. PFont.preloading.add(index ? JSON.parse("{" + jsonItems[index[1]] + "}") : fontName)
  9735. }
  9736. } else if (key === "pauseOnBlur") sketch.options.pauseOnBlur = value === "true";
  9737. else if (key === "globalKeyEvents") sketch.options.globalKeyEvents = value === "true";
  9738. else if (key.substring(0, 6) === "param-") sketch.params[key.substring(6)] = value;
  9739. else sketch.options[key] = value
  9740. }
  9741. }
  9742. }
  9743. return aCode
  9744. }
  9745. Processing.compile = function(pdeCode) {
  9746. var sketch = new Processing.Sketch;
  9747. var code = preprocessCode(pdeCode, sketch);
  9748. var compiledPde = parseProcessing(code);
  9749. sketch.sourceCode = compiledPde;
  9750. return sketch
  9751. };
  9752. var tinylogLite = function() {
  9753. var tinylogLite = {},
  9754. undef = "undefined",
  9755. func = "function",
  9756. False = !1,
  9757. True = !0,
  9758. logLimit = 512,
  9759. log = "log";
  9760. if (typeof tinylog !== undef && typeof tinylog[log] === func) tinylogLite[log] = tinylog[log];
  9761. else if (typeof document !== undef && !document.fake)(function() {
  9762. var doc = document,
  9763. $div = "div",
  9764. $style = "style",
  9765. $title = "title",
  9766. containerStyles = {
  9767. zIndex: 1E4,
  9768. position: "fixed",
  9769. bottom: "0px",
  9770. width: "100%",
  9771. height: "15%",
  9772. fontFamily: "sans-serif",
  9773. color: "#ccc",
  9774. backgroundColor: "black"
  9775. },
  9776. outputStyles = {
  9777. position: "relative",
  9778. fontFamily: "monospace",
  9779. overflow: "auto",
  9780. height: "100%",
  9781. paddingTop: "5px"
  9782. },
  9783. resizerStyles = {
  9784. height: "5px",
  9785. marginTop: "-5px",
  9786. cursor: "n-resize",
  9787. backgroundColor: "darkgrey"
  9788. },
  9789. closeButtonStyles = {
  9790. position: "absolute",
  9791. top: "5px",
  9792. right: "20px",
  9793. color: "#111",
  9794. MozBorderRadius: "4px",
  9795. webkitBorderRadius: "4px",
  9796. borderRadius: "4px",
  9797. cursor: "pointer",
  9798. fontWeight: "normal",
  9799. textAlign: "center",
  9800. padding: "3px 5px",
  9801. backgroundColor: "#333",
  9802. fontSize: "12px"
  9803. },
  9804. entryStyles = {
  9805. minHeight: "16px"
  9806. },
  9807. entryTextStyles = {
  9808. fontSize: "12px",
  9809. margin: "0 8px 0 8px",
  9810. maxWidth: "100%",
  9811. whiteSpace: "pre-wrap",
  9812. overflow: "auto"
  9813. },
  9814. view = doc.defaultView,
  9815. docElem = doc.documentElement,
  9816. docElemStyle = docElem[$style],
  9817. setStyles = function() {
  9818. var i = arguments.length,
  9819. elemStyle, styles, style;
  9820. while (i--) {
  9821. styles = arguments[i--];
  9822. elemStyle = arguments[i][$style];
  9823. for (style in styles) if (styles.hasOwnProperty(style)) elemStyle[style] = styles[style]
  9824. }
  9825. },
  9826. observer = function(obj, event, handler) {
  9827. if (obj.addEventListener) obj.addEventListener(event, handler, False);
  9828. else if (obj.attachEvent) obj.attachEvent("on" + event, handler);
  9829. return [obj, event, handler]
  9830. },
  9831. unobserve = function(obj, event, handler) {
  9832. if (obj.removeEventListener) obj.removeEventListener(event, handler, False);
  9833. else if (obj.detachEvent) obj.detachEvent("on" + event, handler)
  9834. },
  9835. clearChildren = function(node) {
  9836. var children = node.childNodes,
  9837. child = children.length;
  9838. while (child--) node.removeChild(children.item(0))
  9839. },
  9840. append = function(to, elem) {
  9841. return to.appendChild(elem)
  9842. },
  9843. createElement = function(localName) {
  9844. return doc.createElement(localName)
  9845. },
  9846. createTextNode = function(text) {
  9847. return doc.createTextNode(text)
  9848. },
  9849. createLog = tinylogLite[log] = function(message) {
  9850. var uninit, originalPadding = docElemStyle.paddingBottom,
  9851. container = createElement($div),
  9852. containerStyle = container[$style],
  9853. resizer = append(container, createElement($div)),
  9854. output = append(container, createElement($div)),
  9855. closeButton = append(container, createElement($div)),
  9856. resizingLog = False,
  9857. previousHeight = False,
  9858. previousScrollTop = False,
  9859. messages = 0,
  9860. updateSafetyMargin = function() {
  9861. docElemStyle.paddingBottom = container.clientHeight + "px"
  9862. },
  9863. setContainerHeight = function(height) {
  9864. var viewHeight = view.innerHeight,
  9865. resizerHeight = resizer.clientHeight;
  9866. if (height < 0) height = 0;
  9867. else if (height + resizerHeight > viewHeight) height = viewHeight - resizerHeight;
  9868. containerStyle.height = height / viewHeight * 100 + "%";
  9869. updateSafetyMargin()
  9870. },
  9871. observers = [observer(doc, "mousemove", function(evt) {
  9872. if (resizingLog) {
  9873. setContainerHeight(view.innerHeight - evt.clientY);
  9874. output.scrollTop = previousScrollTop
  9875. }
  9876. }), observer(doc, "mouseup", function() {
  9877. if (resizingLog) resizingLog = previousScrollTop = False
  9878. }), observer(resizer, "dblclick", function(evt) {
  9879. evt.preventDefault();
  9880. if (previousHeight) {
  9881. setContainerHeight(previousHeight);
  9882. previousHeight = False
  9883. } else {
  9884. previousHeight = container.clientHeight;
  9885. containerStyle.height = "0px"
  9886. }
  9887. }), observer(resizer, "mousedown", function(evt) {
  9888. evt.preventDefault();
  9889. resizingLog = True;
  9890. previousScrollTop = output.scrollTop
  9891. }), observer(resizer, "contextmenu", function() {
  9892. resizingLog = False
  9893. }), observer(closeButton, "click", function() {
  9894. uninit()
  9895. })];
  9896. uninit = function() {
  9897. var i = observers.length;
  9898. while (i--) unobserve.apply(tinylogLite, observers[i]);
  9899. docElem.removeChild(container);
  9900. docElemStyle.paddingBottom = originalPadding;
  9901. clearChildren(output);
  9902. clearChildren(container);
  9903. tinylogLite[log] = createLog
  9904. };
  9905. setStyles(container, containerStyles, output, outputStyles, resizer, resizerStyles, closeButton, closeButtonStyles);
  9906. closeButton[$title] = "Close Log";
  9907. append(closeButton, createTextNode("\u2716"));
  9908. resizer[$title] = "Double-click to toggle log minimization";
  9909. docElem.insertBefore(container, docElem.firstChild);
  9910. tinylogLite[log] = function(message) {
  9911. if (messages === logLimit) output.removeChild(output.firstChild);
  9912. else messages++;
  9913. var entry = append(output, createElement($div)),
  9914. entryText = append(entry, createElement($div));
  9915. entry[$title] = (new Date).toLocaleTimeString();
  9916. setStyles(entry, entryStyles, entryText, entryTextStyles);
  9917. append(entryText, createTextNode(message));
  9918. output.scrollTop = output.scrollHeight
  9919. };
  9920. tinylogLite[log](message);
  9921. updateSafetyMargin()
  9922. }
  9923. })();
  9924. else if (typeof print === func) tinylogLite[log] = print;
  9925. return tinylogLite
  9926. }();
  9927. Processing.logger = tinylogLite;
  9928. Processing.version = "1.4.1";
  9929. Processing.lib = {};
  9930. Processing.registerLibrary = function(name, desc) {
  9931. Processing.lib[name] = desc;
  9932. if (desc.hasOwnProperty("init")) desc.init(defaultScope)
  9933. };
  9934. Processing.instances = processingInstances;
  9935. Processing.getInstanceById = function(name) {
  9936. return processingInstances[processingInstanceIds[name]]
  9937. };
  9938. Processing.Sketch = function(attachFunction) {
  9939. this.attachFunction = attachFunction;
  9940. this.options = {
  9941. pauseOnBlur: false,
  9942. globalKeyEvents: false
  9943. };
  9944. this.onLoad = nop;
  9945. this.onSetup = nop;
  9946. this.onPause = nop;
  9947. this.onLoop = nop;
  9948. this.onFrameStart = nop;
  9949. this.onFrameEnd = nop;
  9950. this.onExit = nop;
  9951. this.params = {};
  9952. this.imageCache = {
  9953. pending: 0,
  9954. images: {},
  9955. operaCache: {},
  9956. add: function(href, img) {
  9957. if (this.images[href]) return;
  9958. if (!isDOMPresent) this.images[href] = null;
  9959. if (!img) {
  9960. img = new Image;
  9961. img.onload = function(owner) {
  9962. return function() {
  9963. owner.pending--
  9964. }
  9965. }(this);
  9966. this.pending++;
  9967. img.src = href
  9968. }
  9969. this.images[href] = img;
  9970. if (window.opera) {
  9971. var div = document.createElement("div");
  9972. div.appendChild(img);
  9973. div.style.position = "absolute";
  9974. div.style.opacity = 0;
  9975. div.style.width = "1px";
  9976. div.style.height = "1px";
  9977. if (!this.operaCache[href]) {
  9978. document.body.appendChild(div);
  9979. this.operaCache[href] = div
  9980. }
  9981. }
  9982. }
  9983. };
  9984. this.sourceCode = undefined;
  9985. this.attach = function(processing) {
  9986. if (typeof this.attachFunction === "function") this.attachFunction(processing);
  9987. else if (this.sourceCode) {
  9988. var func = (new Function("return (" + this.sourceCode + ");"))();
  9989. func(processing);
  9990. this.attachFunction = func
  9991. } else throw "Unable to attach sketch to the processing instance";
  9992. };
  9993. this.toString = function() {
  9994. var i;
  9995. var code = "((function(Sketch) {\n";
  9996. code += "var sketch = new Sketch(\n" + this.sourceCode + ");\n";
  9997. for (i in this.options) if (this.options.hasOwnProperty(i)) {
  9998. var value = this.options[i];
  9999. code += "sketch.options." + i + " = " + (typeof value === "string" ? '"' + value + '"' : "" + value) + ";\n"
  10000. }
  10001. for (i in this.imageCache) if (this.options.hasOwnProperty(i)) code += 'sketch.imageCache.add("' + i + '");\n';
  10002. code += "return sketch;\n})(Processing.Sketch))";
  10003. return code
  10004. }
  10005. };
  10006. var loadSketchFromSources = function(canvas, sources) {
  10007. var code = [],
  10008. errors = [],
  10009. sourcesCount = sources.length,
  10010. loaded = 0;
  10011. function ajaxAsync(url, callback) {
  10012. var xhr = new XMLHttpRequest;
  10013. xhr.onreadystatechange = function() {
  10014. if (xhr.readyState === 4) {
  10015. var error;
  10016. if (xhr.status !== 200 && xhr.status !== 0) error = "Invalid XHR status " + xhr.status;
  10017. 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.";
  10018. else error = "File is empty.";
  10019. callback(xhr.responseText, error)
  10020. }
  10021. };
  10022. xhr.open("GET", url, true);
  10023. if (xhr.overrideMimeType) xhr.overrideMimeType("application/json");
  10024. xhr.setRequestHeader("If-Modified-Since", "Fri, 01 Jan 1960 00:00:00 GMT");
  10025. xhr.send(null)
  10026. }
  10027. function loadBlock(index, filename) {
  10028. function callback(block, error) {
  10029. code[index] = block;
  10030. ++loaded;
  10031. if (error) errors.push(filename + " ==> " + error);
  10032. if (loaded === sourcesCount) if (errors.length === 0) try {
  10033. return new Processing(canvas, code.join("\n"))
  10034. } catch(e) {
  10035. throw "Processing.js: Unable to execute pjs sketch: " + e;
  10036. } else throw "Processing.js: Unable to load pjs sketch files: " + errors.join("\n");
  10037. }
  10038. if (filename.charAt(0) === "#") {
  10039. var scriptElement = document.getElementById(filename.substring(1));
  10040. if (scriptElement) callback(scriptElement.text || scriptElement.textContent);
  10041. else callback("", "Unable to load pjs sketch: element with id '" + filename.substring(1) + "' was not found");
  10042. return
  10043. }
  10044. ajaxAsync(filename, callback)
  10045. }
  10046. for (var i = 0; i < sourcesCount; ++i) loadBlock(i, sources[i])
  10047. };
  10048. var init = function() {
  10049. document.removeEventListener("DOMContentLoaded", init, false);
  10050. processingInstances = [];
  10051. var canvas = document.getElementsByTagName("canvas"),
  10052. filenames;
  10053. for (var i = 0, l = canvas.length; i < l; i++) {
  10054. var processingSources = canvas[i].getAttribute("data-processing-sources");
  10055. if (processingSources === null) {
  10056. processingSources = canvas[i].getAttribute("data-src");
  10057. if (processingSources === null) processingSources = canvas[i].getAttribute("datasrc")
  10058. }
  10059. if (processingSources) {
  10060. filenames = processingSources.split(/\s+/g);
  10061. for (var j = 0; j < filenames.length;) if (filenames[j]) j++;
  10062. else filenames.splice(j, 1);
  10063. loadSketchFromSources(canvas[i], filenames)
  10064. }
  10065. }
  10066. var s, last, source, instance, nodelist = document.getElementsByTagName("script"),
  10067. scripts = [];
  10068. for (s = nodelist.length - 1; s >= 0; s--) scripts.push(nodelist[s]);
  10069. for (s = 0, last = scripts.length; s < last; s++) {
  10070. var script = scripts[s];
  10071. if (!script.getAttribute) continue;
  10072. var type = script.getAttribute("type");
  10073. if (type && (type.toLowerCase() === "text/processing" || type.toLowerCase() === "application/processing")) {
  10074. var target = script.getAttribute("data-processing-target");
  10075. canvas = undef;
  10076. if (target) canvas = document.getElementById(target);
  10077. else {
  10078. var nextSibling = script.nextSibling;
  10079. while (nextSibling && nextSibling.nodeType !== 1) nextSibling = nextSibling.nextSibling;
  10080. if (nextSibling && nextSibling.nodeName.toLowerCase() === "canvas") canvas = nextSibling
  10081. }
  10082. if (canvas) {
  10083. if (script.getAttribute("src")) {
  10084. filenames = script.getAttribute("src").split(/\s+/);
  10085. loadSketchFromSources(canvas, filenames);
  10086. continue
  10087. }
  10088. source = script.textContent || script.text;
  10089. instance = new Processing(canvas, source)
  10090. }
  10091. }
  10092. }
  10093. };
  10094. Processing.reload = function() {
  10095. if (processingInstances.length > 0) for (var i = processingInstances.length - 1; i >= 0; i--) if (processingInstances[i]) processingInstances[i].exit();
  10096. init()
  10097. };
  10098. Processing.loadSketchFromSources = loadSketchFromSources;
  10099. Processing.disableInit = function() {
  10100. if (isDOMPresent) document.removeEventListener("DOMContentLoaded", init, false)
  10101. };
  10102. if (isDOMPresent) {
  10103. window["Processing"] = Processing;
  10104. document.addEventListener("DOMContentLoaded", init, false)
  10105. } else this.Processing = Processing
  10106. })(window, window.document, Math);